Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
JEventProcessor_BCAL_Hadronic_Eff.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: JEventProcessor_BCAL_Hadronic_Eff.cc
4 //
5 
7 
8 // Routine used to create our JEventProcessor
9 extern "C"
10 {
11  void InitPlugin(JApplication *locApplication)
12  {
13  InitJANAPlugin(locApplication);
14  locApplication->AddProcessor(new JEventProcessor_BCAL_Hadronic_Eff()); //register this plugin
15  }
16 } // "C"
17 
18 //define static local variable //declared in header file
20 
21 //------------------
22 // init
23 //------------------
25 {
26  //TRACK REQUIREMENTS
27  dMaxBCALDeltaT = 1.0;;
28  dMinTrackingFOM = 5.73303E-7; // +/- 5 sigma
29  dMinNumTrackHits = 14; //e.g. 6 in CDC, 8 in
32  dMaxVertexR = 1.0;
34  //action initialize not necessary: is empty
35 
36  TDirectory* locOriginalDir = gDirectory;
37  gDirectory->mkdir("bcal_hadronic_eff")->cd();
38 
40  for(int locLayer = 1; locLayer <= 4; ++locLayer)
41  {
42  ostringstream locHistName, locHistTitle;
43 
44  //Upstream, Found
45  locHistName << "HitFound_Layer" << locLayer << "_Upstream";
46  locHistTitle << "Hit Found, Layer " << locLayer << ", Upstream;Sector";
47  dHistMap_HitFound[locLayer][true] = new TH1I(locHistName.str().c_str(), locHistTitle.str().c_str(), 192, 0.5, 192.5);
48 
49  //Upstream, Total
50  locHistName.str("");
51  locHistName << "HitTotal_Layer" << locLayer << "_Upstream";
52  locHistTitle.str("");
53  locHistTitle << "Hit Total, Layer " << locLayer << ", Upstream;Sector";
54  dHistMap_HitTotal[locLayer][true] = new TH1I(locHistName.str().c_str(), locHistTitle.str().c_str(), 192, 0.5, 192.5);
55 
56  //Downstream, Found
57  locHistName.str("");
58  locHistName << "HitFound_Layer" << locLayer << "_Downstream";
59  locHistTitle.str("");
60  locHistTitle << "Hit Found, Layer " << locLayer << ", Downstream;Sector";
61  dHistMap_HitFound[locLayer][false] = new TH1I(locHistName.str().c_str(), locHistTitle.str().c_str(), 192, 0.5, 192.5);
62 
63  //Downstream, Total
64  locHistName.str("");
65  locHistName << "HitTotal_Layer" << locLayer << "_Downstream";
66  locHistTitle.str("");
67  locHistTitle << "Hit Total, Layer " << locLayer << ", Downstream;Sector";
68  dHistMap_HitTotal[locLayer][false] = new TH1I(locHistName.str().c_str(), locHistTitle.str().c_str(), 192, 0.5, 192.5);
69  }
70 
71  // back to original dir
72  locOriginalDir->cd();
73 
74  //TTREE INTERFACE
75  //MUST DELETE WHEN FINISHED: OR ELSE DATA WON'T BE SAVED!!!
76  dTreeInterface = DTreeInterface::Create_DTreeInterface("bcal_hadronic_eff", "tree_bcal_hadronic_eff.root");
77 
78  //TTREE BRANCHES
79  DTreeBranchRegister locTreeBranchRegister;
80 
81  //TRACK
82  locTreeBranchRegister.Register_Single<Int_t>("PID_PDG"); //gives charge, mass, beta
83  locTreeBranchRegister.Register_Single<Float_t>("TrackVertexZ");
84  locTreeBranchRegister.Register_Single<TVector3>("TrackP3");
85  locTreeBranchRegister.Register_Single<UInt_t>("TrackCDCRings"); //rings correspond to bits (1 -> 28)
86  locTreeBranchRegister.Register_Single<UInt_t>("TrackFDCPlanes"); //planes correspond to bits (1 -> 24)
87 
88  //SHOWER
89  locTreeBranchRegister.Register_Single<Float_t>("ShowerEnergy");
90  locTreeBranchRegister.Register_Single<Float_t>("TrackDeltaPhiToShower"); //is signed: BCAL - Track //degrees
91  locTreeBranchRegister.Register_Single<Float_t>("TrackDeltaZToShower"); //is signed: BCAL - Track
92  //"Sector:" 4*(module - 1) + sector //sector: 1 -> 192
93  locTreeBranchRegister.Register_Single<UChar_t>("TrackProjectedBCALSector"); //from track extrapolation //0 if proj to miss
94  locTreeBranchRegister.Register_Single<Float_t>("ProjectedBCALHitPhi"); //degrees
95  locTreeBranchRegister.Register_Single<Float_t>("ProjectedBCALHitZ");
96 
97  //HIT SEARCH
98  //BCALClusterLayers: first 4 bits: point layers, next 4: unmatched-unified-hit layers
99  locTreeBranchRegister.Register_Single<UChar_t>("BCALClusterLayers"); //is 0 if track not matched to shower: ignore hit efficiencies
100  //IsHitInCluster: bits 1 -> 8 correspond to Upstream layer 1 -> 4, then Downstream layer 1 -> 4
101  locTreeBranchRegister.Register_Single<UChar_t>("IsHitInCluster"); //1 if true, 0 if false or no hit
102  //LAYER 1:
103  //"Sector:" 4*(module - 1) + sector //sector: 1 -> 192
104  locTreeBranchRegister.Register_Single<UChar_t>("ProjectedBCALSectors_Layer1"); //0 if biased or indeterminate
105  locTreeBranchRegister.Register_Single<UChar_t>("NearestBCALSectors_Layer1_Downstream"); //0 if not found
106  locTreeBranchRegister.Register_Single<UChar_t>("NearestBCALSectors_Layer1_Upstream"); //0 if not found
107  locTreeBranchRegister.Register_Single<Float_t>("NearestBCALEnergy_Layer1_Downstream"); //0 if not found
108  locTreeBranchRegister.Register_Single<Float_t>("NearestBCALEnergy_Layer1_Upstream"); //0 if not found
109  //LAYER 2:
110  locTreeBranchRegister.Register_Single<UChar_t>("ProjectedBCALSectors_Layer2"); //0 if biased or indeterminate
111  locTreeBranchRegister.Register_Single<UChar_t>("NearestBCALSectors_Layer2_Downstream"); //0 if not found
112  locTreeBranchRegister.Register_Single<UChar_t>("NearestBCALSectors_Layer2_Upstream"); //0 if not found
113  locTreeBranchRegister.Register_Single<Float_t>("NearestBCALEnergy_Layer2_Downstream"); //0 if not found
114  locTreeBranchRegister.Register_Single<Float_t>("NearestBCALEnergy_Layer2_Upstream"); //0 if not found
115  //LAYER 3:
116  locTreeBranchRegister.Register_Single<UChar_t>("ProjectedBCALSectors_Layer3"); //0 if biased or indeterminate
117  locTreeBranchRegister.Register_Single<UChar_t>("NearestBCALSectors_Layer3_Downstream"); //0 if not found
118  locTreeBranchRegister.Register_Single<UChar_t>("NearestBCALSectors_Layer3_Upstream"); //0 if not found
119  locTreeBranchRegister.Register_Single<Float_t>("NearestBCALEnergy_Layer3_Downstream"); //0 if not found
120  locTreeBranchRegister.Register_Single<Float_t>("NearestBCALEnergy_Layer3_Upstream"); //0 if not found
121  //LAYER 4:
122  locTreeBranchRegister.Register_Single<UChar_t>("ProjectedBCALSectors_Layer4"); //0 if biased or indeterminate
123  locTreeBranchRegister.Register_Single<UChar_t>("NearestBCALSectors_Layer4_Downstream"); //0 if not found
124  locTreeBranchRegister.Register_Single<UChar_t>("NearestBCALSectors_Layer4_Upstream"); //0 if not found
125  locTreeBranchRegister.Register_Single<Float_t>("NearestBCALEnergy_Layer4_Downstream"); //0 if not found
126  locTreeBranchRegister.Register_Single<Float_t>("NearestBCALEnergy_Layer4_Upstream"); //0 if not found
127 
128 
129  //REGISTER BRANCHES
130  dTreeInterface->Create_Branches(locTreeBranchRegister);
131 
132  return NOERROR;
133 }
134 
135 //------------------
136 // brun
137 //------------------
138 jerror_t JEventProcessor_BCAL_Hadronic_Eff::brun(jana::JEventLoop* locEventLoop, int locRunNumber)
139 {
140  // This is called whenever the run number changes
141 
142  //Get Target Center Z
143  DApplication* locApplication = dynamic_cast<DApplication*>(locEventLoop->GetJApplication());
144  DGeometry* locGeometry = locApplication->GetDGeometry(locEventLoop->GetJEvent().GetRunNumber());
145  locGeometry->GetTargetZ(dTargetCenterZ);
146 
147  //Effective velocities
148  locEventLoop->GetCalib("/BCAL/effective_velocities", effective_velocities);
149 
150  return NOERROR;
151 }
152 
153 //------------------
154 // evnt
155 //------------------
156 
157 jerror_t JEventProcessor_BCAL_Hadronic_Eff::evnt(jana::JEventLoop* locEventLoop, uint64_t locEventNumber)
158 {
159  // This is called for every event. Use of common resources like writing
160  // to a file or filling a histogram should be mutex protected. Using
161  // locEventLoop->Get(...) to get reconstructed objects (and thereby activating the
162  // reconstruction algorithm) should be done outside of any mutex lock
163  // since multiple threads may call this method at the same time.
164 
165  // This plugin is used to determine the reconstruction efficiency of hits in the BCAL
166  // Note, this is hit-level, not shower-level. Hits: By sector/layer/module/end
167 
168  //CUT ON TRIGGER TYPE
169  const DTrigger* locTrigger = NULL;
170  locEventLoop->GetSingle(locTrigger);
171  if(locTrigger->Get_L1FrontPanelTriggerBits() != 0)
172  return NOERROR;
173 
174  // load BCAL geometry
175  vector<const DBCALGeometry *> BCALGeomVec;
176  locEventLoop->Get(BCALGeomVec);
177  if(BCALGeomVec.size() == 0)
178  throw JException("Could not load locBCALGeometry object!");
179  const DBCALGeometry *locBCALGeom = BCALGeomVec[0];;
180 
181  //COMPUTE TOTAL FCAL ENERGY
182  vector<const DFCALShower*> locFCALShowers;
183  locEventLoop->Get(locFCALShowers);
184 
185  double locTotalFCALEnergy = 0.0;
186  for(auto& locShower : locFCALShowers)
187  locTotalFCALEnergy += locShower->getEnergy();
188 
189  //SEE IF BCAL REQUIRED TO TRIGGER
190  uint32_t locTriggerBits = locTrigger->Get_L1TriggerBits();
191  bool locBCALRequiredForTriggerFlag = true;
192  if(((locTriggerBits & 2) == 2) || ((locTriggerBits & 32) == 32) || ((locTriggerBits & 64) == 64))
193  locBCALRequiredForTriggerFlag = false;
194  if(((locTriggerBits & 1) == 1) && (locTotalFCALEnergy > 1.0))
195  locBCALRequiredForTriggerFlag = false;
196  if(locBCALRequiredForTriggerFlag)
197  return NOERROR;
198 
199  const DEventRFBunch* locEventRFBunch = NULL;
200  locEventLoop->GetSingle(locEventRFBunch);
201  if(locEventRFBunch->dNumParticleVotes <= 1)
202  return NOERROR; //don't trust PID: beta-dependence
203 
204  vector<const DChargedTrack*> locChargedTracks;
205  locEventLoop->Get(locChargedTracks);
206 
207  const DParticleID* locParticleID = NULL;
208  locEventLoop->GetSingle(locParticleID);
209 
210  const DDetectorMatches* locDetectorMatches = NULL;
211  locEventLoop->GetSingle(locDetectorMatches);
212 
213  vector<const DBCALUnifiedHit*> locBCALUnifiedHits;
214  locEventLoop->Get(locBCALUnifiedHits);
215 
216  vector<const DBCALPoint*> locBCALPoints;
217  locEventLoop->Get(locBCALPoints);
218 
219  vector<const DBCALShower*> locBCALShowers;
220  locEventLoop->Get(locBCALShowers);
221 
222  //sort bcal points by layer, total sector //first int: layer. second int: sector
223  map<int, map<int, set<const DBCALPoint*> > > locSortedPoints;
224  for(const auto& locPoint : locBCALPoints)
225  {
226  int locSector = (locPoint->module() - 1)*4 + locPoint->sector(); //1 -> 192
227  locSortedPoints[locPoint->layer()][locSector].insert(locPoint);
228  }
229 
230  //sort unified hits by layer, total sector //first int: layer. second int: sector
231  map<int, map<int, set<const DBCALUnifiedHit*> > > locSortedHits_Upstream, locSortedHits_Downstream;
232  for(const auto& locUnifiedHit : locBCALUnifiedHits)
233  {
234  int locSector = (locUnifiedHit->module - 1)*4 + locUnifiedHit->sector;
235  if(locUnifiedHit->end == DBCALGeometry::kUpstream)
236  locSortedHits_Upstream[locUnifiedHit->layer][locSector].insert(locUnifiedHit);
237  else
238  locSortedHits_Downstream[locUnifiedHit->layer][locSector].insert(locUnifiedHit);
239  }
240 
241  //Try to select the most-pure sample of tracks possible
242  set<const DChargedTrackHypothesis*> locBestTracks;
243  for(auto& locChargedTrack : locChargedTracks)
244  {
245  //loop over PID hypotheses and find the best (if any good enough)
246  const DChargedTrackHypothesis* locBestChargedTrackHypothesis = nullptr;
247  double locBestTrackingFOM = -1.0;
248  for(auto& locChargedTrackHypothesis : locChargedTrack->dChargedTrackHypotheses)
249  {
250  if((locChargedTrackHypothesis->PID() == Electron) || (locChargedTrackHypothesis->PID() == Positron))
251  continue; //don't evaluate for these
252 
253  if(locChargedTrackHypothesis->position().Perp() > dMaxVertexR)
254  continue; //don't trust reconstruction if not close to target
255 
256  //Need PID for beta-dependence
257  if(!Cut_BCALTiming(locChargedTrackHypothesis))
258  continue; //also requires match to BCAL: no need for separate check
259 
260  auto locTrackTimeBased = locChargedTrackHypothesis->Get_TrackTimeBased();
261  if(locTrackTimeBased->FOM < dMinTrackingFOM)
262  continue; //don't trust tracking results: bad tracking FOM
263 
264  if(!locDetectorMatches->Get_IsMatchedToDetector(locTrackTimeBased, SYS_START))
265  continue; //not matched to SC
266 
267  if(!dCutAction_TrackHitPattern->Cut_TrackHitPattern(locParticleID, locTrackTimeBased))
268  continue; //don't trust tracking results: not many grouped hits
269 
270  unsigned int locNumTrackHits = locTrackTimeBased->Ndof + 5;
271  if(locNumTrackHits < dMinNumTrackHits)
272  continue; //don't trust tracking results: not many hits
273 
274  if(locTrackTimeBased->FOM < locBestTrackingFOM)
275  continue; //not the best mass hypothesis
276 
277  locBestTrackingFOM = locTrackTimeBased->FOM;
278  locBestChargedTrackHypothesis = locChargedTrackHypothesis;
279  }
280 
281  //if passed all cuts, save the best
282  if(locBestChargedTrackHypothesis != nullptr)
283  locBestTracks.insert(locBestChargedTrackHypothesis);
284  }
285 
286  //for histograms, keep running total of what to fill //int = layer, bool = isUpstream
287  //will fill at end: only one lock
288  map<int, map<bool, vector<int> > > locHitMap_HitFound, locHitMap_HitTotal;
289 
290  // Loop over the good tracks, using the best DTrackTimeBased object for each
291  for(auto& locChargedTrackHypothesis : locBestTracks)
292  {
293  auto locTrackTimeBased = locChargedTrackHypothesis->Get_TrackTimeBased();
294 
295  /************************************************ CHECK SHOWER MATCH EFFICIENCY ************************************************/
296 
297  //get the best-matched DBCALShower for this track (if any)
298  auto locBCALShowerMatchParams = locChargedTrackHypothesis->Get_BCALShowerMatchParams();
299  if(locBCALShowerMatchParams == NULL)
300  continue; //don't compute hit efficiencies
301 
302  /*************************************************** GET & SORT CLUSTER HITS ***************************************************/
303 
304  //use the DBCALPoints in this DBCALShower to help define where DBCALUnifiedHits are expected to be
305  //The DBCALShower reconstruction does not care which BCAL layers fired
306  //Therefore, given a DBCALShower hit layer, whether or not there are hits in the other layers is an unbiased check
307 
308  //get the clusters in the shower, reject if > 1
309  vector<const DBCALCluster*> locClusters;
310  locBCALShowerMatchParams->dBCALShower->Get(locClusters);
311  if(locClusters.size() > 1)
312  continue; //likely a messy shower, will probably mess up efficiency calculation.
313 
314  //get cluster, points, unmatched hits
315  const DBCALCluster* locCluster = locClusters[0];
316  vector<const DBCALPoint*> locClusterBCALPoints = locCluster->points();
317  vector<pair<const DBCALUnifiedHit*, double> > locClusterBCALHits = locCluster->hits(); //double: corrected energy
318 
319  //sort cluster points by layer, total sector //first int: layer. second int: sector
320  //also, build set of all cluster points
321  set<const DBCALPoint*> locClusterPointSet;
322  map<int, map<int, set<const DBCALPoint*> > > locSortedClusterPoints;
323  for(const auto& locPoint : locClusterBCALPoints)
324  {
325  locClusterPointSet.insert(locPoint);
326  int locSector = (locPoint->module() - 1)*4 + locPoint->sector(); //1 -> 192
327  locSortedClusterPoints[locPoint->layer()][locSector].insert(locPoint);
328  }
329 
330  //require points in at least 2 layers: make sure it's not a noise cluster
331  //Note: This can introduce bias into the study. To avoid bias, only evaluate layer efficiency if at least 2 OTHER layers have hits
332  if(locSortedClusterPoints.size() < 2)
333  continue; //don't compute hit efficiencies
334 
335  //sort cluster unified hits by layer, total sector //first int: layer. second int: sector
336  //also, build set of all cluster unmatched unified hits
337  set<const DBCALUnifiedHit*> locClusterUnifiedHitSet;
338  map<int, map<int, set<const DBCALUnifiedHit*> > > locSortedClusterHits_Upstream, locSortedClusterHits_Downstream;
339  for(const auto& locUnifiedHitPair : locClusterBCALHits)
340  {
341  const DBCALUnifiedHit* locUnifiedHit = locUnifiedHitPair.first;
342  locClusterUnifiedHitSet.insert(locUnifiedHit);
343 
344  int locSector = (locUnifiedHit->module - 1)*4 + locUnifiedHit->sector;
345  if(locUnifiedHit->end == DBCALGeometry::kUpstream)
346  locSortedClusterHits_Upstream[locUnifiedHit->layer][locSector].insert(locUnifiedHit);
347  else
348  locSortedClusterHits_Downstream[locUnifiedHit->layer][locSector].insert(locUnifiedHit);
349  }
350 
351  //register layers
352  UChar_t locClusterLayers = 0; //which layers are in the cluster (both by points & by hits): 4bits each: 8total
353  for(auto& locLayerPair : locSortedClusterPoints)
354  locClusterLayers |= (1 << (locLayerPair.first - 1));
355  for(auto& locLayerPair : locSortedClusterHits_Upstream)
356  locClusterLayers |= (1 << (locLayerPair.first + 4 - 1));
357  for(auto& locLayerPair : locSortedClusterHits_Downstream)
358  locClusterLayers |= (1 << (locLayerPair.first + 4 - 1));
359 
360  /**************************************************** LOOP OVER BCAL LAYERS ****************************************************/
361 
362  //Tree-save variables
363  map<int, UChar_t> locProjectedSectorsMap, locNearestSectorsMap_Downstream, locNearestSectorsMap_Upstream;
364  map<int, Float_t> locNearestHitEnergy_Upstream, locNearestHitEnergy_Downstream;
365  //locProjectedSectors: (rounded from search): 4*(module - 1) + sector //sector: 1 -> 192, 0 if biased or indeterminate
366  //locNearestSectors_Downstream & locNearestSectors_Upstream: 4*(module - 1) + sector //sector: 1 -> 192, 0 if not found
367  UChar_t locIsHitInClusterBits = 0; //bits 1 -> 8 correspond to Upstream layer 1 -> 4, then Downstream layer 1 -> 4
368 
369  //loop over layers
370  for(int locLayer = 1; locLayer <= 4; ++locLayer)
371  {
372  //initialize to 0's
373  locProjectedSectorsMap[locLayer] = 0;
374  locNearestSectorsMap_Downstream[locLayer] = 0;
375  locNearestSectorsMap_Upstream[locLayer] = 0;
376  locNearestHitEnergy_Upstream[locLayer] = 0;
377  locNearestHitEnergy_Downstream[locLayer] = 0;
378 
379  //require at least 2 other layers in the cluster to have points
380  //use the DBCALPoint's (double-ended hits) to define where hits are to be expected (not the single-ended ones!)
381  //if no hit in this layer, then requirement is already met. if there is, must check
382  auto locClusterPointsIterator = locSortedClusterPoints.find(locLayer);
383  if((locClusterPointsIterator != locSortedClusterPoints.end()) && (locSortedClusterPoints.size() <= 2))
384  continue; //not at least 2 hits in other layers
385 
386  //ideally, would require hits in adjacent layers, but cannot since one may be dead: won't be able to evaluate for this layer
387  //can always constrain this later though, if desired
388 
389  //ok, can now evaluate whether or not there are hits in this layer in an unbiased manner
390 
391  /******************************************** PROJECT HIT LOCATION ********************************************/
392 
393  //in this layer, need to know where to search for a hit:
394  //showers may contain hits in multiple sectors within a layer:
395  //cannot evaluate all found as "good," because when missing, don't know how many to mark as "bad"
396  //so, pick the most-probable location: energy-weighted average of hit locations in the nearest layers
397 
398  //locProjectedSector is (module - 1)*4 + sector //double: average
399  double locProjectedSector = Calc_ProjectedSector(locLayer, locSortedClusterPoints);
400  int locProjectedSectorInt = int(locProjectedSector + 0.5);
401 
402  //register for tree & hists:
403  locProjectedSectorsMap[locLayer] = UChar_t(locProjectedSectorInt); //tree
404  locHitMap_HitTotal[locLayer][true].push_back(locProjectedSectorInt); //hist
405  locHitMap_HitTotal[locLayer][false].push_back(locProjectedSectorInt); //hist
406 
407  /*************************************************** SEARCH ***************************************************/
408 
409  //now, find the closest hits in the layer, separately for in-cluster and not-in-cluster
410  //time cuts copied from DBCALCluster_factory constructor
411 
412  //first, search ALL points
413  auto locPointsIterator = locSortedPoints.find(locLayer);
414  pair<const DBCALPoint*, double> locNearestPoint(NULL, 999.0);
415  if(locPointsIterator != locSortedPoints.end())
416  locNearestPoint = Find_NearestPoint(locProjectedSector, locPointsIterator->second, locCluster, 8.0);
417 
418  //next, search ALL hits: Upstream
419  pair<const DBCALUnifiedHit*, double> locNearestHit_Upstream(NULL, 999.0);
420  auto locHitsIterator = locSortedHits_Upstream.find(locLayer);
421  if(locHitsIterator != locSortedHits_Upstream.end())
422  locNearestHit_Upstream = Find_NearestHit(locProjectedSector, locHitsIterator->second, locCluster, locBCALGeom, 20.0);
423 
424  //finally, search ALL hits: Downstream
425  pair<const DBCALUnifiedHit*, double> locNearestHit_Downstream(NULL, 999.0);
426  locHitsIterator = locSortedHits_Downstream.find(locLayer);
427  if(locHitsIterator != locSortedHits_Downstream.end())
428  locNearestHit_Downstream = Find_NearestHit(locProjectedSector, locHitsIterator->second, locCluster, locBCALGeom, 20.0);
429 
430  /********************************************** REGISTER RESULTS **********************************************/
431 
432  //UPSTREAM
433  if((locNearestPoint.first != nullptr) || (locNearestHit_Upstream.first != nullptr))
434  {
435  bool locUsePointFlag = (locNearestPoint.second <= locNearestHit_Upstream.second);
436 
437  int locFoundSector = 0;
438  bool locIsInClusterFlag = false;
439  float locFoundE = 0.;
440  if(locUsePointFlag)
441  {
442  locFoundSector = (locNearestPoint.first->module() - 1)*4 + locNearestPoint.first->sector();
443  locIsInClusterFlag = (locClusterPointSet.find(locNearestPoint.first) != locClusterPointSet.end());
444  locFoundE = locNearestPoint.first->E();
445  }
446  else
447  {
448  locFoundSector = (locNearestHit_Upstream.first->module - 1)*4 + locNearestHit_Upstream.first->sector;
449  locIsInClusterFlag = (locClusterUnifiedHitSet.find(locNearestHit_Upstream.first) != locClusterUnifiedHitSet.end());
450  locFoundE = locNearestHit_Upstream.first->E;
451  }
452 
453  locNearestSectorsMap_Upstream[locLayer] = UChar_t(locFoundSector);
454  locNearestHitEnergy_Upstream[locLayer] = (Float_t) locFoundE;
455  if(locIsInClusterFlag)
456  locIsHitInClusterBits |= (1 << (locLayer - 1)); //Upstream bits: 1 -> 4
457 
458  int locDeltaSector = Calc_DeltaSector<int>(locFoundSector, locProjectedSectorInt);
459  if(abs(locDeltaSector) <= dHistFoundDeltaSector)
460  locHitMap_HitFound[locLayer][true].push_back(locProjectedSectorInt); //true: upstream
461  }
462 
463  //DOWNSTREAM
464  if((locNearestPoint.first != nullptr) || (locNearestHit_Downstream.first != nullptr))
465  {
466  bool locUsePointFlag = (locNearestPoint.second <= locNearestHit_Downstream.second);
467 
468  int locFoundSector = 0;
469  bool locIsInClusterFlag = false;
470  float locFoundE = 0.;
471  if(locUsePointFlag)
472  {
473  locFoundSector = (locNearestPoint.first->module() - 1)*4 + locNearestPoint.first->sector();
474  locIsInClusterFlag = (locClusterPointSet.find(locNearestPoint.first) != locClusterPointSet.end());
475  locFoundE = locNearestPoint.first->E();
476  }
477  else
478  {
479  locFoundSector = (locNearestHit_Downstream.first->module - 1)*4 + locNearestHit_Downstream.first->sector;
480  locIsInClusterFlag = (locClusterUnifiedHitSet.find(locNearestHit_Downstream.first) != locClusterUnifiedHitSet.end());
481  locFoundE = locNearestHit_Downstream.first->E;
482  }
483 
484  locNearestSectorsMap_Downstream[locLayer] = UChar_t(locFoundSector);;
485  locNearestHitEnergy_Downstream[locLayer] = (Float_t) locFoundE;
486  if(locIsInClusterFlag)
487  locIsHitInClusterBits |= (1 << (locLayer - 1 + 4)); //Downstream bits: 5 -> 8
488 
489  int locDeltaSector = Calc_DeltaSector<int>(locFoundSector, locProjectedSectorInt);
490  if(abs(locDeltaSector) <= dHistFoundDeltaSector)
491  locHitMap_HitFound[locLayer][false].push_back(locProjectedSectorInt); //false: downstream
492  }
493  }
494 
495  //Predict BCAL Surface Hit Location
496  unsigned int locPredictedSurfaceModule = 0, locPredictedSurfaceSector = 0;
497  DVector3 locPredictedSurfacePosition;
498  locParticleID->PredictBCALWedge(locTrackTimeBased->extrapolations.at(SYS_BCAL), locPredictedSurfaceModule, locPredictedSurfaceSector, &locPredictedSurfacePosition);
499  unsigned int locTrackProjectedBCALSector = 4*(locPredictedSurfaceModule - 1) + locPredictedSurfaceSector;
500 
501  //STAGE DATA FOR TREE FILL
502 
503  //TRACK
504  dTreeFillData.Fill_Single<Int_t>("PID_PDG", PDGtype(locChargedTrackHypothesis->PID()));
505  dTreeFillData.Fill_Single<Float_t>("TrackVertexZ", locChargedTrackHypothesis->position().Z());
506  DVector3 locDP3 = locChargedTrackHypothesis->momentum();
507  TVector3 locP3(locDP3.X(), locDP3.Y(), locDP3.Z());
508  dTreeFillData.Fill_Single<TVector3>("TrackP3", locP3);
509  dTreeFillData.Fill_Single<UInt_t>("TrackCDCRings", locTrackTimeBased->dCDCRings);
510  dTreeFillData.Fill_Single<UInt_t>("TrackFDCPlanes", locTrackTimeBased->dFDCPlanes);
511 
512  //SHOWER
513  dTreeFillData.Fill_Single<Float_t>("ShowerEnergy", locBCALShowerMatchParams->dBCALShower->E);
514  dTreeFillData.Fill_Single<Float_t>("TrackDeltaPhiToShower", 180.0*locBCALShowerMatchParams->dDeltaPhiToShower/TMath::Pi()); //is signed: BCAL - Track
515  dTreeFillData.Fill_Single<Float_t>("TrackDeltaZToShower", locBCALShowerMatchParams->dDeltaZToShower); //is signed: BCAL - Track
516  dTreeFillData.Fill_Single<UChar_t>("TrackProjectedBCALSector", locTrackProjectedBCALSector);
517  dTreeFillData.Fill_Single<Float_t>("ProjectedBCALHitPhi", locPredictedSurfacePosition.Phi()*180.0/TMath::Pi());
518  dTreeFillData.Fill_Single<Float_t>("ProjectedBCALHitZ", locPredictedSurfacePosition.Z());
519 
520  //HIT SEARCH
521  //BCALClusterLayers: first 4 bits: point layers, next 4: unmatched-unified-hit layers
522  dTreeFillData.Fill_Single<UChar_t>("BCALClusterLayers", locClusterLayers);
523  dTreeFillData.Fill_Single<UChar_t>("IsHitInCluster", locIsHitInClusterBits);
524  //Sector Branches: 4*(module - 1) + sector //sector: 1 -> 192
525  //LAYER 1:
526  dTreeFillData.Fill_Single<UInt_t>("ProjectedBCALSectors_Layer1", locProjectedSectorsMap[1]);
527  dTreeFillData.Fill_Single<UInt_t>("NearestBCALSectors_Layer1_Downstream", locNearestSectorsMap_Downstream[1]);
528  dTreeFillData.Fill_Single<UInt_t>("NearestBCALSectors_Layer1_Upstream", locNearestSectorsMap_Upstream[1]);
529  dTreeFillData.Fill_Single<Float_t>("NearestBCALEnergy_Layer1_Downstream", locNearestHitEnergy_Upstream[1]);
530  dTreeFillData.Fill_Single<Float_t>("NearestBCALEnergy_Layer1_Upstream", locNearestHitEnergy_Downstream[1]);
531  //LAYER 2:
532  dTreeFillData.Fill_Single<UInt_t>("ProjectedBCALSectors_Layer2", locProjectedSectorsMap[2]);
533  dTreeFillData.Fill_Single<UInt_t>("NearestBCALSectors_Layer2_Downstream", locNearestSectorsMap_Downstream[2]);
534  dTreeFillData.Fill_Single<UInt_t>("NearestBCALSectors_Layer2_Upstream", locNearestSectorsMap_Upstream[2]);
535  dTreeFillData.Fill_Single<Float_t>("NearestBCALEnergy_Layer2_Downstream", locNearestHitEnergy_Upstream[2]);
536  dTreeFillData.Fill_Single<Float_t>("NearestBCALEnergy_Layer2_Upstream", locNearestHitEnergy_Downstream[2]);
537  //LAYER 3:
538  dTreeFillData.Fill_Single<UInt_t>("ProjectedBCALSectors_Layer3", locProjectedSectorsMap[3]);
539  dTreeFillData.Fill_Single<UInt_t>("NearestBCALSectors_Layer3_Downstream", locNearestSectorsMap_Downstream[3]);
540  dTreeFillData.Fill_Single<UInt_t>("NearestBCALSectors_Layer3_Upstream", locNearestSectorsMap_Upstream[3]);
541  dTreeFillData.Fill_Single<Float_t>("NearestBCALEnergy_Layer3_Downstream", locNearestHitEnergy_Upstream[3]);
542  dTreeFillData.Fill_Single<Float_t>("NearestBCALEnergy_Layer3_Upstream", locNearestHitEnergy_Downstream[3]);
543  //LAYER 4:
544  dTreeFillData.Fill_Single<UInt_t>("ProjectedBCALSectors_Layer4", locProjectedSectorsMap[4]);
545  dTreeFillData.Fill_Single<UInt_t>("NearestBCALSectors_Layer4_Downstream", locNearestSectorsMap_Downstream[4]);
546  dTreeFillData.Fill_Single<UInt_t>("NearestBCALSectors_Layer4_Upstream", locNearestSectorsMap_Upstream[4]);
547  dTreeFillData.Fill_Single<Float_t>("NearestBCALEnergy_Layer4_Downstream", locNearestHitEnergy_Upstream[4]);
548  dTreeFillData.Fill_Single<Float_t>("NearestBCALEnergy_Layer4_Upstream", locNearestHitEnergy_Downstream[4]);
549 
550  //FILL TTREE
552  }
553 
554  // FILL HISTOGRAMS
555  // Since we are filling histograms local to this plugin, it will not interfere with other ROOT operations: can use plugin-wide ROOT fill lock
556  japp->RootFillLock(this); //ACQUIRE ROOT FILL LOCK
557  {
558  //Fill Hit Found
559  for(auto& locLayerPair : locHitMap_HitFound)
560  {
561  for(auto& locEndPair : locLayerPair.second)
562  {
563  for(int& locSector : locEndPair.second)
564  dHistMap_HitFound[locLayerPair.first][locEndPair.first]->Fill(locSector);
565  }
566  }
567 
568  //Fill Hit Total
569  for(auto& locLayerPair : locHitMap_HitTotal)
570  {
571  for(auto& locEndPair : locLayerPair.second)
572  {
573  for(int& locSector : locEndPair.second)
574  dHistMap_HitTotal[locLayerPair.first][locEndPair.first]->Fill(locSector);
575  }
576  }
577  }
578  japp->RootFillUnLock(this); //RELEASE ROOT FILL LOCK
579 
580  return NOERROR;
581 }
582 
583 double JEventProcessor_BCAL_Hadronic_Eff::Calc_ProjectedSector(int locLayer, const map<int, map<int, set<const DBCALPoint*> > >& locSortedPoints)
584 {
585  //in the nearest layer of the cluster, find the average hit-sector
586  //if two layers are adjacent: average them
587 
588  //ProjectedSector is (module - 1)*4 + sector //double: can be average
589  if((locLayer == 2) || (locLayer == 3))
590  {
591  //if layer 2 or 3, there must be an adjacent layer present (must be 2 others)
592  vector<double> locSectors;
593  auto locLayerIterator = locSortedPoints.find(locLayer - 1);
594  if(locLayerIterator != locSortedPoints.end())
595  locSectors.push_back(Calc_AverageSector(locLayerIterator->second));
596 
597  locLayerIterator = locSortedPoints.find(locLayer + 1);
598  if(locLayerIterator != locSortedPoints.end())
599  locSectors.push_back(Calc_AverageSector(locLayerIterator->second));
600 
601  //average results if hits in 2 layers, but beware 0/2pi wrap-around
602  if(locSectors.size() == 1)
603  return locSectors[0];
604 
605  double locProjectedSector = locSectors[0] + locSectors[1];
606  if(abs(locSectors[0] - locSectors[1]) > 96.0) //wrap-around!
607  locProjectedSector += 192.0;
608  locProjectedSector /= 2.0;
609  while(locProjectedSector >= 193.0)
610  locProjectedSector -= 192.0;
611  return locProjectedSector;
612  }
613  else if(locLayer == 1)
614  {
615  auto locLayerIterator = locSortedPoints.find(2);
616  if(locLayerIterator != locSortedPoints.end())
617  return Calc_AverageSector(locLayerIterator->second);
618  else
619  return Calc_AverageSector(locSortedPoints.at(3));
620  }
621  else //layer 4
622  {
623  auto locLayerIterator = locSortedPoints.find(3);
624  if(locLayerIterator != locSortedPoints.end())
625  return Calc_AverageSector(locLayerIterator->second);
626  else
627  return Calc_AverageSector(locSortedPoints.at(2));
628  }
629 }
630 
631 double JEventProcessor_BCAL_Hadronic_Eff::Calc_AverageSector(const map<int, set<const DBCALPoint*> >& locBCALPoints)
632 {
633  //int: full sector
634  if(locBCALPoints.empty())
635  return -1.0;
636 
637  //Has low/high: Beware 0/2pi wrap-around showers!
638  vector<pair<double, double> > locSectors; //double: energy
639  bool locHasLowPhiHits = false, locHasHighPhiHits = false;
640  for(auto& locPointPair : locBCALPoints)
641  {
642  //sum energy of hits in the sector //if somehow > 1
643  double locEnergySum = 0.0;
644  for(auto& locPoint : locPointPair.second)
645  locEnergySum += locPoint->E();
646 
647  locSectors.push_back(pair<double, double>(double(locPointPair.first), locEnergySum));
648  if(locPointPair.first <= 12.0) //first 3 modules
649  locHasLowPhiHits = true;
650  else if(locPointPair.first >= 179) //last 3 modules
651  locHasHighPhiHits = true;
652  }
653 
654  //compute weighted average: numerator & denominator
655  double locNumerator = 0.0, locDenominator = 0.0;
656  for(auto& locSectorPair : locSectors)
657  {
658  double locWeight = 1.0/(locSectorPair.second*locSectorPair.second);
659 
660  double locSector = locSectorPair.first;
661  if(locHasLowPhiHits && locHasHighPhiHits && (locSector < 96.0)) //96: half-way point
662  locSector += 192.0; //add 2pi
663  locNumerator += locSector*locWeight;
664 
665  locDenominator += locWeight;
666  }
667 
668  //calc average
669  double locAverageSector = locNumerator/locDenominator;
670  while(locAverageSector >= 193.0)
671  locAverageSector -= 192.0;
672 
673  //return
674  return locAverageSector;
675 }
676 
677 pair<const DBCALPoint*, double> JEventProcessor_BCAL_Hadronic_Eff::Find_NearestPoint(double locProjectedSector, const map<int, set<const DBCALPoint*> >& locLayerBCALPoints, const DBCALCluster* locBCALCluster, double locTimeCut)
678 {
679  //input map int: full_sector
680  //returned double: delta-sector
681  const DBCALPoint* locBestBCALPoint = NULL;
682  double locBestDeltaSector = 999.0;
683 
684  for(auto& locPointPair : locLayerBCALPoints)
685  {
686  //do time cut!
687  const DBCALPoint* locBCALPoint = Find_ClosestTimePoint(locPointPair.second, locBCALCluster, locTimeCut);
688  if(locBCALPoint == NULL)
689  continue; //no points, or failed time cut //not applied if cut <= 0 //cluster
690 
691  double locDeltaSector = Calc_DeltaSector<double>(locPointPair.first, locProjectedSector);
692  if(fabs(locDeltaSector) >= fabs(locBestDeltaSector))
693  continue;
694  locBestDeltaSector = locDeltaSector;
695  locBestBCALPoint = locBCALPoint;
696  }
697 
698  return pair<const DBCALPoint*, double>(locBestBCALPoint, locBestDeltaSector);
699 }
700 
701 pair<const DBCALUnifiedHit*, double> JEventProcessor_BCAL_Hadronic_Eff::Find_NearestHit(double locProjectedSector, const map<int, set<const DBCALUnifiedHit*> >& locLayerUnifiedHits,
702  const DBCALCluster* locBCALCluster, const DBCALGeometry *locBCALGeom, double locTimeCut)
703 {
704  //input map int: full_sector
705  //returned double: delta-sector
706  const DBCALUnifiedHit* locBestBCALHit = NULL;
707  double locBestDeltaSector = 999.0;
708 
709  for(auto& locHitPair : locLayerUnifiedHits)
710  {
711  const DBCALUnifiedHit* locHit = Find_ClosestTimeHit(locHitPair.second, locBCALCluster, locTimeCut, locBCALGeom);
712  if(locHit == NULL)
713  continue; //no hits, or failed time cut //not applied if cut <= 0 //cluster
714 
715  double locDeltaSector = Calc_DeltaSector<double>(locHitPair.first, locProjectedSector);
716  if(fabs(locDeltaSector) >= fabs(locBestDeltaSector))
717  continue;
718  locBestDeltaSector = locDeltaSector;
719  locBestBCALHit = locHit;
720  }
721 
722  return pair<const DBCALUnifiedHit*, double>(locBestBCALHit, locBestDeltaSector);
723 }
724 
725 const DBCALPoint* JEventProcessor_BCAL_Hadronic_Eff::Find_ClosestTimePoint(const set<const DBCALPoint*>& locPoints, const DBCALCluster* locBCALCluster, double locTimeCut)
726 {
727  if(locPoints.empty())
728  return nullptr;
729  if(locTimeCut <= 0.0)
730  return *(locPoints.begin()); //no cut, doesn't matter which one
731 
732  const DBCALPoint* locBestPoint = NULL;
733  for(auto& locPoint : locPoints)
734  {
735  double locDeltaT = fabs(locBCALCluster->t() - locPoint->t());
736  if(locDeltaT > locTimeCut)
737  continue;
738 
739  //if best time, register new delta-t
740  locTimeCut = locDeltaT; //cut becomes tighter to improve match
741  locBestPoint = locPoint;
742  }
743 
744  return locBestPoint;
745 }
746 
747 const DBCALUnifiedHit* JEventProcessor_BCAL_Hadronic_Eff::Find_ClosestTimeHit(const set<const DBCALUnifiedHit*>& locHits,
748  const DBCALCluster* locBCALCluster, double locTimeCut, const DBCALGeometry *locBCALGeom)
749 {
750  if(locHits.empty())
751  return nullptr;
752  if(locTimeCut <= 0.0)
753  return *(locHits.begin()); //no cut, doesn't matter which one
754 
755  //THIS CODE HAS BEEN COPIED FROM DBCALCluster_factory.cc
756  const DBCALUnifiedHit* locBestHit = NULL;
757  for(auto& locHit : locHits)
758  {
759  // given the location of the cluster, we need the best guess for z with respect to target at this radius
760  double locClusterZ = locBCALCluster->rho()*cos(locBCALCluster->theta()) + dTargetCenterZ;
761 
762  // calc the distance to upstream or downstream end of BCAL depending on where the hit was with respect to the cluster z position.
763  double locDistance = locBCALGeom->GetBCAL_length()/2.0;
764  if(locHit->end == 0)
765  locDistance += locClusterZ - locBCALGeom->GetBCAL_center();
766  else
767  locDistance += locBCALGeom->GetBCAL_center() - locClusterZ;
768 
769  //correct time, calc delta-t
770  int channel_calib = 16*(locHit->module - 1) + 4*(locHit->layer - 1) + locHit->sector - 1; //for CCDB
771  double locCorrectedHitTime = locHit->t - locDistance/effective_velocities[channel_calib]; // to the interaction point in the bar.
772  double locDeltaT = fabs(locCorrectedHitTime - locBCALCluster->t());
773 
774  //if best time, register new delta-t
775  if(locDeltaT > locTimeCut)
776  continue;
777  locTimeCut = locDeltaT; //cut becomes tighter to improve match
778  locBestHit = locHit;
779  }
780 
781  return locBestHit;
782 }
783 
785 {
786  if(locChargedTrackHypothesis->t1_detector() != SYS_BCAL)
787  return false;
788 
789  double locDeltaT = locChargedTrackHypothesis->time() - locChargedTrackHypothesis->t0();
790  return (fabs(locDeltaT) <= dMaxBCALDeltaT);
791 }
792 
793 //------------------
794 // erun
795 //------------------
797 {
798  // This is called whenever the run number changes, before it is
799  // changed to give you a chance to clean up before processing
800  // events from the next run number.
801 
802  return NOERROR;
803 }
804 
805 //------------------
806 // fini
807 //------------------
809 {
810  // Called before program exit after event processing is finished.
811 
813  delete dTreeInterface; //saves trees to file, closes file
814 
815  return NOERROR;
816 }
pair< const DBCALPoint *, double > Find_NearestPoint(double locProjectedSector, const map< int, set< const DBCALPoint * > > &locLayerBCALPoints, const DBCALCluster *locBCALCluster, double locTimeCut=-1.0)
TVector3 DVector3
Definition: DVector3.h:14
uint32_t Get_L1TriggerBits(void) const
float rho() const
Definition: DBCALCluster.h:59
void Register_Single(string locBranchName)
double Calc_AverageSector(const map< int, set< const DBCALPoint * > > &locBCALPoints)
const DBCALPoint * Find_ClosestTimePoint(const set< const DBCALPoint * > &locPoints, const DBCALCluster *locBCALCluster, double locTimeCut)
const DTrackTimeBased * Get_TrackTimeBased(void) const
bool Create_Branches(const DTreeBranchRegister &locTreeBranchRegister)
uint32_t Get_L1FrontPanelTriggerBits(void) const
float t() const
Definition: DBCALCluster.h:49
static int PDGtype(Particle_t p)
Definition: GlueX.h:19
jerror_t evnt(jana::JEventLoop *locEventLoop, uint64_t locEventNumber)
Called every event.
JApplication * japp
jerror_t fini(void)
Called after last event of last event source has been processed.
jerror_t init(void)
Called once at program start.
double time(void) const
float GetBCAL_length() const
void Fill(DTreeFillData &locTreeFillData)
static DTreeInterface * Create_DTreeInterface(string locTreeName, string locFileName)
InitPlugin_t InitPlugin
map< int, map< bool, TH1I * > > dHistMap_HitTotal
DGeometry * GetDGeometry(unsigned int run_number)
pair< const DBCALUnifiedHit *, double > Find_NearestHit(double locProjectedSector, const map< int, set< const DBCALUnifiedHit * > > &locLayerUnifiedHits, const DBCALCluster *locBCALCluster, const DBCALGeometry *locBCALGeom, double locTimeCut=-1.0)
DBCALGeometry::End end
vector< pair< const DBCALUnifiedHit *, double > > hits() const
Definition: DBCALCluster.h:35
DCutAction_TrackHitPattern * dCutAction_TrackHitPattern
int Ndof
Number of degrees of freedom in the fit.
vector< const DBCALPoint * > points() const
Definition: DBCALCluster.h:31
map< int, map< bool, TH1I * > > dHistMap_HitFound
float theta() const
Definition: DBCALCluster.h:62
double Calc_ProjectedSector(int locLayer, const map< int, map< int, set< const DBCALPoint * > > > &locSortedPoints)
jerror_t brun(jana::JEventLoop *locEventLoop, int locRunNumber)
Called every time a new run number is detected.
float GetBCAL_center() const
bool Cut_TrackHitPattern(const DParticleID *locParticleID, const DKinematicData *locTrack) const
Definition: DCutActions.cc:809
static thread_local DTreeFillData dTreeFillData
const DBCALUnifiedHit * Find_ClosestTimeHit(const set< const DBCALUnifiedHit * > &locHits, const DBCALCluster *locBCALCluster, double locTimeCut, const DBCALGeometry *locBCALGeom)
jerror_t erun(void)
Called every time run number changes, provided brun has been called.
bool Cut_BCALTiming(const DChargedTrackHypothesis *locChargedTrackHypothesis)
unsigned int dNumParticleVotes
Definition: DEventRFBunch.h:32
DetectorSystem_t t1_detector(void) const
bool PredictBCALWedge(const DReferenceTrajectory *rt, unsigned int &module, unsigned int &sector, DVector3 *intersection=nullptr) const
bool GetTargetZ(double &z_target) const
z-location of center of target
Definition: DGeometry.cc:1933
bool Get_IsMatchedToDetector(const DTrackingData *locTrack, DetectorSystem_t locDetectorSystem) const
void Fill_Single(string locBranchName, const DType &locData)