10 #include <ecl/modules/eclHadronTimeCalibrationValidationCollector/eclHadronTimeCalibrationValidationCollectorModule.h>
11 #include <framework/dataobjects/EventMetaData.h>
12 #include <framework/gearbox/Const.h>
13 #include <ecl/dataobjects/ECLDigit.h>
14 #include <ecl/dataobjects/ECLCalDigit.h>
15 #include <ecl/dataobjects/ECLTrig.h>
16 #include <mdst/dataobjects/ECLCluster.h>
17 #include <mdst/dataobjects/Track.h>
18 #include <mdst/dataobjects/HitPatternCDC.h>
19 #include <ecl/digitization/EclConfiguration.h>
21 #include <boost/optional.hpp>
34 REG_MODULE(eclHadronTimeCalibrationValidationCollector)
42 m_dbg_tree_photonClusters(0),
47 setDescription(
"This module validates the ECL cluster times");
49 addParam(
"timeAbsMax", m_timeAbsMax,
50 "Events with fabs(getTimeFit) > m_timeAbsMax "
51 "are excluded", (
short)80);
53 addParam(
"saveTree", m_saveTree,
54 "If true, TTree 'tree' with more detailed event info is saved in "
55 "the output file specified by HistoManager",
58 addParam(
"looseTrkZ0", m_looseTrkZ0,
"max Z0 for loose tracks (cm)", 10.);
59 addParam(
"tightTrkZ0", m_tightTrkZ0,
"max Z0 for tight tracks (cm)", 2.);
60 addParam(
"looseTrkD0", m_looseTrkD0,
"max D0 for loose tracks (cm)", 2.);
61 addParam(
"tightTrkD0", m_tightTrkD0,
"max D0 for tight tracks (cm)", 0.5);
65 setPropertyFlags(c_ParallelProcessingCertified);
78 m_dbg_tree_photonClusters =
new TTree(
"tree_photonClusters",
79 "Validating crystal and crate time calibrations using photon clusters in events with lots of tracks and clusters") ;
80 m_dbg_tree_photonClusters->Branch(
"EventNum" , &m_tree_evt_num) ->SetTitle(
"Event number") ;
81 m_dbg_tree_photonClusters->Branch(
"cluster_time" , &m_tree_time) ->SetTitle(
"Cluster time t (calibrated), ns") ;
82 m_dbg_tree_photonClusters->Branch(
"clust_E" , &m_E_photon_clust) ->SetTitle(
"Photon type cluster energy, GeV") ;
83 m_dbg_tree_photonClusters->Branch(
"Ntracks" , &m_NtightTracks) ->SetTitle(
"Number of tracks") ;
84 m_dbg_tree_photonClusters->Branch(
"NphotonClusters" , &m_NphotonClusters) ->SetTitle(
"Number of photons") ;
85 m_dbg_tree_photonClusters->Branch(
"NGoodClusters" , &m_NGoodClusters) ->SetTitle(
"Number of good ECL clusters") ;
86 m_dbg_tree_photonClusters->Branch(
"t0" , &m_tree_t0) ->SetTitle(
"T0, ns") ;
87 m_dbg_tree_photonClusters->Branch(
"t0_unc" , &m_tree_t0_unc) ->SetTitle(
"T0 uncertainty, ns") ;
88 m_dbg_tree_photonClusters->Branch(
"runNum" , &m_tree_run) ->SetTitle(
"Run number") ;
89 m_dbg_tree_photonClusters->Branch(
"CrystalCellID" , &m_tree_cid) ->SetTitle(
"Cell ID, 1..8736") ;
90 m_dbg_tree_photonClusters->Branch(
"dt99" , &m_tree_dt99) ->SetTitle(
"Cluster dt99, ns") ;
91 m_dbg_tree_photonClusters->SetAutoSave(10) ;
94 m_dbg_tree_event =
new TTree(
"tree_event",
95 "Validating crystal and crate time calibrations using photon clusters in events with lots of tracks and clusters") ;
96 m_dbg_tree_event->Branch(
"EventNum" , &m_tree_evt_num) ->SetTitle(
"Event number") ;
97 m_dbg_tree_event->Branch(
"t0" , &m_tree_t0) ->SetTitle(
"T0, ns") ;
98 m_dbg_tree_event->Branch(
"t0_unc" , &m_tree_t0_unc) ->SetTitle(
"T0 uncertainty, ns") ;
99 m_dbg_tree_event->Branch(
"runNum" , &m_tree_run) ->SetTitle(
"Run number") ;
100 m_dbg_tree_event->Branch(
"Ntracks" , &m_NtightTracks) ->SetTitle(
"Number of tracks") ;
101 m_dbg_tree_event->Branch(
"NphotonClusters" , &m_NphotonClusters) ->SetTitle(
"Number of photons") ;
102 m_dbg_tree_event->Branch(
"NGoodClusters" , &m_NGoodClusters) ->SetTitle(
"Number of good ECL clusters") ;
103 m_dbg_tree_event->Branch(
"E0" , &m_tree_E0) ->SetTitle(
"Highest E cluster E") ;
104 m_dbg_tree_event->Branch(
"time_E0" , &m_tree_time_fromE0) ->SetTitle(
"Cluster time of highest E cluster") ;
105 m_dbg_tree_event->SetAutoSave(10) ;
113 B2INFO(
"eclHadronTimeCalibrationValidationCollector: Experiment = " << evtMetaData->getExperiment() <<
114 " run = " << evtMetaData->getRun()) ;
119 double binSize = 2000.0 / pow(2, 12);
120 double halfBinSize = binSize / 2.0;
124 double nBinsNeg = floor((m_timeAbsMax - halfBinSize) / binSize);
125 double min_t = -nBinsNeg * binSize - halfBinSize;
126 int nbins = nBinsNeg * 2 + 1;
127 double max_t = min_t + nbins * binSize;
131 const Int_t N_E_BIN_EDGES = 64;
132 const Int_t N_E_BINS = N_E_BIN_EDGES - 1;
133 Double_t energyBinEdges[N_E_BIN_EDGES] = {0, 0.05, 0.051, 0.052, 0.053, 0.054, 0.055, 0.056, 0.057, 0.058, 0.059, 0.06, 0.062, 0.064, 0.066, 0.068, 0.07, 0.075, 0.08, 0.085, 0.09, 0.095, 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.25, 0.3, 0.35, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.2, 1.4, 1.6, 1.8, 2, 2.25, 2.5, 2.8, 3.2, 3.6, 4, 4.4, 4.8, 5.2, 5.6, 6, 6.4, 6.8, 7.2, 7.6, 8};
136 auto cutflow =
new TH1F(
"cutflow",
" ;Cut label number ;Number of events passing cut", 10, 0, 10) ;
137 registerObject<TH1F>(
"cutflow", cutflow) ;
139 auto clusterTime =
new TH1F(
"clusterTime",
";Photon ECL cluster time [ns]; number of photon ECL clusters", nbins, min_t, max_t) ;
140 registerObject<TH1F>(
"clusterTime", clusterTime) ;
142 auto clusterTime_cid =
new TH2F(
"clusterTime_cid",
143 ";crystal Cell ID ;Photon ECL cluster time [ns]", 8736, 1, 8736 + 1, nbins, min_t, max_t) ;
144 registerObject<TH2F>(
"clusterTime_cid", clusterTime_cid) ;
146 auto clusterTime_run =
new TH2F(
"clusterTime_run",
147 ";Run number ;Photon ECL cluster time [ns]", 7000, 0, 7000, nbins, min_t, max_t) ;
148 registerObject<TH2F>(
"clusterTime_run", clusterTime_run) ;
151 auto clusterTimeClusterE =
new TH2F(
"clusterTimeClusterE",
152 ";Photon cluster energy [GeV];Photon cluster time [ns]", N_E_BINS, energyBinEdges, nbins, min_t, max_t) ;
153 registerObject<TH2F>(
"clusterTimeClusterE", clusterTimeClusterE) ;
156 auto dt99_clusterE =
new TH2F(
"dt99_clusterE",
157 ";Photon cluster energy [GeV];dt99 [ns]", N_E_BINS, energyBinEdges, nbins, 0, max_t) ;
158 registerObject<TH2F>(
"dt99_clusterE", dt99_clusterE) ;
161 auto eventT0 =
new TH1F(
"eventT0",
";event t0 [ns]; number of events", nbins, min_t, max_t) ;
162 registerObject<TH1F>(
"eventT0", eventT0) ;
165 auto clusterTimeE0E1diff =
new TH1F(
"clusterTimeE0E1diff",
166 ";ECL cluster time of max E photon - ECL cluster time of 2nd max E photon [ns]; number of photon ECL cluster time differences",
167 nbins, min_t, max_t) ;
168 registerObject<TH1F>(
"clusterTimeE0E1diff", clusterTimeE0E1diff) ;
172 tracks.isRequired() ;
173 m_eclClusterArray.isRequired() ;
174 m_eclCalDigitArray.isRequired() ;
180 int cutIndexPassed = 0;
181 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
182 B2DEBUG(22,
"Cutflow: no cuts: index = " << cutIndexPassed);
187 m_EperCrys.resize(8736);
188 for (
auto& eclCalDigit : m_eclCalDigitArray) {
189 int tempCrysID = eclCalDigit.getCellId() - 1;
190 m_EperCrys[tempCrysID] = eclCalDigit.getEnergy();
195 double evt_t0 = -1000 ;
196 double evt_t0_unc = -1000 ;
199 if (m_eventT0.isOptional()) {
200 if (!m_eventT0.isValid()) {
203 if (!m_eventT0->hasEventT0()) {
207 evt_t0 = m_eventT0->getEventT0() ;
208 evt_t0_unc = m_eventT0->getEventT0Uncertainty() ;
210 B2DEBUG(26,
"Found event t0") ;
216 int nTrkAll = tracks.getEntries() ;
225 for (
int iTrk = 0 ; iTrk < nTrkAll ; iTrk++) {
229 if (not tempTrackFit) {continue ;}
233 double z0 = tempTrackFit->
getZ0() ;
234 double d0 = tempTrackFit->
getD0() ;
242 if (fabs(d0) > m_looseTrkD0) {
245 if (fabs(z0) > m_looseTrkZ0) {
263 if (fabs(d0) > m_tightTrkD0) {
266 if (fabs(z0) > m_tightTrkZ0) {
273 B2DEBUG(26,
"Found loose and tight tracks") ;
276 int numGoodTightTracks_minCut = 4 ;
277 if (nTrkTight < numGoodTightTracks_minCut) {
282 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed) ;
283 B2DEBUG(22,
"Cutflow: At least " << numGoodTightTracks_minCut <<
" tight tracks: index = " << cutIndexPassed) ;
286 int numGoodLooseTracks_minCut = numGoodTightTracks_minCut ;
287 if (nTrkLoose < numGoodLooseTracks_minCut) {
292 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed) ;
293 B2DEBUG(22,
"Cutflow: No additional loose tracks: index = " << cutIndexPassed) ;
298 double clusterE_minCut = 0.1 ;
299 int nclust = m_eclClusterArray.getEntries();
300 int nGoodClusts = 0 ;
301 vector<int> goodClusterIdxs ;
302 for (
int ic = 0; ic < nclust; ic++) {
304 if (eClust > clusterE_minCut) {
305 goodClusterIdxs.push_back(ic) ;
312 int numGoodEMclusters_minCut = 5 ;
313 if (nGoodClusts < numGoodEMclusters_minCut) {
318 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed) ;
319 B2DEBUG(22,
"Cutflow: At least " << numGoodEMclusters_minCut <<
" ECL clusters: index = " << cutIndexPassed) ;
325 double photonE_minCut = 0.05 ;
326 double zernikeMVA_minCut = 0.2 ;
329 vector<int> goodPhotonClusterIdxs ;
330 for (
int ic = 0; ic < nclust; ic++) {
333 double photonTime = m_eclClusterArray[ic]->getTime();
334 double zernikeMVA = m_eclClusterArray[ic]->getZernikeMVA();
335 bool badPhotonTime = m_eclClusterArray[ic]->hasFailedFitTime();
336 bool badPhotonTimeResolution = m_eclClusterArray[ic]->hasFailedTimeResolution();
337 bool hasTrack = m_eclClusterArray[ic]->isTrack();
338 if ((eClust > photonE_minCut) &&
339 (fabs(photonTime) < m_timeAbsMax) &&
341 (!badPhotonTimeResolution) &&
342 (zernikeMVA > zernikeMVA_minCut) &&
344 goodPhotonClusterIdxs.push_back(ic) ;
352 int numGoodPhotonclusters_minCut = 1 ;
353 if (nPhotons < numGoodPhotonclusters_minCut) {
358 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed) ;
359 B2DEBUG(22,
"Cutflow: At least " << numGoodPhotonclusters_minCut <<
" good photon: index = " << cutIndexPassed) ;
366 vector<double> goodClustTimes ;
367 vector<double> goodClust_dt99 ;
368 vector<double> goodClusters_crysE ;
369 vector<double> goodClustE ;
370 vector<int> goodClustMaxEcrys_cid ;
371 for (
long unsigned int i = 0; i < goodPhotonClusterIdxs.size(); i++) {
372 int ic = goodPhotonClusterIdxs[i] ;
376 short cid = m_eclClusterArray[ic]->getMaxECellId() ;
378 goodClustMaxEcrys_cid.push_back(cid) ;
379 goodClustTimes.push_back(m_eclClusterArray[ic]->getTime()) ;
380 goodClust_dt99.push_back(m_eclClusterArray[ic]->getDeltaTime99()) ;
381 goodClusters_crysE.push_back(m_EperCrys[cid - 1]) ;
382 goodClustE.push_back(eClust);
389 vector< pair<double, double> > pair_energy_time ;
390 for (
long unsigned int ic = 0; ic < goodClusters_crysE.size(); ic++) {
391 pair_energy_time.push_back(make_pair(goodClusters_crysE[ic], goodClustTimes[ic])) ;
396 sort(pair_energy_time.begin(), pair_energy_time.end(), greater<>()) ;
400 B2DEBUG(22,
"Event passed all cuts");
404 getObjectPtr<TH1F>(
"eventT0")->Fill(evt_t0) ;
406 bool isCDCt0 = (
static_cast<EventT0::EventT0Component>(*m_eventT0->getEventT0Component())).detectorSet.contains(Const::CDC);
407 bool isECLt0 = (
static_cast<EventT0::EventT0Component>(*m_eventT0->getEventT0Component())).detectorSet.contains(Const::ECL);
408 string t0Detector =
"UNKNOWN... WHY?";
411 }
else if (isECLt0) {
415 B2DEBUG(26,
"t0 = " << evt_t0 <<
" ns. t0 is from CDC?=" << isCDCt0 <<
", t0 is from ECL?=" << isECLt0 <<
" t0 from " <<
423 for (
long unsigned int i = 0 ; i < goodPhotonClusterIdxs.size() ; i++) {
424 getObjectPtr<TH1F>(
"clusterTime")->Fill(goodClustTimes[i]) ;
425 getObjectPtr<TH2F>(
"clusterTime_cid")->Fill(goodClustMaxEcrys_cid[i] + 0.001, goodClustTimes[i] , 1) ;
426 getObjectPtr<TH2F>(
"clusterTime_run")->Fill(evtMetaData->getRun() + 0.001, goodClustTimes[i] , 1) ;
427 getObjectPtr<TH2F>(
"clusterTimeClusterE")->Fill(goodClustE[i], goodClustTimes[i], 1) ;
428 getObjectPtr<TH2F>(
"dt99_clusterE")->Fill(goodClustE[i], goodClust_dt99[i], 1) ;
433 m_tree_time = goodClustTimes[i] ;
434 m_E_photon_clust = goodClusters_crysE[i] ;
436 m_tree_t0_unc = evt_t0_unc ;
437 m_NtightTracks = nTrkTight ;
438 m_NphotonClusters = nPhotons ;
439 m_NGoodClusters = nGoodClusts ;
440 m_tree_evt_num = evtMetaData->getEvent() ;
441 m_tree_run = evtMetaData->getRun() ;
442 m_tree_cid = goodClustMaxEcrys_cid[i] ;
443 m_tree_dt99 = goodClust_dt99[i] ;
445 m_dbg_tree_photonClusters->Fill() ;
449 B2DEBUG(26,
"Filled cluster tree") ;
452 if (pair_energy_time.size() >= 2) {
453 getObjectPtr<TH1F>(
"clusterTimeE0E1diff")->Fill(pair_energy_time[0].second - pair_energy_time[1].second) ;
460 m_tree_t0_unc = evt_t0_unc ;
461 m_tree_evt_num = evtMetaData->getEvent() ;
462 m_tree_run = evtMetaData->getRun() ;
463 m_NtightTracks = nTrkTight ;
464 m_NphotonClusters = nPhotons ;
465 m_NGoodClusters = nGoodClusts ;
467 m_tree_E0 = pair_energy_time[0].first ;
468 m_tree_time_fromE0 = pair_energy_time[0].second ;
469 m_dbg_tree_event->Fill() ;
472 B2DEBUG(26,
"Filled event tree") ;
Calibration collector module base class.
static const ChargedStable pion
charged pion particle
@ c_nPhotons
CR is split into n photons (N1)
unsigned short getNHits() const
Get the total Number of CDC hits in the fit.
Type-safe access to single objects in the data store.
Values of the result of a track fit with a given particle hypothesis.
double getD0() const
Getter for d0.
double getZ0() const
Getter for z0.
HitPatternCDC getHitPatternCDC() const
Getter for the hit pattern in the CDC;.
This module generates 'TimevsCrys' histogram to later (in eclBhabhaTAlgorithm) find time offset from ...
void collect() override
Select events and crystals and accumulate histograms.
virtual ~eclHadronTimeCalibrationValidationCollectorModule()
Module destructor.
void prepare() override
Define histograms and read payloads from DB.
void inDefineHisto() override
Replacement for defineHisto() in CalibrationCollector modules.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.
Structure for storing the extracted event t0s together with its detector and its uncertainty.