Belle II Software  release-08-00-10
eclGammaGammaECollectorModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 /* Own header. */
10 #include <ecl/modules/eclGammaGammaECollector/eclGammaGammaECollectorModule.h>
11 
12 /* ECL headers. */
13 #include <ecl/dataobjects/ECLDigit.h>
14 #include <ecl/dataobjects/ECLElementNumbers.h>
15 #include <ecl/dbobjects/ECLCrystalCalib.h>
16 
17 /* Basf2 headers. */
18 #include <analysis/ClusterUtility/ClusterUtils.h>
19 #include <analysis/utility/PCmsLabTransform.h>
20 #include <framework/dataobjects/EventMetaData.h>
21 #include <framework/datastore/RelationVector.h>
22 #include <framework/gearbox/Const.h>
23 #include <framework/geometry/VectorUtil.h>
24 #include <mdst/dataobjects/ECLCluster.h>
25 #include <mdst/dataobjects/HitPatternCDC.h>
26 #include <mdst/dataobjects/Track.h>
27 #include <mdst/dataobjects/TrackFitResult.h>
28 #include <mdst/dataobjects/TRGSummary.h>
29 
30 /* ROOT headers. */
31 #include <Math/Vector3D.h>
32 #include <Math/Vector4D.h>
33 #include <TH2F.h>
34 
35 using namespace std;
36 using namespace Belle2;
37 
38 
39 //-----------------------------------------------------------------
40 // Register the Module
41 //-----------------------------------------------------------------
42 REG_MODULE(eclGammaGammaECollector);
43 
44 //-----------------------------------------------------------------
45 // Implementation
46 //-----------------------------------------------------------------
47 
48 //-----------------------------------------------------------------------------------------------------
49 
50 eclGammaGammaECollectorModule::eclGammaGammaECollectorModule() : CalibrationCollectorModule(),
51  m_ECLExpGammaGammaE("ECLExpGammaGammaE"),
52  m_ElectronicsCalib("ECLCrystalElectronics"), m_GammaGammaECalib("ECLCrystalEnergyGammaGamma")
53 {
54  // Set module properties
55  setDescription("Calibration Collector Module for ECL single crystal energy calibration using gamma gamma events");
57  addParam("thetaLabMinDeg", m_thetaLabMinDeg, "miniumum photon theta in lab (degrees)", 0.);
58  addParam("thetaLabMaxDeg", m_thetaLabMaxDeg, "maximum photon theta in lab (degrees)", 180.);
59  addParam("minPairMass", m_minPairMass, "minimum invariant mass of the pair of photons (GeV/c^2)", 9.);
60  addParam("mindPhi", m_mindPhi, "minimum delta phi between clusters (deg)", 179.);
61  addParam("maxTime", m_maxTime, "maximum (time-<t>)/dt99 of photons", 1.);
62  addParam("measureTrueEnergy", m_measureTrueEnergy, "use MC events to obtain expected energies", false);
63  addParam("requireL1", m_requireL1, "only use events that have a level 1 trigger", true);
64 }
65 
66 
67 
71 {
72 
74  B2INFO("eclGammaGammaECollector: Experiment = " << m_evtMetaData->getExperiment() << " run = " << m_evtMetaData->getRun());
75 
78  auto EnVsCrysID = new TH2F("EnVsCrysID", "Normalized energy for each crystal;crystal ID;E/Expected", ECLElementNumbers::c_NCrystals,
79  0, ECLElementNumbers::c_NCrystals, 140, 0, 1.4);
80  registerObject<TH2F>("EnVsCrysID", EnVsCrysID);
81 
82  auto ExpEvsCrys = new TH1F("ExpEvsCrys", "Sum expected energy vs crystal ID;crystal ID;Energy (GeV)",
84  registerObject<TH1F>("ExpEvsCrys", ExpEvsCrys);
85 
86  auto ElecCalibvsCrys = new TH1F("ElecCalibvsCrys", "Sum electronics calib const vs crystal ID;crystal ID;calibration constant",
88  registerObject<TH1F>("ElecCalibvsCrys", ElecCalibvsCrys);
89 
90  auto InitialCalibvsCrys = new TH1F("InitialCalibvsCrys",
91  "Sum initial gamma gamma calib const vs crystal ID;crystal ID;calibration constant", ECLElementNumbers::c_NCrystals, 0,
93  registerObject<TH1F>("InitialCalibvsCrys", InitialCalibvsCrys);
94 
95  auto CalibEntriesvsCrys = new TH1F("CalibEntriesvsCrys", "Entries in calib vs crys histograms;crystal ID;Entries per crystal",
98  registerObject<TH1F>("CalibEntriesvsCrys", CalibEntriesvsCrys);
99 
101  auto RawDigitAmpvsCrys = new TH2F("RawDigitAmpvsCrys", "Digit Amplitude vs crystal ID;crystal ID;Amplitude",
103  200000);
104  registerObject<TH2F>("RawDigitAmpvsCrys", RawDigitAmpvsCrys);
105 
106  auto RawDigitTimevsCrys = new TH2F("RawDigitTimevsCrys", "Digit Time vs crystal ID;crystal ID;Time", ECLElementNumbers::c_NCrystals,
107  0, ECLElementNumbers::c_NCrystals, 200, -2000,
108  2000);
109  registerObject<TH2F>("RawDigitTimevsCrys", RawDigitTimevsCrys);
110 
111  auto TimeMinusAverage = new TH1F("TimeMinusAverage", "Photon time - average / dt99;(T-T_ave)/dt99 ", 100, -10, 10);
112  registerObject<TH1F>("TimeMinusAverage", TimeMinusAverage);
113 
114 
115  //------------------------------------------------------------------------
117  B2INFO("Input parameters to eclGammaGammaECollector:");
118  B2INFO("thetaLabMinDeg: " << m_thetaLabMinDeg);
119  B2INFO("thetaLabMaxDeg: " << m_thetaLabMaxDeg);
120  thetaLabMin = m_thetaLabMinDeg / TMath::RadToDeg();
121  thetaLabMax = m_thetaLabMaxDeg / TMath::RadToDeg();
122  B2INFO("minPairMass: " << m_minPairMass);
123  B2INFO("mindPhi: " << m_mindPhi);
124  B2INFO("maxTime: " << m_maxTime);
125  B2INFO("measureTrueEnergy: " << m_measureTrueEnergy);
126  B2INFO("requireL1: " << m_requireL1);
127 
130 
133  if (m_ECLExpGammaGammaE.hasChanged()) {ExpGammaGammaE = m_ECLExpGammaGammaE->getCalibVector();}
134  if (m_ElectronicsCalib.hasChanged()) {ElectronicsCalib = m_ElectronicsCalib->getCalibVector();}
135  if (m_GammaGammaECalib.hasChanged()) {GammaGammaECalib = m_GammaGammaECalib->getCalibVector();}
136 
138  for (int ic = 1; ic < 9000; ic += 1000) {
139  B2INFO("DB constants for cellID=" << ic << ": ExpGammaGammaE = " << ExpGammaGammaE[ic - 1] << " ElectronicsCalib = " <<
140  ElectronicsCalib[ic - 1]
141  << " GammaGammaECalib = " << GammaGammaECalib[ic - 1]);
142  }
143 
145  for (int crysID = 0; crysID < ECLElementNumbers::c_NCrystals; crysID++) {
146  if (ElectronicsCalib[crysID] <= 0) {B2FATAL("eclGammaGammaECollector: ElectronicsCalib = " << ElectronicsCalib[crysID] << " for crysID = " << crysID);}
147  if (ExpGammaGammaE[crysID] == 0) {B2FATAL("eclGammaGammaECollector: ExpGammaGammaE = 0 for crysID = " << crysID);}
148  if (GammaGammaECalib[crysID] == 0) {B2FATAL("eclGammaGammaECollector: GammaGammaECalib = 0 for crysID = " << crysID);}
149  }
150 
153  m_trackArray.isRequired();
154  m_eclClusterArray.isRequired();
155  if (!m_measureTrueEnergy) {m_eclDigitArray.isRequired();}
156 
157 }
158 
159 
163 {
164 
166  if (storeCalib) {
167  for (int crysID = 0; crysID < ECLElementNumbers::c_NCrystals; crysID++) {
168  getObjectPtr<TH1F>("ExpEvsCrys")->Fill(crysID + 0.001, ExpGammaGammaE[crysID]);
169  getObjectPtr<TH1F>("ElecCalibvsCrys")->Fill(crysID + 0.001, ElectronicsCalib[crysID]);
170  getObjectPtr<TH1F>("InitialCalibvsCrys")->Fill(crysID + 0.001, GammaGammaECalib[crysID]);
171  getObjectPtr<TH1F>("CalibEntriesvsCrys")->Fill(crysID + 0.001);
172  }
173  storeCalib = false;
174  }
175 
178  bool newConst = false;
179  if (m_ECLExpGammaGammaE.hasChanged()) {
180  newConst = true;
181  B2INFO("ECLExpGammaGammaE has changed, exp = " << m_evtMetaData->getExperiment() << " run = " << m_evtMetaData->getRun());
182  ExpGammaGammaE = m_ECLExpGammaGammaE->getCalibVector();
183  }
184  if (m_ElectronicsCalib.hasChanged()) {
185  newConst = true;
186  B2INFO("ECLCrystalElectronics has changed, exp = " << m_evtMetaData->getExperiment() << " run = " << m_evtMetaData->getRun());
187  ElectronicsCalib = m_ElectronicsCalib->getCalibVector();
188  }
189  if (m_GammaGammaECalib.hasChanged()) {
190  newConst = true;
191  B2INFO("ECLCrystalEnergyGammaGamma has changed, exp = " << m_evtMetaData->getExperiment() << " run = " << m_evtMetaData->getRun());
192  GammaGammaECalib = m_GammaGammaECalib->getCalibVector();
193  }
194 
195  if (newConst) {
196  for (int ic = 1; ic < 9000; ic += 1000) {
197  B2INFO("DB constants for cellID=" << ic << ": ExpGammaGammaE = " << ExpGammaGammaE[ic - 1] << " ElectronicsCalib = " <<
198  ElectronicsCalib[ic - 1]
199  << " GammaGammaECalib = " << GammaGammaECalib[ic - 1]);
200  }
201 
203  for (int crysID = 0; crysID < ECLElementNumbers::c_NCrystals; crysID++) {
204  if (ElectronicsCalib[crysID] <= 0) {B2FATAL("eclGammaGammaECollector: ElectronicsCalib = " << ElectronicsCalib[crysID] << " for crysID = " << crysID);}
205  if (ExpGammaGammaE[crysID] == 0) {B2FATAL("eclGammaGammaECollector: ExpGammaGammaE = 0 for crysID = " << crysID);}
206  if (GammaGammaECalib[crysID] == 0) {B2FATAL("eclGammaGammaECollector: GammaGammaECalib = 0 for crysID = " << crysID);}
207  }
208  }
209 
212  if (m_requireL1) {
213  unsigned int L1TriggerResults = m_TRGResults->getTRGSummary(0);
214  if (L1TriggerResults == 0) {return;}
215  }
216 
217  //------------------------------------------------------------------------
219  int nGoodTrk = 0;
220  for (auto& track : m_trackArray) {
221  const TrackFitResult* temptrackFit = track.getTrackFitResult(Const::ChargedStable(211));
222  if (temptrackFit) {
223  double pt = temptrackFit->getTransverseMomentum();
224  double z0 = temptrackFit->getZ0();
225  double d0 = temptrackFit->getD0();
226  double pValue = temptrackFit->getPValue();
227  int nCDChits = temptrackFit->getHitPatternCDC().getNHits();
228  if (pt > minTrkpt && abs(z0) < maxZ0 && abs(d0) < maxD0 && pValue > minpValue && nCDChits >= minCDChits) {nGoodTrk++;}
229  }
230  }
231  if (nGoodTrk > 0) {return;}
232 
233  //------------------------------------------------------------------------
236  int icMax[2] = { -1, -1};
237  double maxClustE[2] = { -1., -1.};
238  int nclust = m_eclClusterArray.getEntries();
239  for (int ic = 0; ic < nclust; ic++) {
240  if (m_eclClusterArray[ic]->hasHypothesis(usePhotons)) {
241  double eClust = m_eclClusterArray[ic]->getEnergy(usePhotons);
242  if (eClust > maxClustE[0]) {
243  maxClustE[1] = maxClustE[0];
244  icMax[1] = icMax[0];
245  maxClustE[0] = eClust;
246  icMax[0] = ic;
247  } else if (eClust > maxClustE[1]) {
248  maxClustE[1] = eClust;
249  icMax[1] = ic;
250  }
251  }
252  }
253 
254  //------------------------------------------------------------------------
257  if (icMax[0] == -1 || icMax[1] == -1) {return;}
258  double theta0 = m_eclClusterArray[icMax[0]]->getTheta();
259  double theta1 = m_eclClusterArray[icMax[1]]->getTheta();
260  if (theta0 < thetaLabMin || theta0 > thetaLabMax || theta1 < thetaLabMin || theta1 > thetaLabMax) {return;}
261 
263  double t0 = m_eclClusterArray[icMax[0]]->getTime();
264  double t990 = m_eclClusterArray[icMax[0]]->getDeltaTime99();
265  double t1 = m_eclClusterArray[icMax[1]]->getTime();
266  double t991 = m_eclClusterArray[icMax[1]]->getDeltaTime99();
267  double taverage = (t0 / (t990 * t990) + t1 / (t991 * t991)) / (1. / (t990 * t990) + 1. / (t991 * t991));
268  if (abs(t0 - taverage) > t990 * m_maxTime || abs(t1 - taverage) > t991 * m_maxTime) {return;}
269 
271  ClusterUtils cUtil;
272  const ROOT::Math::XYZVector clustervertex = cUtil.GetIPPosition();
273 
274  double phi0 = m_eclClusterArray[icMax[0]]->getPhi();
275  ROOT::Math::XYZVector p30;
276  VectorUtil::setMagThetaPhi(p30, maxClustE[0], theta0, phi0);
277  const ROOT::Math::PxPyPzEVector p40 = cUtil.Get4MomentumFromCluster(m_eclClusterArray[icMax[0]], clustervertex, usePhotons);
278 
279  double phi1 = m_eclClusterArray[icMax[1]]->getPhi();
280  ROOT::Math::XYZVector p31;
281  VectorUtil::setMagThetaPhi(p31, maxClustE[1], theta1, phi1);
282  const ROOT::Math::PxPyPzEVector p41 = cUtil.Get4MomentumFromCluster(m_eclClusterArray[icMax[1]], clustervertex, usePhotons);
283 
284  double pairmass = (p40 + p41).M();
285  if (pairmass < m_minPairMass) {return;}
286 
288  PCmsLabTransform boostrotate;
289  ROOT::Math::PxPyPzEVector p40COM = boostrotate.rotateLabToCms() * p40;
290  ROOT::Math::PxPyPzEVector p41COM = boostrotate.rotateLabToCms() * p41;
291  double dphi = abs(p41COM.Phi() - p40COM.Phi()) * TMath::RadToDeg();
292  if (dphi > 180.) {dphi = 360. - dphi;}
293  if (dphi < m_mindPhi) {return;}
294 
295  //------------------------------------------------------------------------
296  //** Find the most energetic crystal in each photon cluster */
297  int crysIDMax[2] = { -1, -1};
298  for (int ic = 0; ic < 2; ic++) {
299  crysIDMax[ic] = m_eclClusterArray[icMax[ic]]->getMaxECellId() - 1;
300  }
301 
302  //------------------------------------------------------------------------
304  memset(&EperCrys[0], 0, EperCrys.size()*sizeof EperCrys[0]);
305  if (!m_measureTrueEnergy) {
306  for (auto& eclDigit : m_eclDigitArray) {
307  int crysID = eclDigit.getCellId() - 1;
308  getObjectPtr<TH2F>("RawDigitAmpvsCrys")->Fill(crysID + 0.001, eclDigit.getAmp());
309 
311  EperCrys[crysID] = eclDigit.getAmp() * abs(GammaGammaECalib[crysID]) * ElectronicsCalib[crysID];
312  if (EperCrys[crysID] > 0.01) {
313  getObjectPtr<TH2F>("RawDigitTimevsCrys")->Fill(crysID + 0.001, eclDigit.getTimeFit());
314  }
315  }
316 
318  } else {
319 
320  //..getEnergyHighestCrystal() includes the leakage correction; we want raw energy.
321  for (int ic = 0; ic < 2; ic++) {
322  float undoCorrection = m_eclClusterArray[icMax[ic]]->getEnergyRaw() / m_eclClusterArray[icMax[ic]]->getEnergy(
324  EperCrys[crysIDMax[ic]] = undoCorrection * m_eclClusterArray[icMax[ic]]->getEnergyHighestCrystal();
325 
326  }
327  }
328 
329  //------------------------------------------------------------------------
330  //** Store the normalized energies of the two crystals */
331  for (int ic = 0; ic < 2; ic++) {
332  if (crysIDMax[ic] >= 0) {
334  getObjectPtr<TH2F>("EnVsCrysID")->Fill(crysIDMax[ic] + 0.001, EperCrys[crysIDMax[ic]] / abs(ExpGammaGammaE[crysIDMax[ic]]));
335  getObjectPtr<TH1F>("ExpEvsCrys")->Fill(crysIDMax[ic] + 0.001, ExpGammaGammaE[crysIDMax[ic]]);
336  getObjectPtr<TH1F>("ElecCalibvsCrys")->Fill(crysIDMax[ic] + 0.001, ElectronicsCalib[crysIDMax[ic]]);
337  getObjectPtr<TH1F>("InitialCalibvsCrys")->Fill(crysIDMax[ic] + 0.001, GammaGammaECalib[crysIDMax[ic]]);
338  getObjectPtr<TH1F>("CalibEntriesvsCrys")->Fill(crysIDMax[ic] + 0.001);
339  }
340  }
341  if (crysIDMax[0] >= 0 && crysIDMax[1] >= 0) {
342  getObjectPtr<TH1F>("TimeMinusAverage")->Fill((t0 - taverage) / t990);
343  getObjectPtr<TH1F>("TimeMinusAverage")->Fill((t1 - taverage) / t991);
344  }
345 }
Calibration collector module base class.
Class to provide momentum-related information from ECLClusters.
Definition: ClusterUtils.h:35
const ROOT::Math::PxPyPzEVector Get4MomentumFromCluster(const ECLCluster *cluster, ECLCluster::EHypothesisBit hypo)
Returns four momentum vector.
Definition: ClusterUtils.cc:25
const ROOT::Math::XYZVector GetIPPosition()
Returns default IP position from beam parameters.
Provides a type-safe way to pass members of the chargedStableSet set.
Definition: Const.h:580
EHypothesisBit
The hypothesis bits for this ECLCluster (Connected region (CR) is split using this hypothesis.
Definition: ECLCluster.h:31
@ c_nPhotons
CR is split into n photons (N1)
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.
Definition: Module.cc:214
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
Definition: Module.cc:208
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Definition: Module.h:80
Class to hold Lorentz transformations from/to CMS and boost vector.
const ROOT::Math::LorentzRotation rotateLabToCms() const
Returns Lorentz transformation from Lab to CMS.
Values of the result of a track fit with a given particle hypothesis.
double getPValue() const
Getter for Chi2 Probability of the track fit.
double getD0() const
Getter for d0.
double getTransverseMomentum() const
Getter for the absolute value of the transverse momentum at the perigee.
double getZ0() const
Getter for z0.
HitPatternCDC getHitPatternCDC() const
Getter for the hit pattern in the CDC;.
DBObjPtr< ECLCrystalCalib > m_ECLExpGammaGammaE
Expected energies from database.
double maxD0
(cm) maximum abs(D0) of a good track
double minTrkpt
(GeV/c) minimum pt of a good track
StoreArray< ECLDigit > m_eclDigitArray
Required input array of ECLDigits.
DBObjPtr< ECLCrystalCalib > m_GammaGammaECalib
Existing single crystal calibration from DB; will be updated by CAF.
bool m_requireL1
require events to satisfy a level 1 trigger (true)
double m_maxTime
maximum photon (time - <t>)/dt99 (1)
double m_mindPhi
minimum delta phi between clusters (179 deg)
StoreArray< ECLCluster > m_eclClusterArray
Required input array of ECLClusters.
StoreObjPtr< TRGSummary > m_TRGResults
dataStore TRGSummary
std::vector< float > ExpGammaGammaE
vector obtained from DB object
double thetaLabMin
Some other useful quantities.
bool storeCalib
force the input calibration constants to be saved first event
std::vector< float > EperCrys
ECL digit energy for each crystal.
void collect() override
Select events and crystals and accumulate histograms.
double m_minPairMass
minimum invariant mass of the pair of photons (9 GeV/c^2)
StoreObjPtr< EventMetaData > m_evtMetaData
dataStore EventMetaData
std::vector< float > ElectronicsCalib
vector obtained from DB object
int minCDChits
minimum CDC hits for a good track
double minpValue
minimum p value of a good track
void prepare() override
Define histograms and read payloads from DB.
double maxZ0
(cm) maximum abs(Z0) of a good track
double thetaLabMax
m_thetaLabMaxDeg converted to radians (coneversion in Module::init)
double m_thetaLabMaxDeg
maximum photon theta in lab (180 degrees)
double m_thetaLabMinDeg
Parameters to control the job.
DBObjPtr< ECLCrystalCalib > m_ElectronicsCalib
Electronics calibration from database.
bool m_measureTrueEnergy
use eclCalDigit to determine MC deposited energy (false)
std::vector< float > GammaGammaECalib
vector obtained from DB object
StoreArray< Track > m_trackArray
Required arrays.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
const int c_NCrystals
Number of crystals.
Abstract base class for different kinds of events.