10 #include <ecl/modules/eclHadronTimeCalibrationValidationCollector/eclHadronTimeCalibrationValidationCollectorModule.h>
11 #include <framework/dataobjects/EventMetaData.h>
12 #include <framework/gearbox/Const.h>
13 #include <ecl/dbobjects/ECLCrystalCalib.h>
14 #include <ecl/dataobjects/ECLDigit.h>
15 #include <ecl/dataobjects/ECLCalDigit.h>
16 #include <ecl/dataobjects/ECLTrig.h>
17 #include <mdst/dataobjects/ECLCluster.h>
18 #include <mdst/dataobjects/Track.h>
19 #include <mdst/dataobjects/HitPatternCDC.h>
20 #include <tracking/dataobjects/RecoTrack.h>
21 #include <ecl/digitization/EclConfiguration.h>
23 #include <analysis/utility/PCmsLabTransform.h>
24 #include <analysis/ClusterUtility/ClusterUtils.h>
25 #include <boost/optional.hpp>
38 REG_MODULE(eclHadronTimeCalibrationValidationCollector)
46 m_dbg_tree_photonClusters(0),
51 setDescription(
"This module validates the ECL cluster times");
53 addParam(
"timeAbsMax", m_timeAbsMax,
54 "Events with fabs(getTimeFit) > m_timeAbsMax "
55 "are excluded", (
short)80);
57 addParam(
"saveTree", m_saveTree,
58 "If true, TTree 'tree' with more detailed event info is saved in "
59 "the output file specified by HistoManager",
62 addParam(
"looseTrkZ0", m_looseTrkZ0,
"max Z0 for loose tracks (cm)", 10.);
63 addParam(
"tightTrkZ0", m_tightTrkZ0,
"max Z0 for tight tracks (cm)", 2.);
64 addParam(
"looseTrkD0", m_looseTrkD0,
"max D0 for loose tracks (cm)", 2.);
65 addParam(
"tightTrkD0", m_tightTrkD0,
"max D0 for tight tracks (cm)", 0.5);
69 setPropertyFlags(c_ParallelProcessingCertified);
82 m_dbg_tree_photonClusters =
new TTree(
"tree_photonClusters",
83 "Validating crystal and crate time calibrations using photon clusters in events with lots of tracks and clusters") ;
84 m_dbg_tree_photonClusters->Branch(
"EventNum" , &m_tree_evt_num) ->SetTitle(
"Event number") ;
85 m_dbg_tree_photonClusters->Branch(
"cluster_time" , &m_tree_time) ->SetTitle(
"Cluster time t (calibrated), ns") ;
86 m_dbg_tree_photonClusters->Branch(
"clust_E" , &m_E_photon_clust) ->SetTitle(
"Photon type cluster energy, GeV") ;
87 m_dbg_tree_photonClusters->Branch(
"Ntracks" , &m_NtightTracks) ->SetTitle(
"Number of tracks") ;
88 m_dbg_tree_photonClusters->Branch(
"NphotonClusters" , &m_NphotonClusters) ->SetTitle(
"Number of photons") ;
89 m_dbg_tree_photonClusters->Branch(
"NGoodClusters" , &m_NGoodClusters) ->SetTitle(
"Number of good ECL clusters") ;
90 m_dbg_tree_photonClusters->Branch(
"t0" , &m_tree_t0) ->SetTitle(
"T0, ns") ;
91 m_dbg_tree_photonClusters->Branch(
"t0_unc" , &m_tree_t0_unc) ->SetTitle(
"T0 uncertainty, ns") ;
92 m_dbg_tree_photonClusters->Branch(
"runNum" , &m_tree_run) ->SetTitle(
"Run number") ;
93 m_dbg_tree_photonClusters->Branch(
"CrystalCellID" , &m_tree_cid) ->SetTitle(
"Cell ID, 1..8736") ;
94 m_dbg_tree_photonClusters->Branch(
"dt99" , &m_tree_dt99) ->SetTitle(
"Cluster dt99, ns") ;
95 m_dbg_tree_photonClusters->SetAutoSave(10) ;
98 m_dbg_tree_event =
new TTree(
"tree_event",
99 "Validating crystal and crate time calibrations using photon clusters in events with lots of tracks and clusters") ;
100 m_dbg_tree_event->Branch(
"EventNum" , &m_tree_evt_num) ->SetTitle(
"Event number") ;
101 m_dbg_tree_event->Branch(
"t0" , &m_tree_t0) ->SetTitle(
"T0, ns") ;
102 m_dbg_tree_event->Branch(
"t0_unc" , &m_tree_t0_unc) ->SetTitle(
"T0 uncertainty, ns") ;
103 m_dbg_tree_event->Branch(
"runNum" , &m_tree_run) ->SetTitle(
"Run number") ;
104 m_dbg_tree_event->Branch(
"Ntracks" , &m_NtightTracks) ->SetTitle(
"Number of tracks") ;
105 m_dbg_tree_event->Branch(
"NphotonClusters" , &m_NphotonClusters) ->SetTitle(
"Number of photons") ;
106 m_dbg_tree_event->Branch(
"NGoodClusters" , &m_NGoodClusters) ->SetTitle(
"Number of good ECL clusters") ;
107 m_dbg_tree_event->Branch(
"E0" , &m_tree_E0) ->SetTitle(
"Highest E cluster E") ;
108 m_dbg_tree_event->Branch(
"time_E0" , &m_tree_time_fromE0) ->SetTitle(
"Cluster time of highest E cluster") ;
109 m_dbg_tree_event->SetAutoSave(10) ;
117 B2INFO(
"eclHadronTimeCalibrationValidationCollector: Experiment = " << evtMetaData->getExperiment() <<
118 " run = " << evtMetaData->getRun()) ;
123 double binSize = 2000.0 / pow(2, 12);
124 double halfBinSize = binSize / 2.0;
128 double nBinsNeg = floor((m_timeAbsMax - halfBinSize) / binSize);
129 double min_t = -nBinsNeg * binSize - halfBinSize;
130 int nbins = nBinsNeg * 2 + 1;
131 double max_t = min_t + nbins * binSize;
135 const Int_t N_E_BIN_EDGES = 64;
136 const Int_t N_E_BINS = N_E_BIN_EDGES - 1;
137 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};
140 auto cutflow =
new TH1F(
"cutflow",
" ;Cut label number ;Number of events passing cut", 10, 0, 10) ;
141 registerObject<TH1F>(
"cutflow", cutflow) ;
143 auto clusterTime =
new TH1F(
"clusterTime",
";Photon ECL cluster time [ns]; number of photon ECL clusters", nbins, min_t, max_t) ;
144 registerObject<TH1F>(
"clusterTime", clusterTime) ;
146 auto clusterTime_cid =
new TH2F(
"clusterTime_cid",
147 ";crystal Cell ID ;Photon ECL cluster time [ns]", 8736, 1, 8736 + 1, nbins, min_t, max_t) ;
148 registerObject<TH2F>(
"clusterTime_cid", clusterTime_cid) ;
150 auto clusterTime_run =
new TH2F(
"clusterTime_run",
151 ";Run number ;Photon ECL cluster time [ns]", 7000, 0, 7000, nbins, min_t, max_t) ;
152 registerObject<TH2F>(
"clusterTime_run", clusterTime_run) ;
155 auto clusterTimeClusterE =
new TH2F(
"clusterTimeClusterE",
156 ";Photon cluster energy [GeV];Photon cluster time [ns]", N_E_BINS, energyBinEdges, nbins, min_t, max_t) ;
157 registerObject<TH2F>(
"clusterTimeClusterE", clusterTimeClusterE) ;
160 auto dt99_clusterE =
new TH2F(
"dt99_clusterE",
161 ";Photon cluster energy [GeV];dt99 [ns]", N_E_BINS, energyBinEdges, nbins, 0, max_t) ;
162 registerObject<TH2F>(
"dt99_clusterE", dt99_clusterE) ;
165 auto eventT0 =
new TH1F(
"eventT0",
";event t0 [ns]; number of events", nbins, min_t, max_t) ;
166 registerObject<TH1F>(
"eventT0", eventT0) ;
169 auto clusterTimeE0E1diff =
new TH1F(
"clusterTimeE0E1diff",
170 ";ECL cluster time of max E photon - ECL cluster time of 2nd max E photon [ns]; number of photon ECL cluster time differences",
171 nbins, min_t, max_t) ;
172 registerObject<TH1F>(
"clusterTimeE0E1diff", clusterTimeE0E1diff) ;
176 tracks.isRequired() ;
177 m_eclClusterArray.isRequired() ;
178 m_eclCalDigitArray.isRequired() ;
184 int cutIndexPassed = 0;
185 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
186 B2DEBUG(22,
"Cutflow: no cuts: index = " << cutIndexPassed);
198 m_EperCrys.resize(8736);
199 for (
auto& eclCalDigit : m_eclCalDigitArray) {
200 int tempCrysID = eclCalDigit.getCellId() - 1;
201 m_EperCrys[tempCrysID] = eclCalDigit.getEnergy();
206 double evt_t0 = -1000 ;
207 double evt_t0_unc = -1000 ;
210 if (m_eventT0.isOptional()) {
211 if (!m_eventT0.isValid()) {
214 if (!m_eventT0->hasEventT0()) {
218 evt_t0 = m_eventT0->getEventT0() ;
219 evt_t0_unc = m_eventT0->getEventT0Uncertainty() ;
221 B2DEBUG(26,
"Found event t0") ;
227 int nTrkAll = tracks.getEntries() ;
236 for (
int iTrk = 0 ; iTrk < nTrkAll ; iTrk++) {
240 if (not tempTrackFit) {continue ;}
244 double z0 = tempTrackFit->getZ0() ;
245 double d0 = tempTrackFit->getD0() ;
246 int nCDChits = tempTrackFit->getHitPatternCDC().getNHits() ;
253 if (fabs(d0) > m_looseTrkD0) {
256 if (fabs(z0) > m_looseTrkZ0) {
274 if (fabs(d0) > m_tightTrkD0) {
277 if (fabs(z0) > m_tightTrkZ0) {
284 B2DEBUG(26,
"Found loose and tight tracks") ;
287 int numGoodTightTracks_minCut = 4 ;
288 if (nTrkTight < numGoodTightTracks_minCut) {
293 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed) ;
294 B2DEBUG(22,
"Cutflow: At least " << numGoodTightTracks_minCut <<
" tight tracks: index = " << cutIndexPassed) ;
297 int numGoodLooseTracks_minCut = numGoodTightTracks_minCut ;
298 if (nTrkLoose < numGoodLooseTracks_minCut) {
303 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed) ;
304 B2DEBUG(22,
"Cutflow: No additional loose tracks: index = " << cutIndexPassed) ;
309 double clusterE_minCut = 0.1 ;
310 int nclust = m_eclClusterArray.getEntries();
311 int nGoodClusts = 0 ;
312 vector<int> goodClusterIdxs ;
313 for (
int ic = 0; ic < nclust; ic++) {
315 if (eClust > clusterE_minCut) {
316 goodClusterIdxs.push_back(ic) ;
323 int numGoodEMclusters_minCut = 5 ;
324 if (nGoodClusts < numGoodEMclusters_minCut) {
329 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed) ;
330 B2DEBUG(22,
"Cutflow: At least " << numGoodEMclusters_minCut <<
" ECL clusters: index = " << cutIndexPassed) ;
336 double photonE_minCut = 0.05 ;
337 double zernikeMVA_minCut = 0.2 ;
340 vector<int> goodPhotonClusterIdxs ;
341 for (
int ic = 0; ic < nclust; ic++) {
344 double photonTime = m_eclClusterArray[ic]->getTime();
345 double zernikeMVA = m_eclClusterArray[ic]->getZernikeMVA();
346 bool badPhotonTime = m_eclClusterArray[ic]->hasFailedFitTime();
347 bool badPhotonTimeResolution = m_eclClusterArray[ic]->hasFailedTimeResolution();
348 bool hasTrack = m_eclClusterArray[ic]->isTrack();
349 if ((eClust > photonE_minCut) &&
350 (fabs(photonTime) < m_timeAbsMax) &&
352 (!badPhotonTimeResolution) &&
353 (zernikeMVA > zernikeMVA_minCut) &&
355 goodPhotonClusterIdxs.push_back(ic) ;
363 int numGoodPhotonclusters_minCut = 1 ;
364 if (nPhotons < numGoodPhotonclusters_minCut) {
369 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed) ;
370 B2DEBUG(22,
"Cutflow: At least " << numGoodPhotonclusters_minCut <<
" good photon: index = " << cutIndexPassed) ;
377 vector<double> goodClustTimes ;
378 vector<double> goodClust_dt99 ;
379 vector<double> goodClusters_crysE ;
380 vector<double> goodClustE ;
381 vector<int> goodClustMaxEcrys_cid ;
382 for (
long unsigned int i = 0; i < goodPhotonClusterIdxs.size(); i++) {
383 int ic = goodPhotonClusterIdxs[i] ;
387 short cid = m_eclClusterArray[ic]->getMaxECellId() ;
389 goodClustMaxEcrys_cid.push_back(cid) ;
390 goodClustTimes.push_back(m_eclClusterArray[ic]->getTime()) ;
391 goodClust_dt99.push_back(m_eclClusterArray[ic]->getDeltaTime99()) ;
392 goodClusters_crysE.push_back(m_EperCrys[cid - 1]) ;
393 goodClustE.push_back(eClust);
400 vector< pair<double, double> > pair_energy_time ;
401 for (
long unsigned int ic = 0; ic < goodClusters_crysE.size(); ic++) {
402 pair_energy_time.push_back(make_pair(goodClusters_crysE[ic], goodClustTimes[ic])) ;
407 sort(pair_energy_time.begin(), pair_energy_time.end(), greater<>()) ;
411 B2DEBUG(22,
"Event passed all cuts");
415 getObjectPtr<TH1F>(
"eventT0")->Fill(evt_t0) ;
417 bool isCDCt0 = (
static_cast<EventT0::EventT0Component>(*m_eventT0->getEventT0Component())).detectorSet.contains(Const::CDC);
418 bool isECLt0 = (
static_cast<EventT0::EventT0Component>(*m_eventT0->getEventT0Component())).detectorSet.contains(Const::ECL);
419 string t0Detector =
"UNKNOWN... WHY?";
422 }
else if (isECLt0) {
426 B2DEBUG(26,
"t0 = " << evt_t0 <<
" ns. t0 is from CDC?=" << isCDCt0 <<
", t0 is from ECL?=" << isECLt0 <<
" t0 from " <<
434 for (
long unsigned int i = 0 ; i < goodPhotonClusterIdxs.size() ; i++) {
435 getObjectPtr<TH1F>(
"clusterTime")->Fill(goodClustTimes[i]) ;
436 getObjectPtr<TH2F>(
"clusterTime_cid")->Fill(goodClustMaxEcrys_cid[i] + 0.001, goodClustTimes[i] , 1) ;
437 getObjectPtr<TH2F>(
"clusterTime_run")->Fill(evtMetaData->getRun() + 0.001, goodClustTimes[i] , 1) ;
438 getObjectPtr<TH2F>(
"clusterTimeClusterE")->Fill(goodClustE[i], goodClustTimes[i], 1) ;
439 getObjectPtr<TH2F>(
"dt99_clusterE")->Fill(goodClustE[i], goodClust_dt99[i], 1) ;
444 m_tree_time = goodClustTimes[i] ;
445 m_E_photon_clust = goodClusters_crysE[i] ;
447 m_tree_t0_unc = evt_t0_unc ;
448 m_NtightTracks = nTrkTight ;
449 m_NphotonClusters = nPhotons ;
450 m_NGoodClusters = nGoodClusts ;
451 m_tree_evt_num = evtMetaData->getEvent() ;
452 m_tree_run = evtMetaData->getRun() ;
453 m_tree_cid = goodClustMaxEcrys_cid[i] ;
454 m_tree_dt99 = goodClust_dt99[i] ;
456 m_dbg_tree_photonClusters->Fill() ;
460 B2DEBUG(26,
"Filled cluster tree") ;
463 if (pair_energy_time.size() >= 2) {
464 getObjectPtr<TH1F>(
"clusterTimeE0E1diff")->Fill(pair_energy_time[0].second - pair_energy_time[1].second) ;
471 m_tree_t0_unc = evt_t0_unc ;
472 m_tree_evt_num = evtMetaData->getEvent() ;
473 m_tree_run = evtMetaData->getRun() ;
474 m_NtightTracks = nTrkTight ;
475 m_NphotonClusters = nPhotons ;
476 m_NGoodClusters = nGoodClusts ;
478 m_tree_E0 = pair_energy_time[0].first ;
479 m_tree_time_fromE0 = pair_energy_time[0].second ;
480 m_dbg_tree_event->Fill() ;
483 B2DEBUG(26,
"Filled event tree") ;