Belle II Software development
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/gearbox/Const.h>
22#include <framework/geometry/VectorUtil.h>
23#include <mdst/dataobjects/ECLCluster.h>
24#include <mdst/dataobjects/HitPatternCDC.h>
25#include <mdst/dataobjects/Track.h>
26#include <mdst/dataobjects/TrackFitResult.h>
27#include <mdst/dataobjects/TRGSummary.h>
28
29/* ROOT headers. */
30#include <Math/Vector3D.h>
31#include <Math/Vector4D.h>
32#include <TH2F.h>
33
34using namespace std;
35using namespace Belle2;
36
37
38//-----------------------------------------------------------------
39// Register the Module
40//-----------------------------------------------------------------
41REG_MODULE(eclGammaGammaECollector);
42
43//-----------------------------------------------------------------
44// Implementation
45//-----------------------------------------------------------------
46
47//-----------------------------------------------------------------------------------------------------
48
50 m_ECLExpGammaGammaE("ECLExpGammaGammaE"),
51 m_ElectronicsCalib("ECLCrystalElectronics"), m_GammaGammaECalib("ECLCrystalEnergyGammaGamma")
52{
53 // Set module properties
54 setDescription("Calibration Collector Module for ECL single crystal energy calibration using gamma gamma events");
56 addParam("thetaLabMinDeg", m_thetaLabMinDeg, "minimum photon theta in lab (degrees)", 0.);
57 addParam("thetaLabMaxDeg", m_thetaLabMaxDeg, "maximum photon theta in lab (degrees)", 180.);
58 addParam("minPairMass", m_minPairMass, "minimum invariant mass of the pair of photons (GeV/c^2)", 9.);
59 addParam("mindPhi", m_mindPhi, "minimum delta phi between clusters (deg)", 179.);
60 addParam("maxTime", m_maxTime, "maximum (time-<t>)/dt99 of photons", 1.);
61 addParam("measureTrueEnergy", m_measureTrueEnergy, "use MC events to obtain expected energies", false);
62 addParam("requireL1", m_requireL1, "only use events that have a level 1 trigger", true);
63 addParam("expectedEnergyScale", m_expectedEnergyScale, "scale expected energies for non-4S calibration", 1.);
64
65}
66
67
68
72{
73
75 B2INFO("eclGammaGammaECollector: Experiment = " << m_evtMetaData->getExperiment() << " run = " << m_evtMetaData->getRun());
76
79 auto EnVsCrysID = new TH2F("EnVsCrysID", "Normalized energy for each crystal;crystal ID;E/Expected", ECLElementNumbers::c_NCrystals,
80 0, ECLElementNumbers::c_NCrystals, 140, 0, 1.4);
81 registerObject<TH2F>("EnVsCrysID", EnVsCrysID);
82
83 auto ExpEvsCrys = new TH1F("ExpEvsCrys", "Sum expected energy vs crystal ID;crystal ID;Energy (GeV)",
85 registerObject<TH1F>("ExpEvsCrys", ExpEvsCrys);
86
87 auto ElecCalibvsCrys = new TH1F("ElecCalibvsCrys", "Sum electronics calib const vs crystal ID;crystal ID;calibration constant",
89 registerObject<TH1F>("ElecCalibvsCrys", ElecCalibvsCrys);
90
91 auto InitialCalibvsCrys = new TH1F("InitialCalibvsCrys",
92 "Sum initial gamma gamma calib const vs crystal ID;crystal ID;calibration constant", ECLElementNumbers::c_NCrystals, 0,
94 registerObject<TH1F>("InitialCalibvsCrys", InitialCalibvsCrys);
95
96 auto CalibEntriesvsCrys = new TH1F("CalibEntriesvsCrys", "Entries in calib vs crys histograms;crystal ID;Entries per crystal",
99 registerObject<TH1F>("CalibEntriesvsCrys", CalibEntriesvsCrys);
100
102 auto RawDigitAmpvsCrys = new TH2F("RawDigitAmpvsCrys", "Digit Amplitude vs crystal ID;crystal ID;Amplitude",
104 200000);
105 registerObject<TH2F>("RawDigitAmpvsCrys", RawDigitAmpvsCrys);
106
107 auto RawDigitTimevsCrys = new TH2F("RawDigitTimevsCrys", "Digit Time vs crystal ID;crystal ID;Time", ECLElementNumbers::c_NCrystals,
108 0, ECLElementNumbers::c_NCrystals, 200, -2000,
109 2000);
110 registerObject<TH2F>("RawDigitTimevsCrys", RawDigitTimevsCrys);
111
112 auto TimeMinusAverage = new TH1F("TimeMinusAverage", "Photon time - average / dt99;(T-T_ave)/dt99 ", 100, -10, 10);
113 registerObject<TH1F>("TimeMinusAverage", TimeMinusAverage);
114
115
116 //------------------------------------------------------------------------
118 B2INFO("Input parameters to eclGammaGammaECollector:");
119 B2INFO("thetaLabMinDeg: " << m_thetaLabMinDeg);
120 B2INFO("thetaLabMaxDeg: " << m_thetaLabMaxDeg);
121 thetaLabMin = m_thetaLabMinDeg / TMath::RadToDeg();
122 thetaLabMax = m_thetaLabMaxDeg / TMath::RadToDeg();
123 B2INFO("minPairMass: " << m_minPairMass);
124 B2INFO("mindPhi: " << m_mindPhi);
125 B2INFO("maxTime: " << m_maxTime);
126 B2INFO("measureTrueEnergy: " << m_measureTrueEnergy);
127 B2INFO("requireL1: " << m_requireL1);
128 B2INFO("expectedEnergyScale: " << m_expectedEnergyScale);
129
132
135 if (m_ECLExpGammaGammaE.hasChanged()) {ExpGammaGammaE = m_ECLExpGammaGammaE->getCalibVector();}
136 if (m_ElectronicsCalib.hasChanged()) {ElectronicsCalib = m_ElectronicsCalib->getCalibVector();}
137 if (m_GammaGammaECalib.hasChanged()) {GammaGammaECalib = m_GammaGammaECalib->getCalibVector();}
138
140 for (int ic = 1; ic < 9000; ic += 1000) {
141 B2INFO("DB constants for cellID=" << ic << ": ExpGammaGammaE = " << ExpGammaGammaE[ic - 1] << " ElectronicsCalib = " <<
142 ElectronicsCalib[ic - 1]
143 << " GammaGammaECalib = " << GammaGammaECalib[ic - 1]);
144 }
145
147 for (int crysID = 0; crysID < ECLElementNumbers::c_NCrystals; crysID++) {
148 if (ElectronicsCalib[crysID] <= 0) {B2FATAL("eclGammaGammaECollector: ElectronicsCalib = " << ElectronicsCalib[crysID] << " for crysID = " << crysID);}
149 if (ExpGammaGammaE[crysID] == 0) {B2FATAL("eclGammaGammaECollector: ExpGammaGammaE = 0 for crysID = " << crysID);}
150 if (GammaGammaECalib[crysID] == 0) {B2FATAL("eclGammaGammaECollector: GammaGammaECalib = 0 for crysID = " << crysID);}
151 }
152
155 m_trackArray.isRequired();
156 m_eclClusterArray.isRequired();
157 if (!m_measureTrueEnergy) {m_eclDigitArray.isRequired();}
158
159}
160
161
165{
166
168 if (storeCalib) {
169 for (int crysID = 0; crysID < ECLElementNumbers::c_NCrystals; crysID++) {
170 getObjectPtr<TH1F>("ExpEvsCrys")->Fill(crysID + 0.001, ExpGammaGammaE[crysID]);
171 getObjectPtr<TH1F>("ElecCalibvsCrys")->Fill(crysID + 0.001, ElectronicsCalib[crysID]);
172 getObjectPtr<TH1F>("InitialCalibvsCrys")->Fill(crysID + 0.001, GammaGammaECalib[crysID]);
173 getObjectPtr<TH1F>("CalibEntriesvsCrys")->Fill(crysID + 0.001);
174 }
175 storeCalib = false;
176 }
177
180 bool newConst = false;
181 if (m_ECLExpGammaGammaE.hasChanged()) {
182 newConst = true;
183 B2INFO("ECLExpGammaGammaE has changed, exp = " << m_evtMetaData->getExperiment() << " run = " << m_evtMetaData->getRun());
184 ExpGammaGammaE = m_ECLExpGammaGammaE->getCalibVector();
185 }
186 if (m_ElectronicsCalib.hasChanged()) {
187 newConst = true;
188 B2INFO("ECLCrystalElectronics has changed, exp = " << m_evtMetaData->getExperiment() << " run = " << m_evtMetaData->getRun());
189 ElectronicsCalib = m_ElectronicsCalib->getCalibVector();
190 }
191 if (m_GammaGammaECalib.hasChanged()) {
192 newConst = true;
193 B2INFO("ECLCrystalEnergyGammaGamma has changed, exp = " << m_evtMetaData->getExperiment() << " run = " << m_evtMetaData->getRun());
194 GammaGammaECalib = m_GammaGammaECalib->getCalibVector();
195 }
196
197 if (newConst) {
198 for (int ic = 1; ic < 9000; ic += 1000) {
199 B2INFO("DB constants for cellID=" << ic << ": ExpGammaGammaE = " << ExpGammaGammaE[ic - 1] << " ElectronicsCalib = " <<
200 ElectronicsCalib[ic - 1]
201 << " GammaGammaECalib = " << GammaGammaECalib[ic - 1]);
202 }
203
205 for (int crysID = 0; crysID < ECLElementNumbers::c_NCrystals; crysID++) {
206 if (ElectronicsCalib[crysID] <= 0) {B2FATAL("eclGammaGammaECollector: ElectronicsCalib = " << ElectronicsCalib[crysID] << " for crysID = " << crysID);}
207 if (ExpGammaGammaE[crysID] == 0) {B2FATAL("eclGammaGammaECollector: ExpGammaGammaE = 0 for crysID = " << crysID);}
208 if (GammaGammaECalib[crysID] == 0) {B2FATAL("eclGammaGammaECollector: GammaGammaECalib = 0 for crysID = " << crysID);}
209 }
210 }
211
214 if (m_requireL1) {
215 unsigned int L1TriggerResults = m_TRGResults->getTRGSummary(0);
216 if (L1TriggerResults == 0) {return;}
217 }
218
219 //------------------------------------------------------------------------
221 int nGoodTrk = 0;
222 for (auto& track : m_trackArray) {
223 const TrackFitResult* temptrackFit = track.getTrackFitResult(Const::ChargedStable(211));
224 if (temptrackFit) {
225 double pt = temptrackFit->getTransverseMomentum();
226 double z0 = temptrackFit->getZ0();
227 double d0 = temptrackFit->getD0();
228 double pValue = temptrackFit->getPValue();
229 int nCDChits = temptrackFit->getHitPatternCDC().getNHits();
230 if (pt > minTrkpt && abs(z0) < maxZ0 && abs(d0) < maxD0 && pValue > minpValue && nCDChits >= minCDChits) {nGoodTrk++;}
231 }
232 }
233 if (nGoodTrk > 0) {return;}
234
235 //------------------------------------------------------------------------
238 int icMax[2] = { -1, -1};
239 double maxClustE[2] = { -1., -1.};
240 int nclust = m_eclClusterArray.getEntries();
241 for (int ic = 0; ic < nclust; ic++) {
242 if (m_eclClusterArray[ic]->hasHypothesis(usePhotons)) {
243 double eClust = m_eclClusterArray[ic]->getEnergy(usePhotons);
244 if (eClust > maxClustE[0]) {
245 maxClustE[1] = maxClustE[0];
246 icMax[1] = icMax[0];
247 maxClustE[0] = eClust;
248 icMax[0] = ic;
249 } else if (eClust > maxClustE[1]) {
250 maxClustE[1] = eClust;
251 icMax[1] = ic;
252 }
253 }
254 }
255
256 //------------------------------------------------------------------------
259 if (icMax[0] == -1 || icMax[1] == -1) {return;}
260 double theta0 = m_eclClusterArray[icMax[0]]->getTheta();
261 double theta1 = m_eclClusterArray[icMax[1]]->getTheta();
262 if (theta0 < thetaLabMin || theta0 > thetaLabMax || theta1 < thetaLabMin || theta1 > thetaLabMax) {return;}
263
265 double t0 = m_eclClusterArray[icMax[0]]->getTime();
266 double t990 = m_eclClusterArray[icMax[0]]->getDeltaTime99();
267 double t1 = m_eclClusterArray[icMax[1]]->getTime();
268 double t991 = m_eclClusterArray[icMax[1]]->getDeltaTime99();
269 double taverage = (t0 / (t990 * t990) + t1 / (t991 * t991)) / (1. / (t990 * t990) + 1. / (t991 * t991));
270 if (abs(t0 - taverage) > t990 * m_maxTime || abs(t1 - taverage) > t991 * m_maxTime) {return;}
271
273 ClusterUtils cUtil;
274 const ROOT::Math::XYZVector clustervertex = cUtil.GetIPPosition();
275
276 double phi0 = m_eclClusterArray[icMax[0]]->getPhi();
277 ROOT::Math::XYZVector p30;
278 VectorUtil::setMagThetaPhi(p30, maxClustE[0], theta0, phi0);
279 const ROOT::Math::PxPyPzEVector p40 = cUtil.Get4MomentumFromCluster(m_eclClusterArray[icMax[0]], clustervertex, usePhotons);
280
281 double phi1 = m_eclClusterArray[icMax[1]]->getPhi();
282 ROOT::Math::XYZVector p31;
283 VectorUtil::setMagThetaPhi(p31, maxClustE[1], theta1, phi1);
284 const ROOT::Math::PxPyPzEVector p41 = cUtil.Get4MomentumFromCluster(m_eclClusterArray[icMax[1]], clustervertex, usePhotons);
285
286 double pairmass = (p40 + p41).M();
287 if (pairmass < m_minPairMass) {return;}
288
290 PCmsLabTransform boostrotate;
291 ROOT::Math::PxPyPzEVector p40COM = boostrotate.rotateLabToCms() * p40;
292 ROOT::Math::PxPyPzEVector p41COM = boostrotate.rotateLabToCms() * p41;
293 double dphi = abs(p41COM.Phi() - p40COM.Phi()) * TMath::RadToDeg();
294 if (dphi > 180.) {dphi = 360. - dphi;}
295 if (dphi < m_mindPhi) {return;}
296
297 //------------------------------------------------------------------------
298 //** Find the most energetic crystal in each photon cluster */
299 int crysIDMax[2] = { -1, -1};
300 for (int ic = 0; ic < 2; ic++) {
301 crysIDMax[ic] = m_eclClusterArray[icMax[ic]]->getMaxECellId() - 1;
302 }
303
304 //------------------------------------------------------------------------
306 memset(&EperCrys[0], 0, EperCrys.size()*sizeof EperCrys[0]);
307 if (!m_measureTrueEnergy) {
308 for (auto& eclDigit : m_eclDigitArray) {
309 int crysID = eclDigit.getCellId() - 1;
310 getObjectPtr<TH2F>("RawDigitAmpvsCrys")->Fill(crysID + 0.001, eclDigit.getAmp());
311
313 EperCrys[crysID] = eclDigit.getAmp() * abs(GammaGammaECalib[crysID]) * ElectronicsCalib[crysID];
314 if (EperCrys[crysID] > 0.01) {
315 getObjectPtr<TH2F>("RawDigitTimevsCrys")->Fill(crysID + 0.001, eclDigit.getTimeFit());
316 }
317 }
318
320 } else {
321
322 //..getEnergyHighestCrystal() includes the leakage correction; we want raw energy.
323 for (int ic = 0; ic < 2; ic++) {
324 float undoCorrection = m_eclClusterArray[icMax[ic]]->getEnergyRaw() / m_eclClusterArray[icMax[ic]]->getEnergy(
326 EperCrys[crysIDMax[ic]] = undoCorrection * m_eclClusterArray[icMax[ic]]->getEnergyHighestCrystal();
327
328 }
329 }
330
331 //------------------------------------------------------------------------
332 //** Store the normalized energies of the two crystals */
333 for (int ic = 0; ic < 2; ic++) {
334 if (crysIDMax[ic] >= 0) {
336 getObjectPtr<TH2F>("EnVsCrysID")->Fill(crysIDMax[ic] + 0.001,
337 EperCrys[crysIDMax[ic]] / (m_expectedEnergyScale * abs(ExpGammaGammaE[crysIDMax[ic]])));
338 getObjectPtr<TH1F>("ExpEvsCrys")->Fill(crysIDMax[ic] + 0.001, ExpGammaGammaE[crysIDMax[ic]]);
339 getObjectPtr<TH1F>("ElecCalibvsCrys")->Fill(crysIDMax[ic] + 0.001, ElectronicsCalib[crysIDMax[ic]]);
340 getObjectPtr<TH1F>("InitialCalibvsCrys")->Fill(crysIDMax[ic] + 0.001, GammaGammaECalib[crysIDMax[ic]]);
341 getObjectPtr<TH1F>("CalibEntriesvsCrys")->Fill(crysIDMax[ic] + 0.001);
342 }
343 }
344 if (crysIDMax[0] >= 0 && crysIDMax[1] >= 0) {
345 getObjectPtr<TH1F>("TimeMinusAverage")->Fill((t0 - taverage) / t990);
346 getObjectPtr<TH1F>("TimeMinusAverage")->Fill((t1 - taverage) / t991);
347 }
348}
Calibration collector module base class.
Class to provide momentum-related information from ECLClusters.
Definition: ClusterUtils.h:36
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:589
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
eclGammaGammaECollectorModule()
Constructor: Sets the description, the properties and the parameters of the module.
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
double m_expectedEnergyScale
scale expected energies for non-4S calibration (1.)
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.
STL namespace.