27 #include <ecl/modules/eclBhabhaTimeCalibrationValidationCollector/eclBhabhaTimeCalibrationValidationCollectorModule.h>
30 #include <ecl/dataobjects/ECLCalDigit.h>
31 #include <ecl/dataobjects/ECLDigit.h>
32 #include <ecl/dataobjects/ECLElementNumbers.h>
33 #include <ecl/dataobjects/ECLTrig.h>
34 #include <ecl/dbobjects/ECLCrystalCalib.h>
35 #include <ecl/digitization/EclConfiguration.h>
38 #include <analysis/ClusterUtility/ClusterUtils.h>
39 #include <analysis/utility/PCmsLabTransform.h>
40 #include <framework/gearbox/Const.h>
41 #include <mdst/dataobjects/ECLCluster.h>
42 #include <mdst/dataobjects/HitPatternCDC.h>
43 #include <mdst/dataobjects/Track.h>
57 REG_MODULE(eclBhabhaTimeCalibrationValidationCollector);
65 m_dbg_tree_electronClusters(0),
68 m_CrateTimeDB(
"ECLCrateTimeOffset"),
69 m_channelMapDB(
"ECLChannelMap")
74 "Events with fabs(getTimeFit) > m_timeAbsMax "
75 "are excluded", (
short)80);
78 "If true, TTree 'tree' with more detailed event info is saved in "
79 "the output file specified by HistoManager",
86 addParam(
"skipTrgSel",
skipTrgSel,
"boolean to skip the trigger skim selection",
false);
108 "Validating crystal and crate time calibrations using electron clusters in events with lots of tracks and clusters") ;
121 "Validating crystal and crate time calibrations using electron clusters in events with lots of tracks and clusters") ;
134 m_dbg_tree_run =
new TTree(
"tree_run",
"Storing crate time constants") ;
145 B2INFO(
"eclBhabhaTimeCalibrationValidationCollector: Experiment = " <<
m_EventMetaData->getExperiment() <<
151 double binSize = 2000.0 / pow(2, 12);
152 double halfBinSize = binSize / 2.0;
156 double nBinsNeg = floor((
m_timeAbsMax - halfBinSize) / binSize);
157 double min_t = -nBinsNeg * binSize - halfBinSize;
158 int nbins = nBinsNeg * 2 + 1;
159 double max_t = min_t + nbins * binSize;
163 const Int_t N_E_BIN_EDGES = 64;
164 const Int_t N_E_BINS = N_E_BIN_EDGES - 1;
165 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};
168 auto cutflow =
new TH1F(
"cutflow",
" ;Cut label number ;Number of events passing cut", 10, 0, 10) ;
169 registerObject<TH1F>(
"cutflow", cutflow) ;
171 auto clusterTime =
new TH1F(
"clusterTime",
";Electron ECL cluster time [ns]; number of ECL clusters", nbins, min_t, max_t) ;
172 registerObject<TH1F>(
"clusterTime", clusterTime) ;
174 auto clusterTime_cid =
new TH2F(
"clusterTime_cid",
177 registerObject<TH2F>(
"clusterTime_cid", clusterTime_cid) ;
179 auto clusterTime_run =
new TH2F(
"clusterTime_run",
180 ";Run number ;Electron ECL cluster time [ns]", 7000, 0, 7000, nbins, min_t, max_t) ;
181 registerObject<TH2F>(
"clusterTime_run", clusterTime_run) ;
184 auto clusterTimeClusterE =
new TH2F(
"clusterTimeClusterE",
185 ";Electron cluster energy [GeV];Electron cluster time [ns]", N_E_BINS, energyBinEdges, nbins, min_t, max_t) ;
186 registerObject<TH2F>(
"clusterTimeClusterE", clusterTimeClusterE) ;
188 auto dt99_clusterE =
new TH2F(
"dt99_clusterE",
189 ";Electron cluster energy [GeV];dt99 [ns]", N_E_BINS, energyBinEdges, nbins, 0, max_t) ;
190 registerObject<TH2F>(
"dt99_clusterE", dt99_clusterE) ;
193 auto eventT0 =
new TH1F(
"eventT0",
";event t0 [ns]; number of events", nbins, min_t, max_t) ;
194 registerObject<TH1F>(
"eventT0", eventT0) ;
196 auto clusterTimeE0E1diff =
new TH1F(
"clusterTimeE0E1diff",
197 ";ECL cluster time of max E electron - ECL cluster time of 2nd max E electron [ns]; number of electron ECL cluster time differences",
198 nbins, min_t, max_t) ;
199 registerObject<TH1F>(
"clusterTimeE0E1diff", clusterTimeE0E1diff) ;
214 int cutIndexPassed = 0;
215 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
216 B2DEBUG(22,
"Cutflow: no cuts: index = " << cutIndexPassed);
225 B2WARNING(
"SoftwareTriggerResult required to select bhabha event is not found");
231 const std::map<std::string, int>& fresults =
m_TrgResult->getResults();
232 if (fresults.find(
"software_trigger_cut&skim&accept_bhabha") == fresults.end()) {
233 B2WARNING(
"Can't find required bhabha trigger identifier");
237 const bool eBhabha = (
m_TrgResult->getResult(
"software_trigger_cut&skim&accept_bhabha") ==
239 B2DEBUG(22,
"eBhabha (trigger passed) = " << eBhabha);
249 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
250 B2DEBUG(22,
"Cutflow: Trigger cut passed: index = " << cutIndexPassed);
262 if (ECLchannelMapHasChanged) {
263 B2INFO(
"eclBhabhaTimeCalibrationValidationCollectorModule::collect() " <<
LogVar(
"ECLchannelMapHasChanged",
264 ECLchannelMapHasChanged));
266 B2FATAL(
"eclBhabhaTimeCalibrationValidationCollectorModule::collect() : Can't initialize eclChannelMapper!");
274 B2DEBUG(29,
"Finished checking if previous crystal time payload has changed");
281 B2DEBUG(25,
"eclBhabhaTimeCalibrationValidationCollector:: loaded ECLCrateTimeOffset from the database"
291 vector<float> Crate_time_ns(52, 0.0);
292 vector<float> Crate_time_unc_ns(52, 0.0);
297 Crate_time_ns[crateID_temp - 1] =
m_CrateTime[crysID] * TICKS_TO_NS;
298 Crate_time_unc_ns[crateID_temp - 1] =
m_CrateTimeUnc[crysID] * TICKS_TO_NS;
306 int tempCrysID = eclCalDigit.getCellId() - 1;
307 m_EperCrys[tempCrysID] = eclCalDigit.getEnergy();
313 double evt_t0 = -1000 ;
314 double evt_t0_unc = -1000 ;
326 evt_t0_unc =
m_eventT0->getEventT0Uncertainty() ;
328 B2DEBUG(26,
"Found event t0") ;
339 double maxp[2] = {0., 0.};
340 int maxiTrk[2] = { -1, -1};
341 int nTrkAll =
tracks.getEntries() ;
350 for (
int iTrk = 0 ; iTrk < nTrkAll ; iTrk++) {
354 if (not tempTrackFit) {continue ;}
358 double z0 = tempTrackFit->
getZ0() ;
359 double d0 = tempTrackFit->
getD0() ;
398 if (charge > 0) {icharge = 1;}
399 if (p > maxp[icharge]) {
401 maxiTrk[icharge] = iTrk;
410 if (nTrkTight != 2) {
415 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
416 B2DEBUG(22,
"Cutflow: Two tight tracks: index = " << cutIndexPassed);
419 if (nTrkLoose != 2) {
424 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed) ;
425 B2DEBUG(22,
"Cutflow: No additional loose tracks: index = " << cutIndexPassed) ;
430 bool oppositelyChargedTracksPassed = maxiTrk[0] != -1 && maxiTrk[1] != -1;
431 if (!oppositelyChargedTracksPassed) {
436 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
437 B2DEBUG(22,
"Cutflow: Oppositely charged tracks: index = " << cutIndexPassed);
445 double trkEClustLab[2] = {0., 0.};
446 double trkEClustCOM[2] = {0., 0.};
449 ROOT::Math::PxPyPzEVector trkp4Lab[2];
450 ROOT::Math::PxPyPzEVector trkp4COM[2];
453 int numClustersPerTrack[2] = { 0, 0 };
456 vector<double> goodClustTimes ;
457 vector<double> goodClust_dt99 ;
458 vector<double> goodClustE ;
459 vector<int> goodClustMaxEcrys_cid ;
461 for (
int icharge = 0; icharge < 2; icharge++) {
462 if (maxiTrk[icharge] > -1) {
463 B2DEBUG(22,
"looping over the 2 max pt tracks");
466 if (not tempTrackFit) {continue ;}
469 trkp4COM[icharge] = boostrotate.
rotateLabToCms() * trkp4Lab[icharge];
470 trkpLab[icharge] = trkp4Lab[icharge].P();
471 trkpCOM[icharge] = trkp4COM[icharge].P();
477 auto eclClusterRelationsFromTracks =
tracks[maxiTrk[icharge]]->getRelationsTo<
ECLCluster>();
478 for (
unsigned int clusterIdx = 0; clusterIdx < eclClusterRelationsFromTracks.size(); clusterIdx++) {
480 B2DEBUG(22,
"Looking at clusters. index = " << clusterIdx);
481 auto cluster = eclClusterRelationsFromTracks[clusterIdx];
484 numClustersPerTrack[icharge]++;
486 double electronTime = cluster->getTime();
487 bool badElectronTime = cluster->hasFailedFitTime();
488 bool badElectronTimeResolution = cluster->hasFailedTimeResolution();
490 (!badElectronTime) &&
491 (!badElectronTimeResolution)) {
492 trkEClustLab[icharge] += eClust ;
493 short cid = cluster->getMaxECellId() ;
494 goodClustMaxEcrys_cid.push_back(cid) ;
495 goodClustTimes.push_back(electronTime) ;
496 goodClust_dt99.push_back(cluster->getDeltaTime99()) ;
497 goodClustE.push_back(eClust);
501 trkEClustCOM[icharge] = trkEClustLab[icharge] * trkpCOM[icharge] / trkpLab[icharge];
506 E_DIV_p[icharge] = trkEClustCOM[icharge] / trkpCOM[icharge];
513 B2DEBUG(26,
"Extracted time information and E/p for the tracks") ;
524 long unsigned int numGoodElectronClusters_cut = 2 ;
525 if (goodClustTimes.size() != numGoodElectronClusters_cut) {
530 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed) ;
531 B2DEBUG(22,
"Cutflow: Exactly " << numGoodElectronClusters_cut
532 <<
" good clusters connected to tracks: index = " << cutIndexPassed);
538 bool E_DIV_p_instance_passed[2] = {
false,
false};
539 double E_DIV_p_CUT = 0.7;
540 for (
int icharge = 0; icharge < 2; icharge++) {
541 E_DIV_p_instance_passed[icharge] = E_DIV_p[icharge] > E_DIV_p_CUT;
543 if (!E_DIV_p_instance_passed[0] || !E_DIV_p_instance_passed[1]) {
548 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
549 B2DEBUG(22,
"Cutflow: E_i/p_i > " << E_DIV_p_CUT <<
": index = " << cutIndexPassed);
554 double invMassTrk = (trkp4Lab[0] + trkp4Lab[1]).M();
555 double invMass_CUT = 0.9;
557 bool invMassCutsPassed = invMassTrk > (invMass_CUT * boostrotate.
getCMSEnergy());
558 if (!invMassCutsPassed) {
563 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
564 B2DEBUG(22,
"Cutflow: m(track 1+2) > " << invMass_CUT <<
"*E_COM = " << invMass_CUT <<
" * " << boostrotate.
getCMSEnergy() <<
565 " : index = " << cutIndexPassed);
568 B2DEBUG(22,
"Event passed all cuts");
572 getObjectPtr<TH1F>(
"eventT0")->Fill(evt_t0) ;
576 string t0Detector =
"UNKNOWN... WHY?";
579 }
else if (isECLt0) {
583 B2DEBUG(26,
"t0 = " << evt_t0 <<
" ns. t0 is from CDC?=" << isCDCt0 <<
", t0 is from ECL?=" << isECLt0 <<
" t0 from " <<
588 for (
long unsigned int i = 0 ; i < goodClustTimes.size() ; i++) {
589 getObjectPtr<TH1F>(
"clusterTime")->Fill(goodClustTimes[i]) ;
590 getObjectPtr<TH2F>(
"clusterTime_cid")->Fill(goodClustMaxEcrys_cid[i] + 0.001, goodClustTimes[i], 1) ;
591 getObjectPtr<TH2F>(
"clusterTime_run")->Fill(
m_EventMetaData->getRun() + 0.001, goodClustTimes[i], 1) ;
592 getObjectPtr<TH2F>(
"clusterTimeClusterE")->Fill(goodClustE[i], goodClustTimes[i], 1) ;
593 getObjectPtr<TH2F>(
"dt99_clusterE")->Fill(goodClustE[i], goodClust_dt99[i], 1) ;
613 B2DEBUG(26,
"Filled cluster tree") ;
617 if (goodClustE[0] > goodClustE[1]) {
618 tDiff = goodClustTimes[0] - goodClustTimes[1];
620 tDiff = goodClustTimes[1] - goodClustTimes[0];
623 getObjectPtr<TH1F>(
"clusterTimeE0E1diff")->Fill(tDiff) ;
643 for (
int icrate = 1; icrate <= 52; icrate++) {
655 B2DEBUG(26,
"Filled event tree") ;
Calibration collector module base class.
static const ChargedStable pion
charged pion particle
bool hasChanged()
Check whether the object has changed since the last call to hasChanged of the accessor).
@ c_nPhotons
CR is split into n photons (N1)
static double getRF()
See m_rf.
unsigned short getNHits() const
Get the total Number of CDC hits in the fit.
void setDescription(const std::string &description)
Sets the description of the module.
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Values of the result of a track fit with a given particle hypothesis.
short getChargeSign() const
Return track charge (1 or -1).
ROOT::Math::PxPyPzEVector get4Momentum() const
Getter for the 4Momentum at the closest approach of the track in the r/phi projection.
double getD0() const
Getter for d0.
double getZ0() const
Getter for z0.
ROOT::Math::XYZVector getMomentum() const
Getter for vector of momentum at closest approach of track in r/phi projection.
HitPatternCDC getHitPatternCDC() const
Getter for the hit pattern in the CDC;.
TTree * m_dbg_tree_run
debug output tree for per run
std::vector< float > m_CrateTime
vector obtained from DB object
double m_E_electron_clust
Electron cluster energy.
DBObjPtr< ECLCrystalCalib > m_CrateTimeDB
database object
StoreObjPtr< EventT0 > m_eventT0
StoreObjPtr for T0.
double m_tree_time_fromE1
Calibrated time - second highest E cluster.
int m_tree_run
Run number for debug TTree output.
int m_tree_crateid
Crate ID for debug TTree output.
double m_looseTrkD0
Loose track d0 minimum cut.
bool m_saveTree
If true, save TTree with more detailed event info.
int m_tree_PreviousRun
Run number for the previous run for debug TTree output.
StoreArray< ECLCluster > m_eclClusterArray
Required input array of ECLClusters.
virtual ~eclBhabhaTimeCalibrationValidationCollectorModule()
Module destructor.
short m_timeAbsMax
Events with abs(time) > m_timeAbsMax are excluded, mostly for histogram x-range purposes.
int m_tree_cid
ECL Cell ID (1..ECLElementNumbers::c_NCrystals) for debug TTree output.
TTree * m_dbg_tree_event
debug output tree for per event
double m_tree_time
Calibrated time.
double m_tree_E1
second highest E cluster energy
double m_tightTrkZ0
Tight track z0 minimum cut.
double m_tree_E0
Highest E cluster energy.
int m_NtightTracks
Number of tight tracks.
TTree * m_dbg_tree_electronClusters
debug output tree for per electron cluster
DBObjPtr< Belle2::ECLChannelMap > m_channelMapDB
Mapper of ecl channels to various other objects, like crates.
void collect() override
Select events and crystals and accumulate histograms.
std::vector< float > m_CrateTimeUnc
uncertainty vector obtained from DB object
double m_tree_dt99
dt99 for cluster
StoreArray< ECLCalDigit > m_eclCalDigitArray
Required input array of ECLCalDigits.
std::vector< float > m_EperCrys
ECL Cal digit energy for each crystal.
bool skipTrgSel
flag to skip the trigger skim selection in the module
void prepare() override
Define histograms and read payloads from DB.
double m_tightTrkD0
Tight track d0 minimum cut.
double m_tree_t0
EventT0 (not from ECL) for debug TTree output.
double m_tree_time_fromE0
Calibrated time - highest E cluster.
void inDefineHisto() override
Replacement for defineHisto() in CalibrationCollector modules.
eclBhabhaTimeCalibrationValidationCollectorModule()
Module constructor.
double m_tree_tcrate
Crate time for debug TTree output.
StoreArray< Track > tracks
Required input array of tracks.
StoreObjPtr< EventMetaData > m_EventMetaData
Event metadata.
double m_tree_t0_unc
EventT0 uncertainty for debug TTree output.
std::unique_ptr< Belle2::ECL::ECLChannelMapper > m_crystalMapper
ECL object for keeping track of mapping between crystals and crates etc.
int m_tree_evt_num
Event number for debug TTree output.
StoreObjPtr< SoftwareTriggerResult > m_TrgResult
Store array for Trigger selection.
double m_tree_tcrate_unc
Crate time uncertainty for debug TTree output.
double m_looseTrkZ0
Loose track z0 minimum cut.
Class to store variables with their name which were sent to the logging service.
REG_MODULE(arichBtest)
Register the Module.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
@ c_accept
Accept this event.
const int c_NCrystals
Number of crystals.
Abstract base class for different kinds of events.
Structure for storing the extracted event t0s together with its detector and its uncertainty.