Newer
Older
Simon Zhamkochyan
committed
///////////////////////////////////////////////////////////////////////////////
// //
// THcShower //
// //
// Shower counter class, describing a generic segmented shower detector. //
// //
// //
// //
// //
///////////////////////////////////////////////////////////////////////////////
#include "THcShower.h"
Simon Zhamkochyan
committed
#include "THaEvData.h"
#include "THaDetMap.h"
#include "THcDetectorMap.h"
#include "THcGlobals.h"
#include "THaCutList.h"
Simon Zhamkochyan
committed
#include "THcParmList.h"
#include "VarDef.h"
#include "VarType.h"
#include "THaTrack.h"
#include "TClonesArray.h"
#include "THaTrackProj.h"
Simon Zhamkochyan
committed
#include "TMath.h"
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <iostream>
Simon Zhamkochyan
committed
using namespace std;
//_____________________________________________________________________________
THcShower::THcShower( const char* name, const char* description,
THaApparatus* apparatus ) :
THaNonTrackingDetector(name,description,apparatus)
{
// Constructor
fNLayers = 0; // No layers until we make them
fClusterList = new THcShowerClusterList;
Simon Zhamkochyan
committed
}
//_____________________________________________________________________________
THcShower::THcShower( ) :
THaNonTrackingDetector()
{
// Constructor
}
//_____________________________________________________________________________
void THcShower::Setup(const char* name, const char* description)
{
char prefix[2];
prefix[0] = tolower(GetApparatus()->GetName()[0]);
prefix[1] = '\0';
string layernamelist;
DBRequest list[]={
{"cal_num_layers", &fNLayers, kInt},
{"cal_layer_names", &layernamelist, kString},
{0}
};
gHcParms->LoadParmValues((DBRequest*)&list,prefix);
vector<string> layer_names = vsplit(layernamelist);
if(layer_names.size() != (UInt_t) fNLayers) {
cout << "THcShower::Setup ERROR: Number of layers " << fNLayers
<< " doesn't agree with number of layer names "
<< layer_names.size() << endl;
// Should quit. Is there an official way to quit?
}
for(UInt_t i=0;i<fNLayers;i++) {
fLayerNames[i] = new char[layer_names[i].length()+1];
strcpy(fLayerNames[i], layer_names[i].c_str());
}
char *desc = new char[strlen(description)+100];
for(UInt_t i=0;i < fNLayers;i++) {
strcpy(desc, description);
strcat(desc, " Plane ");
strcat(desc, fLayerNames[i]);
fPlanes[i] = new THcShowerPlane(fLayerNames[i], desc, i+1, this);
cout << "---------------------------------------------------------------\n";
cout << "From THcShower::Setup: created Shower planes ";
for(UInt_t i=0;i < fNLayers;i++) {
cout << fLayerNames[i];
i < fNLayers-1 ? cout << ", " : cout << ".\n";
}
cout << "---------------------------------------------------------------\n";
Simon Zhamkochyan
committed
//_____________________________________________________________________________
THaAnalysisObject::EStatus THcShower::Init( const TDatime& date )
{
Setup(GetName(), GetTitle());
Simon Zhamkochyan
committed
// Should probably put this in ReadDatabase as we will know the
// maximum number of hits after setting up the detector map
Stephen A. Wood
committed
InitHitList(fDetMap, "THcRawShowerHit", 100);
Simon Zhamkochyan
committed
EStatus status;
if( (status = THaNonTrackingDetector::Init( date )) )
return fStatus=status;
for(UInt_t ip=0;ip<fNLayers;ip++) {
if((status = fPlanes[ip]->Init( date ))) {
return fStatus=status;
}
}
char EngineDID[] = " CAL";
EngineDID[0] = toupper(GetApparatus()->GetName()[0]);
if( gHcDetectorMap->FillMap(fDetMap, EngineDID) < 0 ) {
static const char* const here = "Init()";
Simon Zhamkochyan
committed
Error( Here(here), "Error filling detectormap for %s.",
Simon Zhamkochyan
committed
return kInitError;
}
cout << "---------------------------------------------------------------\n";
cout << "From THcShower::Init: initialized " << GetName() << endl;
cout << "---------------------------------------------------------------\n";
Simon Zhamkochyan
committed
return fStatus = kOK;
}
//_____________________________________________________________________________
Int_t THcShower::ReadDatabase( const TDatime& date )
{
// Read this detector's parameters from the database file 'fi'.
// This function is called by THaDetectorBase::Init() once at the
// beginning of the analysis.
// 'date' contains the date/time of the run being analyzed.
// static const char* const here = "ReadDatabase()";
char prefix[2];
Simon Zhamkochyan
committed
// Read data from database
// Pull values from the THcParmList instead of reading a database
// file like Hall A does.
// We will probably want to add some kind of method to gHcParms to allow
// bulk retrieval of parameters of interest.
// Will need to determine which spectrometer in order to construct
// the parameter names (e.g. hscin_1x_nr vs. sscin_1x_nr)
prefix[0]=tolower(GetApparatus()->GetName()[0]);
prefix[1]='\0';
Simon Zhamkochyan
committed
{
DBRequest list[]={
{"cal_num_neg_columns", &fNegCols, kInt},
{"cal_slop", &fSlop, kDouble},
{"cal_fv_test", &fvTest, kInt,0,1},
{"cal_fv_delta", &fvDelta, kDouble},
{"dbg_raw_cal", &fdbg_raw_cal, kInt, 0, 1},
{"dbg_decoded_cal", &fdbg_decoded_cal, kInt, 0, 1},
{"dbg_sparsified_cal", &fdbg_sparsified_cal, kInt, 0, 1},
{"dbg_clusters_cal", &fdbg_clusters_cal, kInt, 0, 1},
{"dbg_tracks_cal", &fdbg_tracks_cal, kInt, 0, 1},
{"dbg_init_cal", &fdbg_init_cal, kInt, 0, 1},
fvTest = 0; // Default if not defined
fdbg_raw_cal = 0; // Debugging off by default
fdbg_decoded_cal = 0;
fdbg_sparsified_cal = 0;
fdbg_clusters_cal = 0;
fdbg_tracks_cal = 0;
fdbg_init_cal = 0;
gHcParms->LoadParmValues((DBRequest*)&list, prefix);
}
if (fdbg_init_cal) {
cout << "---------------------------------------------------------------\n";
cout << "Debug output from THcShower::ReadDatabase\n";
cout << " Number of neg. columns = " << fNegCols << endl;
cout << " Slop parameter = " << fSlop << endl;
cout << " Fiducial volume test flag = " << fvTest << endl;
cout << " Fiducial volume excl. width = " << fvDelta << endl;
cout << " Initialize debug flag = " << fdbg_init_cal << endl;
cout << " Raw hit debug flag = " << fdbg_raw_cal << endl;
cout << " Decode debug flag = " << fdbg_decoded_cal << endl;
cout << " Sparsify debug flag = " << fdbg_sparsified_cal << endl;
cout << " Cluster debug flag = " << fdbg_clusters_cal << endl;
cout << " Tracking debug flag = " << fdbg_tracks_cal << endl;
{
DBRequest list[]={
{"cal_a_cor", &fAcor, kDouble},
{"cal_b_cor", &fBcor, kDouble},
{"cal_c_cor", &fCcor, kDouble},
{"cal_d_cor", &fDcor, kDouble},
{0}
};
gHcParms->LoadParmValues((DBRequest*)&list, prefix);
}
if (fdbg_init_cal) {
cout << " HMS Calorimeter coordinate correction constants:" << endl;
cout << " fAcor = " << fAcor << endl;
cout << " fBcor = " << fBcor << endl;
cout << " fCcor = " << fCcor << endl;
cout << " fDcor = " << fDcor << endl;
}
fNBlocks = new UInt_t [fNLayers];
Simon Zhamkochyan
committed
for(UInt_t i=0;i<fNLayers;i++) {
DBRequest list[]={
{Form("cal_%s_thick",fLayerNames[i]), &BlockThick[i], kDouble},
{Form("cal_%s_nr",fLayerNames[i]), &fNBlocks[i], kInt},
{Form("cal_%s_zpos",fLayerNames[i]), &fNLayerZPos[i], kDouble},
{Form("cal_%s_right",fLayerNames[i]), &YPos[2*i], kDouble},
{Form("cal_%s_left",fLayerNames[i]), &YPos[2*i+1], kDouble},
{0}
};
gHcParms->LoadParmValues((DBRequest*)&list, prefix);
Simon Zhamkochyan
committed
}
//Caution! Z positions (fronts) are off in hcal.param! Correct later on.
for(UInt_t i=0;i<fNLayers;i++) {
XPos[i] = new Double_t [fNBlocks[i]];
DBRequest list[]={
{Form("cal_%s_top",fLayerNames[i]),XPos[i], kDouble, fNBlocks[i]},
{0}
};
gHcParms->LoadParmValues((DBRequest*)&list, prefix);
Simon Zhamkochyan
committed
}
if (fdbg_init_cal) {
for(UInt_t i=0;i<fNLayers;i++) {
cout << " Plane " << fLayerNames[i] << ":" << endl;
cout << " Block thickness: " << BlockThick[i] << endl;
cout << " NBlocks : " << fNBlocks[i] << endl;
cout << " Z Position : " << fNLayerZPos[i] << endl;
cout << " Y Positions : " << YPos[2*i] << ", " << YPos[2*i+1]
<<endl;
cout << " X Positions :";
for(UInt_t j=0; j<fNBlocks[i]; j++) {
cout << " " << XPos[i][j];
}
cout << endl;
Simon Zhamkochyan
committed
}
// Fiducial volume limits, based on Plane 1 positions.
//
fvXmin = XPos[0][0] + fvDelta;
fvXmax = XPos[0][fNBlocks[0]-1] + BlockThick[0] - fvDelta;
fvYmin = YPos[0] + fvDelta;
fvYmax = YPos[1] - fvDelta;
if (fdbg_init_cal) {
cout << " Fiducial volume limits:" << endl;
cout << " Xmin = " << fvXmin << " Xmax = " << fvXmax << endl;
cout << " Ymin = " << fvYmin << " Ymax = " << fvYmax << endl;
//Calibration related parameters (from hcal.param).
fNtotBlocks=0; //total number of blocks
for (UInt_t i=0; i<fNLayers; i++) fNtotBlocks += fNBlocks[i];
if (fdbg_init_cal)
cout << " Total number of blocks in the calorimeter: " << fNtotBlocks
//Pedestal limits from hcal.param.
Vardan Tadevosyan
committed
fShPosPedLimit = new Int_t [fNtotBlocks];
fShNegPedLimit = new Int_t [fNtotBlocks];
//Calibration constants
fPosGain = new Double_t [fNtotBlocks];
fNegGain = new Double_t [fNtotBlocks];
//Read in parameters from hcal.param
Double_t hcal_pos_cal_const[fNtotBlocks];
// Double_t hcal_pos_gain_ini[fNtotBlocks]; not used
// Double_t hcal_pos_gain_cur[fNtotBlocks]; not used
// Int_t hcal_pos_ped_limit[fNtotBlocks]; not used
Double_t hcal_pos_gain_cor[fNtotBlocks];
Double_t hcal_neg_cal_const[fNtotBlocks];
// Double_t hcal_neg_gain_ini[fNtotBlocks]; not used
// Double_t hcal_neg_gain_cur[fNtotBlocks]; not used
// Int_t hcal_neg_ped_limit[fNtotBlocks]; not used
Double_t hcal_neg_gain_cor[fNtotBlocks];
DBRequest list[]={
{"cal_pos_cal_const", hcal_pos_cal_const, kDouble, fNtotBlocks},
// {"cal_pos_gain_ini", hcal_pos_gain_ini, kDouble, fNtotBlocks},
// {"cal_pos_gain_cur", hcal_pos_gain_cur, kDouble, fNtotBlocks},
Vardan Tadevosyan
committed
{"cal_pos_ped_limit", fShPosPedLimit, kInt, fNtotBlocks},
{"cal_pos_gain_cor", hcal_pos_gain_cor, kDouble, fNtotBlocks},
{"cal_neg_cal_const", hcal_neg_cal_const, kDouble, fNtotBlocks},
// {"cal_neg_gain_ini", hcal_neg_gain_ini, kDouble, fNtotBlocks},
// {"cal_neg_gain_cur", hcal_neg_gain_cur, kDouble, fNtotBlocks},
Vardan Tadevosyan
committed
{"cal_neg_ped_limit", fShNegPedLimit, kInt, fNtotBlocks},
{"cal_neg_gain_cor", hcal_neg_gain_cor, kDouble, fNtotBlocks},
{"cal_min_peds", &fShMinPeds, kInt},
{0}
};
gHcParms->LoadParmValues((DBRequest*)&list, prefix);
if (fdbg_init_cal) {
cout << " hcal_pos_cal_const:" << endl;
for (UInt_t j=0; j<fNLayers; j++) {
for (UInt_t i=0; i<fNBlocks[j]; i++) {
cout << hcal_pos_cal_const[j*fNBlocks[j]+i] << " ";
};
cout << endl;
cout << " fShPosPedLimit:" << endl;
for (UInt_t j=0; j<fNLayers; j++) {
for (UInt_t i=0; i<fNBlocks[j]; i++) {
cout << fShPosPedLimit[j*fNBlocks[j]+i] << " ";
};
cout << endl;
cout << " hcal_pos_gain_cor:" << endl;
for (UInt_t j=0; j<fNLayers; j++) {
for (UInt_t i=0; i<fNBlocks[j]; i++) {
cout << hcal_pos_gain_cor[j*fNBlocks[j]+i] << " ";
};
cout << endl;
cout << " hcal_neg_cal_const:" << endl;
for (UInt_t j=0; j<fNLayers; j++) {
for (UInt_t i=0; i<fNBlocks[j]; i++) {
cout << hcal_neg_cal_const[j*fNBlocks[j]+i] << " ";
};
cout << endl;
cout << " fShNegPedLimit:" << endl;
for (UInt_t j=0; j<fNLayers; j++) {
for (UInt_t i=0; i<fNBlocks[j]; i++) {
cout << fShNegPedLimit[j*fNBlocks[j]+i] << " ";
};
cout << endl;
cout << " hcal_neg_gain_cor:" << endl;
for (UInt_t j=0; j<fNLayers; j++) {
for (UInt_t i=0; i<fNBlocks[j]; i++) {
cout << hcal_neg_gain_cor[j*fNBlocks[j]+i] << " ";
};
cout << endl;
} // end of debug output
// Calibration constants (GeV / ADC channel).
for (UInt_t i=0; i<fNtotBlocks; i++) {
fPosGain[i] = hcal_pos_cal_const[i] * hcal_pos_gain_cor[i];
fNegGain[i] = hcal_neg_cal_const[i] * hcal_neg_gain_cor[i];
if (fdbg_init_cal) {
cout << " fPosGain:" << endl;
for (UInt_t j=0; j<fNLayers; j++) {
for (UInt_t i=0; i<fNBlocks[j]; i++) {
cout << fPosGain[j*fNBlocks[j]+i] << " ";
};
cout << endl;
cout << " fNegGain:" << endl;
for (UInt_t j=0; j<fNLayers; j++) {
for (UInt_t i=0; i<fNBlocks[j]; i++) {
cout << fNegGain[j*fNBlocks[j]+i] << " ";
};
cout << endl;
// Origin of the calorimeter, at the centre of the face of the detector,
// or at the centre of the front of the 1-st layer.
//
Double_t xOrig = (XPos[0][0] + XPos[0][fNBlocks[0]-1])/2 + BlockThick[0]/2;
Double_t yOrig = (YPos[0] + YPos[1])/2;
Double_t zOrig = fNLayerZPos[0];
fOrigin.SetXYZ(xOrig, yOrig, zOrig);
if (fdbg_init_cal) {
cout << " Origin of the Calorimeter:" << endl;
cout << " Xorig = " << GetOrigin().X() << endl;
cout << " Yorig = " << GetOrigin().Y() << endl;
cout << " Zorig = " << GetOrigin().Z() << endl;
cout << "---------------------------------------------------------------\n";
// Detector axes. Assume no rotation.
//
DefineAxes(0.);
Simon Zhamkochyan
committed
fIsInit = true;
return kOK;
}
//_____________________________________________________________________________
Int_t THcShower::DefineVariables( EMode mode )
{
// Initialize global variables and lookup table for decoder
if( mode == kDefine && fIsSetup ) return kOK;
fIsSetup = ( mode == kDefine );
// Register variables in global list
{ "nhits", "Number of hits", "fNhits" },
{ "nclust", "Number of clusters", "fNclust" },
{ "etot", "Total energy", "fEtot" },
{ "etotnorm", "Total energy divided by Central Momentum", "fEtotNorm" },
{ "ntracks", "Number of shower tracks", "fNtracks" },
return DefineVarsFromList( vars, mode );
Simon Zhamkochyan
committed
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
}
//_____________________________________________________________________________
THcShower::~THcShower()
{
// Destructor. Remove variables from global list.
if( fIsSetup )
RemoveVariables();
if( fIsInit )
DeleteArrays();
if (fTrackProj) {
fTrackProj->Clear();
delete fTrackProj; fTrackProj = 0;
}
}
//_____________________________________________________________________________
void THcShower::DeleteArrays()
{
// Delete member arrays. Used by destructor.
delete [] BlockThick; BlockThick = NULL;
delete [] fNBlocks; fNBlocks = NULL;
delete [] fNLayerZPos; fNLayerZPos = NULL;
delete [] XPos; XPos = NULL;
Simon Zhamkochyan
committed
}
//_____________________________________________________________________________
inline
void THcShower::Clear(Option_t* opt)
Simon Zhamkochyan
committed
{
// Reset per-event data.
for(UInt_t ip=0;ip<fNLayers;ip++) {
fPlanes[ip]->Clear(opt);
}
fNtracks = 0;
// Purge cluster list
for (THcShowerClusterListIt i=fClusterList->begin(); i!=fClusterList->end();
++i) {
delete *i;
*i = 0;
}
fClusterList->clear();
Simon Zhamkochyan
committed
}
//_____________________________________________________________________________
Int_t THcShower::Decode( const THaEvData& evdata )
{
Simon Zhamkochyan
committed
// Get the Hall C style hitlist (fRawHitList) for this event
Stephen A. Wood
committed
Int_t nhits = DecodeToHitList(evdata);
if(gHaCuts->Result("Pedestal_event")) {
Int_t nexthit = 0;
for(UInt_t ip=0;ip<fNLayers;ip++) {
nexthit = fPlanes[ip]->AccumulatePedestals(fRawHitList, nexthit);
}
fAnalyzePedestals = 1; // Analyze pedestals first normal events
return(0);
}
if(fAnalyzePedestals) {
for(UInt_t ip=0;ip<fNLayers;ip++) {
fPlanes[ip]->CalculatePedestals();
}
fAnalyzePedestals = 0; // Don't analyze pedestals next event
}
for(UInt_t ip=0;ip<fNLayers;ip++) {
nexthit = fPlanes[ip]->ProcessHits(fRawHitList, nexthit);
THcHallCSpectrometer *app = static_cast<THcHallCSpectrometer*>(GetApparatus());
fEtotNorm=fEtot/(app->GetPcentral());
Simon Zhamkochyan
committed
return nhits;
}
//_____________________________________________________________________________
Int_t THcShower::CoarseProcess( TClonesArray& tracks)
Simon Zhamkochyan
committed
{
// Calculation of coordinates of particle track cross point with shower
// plane in the detector coordinate system. For this, parameters of track
// reconstructed in THaVDC::CoarseTrack() are used.
//
// Apply corrections and reconstruct the complete hits.
// Clustering of hits.
//
// Fill set of unclustered hits.
THcShowerHitSet HitSet;
for(UInt_t j=0; j < fNLayers; j++) {
for (UInt_t i=0; i<fNBlocks[j]; i++) {
//May be should be done this way.
//
// Double_t Edep = fPlanes[j]->GetEmean(i);
// if (Edep > 0.) { //hit
// Double_t x = YPos[j][i] + BlockThick[j]/2.; //top + thick/2
// Double_t z = fNLayerZPos[j] + BlockThick[j]/2.;//front + thick/2
// THcShowerHit* hit = new THcShowerHit(i,j,x,z,Edep);
//ENGINE way.
//
if (fPlanes[j]->GetApos(i) - fPlanes[j]->GetPosPed(i) >
fPlanes[j]->GetPosThr(i) - fPlanes[j]->GetPosPed(i) ||
fPlanes[j]->GetAneg(i) - fPlanes[j]->GetNegPed(i) >
fPlanes[j]->GetNegThr(i) - fPlanes[j]->GetNegPed(i)) { //hit
Double_t Edep = fPlanes[j]->GetEmean(i);
Double_t Epos = fPlanes[j]->GetEpos(i);
Double_t Eneg = fPlanes[j]->GetEneg(i);
Double_t x = XPos[j][i] + BlockThick[j]/2.; //top + thick/2
Double_t z = fNLayerZPos[j] + BlockThick[j]/2.; //front + thick/2
THcShowerHit* hit = new THcShowerHit(i,j,x,z,Edep,Epos,Eneg);
HitSet.insert(hit); //<set> version
fNhits = HitSet.size();
//Debug output, print out hits before clustering.
if (fdbg_clusters_cal) {
cout << "---------------------------------------------------------------\n";
cout << "Debug output from THcShower::CoarseProcess\n";
cout << " List of unclustered hits. Total hits: " << fNhits << endl;
THcShowerHitIt it = HitSet.begin(); //<set> version
for (Int_t i=0; i!=fNhits; i++) {
cout << " hit " << i << ": ";
fNclust = (*fClusterList).size(); //number of clusters
//Debug output, print out the cluster list.
if (fdbg_clusters_cal) {
cout << " Clustered hits. Number of clusters: " << fNclust << endl;
UInt_t i = 0;
for (THcShowerClusterListIt ppcl = (*fClusterList).begin();
ppcl != (*fClusterList).end(); ppcl++) {
cout << " Cluster #" << i++
<<": E=" << clE(*ppcl)
<< " Epr=" << clEpr(*ppcl)
<< " X=" << clX(*ppcl)
<< " Z=" << clZ(*ppcl)
<< " size=" << (**ppcl).size()
Int_t j=0;
for (THcShowerClusterIt pph=(**ppcl).begin(); pph!=(**ppcl).end();
pph++) {
cout << " hit " << j++ << ": ";
(**pph).show();
cout << "---------------------------------------------------------------\n";
Simon Zhamkochyan
committed
return 0;
}
//-----------------------------------------------------------------------------
void THcShower::ClusterHits(THcShowerHitSet& HitSet) {
// Collect hits from the HitSet into the clusters. The resultant clusters
// of hits are saved in the fClusterList.
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
while (HitSet.size() != 0) {
THcShowerCluster* cluster = new THcShowerCluster;
THcShowerHitIt it = HitSet.end();
(*cluster).insert(*(--it)); //Move the last hit from the hit list
HitSet.erase(it); //into the 1st cluster
bool clustered = true;
while (clustered) { //Proceed while a hit is clustered
clustered = false;
for (THcShowerHitIt i=HitSet.begin(); i!=HitSet.end(); ++i) {
for (THcShowerClusterIt k=(*cluster).begin(); k!=(*cluster).end();
k++) {
if ((**i).isNeighbour(*k)) {
(*cluster).insert(*i); //If the hit #i is neighbouring a hit
HitSet.erase(i); //in the cluster, then move it
//into the cluster.
clustered = true;
}
if (clustered) break;
} //k
if (clustered) break;
} //i
} //while clustered
fClusterList->push_back(cluster); //Put the cluster in the cluster list
} //While hit_list not exhausted
};
//-----------------------------------------------------------------------------
// Various helper functions to accumulate hit related quantities.
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
Double_t addE(Double_t x, THcShowerHit* h) {
return x + h->hitE();
}
Double_t addX(Double_t x, THcShowerHit* h) {
return x + h->hitE() * h->hitX();
}
Double_t addZ(Double_t x, THcShowerHit* h) {
return x + h->hitE() * h->hitZ();
}
Double_t addEpr(Double_t x, THcShowerHit* h) {
return h->hitColumn() == 0 ? x + h->hitE() : x;
}
Double_t addEpos(Double_t x, THcShowerHit* h) {
return x + h->hitEpos();
}
Double_t addEneg(Double_t x, THcShowerHit* h) {
return x + h->hitEneg();
}
// X coordinate of center of gravity of cluster, calculated as hit energy
// weighted average. Put X out of the calorimeter (-75 cm), if there is no
// energy deposition in the cluster.
//
Double_t clX(THcShowerCluster* cluster) {
Double_t Etot = accumulate((*cluster).begin(),(*cluster).end(),0.,addE);
return (Etot != 0. ?
accumulate((*cluster).begin(),(*cluster).end(),0.,addX)/Etot : -75.);
}
// Z coordinate of center of gravity of cluster, calculated as a hit energy
// weighted average. Put Z out of the calorimeter (0 cm), if there is no energy
// deposition in the cluster.
//
Double_t clZ(THcShowerCluster* cluster) {
Double_t Etot = accumulate((*cluster).begin(),(*cluster).end(),0.,addE);
return (Etot != 0. ?
accumulate((*cluster).begin(),(*cluster).end(),0.,addZ)/Etot : 0.);
}
//Energy depostion in a cluster
//
Double_t clE(THcShowerCluster* cluster) {
return accumulate((*cluster).begin(),(*cluster).end(),0.,addE);
}
//Energy deposition in the Preshower (1st plane) for a cluster
//
Double_t clEpr(THcShowerCluster* cluster) {
return accumulate((*cluster).begin(),(*cluster).end(),0.,addEpr);
}
//Cluster energy deposition in plane iplane=0,..,3:
// side=0 -- from positive PMTs only;
// side=1 -- from negative PMTs only;
// side=2 -- from postive and negative PMTs.
//
Double_t clEplane(THcShowerCluster* cluster, Int_t iplane, Int_t side) {
if (side!=0&&side!=1&&side!=2) {
cout << "*** Wrong Side in clEplane:" << side << " ***" << endl;
return -1;
}
THcShowerHitSet pcluster;
for (THcShowerHitIt it=(*cluster).begin(); it!=(*cluster).end(); ++it) {
if ((*it)->hitColumn() == iplane) pcluster.insert(*it);
}
Double_t Eplane;
switch (side) {
case 0 :
Eplane = accumulate(pcluster.begin(),pcluster.end(),0.,addEpos);
break;
case 1 :
Eplane = accumulate(pcluster.begin(),pcluster.end(),0.,addEneg);
break;
case 2 :
Eplane = accumulate(pcluster.begin(),pcluster.end(),0.,addE);
break;
default :
Eplane = 0. ;
}
return Eplane;
}
//-----------------------------------------------------------------------------
Int_t THcShower::MatchCluster(THaTrack* Track,
Vardan Tadevosyan
committed
Double_t& XTrFront, Double_t& YTrFront)
// Match a cluster to a given track. Return the cluster number,
// and track coordinates at the front of calorimeter.
Vardan Tadevosyan
committed
XTrFront = kBig;
YTrFront = kBig;
Double_t pathl = kBig;
// Track interception with face of the calorimeter. The coordinates are
// in the calorimeter's local system.
fOrigin = fPlanes[0]->GetOrigin();
CalcTrackIntercept(Track, pathl, XTrFront, YTrFront);
// Transform coordiantes to the spectrometer's coordinate system.
XTrFront += GetOrigin().X();
YTrFront += GetOrigin().Y();
Bool_t inFidVol = true; // In Fiducial Volume flag
// Re-evaluate Fid. Volume Flag if fid. volume test is requested
if (fvTest) {
// Track coordinates at the back of the detector.
// Origin at the front of the last layer.
fOrigin = fPlanes[fNLayers-1]->GetOrigin();
Double_t XTrBack = kBig;
Double_t YTrBack = kBig;
CalcTrackIntercept(Track, pathl, XTrBack, YTrBack);
XTrBack += GetOrigin().X(); // from local coord. system
YTrBack += GetOrigin().Y(); // to the spectrometer system
inFidVol = (XTrFront <= fvXmax) && (XTrFront >= fvXmin) &&
(YTrFront <= fvYmax) && (YTrFront >= fvYmin) &&
(XTrBack <= fvXmax) && (XTrBack >= fvXmin) &&
(YTrBack <= fvYmax) && (YTrBack >= fvYmin);
}
// Match a cluster to the track.
Int_t mclust = -1; // The match cluster #, initialize with a bogus value.
Double_t deltaX = kBig; // Track to cluster distance
if (inFidVol) {
// Since hits and clusters are in reverse order (with respect to Engine),
// search backwards to be consistent with Engine.
//
for (Int_t i=fNclust-1; i>-1; i--) {
THcShowerCluster* cluster = *(fClusterList->begin()+i);
Double_t dx = TMath::Abs( clX(cluster) - XTrFront );
if (dx <= (0.5*BlockThick[0] + fSlop)) {
fNtracks++; // number of shower tracks (Consistent with engine)
if (dx < deltaX) {
mclust = i;
deltaX = dx;
}
//Debug output.
if (fdbg_tracks_cal) {
cout << "---------------------------------------------------------------\n";
cout << "Debug output from THcShower::MatchCluster\n";
cout << " Track at DC:"
<< " X = " << Track->GetX()
<< " Y = " << Track->GetY()
<< " Theta = " << Track->GetTheta()
<< " Phi = " << Track->GetPhi()
<< endl;
cout << " Track at the front of Calorimeter:"
<< " X = " << XTrFront
<< " Y = " << YTrFront
<< " Pathl = " << pathl
<< endl;
if (fvTest)
cout << " Fiducial volume test: inFidVol = " << inFidVol << endl;
cout << " Matched cluster #" << mclust << ", delatX= " << deltaX
cout << "---------------------------------------------------------------\n";
}
//_____________________________________________________________________________
Float_t THcShower::GetShEnergy(THaTrack* Track) {
// Get total energy deposited in the cluster matched to the given
// spectrometer Track.
// Track coordinates at front of the calorimeter, initialize out of
// acceptance.
Double_t Xtr = -75.;
Double_t Ytr = -40.;
// Associate a cluster to the track.
Int_t mclust = MatchCluster(Track, Xtr, Ytr);
// Coordinate corrected total energy deposition in the cluster.
Float_t Etrk = 0.;
if (mclust >= 0) { // if there is a matched cluster
// Get matched cluster.
THcShowerCluster* cluster = *(fClusterList->begin()+mclust);
// Correct track energy depositions for the impact coordinate.
for (UInt_t ip=0; ip<fNLayers; ip++) {
// Coordinate correction factors for positive and negative sides,
// different for single PMT counters in the 1-st two layes and for
// 2 PMT counters in the rear two layers.
Float_t corpos = 1.;
Float_t corneg = 1.;
if (ip < fNegCols) {
corpos = Ycor(Ytr,0);
corneg = Ycor(Ytr,1);
}
else {
corpos = Ycor(Ytr);
corneg = 0.;
}
Etrk += clEplane(cluster,ip,0) * corpos;
Etrk += clEplane(cluster,ip,1) * corneg;
} //over planes
} //mclust>=0
//Debug output.
if (fdbg_tracks_cal) {
cout << "---------------------------------------------------------------\n";
cout << "Debug output from THcShower::GetShEnergy\n";
cout << " Track at the calorimeter: X = " << Xtr << " Y = " << Ytr;
if (mclust >= 0)
cout << ", matched cluster #" << mclust << "." << endl;
else
cout << ", no matched cluster found." << endl;
cout << " Coordinate corrected track energy = " << Etrk << "." << endl;
cout << "---------------------------------------------------------------\n";
}
return Etrk;
}
Simon Zhamkochyan
committed
//_____________________________________________________________________________
Int_t THcShower::FineProcess( TClonesArray& tracks )
{
// Shower energy assignment to the spectrometer tracks.
Simon Zhamkochyan
committed
//
Int_t Ntracks = tracks.GetLast()+1; // Number of reconstructed tracks