27#include <ecl/modules/eclBhabhaTimeCalibrationValidationCollector/eclBhabhaTimeCalibrationValidationCollectorModule.h>
30#include <ecl/dataobjects/ECLCalDigit.h>
31#include <ecl/dataobjects/ECLElementNumbers.h>
32#include <ecl/dbobjects/ECLCrystalCalib.h>
33#include <ecl/digitization/EclConfiguration.h>
36#include <analysis/utility/PCmsLabTransform.h>
37#include <framework/gearbox/Const.h>
38#include <mdst/dataobjects/ECLCluster.h>
39#include <mdst/dataobjects/HitPatternCDC.h>
40#include <mdst/dataobjects/Track.h>
53REG_MODULE(eclBhabhaTimeCalibrationValidationCollector);
61 m_dbg_tree_electronClusters(0),
64 m_CrateTimeDB(
"ECLCrateTimeOffset"),
65 m_channelMapDB(
"ECLChannelMap")
70 "Events with fabs(getTimeFit) > m_timeAbsMax "
71 "are excluded", (
short)80);
74 "If true, TTree 'tree' with more detailed event info is saved in "
75 "the output file specified by HistoManager",
82 addParam(
"skipTrgSel",
skipTrgSel,
"boolean to skip the trigger skim selection",
false);
104 "Validating crystal and crate time calibrations using electron clusters in events with lots of tracks and clusters") ;
117 "Validating crystal and crate time calibrations using electron clusters in events with lots of tracks and clusters") ;
130 m_dbg_tree_run =
new TTree(
"tree_run",
"Storing crate time constants") ;
141 B2INFO(
"eclBhabhaTimeCalibrationValidationCollector: Experiment = " <<
m_EventMetaData->getExperiment() <<
147 double binSize = 2000.0 / pow(2, 12);
148 double halfBinSize = binSize / 2.0;
152 double nBinsNeg = floor((
m_timeAbsMax - halfBinSize) / binSize);
153 double min_t = -nBinsNeg * binSize - halfBinSize;
154 int nbins = nBinsNeg * 2 + 1;
155 double max_t = min_t + nbins * binSize;
159 const Int_t N_E_BIN_EDGES = 64;
160 const Int_t N_E_BINS = N_E_BIN_EDGES - 1;
161 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};
164 auto cutflow =
new TH1F(
"cutflow",
" ;Cut label number ;Number of events passing cut", 10, 0, 10) ;
165 registerObject<TH1F>(
"cutflow", cutflow) ;
167 auto clusterTime =
new TH1F(
"clusterTime",
";Electron ECL cluster time [ns]; number of ECL clusters", nbins, min_t, max_t) ;
168 registerObject<TH1F>(
"clusterTime", clusterTime) ;
170 auto clusterTime_cid =
new TH2F(
"clusterTime_cid",
173 registerObject<TH2F>(
"clusterTime_cid", clusterTime_cid) ;
175 auto clusterTime_run =
new TH2F(
"clusterTime_run",
176 ";Run number ;Electron ECL cluster time [ns]", 7000, 0, 7000, nbins, min_t, max_t) ;
177 registerObject<TH2F>(
"clusterTime_run", clusterTime_run) ;
180 auto clusterTimeClusterE =
new TH2F(
"clusterTimeClusterE",
181 ";Electron cluster energy [GeV];Electron cluster time [ns]", N_E_BINS, energyBinEdges, nbins, min_t, max_t) ;
182 registerObject<TH2F>(
"clusterTimeClusterE", clusterTimeClusterE) ;
184 auto dt99_clusterE =
new TH2F(
"dt99_clusterE",
185 ";Electron cluster energy [GeV];dt99 [ns]", N_E_BINS, energyBinEdges, nbins, 0, max_t) ;
186 registerObject<TH2F>(
"dt99_clusterE", dt99_clusterE) ;
189 auto eventT0 =
new TH1F(
"eventT0",
";event t0 [ns]; number of events", nbins, min_t, max_t) ;
190 registerObject<TH1F>(
"eventT0", eventT0) ;
192 auto clusterTimeE0E1diff =
new TH1F(
"clusterTimeE0E1diff",
193 ";ECL cluster time of max E electron - ECL cluster time of 2nd max E electron [ns]; number of electron ECL cluster time differences",
194 nbins, min_t, max_t) ;
195 registerObject<TH1F>(
"clusterTimeE0E1diff", clusterTimeE0E1diff) ;
210 int cutIndexPassed = 0;
211 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
212 B2DEBUG(22,
"Cutflow: no cuts: index = " << cutIndexPassed);
221 B2WARNING(
"SoftwareTriggerResult required to select bhabha event is not found");
227 const std::map<std::string, int>& fresults =
m_TrgResult->getResults();
228 if (fresults.find(
"software_trigger_cut&skim&accept_bhabha") == fresults.end()) {
229 B2WARNING(
"Can't find required bhabha trigger identifier");
233 const bool eBhabha = (
m_TrgResult->getResult(
"software_trigger_cut&skim&accept_bhabha") ==
235 B2DEBUG(22,
"eBhabha (trigger passed) = " << eBhabha);
245 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
246 B2DEBUG(22,
"Cutflow: Trigger cut passed: index = " << cutIndexPassed);
258 if (ECLchannelMapHasChanged) {
259 B2INFO(
"eclBhabhaTimeCalibrationValidationCollectorModule::collect() " <<
LogVar(
"ECLchannelMapHasChanged",
260 ECLchannelMapHasChanged));
262 B2FATAL(
"eclBhabhaTimeCalibrationValidationCollectorModule::collect() : Can't initialize eclChannelMapper!");
270 B2DEBUG(29,
"Finished checking if previous crystal time payload has changed");
277 B2DEBUG(25,
"eclBhabhaTimeCalibrationValidationCollector:: loaded ECLCrateTimeOffset from the database"
287 vector<float> Crate_time_ns(52, 0.0);
288 vector<float> Crate_time_unc_ns(52, 0.0);
293 Crate_time_ns[crateID_temp - 1] =
m_CrateTime[crysID] * TICKS_TO_NS;
294 Crate_time_unc_ns[crateID_temp - 1] =
m_CrateTimeUnc[crysID] * TICKS_TO_NS;
302 int tempCrysID = eclCalDigit.getCellId() - 1;
303 m_EperCrys[tempCrysID] = eclCalDigit.getEnergy();
309 double evt_t0 = -1000 ;
310 double evt_t0_unc = -1000 ;
322 evt_t0_unc =
m_eventT0->getEventT0Uncertainty() ;
324 B2DEBUG(26,
"Found event t0") ;
335 double maxp[2] = {0., 0.};
336 int maxiTrk[2] = { -1, -1};
337 int nTrkAll =
tracks.getEntries() ;
346 for (
int iTrk = 0 ; iTrk < nTrkAll ; iTrk++) {
350 if (not tempTrackFit) {continue ;}
354 double z0 = tempTrackFit->
getZ0() ;
355 double d0 = tempTrackFit->
getD0() ;
394 if (charge > 0) {icharge = 1;}
395 if (p > maxp[icharge]) {
397 maxiTrk[icharge] = iTrk;
406 if (nTrkTight != 2) {
411 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
412 B2DEBUG(22,
"Cutflow: Two tight tracks: index = " << cutIndexPassed);
415 if (nTrkLoose != 2) {
420 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed) ;
421 B2DEBUG(22,
"Cutflow: No additional loose tracks: index = " << cutIndexPassed) ;
426 bool oppositelyChargedTracksPassed = maxiTrk[0] != -1 && maxiTrk[1] != -1;
427 if (!oppositelyChargedTracksPassed) {
432 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
433 B2DEBUG(22,
"Cutflow: Oppositely charged tracks: index = " << cutIndexPassed);
441 double trkEClustLab[2] = {0., 0.};
442 double trkEClustCOM[2] = {0., 0.};
445 ROOT::Math::PxPyPzEVector trkp4Lab[2];
446 ROOT::Math::PxPyPzEVector trkp4COM[2];
449 int numClustersPerTrack[2] = { 0, 0 };
452 vector<double> goodClustTimes ;
453 vector<double> goodClust_dt99 ;
454 vector<double> goodClustE ;
455 vector<int> goodClustMaxEcrys_cid ;
457 for (
int icharge = 0; icharge < 2; icharge++) {
458 if (maxiTrk[icharge] > -1) {
459 B2DEBUG(22,
"looping over the 2 max pt tracks");
462 if (not tempTrackFit) {continue ;}
465 trkp4COM[icharge] = boostrotate.
rotateLabToCms() * trkp4Lab[icharge];
466 trkpLab[icharge] = trkp4Lab[icharge].P();
467 trkpCOM[icharge] = trkp4COM[icharge].P();
473 auto eclClusterRelationsFromTracks =
tracks[maxiTrk[icharge]]->getRelationsTo<
ECLCluster>();
474 for (
unsigned int clusterIdx = 0; clusterIdx < eclClusterRelationsFromTracks.size(); clusterIdx++) {
476 B2DEBUG(22,
"Looking at clusters. index = " << clusterIdx);
477 auto cluster = eclClusterRelationsFromTracks[clusterIdx];
480 numClustersPerTrack[icharge]++;
482 double electronTime = cluster->getTime();
483 bool badElectronTime = cluster->hasFailedFitTime();
484 bool badElectronTimeResolution = cluster->hasFailedTimeResolution();
486 (!badElectronTime) &&
487 (!badElectronTimeResolution)) {
488 trkEClustLab[icharge] += eClust ;
489 short cid = cluster->getMaxECellId() ;
490 goodClustMaxEcrys_cid.push_back(cid) ;
491 goodClustTimes.push_back(electronTime) ;
492 goodClust_dt99.push_back(cluster->getDeltaTime99()) ;
493 goodClustE.push_back(eClust);
497 trkEClustCOM[icharge] = trkEClustLab[icharge] * trkpCOM[icharge] / trkpLab[icharge];
502 E_DIV_p[icharge] = trkEClustCOM[icharge] / trkpCOM[icharge];
509 B2DEBUG(26,
"Extracted time information and E/p for the tracks") ;
520 long unsigned int numGoodElectronClusters_cut = 2 ;
521 if (goodClustTimes.size() != numGoodElectronClusters_cut) {
526 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed) ;
527 B2DEBUG(22,
"Cutflow: Exactly " << numGoodElectronClusters_cut
528 <<
" good clusters connected to tracks: index = " << cutIndexPassed);
534 bool E_DIV_p_instance_passed[2] = {
false,
false};
535 double E_DIV_p_CUT = 0.7;
536 for (
int icharge = 0; icharge < 2; icharge++) {
537 E_DIV_p_instance_passed[icharge] = E_DIV_p[icharge] > E_DIV_p_CUT;
539 if (!E_DIV_p_instance_passed[0] || !E_DIV_p_instance_passed[1]) {
544 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
545 B2DEBUG(22,
"Cutflow: E_i/p_i > " << E_DIV_p_CUT <<
": index = " << cutIndexPassed);
550 double invMassTrk = (trkp4Lab[0] + trkp4Lab[1]).M();
551 double invMass_CUT = 0.9;
553 bool invMassCutsPassed = invMassTrk > (invMass_CUT * boostrotate.
getCMSEnergy());
554 if (!invMassCutsPassed) {
559 getObjectPtr<TH1F>(
"cutflow")->Fill(cutIndexPassed);
560 B2DEBUG(22,
"Cutflow: m(track 1+2) > " << invMass_CUT <<
"*E_COM = " << invMass_CUT <<
" * " << boostrotate.
getCMSEnergy() <<
561 " : index = " << cutIndexPassed);
564 B2DEBUG(22,
"Event passed all cuts");
568 getObjectPtr<TH1F>(
"eventT0")->Fill(evt_t0) ;
570 bool isCDCt0 =
m_eventT0->isCDCEventT0();
571 bool isECLt0 =
m_eventT0->isECLEventT0();
572 string t0Detector =
"UNKNOWN... WHY?";
575 }
else if (isECLt0) {
579 B2DEBUG(26,
"t0 = " << evt_t0 <<
" ns. t0 is from CDC?=" << isCDCt0 <<
", t0 is from ECL?=" << isECLt0 <<
" t0 from " <<
584 for (
long unsigned int i = 0 ; i < goodClustTimes.size() ; i++) {
585 getObjectPtr<TH1F>(
"clusterTime")->Fill(goodClustTimes[i]) ;
586 getObjectPtr<TH2F>(
"clusterTime_cid")->Fill(goodClustMaxEcrys_cid[i] + 0.001, goodClustTimes[i], 1) ;
587 getObjectPtr<TH2F>(
"clusterTime_run")->Fill(
m_EventMetaData->getRun() + 0.001, goodClustTimes[i], 1) ;
588 getObjectPtr<TH2F>(
"clusterTimeClusterE")->Fill(goodClustE[i], goodClustTimes[i], 1) ;
589 getObjectPtr<TH2F>(
"dt99_clusterE")->Fill(goodClustE[i], goodClust_dt99[i], 1) ;
609 B2DEBUG(26,
"Filled cluster tree") ;
613 if (goodClustE[0] > goodClustE[1]) {
614 tDiff = goodClustTimes[0] - goodClustTimes[1];
616 tDiff = goodClustTimes[1] - goodClustTimes[0];
619 getObjectPtr<TH1F>(
"clusterTimeE0E1diff")->Fill(tDiff) ;
639 for (
int icrate = 1; icrate <= 52; icrate++) {
651 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.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
@ c_accept
Accept this event.
const int c_NCrystals
Number of crystals.
Abstract base class for different kinds of events.