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
fNTotLayers = 0;
fHasArray = 0;
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';
fHasArray = 0; // Flag for presence of fly's eye array
DBRequest list[]={
{"cal_num_layers", &fNLayers, kInt},
{"cal_layer_names", &layernamelist, kString},
{"cal_array",&fHasArray, kInt,0, 1},
{0}
};
gHcParms->LoadParmValues((DBRequest*)&list,prefix);
fNTotLayers = (fNLayers+(fHasArray!=0?1:0));
vector<string> layer_names = vsplit(layernamelist);
if(layer_names.size() != fNTotLayers) {
cout << "THcShower::Setup ERROR: Number of layers " << fNTotLayers
<< " doesn't agree with number of layer names "
<< layer_names.size() << endl;
// Should quit. Is there an official way to quit?
}
fLayerNames = new char* [fNTotLayers];
for(UInt_t i=0;i<fNTotLayers;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);
if(fHasArray) {
strcpy(desc, description);
strcat(desc, " Array ");
strcat(desc, fLayerNames[fNTotLayers-1]);
fArray = new THcShowerArray(fLayerNames[fNTotLayers-1], desc, fNTotLayers,
this);
} else {
fArray = 0;
}
cout << "---------------------------------------------------------------\n";
cout << "From THcShower::Setup: created Shower planes for "
<< GetApparatus()->GetName() << ": ";
for(UInt_t i=0;i < fNTotLayers;i++) {
i < fNTotLayers-1 ? cout << ", " : cout << ".\n";
if(fHasArray)
cout << fLayerNames[fNTotLayers-1] << " has fly\'s eye configuration\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;
}
}
if(fHasArray) {
if((status = fArray->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;
}
if(fHasArray) {
cout << "THcShower::Init: adjustment of fiducial volume limits to the fly's eye part." << endl;
cout << " Old limits:" << endl;
cout << " Xmin = " << fvXmin << " Xmax = " << fvXmax << endl;
cout << " Ymin = " << fvYmin << " Ymax = " << fvYmax << endl;
fvXmin = TMath::Max(fvXmin, fArray->fvXmin());
fvXmax = TMath::Min(fvXmax, fArray->fvXmax());
fvYmin = TMath::Max(fvYmin, fArray->fvYmin());
fvYmax = TMath::Min(fvYmax, fArray->fvYmax());
cout << " New limits:" << endl;
cout << " Xmin = " << fvXmin << " Xmax = " << fvXmax << endl;
cout << " Ymin = " << fvYmin << " Ymax = " << fvYmax << endl;
}
cout << "---------------------------------------------------------------\n";
cout << "From THcShower::Init: initialized " << GetApparatus()->GetName()
<< 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
fNegCols = fNLayers; // If not defined assume tube on each end
// for every layer
{
DBRequest list[]={
{"cal_num_neg_columns", &fNegCols, kInt, 0, 1},
{"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 for "
<< GetApparatus()->GetName() << endl;
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, 2},
{"cal_d_cor", fDcor, kDouble, 2},
{0}
};
gHcParms->LoadParmValues((DBRequest*)&list, prefix);
}
if (fdbg_init_cal) {
cout << " Coordinate correction constants:\n";
cout << " fAcor = " << fAcor << endl;
cout << " fBcor = " << fBcor << endl;
cout << " fCcor = " << fCcor[0] << ", " << fCcor[1] << endl;
cout << " fDcor = " << fDcor[0] << ", " << fDcor[1] << endl;
fNBlocks = new UInt_t [fNLayers];
fLayerZPos = new Double_t [fNLayers];
fYPos = new Double_t [2*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]), &fLayerZPos[i], kDouble},
{Form("cal_%s_right",fLayerNames[i]), &fYPos[2*i], kDouble},
{Form("cal_%s_left",fLayerNames[i]), &fYPos[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.
fXPos = new Double_t* [fNLayers];
for(UInt_t i=0;i<fNLayers;i++) {
fXPos[i] = new Double_t [fNBlocks[i]];
DBRequest list[]={
{Form("cal_%s_top",fLayerNames[i]),fXPos[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 : " << fLayerZPos[i] << endl;
cout << " Y Positions : " << fYPos[2*i] << ", " << fYPos[2*i+1]
<<endl;
cout << " X Positions :";
for(UInt_t j=0; j<fNBlocks[i]; j++) {
cout << " " << fXPos[i][j];
}
cout << endl;
Simon Zhamkochyan
committed
}
// Fiducial volume limits, based on Plane 1 positions.
//
fvXmin = fXPos[0][0] + fvDelta;
fvXmax = fXPos[0][fNBlocks[0]-1] + BlockThick[0] - fvDelta;
fvYmin = fYPos[0] + fvDelta;
fvYmax = fYPos[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 h(s)cal.param).
fNTotBlocks=0; //total number of blocks in the layers
for (UInt_t i=0; i<fNLayers; i++) fNTotBlocks += fNBlocks[i];
if (fdbg_init_cal)
cout << " Total number of blocks in the layers of calorimeter: " << dec
<< fNTotBlocks << endl;
//Pedestal limits from hcal.param.
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},
{"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},
{"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 = (fXPos[0][0] + fXPos[0][fNBlocks[0]-1])/2 + BlockThick[0]/2;
Double_t yOrig = (fYPos[0] + fYPos[1])/2;
Double_t zOrig = fLayerZPos[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" },
{ "etrack", "Track energy", "fEtrack" },
{ "ntracks", "Number of shower tracks", "fNtracks" },
return DefineVarsFromList( vars, mode );
Simon Zhamkochyan
committed
}
//_____________________________________________________________________________
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 [] fLayerZPos; fLayerZPos = NULL;
delete [] fXPos; fXPos = NULL;
delete [] fZPos; fZPos = 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);
}
if(fHasArray) {
fArray->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);
}
if(fHasArray) {
nexthit = fArray->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();
}
if(fHasArray) {
fArray->CalculatePedestals();
}
fAnalyzePedestals = 0; // Don't analyze pedestals next event
}
for(UInt_t ip=0;ip<fNLayers;ip++) {
nexthit = fPlanes[ip]->ProcessHits(fRawHitList, nexthit);
if(fHasArray) {
nexthit = fArray->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);
// Double_t x = fYPos[j][i] + BlockThick[j]/2.; //top + thick/2
// Double_t z = fLayerZPos[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 = fXPos[j][i] + BlockThick[j]/2.; //top + thick/2
Double_t z = fLayerZPos[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 for "
<< GetApparatus()->GetName() << endl;
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 << ": ";
ClusterHits(HitSet, fClusterList);
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";
if(fHasArray) fArray->CoarseProcess(tracks);
Simon Zhamkochyan
committed
return 0;
}
//-----------------------------------------------------------------------------
void THcShower::ClusterHits(THcShowerHitSet& HitSet,
THcShowerClusterList* ClusterList) {
// Collect hits from the HitSet into the clusters. The resultant clusters
// of hits are saved in the ClusterList.
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
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
ClusterList->push_back(cluster); //Put the cluster in the cluster list
} //While hit_list not exhausted
};
//-----------------------------------------------------------------------------
// Various helper functions to accumulate hit related quantities.
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 (-100 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 : -100.);
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
}
// 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 for "
<< GetApparatus()->GetName() << endl;
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 = -100.;