EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EicCalorimeterReconstruction.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EicCalorimeterReconstruction.cxx
1 //
2 // AYK (ayk@bnl.gov), 2013/06/13
3 //
4 // Calorimeter reconstruction code classes;
5 //
6 
7 #include <assert.h>
8 #include <iostream>
9 #include <cstdlib>
10 
11 #include <EicRunAna.h>
13 
14 // ---------------------------------------------------------------------------------------
15 
17  FairTask("Test version of " + name + " reconstruction code")
18 {
19  ResetVars();
20 
21  mDetName = new EicDetName(name);
22 
24 } // EicCalorimeterReconstruction::EicCalorimeterReconstruction()
25 
26 // ---------------------------------------------------------------------------------------
27 
29 {
31 
32  // As of 2015/07/17 require that reconstruction.C is started with EicRunAna rather
33  // than FairRunAna, sorry;
35  if (!fRun) {
36  std::cout << "-E- EicCalorimeterReconstruction::Init(): no EicRunAna instance found!" << std::endl;
37  std::cout << "-E- EicCalorimeterReconstruction::Init(): please use EicRunAna instead of FairRunAna!" << std::endl;
38  return kERROR;
39  } //if
40 
41  // Read mapping table; missing mapping table is a critical failure;
42  {
43  TFile fgeo(fRun->GetInputFileName());
44  fgeo.GetObject(mDetName->Name() + "GeoParData", mGptr);
45 
46  fgeo.Close();
47 
48  if (!mGptr) {
49  std::cout << "-E- EicCalorimeterReconstruction::Init(): no mapping info found!" << std::endl;
50  return kERROR;
51  } //if
52  }
53 
54  // One of the friends must be digitization file; find it;
55  {
56  for(unsigned fr=0; fr<fRun->GetFriendFiles().size(); fr++) {
57  TFile fin(fRun->GetFriendFiles()[fr]);
58 
59  if (fin.IsOpen()) {
60  fin.GetObject(mDetName->Name() + "CalorimeterDigiParData", mDigi);
61  fin.Close();
62 
63  if (mDigi) break;
64  } //if
65  } //for fr
66 
67  if (!mDigi) {
68  std::cout << "-E- EicCalorimeterReconstruction::Init(): no digi info found!" << std::endl;
69  return kERROR;
70  } //if
71  }
72 
73  // Check threshold settings consistency;
76  std::cout << "-W- " << mDetName->NAME() << " clustering algorithm: strange threshold settings!" <<
77  std::endl;
78 
79  // Find digitized hit array;
80  //mDigiHits = (TClonesArray *)fManager->GetObject(mDetName->Name() + "DigiHit");
81  mDigiHits = (TClonesArray *)fManager->GetObject(mDetName->Name() + "CalorimeterDigiHit");
82  if ( ! mDigiHits ) {
83  std::cout << "-W- EicIdealTracker::Init: No " << mDetName->Name() << "Hit array!" << std::endl;
84  return kERROR;
85  } //if
86 
87  mClusterGroupArray = new TClonesArray("CalorimeterCellGroup");
88  //mClusterGroupArray = new TClonesArray("EicMoCaPoint");
89  fManager->Register(mDetName->Name() + "ClusterGroup", mDetName->NAME(), mClusterGroupArray, kTRUE);
90 
91  // Allocate a single 1D histogram with the "registered" light yield;
93  mLightYieldPlot = new TH1F(mDetName->Name() + "LightYield", mDetName->NAME() + " Light Yield",
95 
96  return kSUCCESS;
97 } // EicCalorimeterReconstruction::Init()
98 
99 // ---------------------------------------------------------------------------------------
100 
101 void EicCalorimeterReconstruction::Exec(Option_t * option)
102 {
103  mCellGroups.clear();
104  hmap.clear();
105 
106  mClusterGroupArray->Clear();
107 
108  // Reset all "mUsed" flags first; can not do this in the main loop because of recursion;
109  // also use this loop to build energy-ordered list of pointers;
110  for (Int_t it=0; it<mDigiHits->GetEntriesFast(); it++)
111  {
113 
114  ghit->mUsed = 0;
115 
116  {
117  const CalorimeterCell *cell = ghit->mPtrCell;
118 
119  // Used twice here -> create an intermediate variable;
120  Long64_t cellPhotonCount = cell->GetPhotonCountSum();
121 
122  // This value will be used in a few places (threshold checks);
124 
125  // No reason to deal with "too low" cells at all; just do not include them
126  // in the ordered cell map;
128  hmap.insert(std::pair<UInt_t,EicCalorimeterDigiHit*>(cellPhotonCount, ghit));
129  }
130  } //for it (hits)
131 
132  // Loop through all hits and arrange cluster groups;
133  for (std::multimap<UInt_t,EicCalorimeterDigiHit*>::reverse_iterator it=hmap.rbegin(); it!=hmap.rend(); it++)
134  {
135  EicCalorimeterDigiHit *ghit = it->second;
136  const CalorimeterCell *cell = ghit->mPtrCell;
137 
138  //printf("%3d %3d -> %5d (%d)\n", (ghit->mCoord >> 16) & 0xFFFF, ghit->mCoord & 0xFFFF,
139  // cell->GetPhotonCountSum(), ghit->mUsed);
140  {
141  printf("@@QQ@@ %8llX -> %3d %3d -> %5d (%d)\n", ghit->mCoord,
142  mGptr->GetX(ghit->mCoord), mGptr->GetY(ghit->mCoord),
143  (unsigned)cell->GetPhotonCountSum(), ghit->mUsed);
144  }
145 
146  // Check that this cell is above cluster seed threshold; actually once a cell is
147  // found which does not satisfy this condition, the following ones can be ignored as
148  // well (multimap is ordered in cell photon counts); so perhaps "break" here would
149  // be more appropriate; fix later;
150  if (cell->mEstimatedEnergyDeposit < mReco->mClusterSeedThreshold) continue;
151 
152  // Skip cells which already belong to other cluster groups;
153  if (ghit->mUsed) continue;
154 
155  // Since this cell was not accounted so far in any cluster group, start a new one;
156  ghit->mUsed = 1;
157 
158  CalorimeterCellGroup group;
159  group.mCells.push_back(cell);
160 
161  AddNeighbors(group, it);
162 
163  mCellGroups.push_back(group);
164  } //for it (hits)
165 
166  // Loop through all cell groups.;
167  {
168  Long64_t eventPhotonCountSum = 0;
169 
170  printf("%d group(s)\n", (unsigned)mCellGroups.size());
171 
172  for (unsigned cg=0; cg<mCellGroups.size(); cg++) {
173  CalorimeterCellGroup *cgroup = &mCellGroups[cg];
174 
175  Long64_t groupPhotonCountSum = 0;
176 
177  for (unsigned iq=0; iq<cgroup->mCells.size(); iq++) {
178  const CalorimeterCell *cell = cgroup->mCells[iq];
179 
180  groupPhotonCountSum += cell->GetPhotonCountSum();
181  } //for iq (mCells)
182 
183  // Consider to account for the simulated average noise level here; subtract expectation value;
184  switch (mDigi->mSensorType) {
186  groupPhotonCountSum -= int(cgroup->mCells.size()*((int)mDigi->mTimingGateWidth*mDigi->mSipmSingleCellNoiseLevel));
187  break;
189  // Seems nothing to do here (digitization added gaussian with a 0.0 mean);
190  break;
191  default:
192  // Put something here if ever want to implement say PMTs;
193  assert(0);
194  } //switch
195 
196  cgroup->mEnergy = groupPhotonCountSum * mReco->mPhotonToEnergyConversionFactor;
197  printf(" -> %8.5f GeV\n", cgroup->mEnergy);
198 
199  eventPhotonCountSum += groupPhotonCountSum;
200 
201  // And eventually estimate per-parent energy share; at this point I should assume
202  // that I know exact photon distribution over parents, which pretty much gives
203  // respective fractions; arrange a separate loop for clarity;
204  {
205  Long64_t groupSignalPhotonCountSum = 0;
206  std::map<std::pair<UInt_t, UInt_t>, Long64_t> perParentSignalPhotonCountSum;
207 
208  for (unsigned iq=0; iq<cgroup->mCells.size(); iq++) {
209  const CalorimeterCell *cell = cgroup->mCells[iq];
210 
211  for (std::map<std::pair<UInt_t, UInt_t>, CalorimeterCellParent>::const_iterator jt=cell->mCellParents.begin();
212  jt!=cell->mCellParents.end(); ++jt) {
213  const CalorimeterCellParent *parent = &jt->second;
214 
215  perParentSignalPhotonCountSum[jt->first] += parent->mSignalPhotonCount;
216  groupSignalPhotonCountSum += parent->mSignalPhotonCount;
217  } //for jt (parents)
218  } //for iq (mCells)
219 
220  // Eventually may fill out guessed energy share per contributing parent particle;
221  for (std::map<std::pair<UInt_t, UInt_t>, Long64_t>::iterator jt=perParentSignalPhotonCountSum.begin();
222  jt!=perParentSignalPhotonCountSum.end(); ++jt)
223  cgroup->mEnergyPerParent[jt->first] = cgroup->mEnergy * (1.0*jt->second/groupSignalPhotonCountSum);
224  }
225  } //for it (groups)
226 
227  // Well, the meaning of this (test) plot is to show estimated overall photon yield;
228  // indeed a single particle simulation mode expected; so sum up everything (and better
229  // take care to set all the thresholds in SetClusterAlgorithmThresholds() to 0.0;
230  if (mLightYieldPlot) mLightYieldPlot->Fill(eventPhotonCountSum);
231  }
232 
233  // Do this more efficienctly later (remove intermediate "groups" vector);
234  for (std::vector<CalorimeterCellGroup>::iterator it=mCellGroups.begin(); it!=mCellGroups.end(); ++it)
235  new((*mClusterGroupArray)[mClusterGroupArray->GetEntriesFast()])
237 } // EicCalorimeterReconstruction::Exec()
238 
239 // ---------------------------------------------------------------------------------------
240 
242  std::multimap<UInt_t,EicCalorimeterDigiHit*>::reverse_iterator it)
243 {
244  for (std::multimap<UInt_t,EicCalorimeterDigiHit*>::reverse_iterator iq=hmap.rbegin(); iq!=hmap.rend(); iq++)
245  {
246  EicCalorimeterDigiHit *ghit = iq->second;
247  const CalorimeterCell *cell = ghit->mPtrCell;
248 
249  if (ghit->mUsed) continue;
250 
251  // Will add all the neighbours recursively;
252  if (AreNeighbors(it->second, ghit))
253  {
254  ghit->mUsed = 1;
255  group.mCells.push_back(cell);
256 
257  // Add neighbors of this cell only if it is above certain threshold in energy; this
258  // should in principle help to decouple cluster groups which "touch" themselves
259  // through the cells which are inbetween "mReco->fCellAccountingThreshold" and
260  // "mReco->fNeighbourSearchThreshold" in estimated energy deposits; check on that, please!;
262  } //if
263  } //for iq (hits)
264 } // EicCalorimeterReconstruction::AddNeighbors()
265 
266 // ---------------------------------------------------------------------------------------
267 
269 {
270  // Yes, want to separate cell hits from different primary parents for now;
271  //if (h1->mPrimaryMother != h2->mPrimaryMother) return false;
272 
273  return mGptr->AreNeighbours(h1->mCoord, h2->mCoord);
274 } // EicCalorimeterReconstruction::AreNeighbors()
275 
276 // ---------------------------------------------------------------------------------------
277 
279 {
280  FairRun *fRun = FairRun::Instance();
281 
282  // I guess there is no need to save/restore current directory here?;
283  fRun->GetOutputFile()->cd();
284 
285  if (mLightYieldPlot) mLightYieldPlot->Write();
286 
287  // Yes, save under detector-specific pre-defined name;
288  mReco->Write(mDetName->Name() + "RecoParData");
289 } // EicCalorimeterReconstruction::Finish()
290 
291 // ---------------------------------------------------------------------------------------
292