9 #include <ecl/modules/eclGammaGammaECollector/eclGammaGammaECollectorModule.h>
15 #include <analysis/utility/PCmsLabTransform.h>
16 #include <analysis/ClusterUtility/ClusterUtils.h>
19 #include <framework/gearbox/Const.h>
20 #include <framework/dataobjects/EventMetaData.h>
21 #include <framework/datastore/RelationVector.h>
24 #include <mdst/dataobjects/TRGSummary.h>
25 #include <mdst/dataobjects/HitPatternCDC.h>
26 #include <mdst/dataobjects/TrackFitResult.h>
27 #include <mdst/dataobjects/Track.h>
28 #include <mdst/dataobjects/ECLCluster.h>
31 #include <ecl/dataobjects/ECLDigit.h>
32 #include <ecl/dbobjects/ECLCrystalCalib.h>
52 m_ECLExpGammaGammaE("ECLExpGammaGammaE"),
53 m_ElectronicsCalib("ECLCrystalElectronics"), m_GammaGammaECalib("ECLCrystalEnergyGammaGamma")
56 setDescription(
"Calibration Collector Module for ECL single crystal energy calibration using gamma gamma events");
57 setPropertyFlags(c_ParallelProcessingCertified);
58 addParam(
"thetaLabMinDeg", m_thetaLabMinDeg,
"miniumum photon theta in lab (degrees)", 0.);
59 addParam(
"thetaLabMaxDeg", m_thetaLabMaxDeg,
"maximum photon theta in lab (degrees)", 180.);
60 addParam(
"minPairMass", m_minPairMass,
"minimum invariant mass of the pair of photons (GeV/c^2)", 9.);
61 addParam(
"mindPhi", m_mindPhi,
"minimum delta phi between clusters (deg)", 179.);
62 addParam(
"maxTime", m_maxTime,
"maximum (time-<t>)/dt99 of photons", 1.);
63 addParam(
"measureTrueEnergy", m_measureTrueEnergy,
"use MC events to obtain expected energies",
false);
64 addParam(
"requireL1", m_requireL1,
"only use events that have a level 1 trigger",
true);
71 void eclGammaGammaECollectorModule::prepare()
75 B2INFO(
"eclGammaGammaECollector: Experiment = " << m_evtMetaData->getExperiment() <<
" run = " << m_evtMetaData->getRun());
79 auto EnVsCrysID =
new TH2F(
"EnVsCrysID",
"Normalized energy for each crystal;crystal ID;E/Expected", 8736, 0, 8736, 140, 0, 1.4);
80 registerObject<TH2F>(
"EnVsCrysID", EnVsCrysID);
82 auto ExpEvsCrys =
new TH1F(
"ExpEvsCrys",
"Sum expected energy vs crystal ID;crystal ID;Energy (GeV)", 8736, 0, 8736);
83 registerObject<TH1F>(
"ExpEvsCrys", ExpEvsCrys);
85 auto ElecCalibvsCrys =
new TH1F(
"ElecCalibvsCrys",
"Sum electronics calib const vs crystal ID;crystal ID;calibration constant",
87 registerObject<TH1F>(
"ElecCalibvsCrys", ElecCalibvsCrys);
89 auto InitialCalibvsCrys =
new TH1F(
"InitialCalibvsCrys",
90 "Sum initial gamma gamma calib const vs crystal ID;crystal ID;calibration constant", 8736, 0, 8736);
91 registerObject<TH1F>(
"InitialCalibvsCrys", InitialCalibvsCrys);
93 auto CalibEntriesvsCrys =
new TH1F(
"CalibEntriesvsCrys",
"Entries in calib vs crys histograms;crystal ID;Entries per crystal", 8736,
95 registerObject<TH1F>(
"CalibEntriesvsCrys", CalibEntriesvsCrys);
98 auto RawDigitAmpvsCrys =
new TH2F(
"RawDigitAmpvsCrys",
"Digit Amplitude vs crystal ID;crystal ID;Amplitude", 8736, 0, 8736, 200, 0,
100 registerObject<TH2F>(
"RawDigitAmpvsCrys", RawDigitAmpvsCrys);
102 auto RawDigitTimevsCrys =
new TH2F(
"RawDigitTimevsCrys",
"Digit Time vs crystal ID;crystal ID;Time", 8736, 0, 8736, 200, -2000,
104 registerObject<TH2F>(
"RawDigitTimevsCrys", RawDigitTimevsCrys);
106 auto TimeMinusAverage =
new TH1F(
"TimeMinusAverage",
"Photon time - average / dt99;(T-T_ave)/dt99 ", 100, -10, 10);
107 registerObject<TH1F>(
"TimeMinusAverage", TimeMinusAverage);
112 B2INFO(
"Input parameters to eclGammaGammaECollector:");
113 B2INFO(
"thetaLabMinDeg: " << m_thetaLabMinDeg);
114 B2INFO(
"thetaLabMaxDeg: " << m_thetaLabMaxDeg);
115 thetaLabMin = m_thetaLabMinDeg / TMath::RadToDeg();
116 thetaLabMax = m_thetaLabMaxDeg / TMath::RadToDeg();
117 B2INFO(
"minPairMass: " << m_minPairMass);
118 B2INFO(
"mindPhi: " << m_mindPhi);
119 B2INFO(
"maxTime: " << m_maxTime);
120 B2INFO(
"measureTrueEnergy: " << m_measureTrueEnergy);
121 B2INFO(
"requireL1: " << m_requireL1);
124 EperCrys.resize(8736);
128 if (m_ECLExpGammaGammaE.hasChanged()) {ExpGammaGammaE = m_ECLExpGammaGammaE->getCalibVector();}
129 if (m_ElectronicsCalib.hasChanged()) {ElectronicsCalib = m_ElectronicsCalib->getCalibVector();}
130 if (m_GammaGammaECalib.hasChanged()) {GammaGammaECalib = m_GammaGammaECalib->getCalibVector();}
133 for (
int ic = 1; ic < 9000; ic += 1000) {
134 B2INFO(
"DB constants for cellID=" << ic <<
": ExpGammaGammaE = " << ExpGammaGammaE[ic - 1] <<
" ElectronicsCalib = " <<
135 ElectronicsCalib[ic - 1]
136 <<
" GammaGammaECalib = " << GammaGammaECalib[ic - 1]);
140 for (
int crysID = 0; crysID < 8736; crysID++) {
141 if (ElectronicsCalib[crysID] <= 0) {B2FATAL(
"eclGammaGammaECollector: ElectronicsCalib = " << ElectronicsCalib[crysID] <<
" for crysID = " << crysID);}
142 if (ExpGammaGammaE[crysID] == 0) {B2FATAL(
"eclGammaGammaECollector: ExpGammaGammaE = 0 for crysID = " << crysID);}
143 if (GammaGammaECalib[crysID] == 0) {B2FATAL(
"eclGammaGammaECollector: GammaGammaECalib = 0 for crysID = " << crysID);}
148 m_trackArray.isRequired();
149 m_eclClusterArray.isRequired();
150 if (!m_measureTrueEnergy) {m_eclDigitArray.isRequired();}
157 void eclGammaGammaECollectorModule::collect()
162 for (
int crysID = 0; crysID < 8736; crysID++) {
163 getObjectPtr<TH1F>(
"ExpEvsCrys")->Fill(crysID + 0.001, ExpGammaGammaE[crysID]);
164 getObjectPtr<TH1F>(
"ElecCalibvsCrys")->Fill(crysID + 0.001, ElectronicsCalib[crysID]);
165 getObjectPtr<TH1F>(
"InitialCalibvsCrys")->Fill(crysID + 0.001, GammaGammaECalib[crysID]);
166 getObjectPtr<TH1F>(
"CalibEntriesvsCrys")->Fill(crysID + 0.001);
173 bool newConst =
false;
174 if (m_ECLExpGammaGammaE.hasChanged()) {
176 B2INFO(
"ECLExpGammaGammaE has changed, exp = " << m_evtMetaData->getExperiment() <<
" run = " << m_evtMetaData->getRun());
177 ExpGammaGammaE = m_ECLExpGammaGammaE->getCalibVector();
179 if (m_ElectronicsCalib.hasChanged()) {
181 B2INFO(
"ECLCrystalElectronics has changed, exp = " << m_evtMetaData->getExperiment() <<
" run = " << m_evtMetaData->getRun());
182 ElectronicsCalib = m_ElectronicsCalib->getCalibVector();
184 if (m_GammaGammaECalib.hasChanged()) {
186 B2INFO(
"ECLCrystalEnergyGammaGamma has changed, exp = " << m_evtMetaData->getExperiment() <<
" run = " << m_evtMetaData->getRun());
187 GammaGammaECalib = m_GammaGammaECalib->getCalibVector();
191 for (
int ic = 1; ic < 9000; ic += 1000) {
192 B2INFO(
"DB constants for cellID=" << ic <<
": ExpGammaGammaE = " << ExpGammaGammaE[ic - 1] <<
" ElectronicsCalib = " <<
193 ElectronicsCalib[ic - 1]
194 <<
" GammaGammaECalib = " << GammaGammaECalib[ic - 1]);
198 for (
int crysID = 0; crysID < 8736; crysID++) {
199 if (ElectronicsCalib[crysID] <= 0) {B2FATAL(
"eclGammaGammaECollector: ElectronicsCalib = " << ElectronicsCalib[crysID] <<
" for crysID = " << crysID);}
200 if (ExpGammaGammaE[crysID] == 0) {B2FATAL(
"eclGammaGammaECollector: ExpGammaGammaE = 0 for crysID = " << crysID);}
201 if (GammaGammaECalib[crysID] == 0) {B2FATAL(
"eclGammaGammaECollector: GammaGammaECalib = 0 for crysID = " << crysID);}
208 unsigned int L1TriggerResults = m_TRGResults->getTRGSummary(0);
209 if (L1TriggerResults == 0) {
return;}
215 for (
auto& track : m_trackArray) {
219 double z0 = temptrackFit->
getZ0();
220 double d0 = temptrackFit->
getD0();
221 double pValue = temptrackFit->
getPValue();
223 if (pt > minTrkpt && abs(z0) < maxZ0 && abs(d0) < maxD0 && pValue > minpValue && nCDChits >= minCDChits) {nGoodTrk++;}
226 if (nGoodTrk > 0) {
return;}
231 int icMax[2] = { -1, -1};
232 double maxClustE[2] = { -1., -1.};
233 int nclust = m_eclClusterArray.getEntries();
234 for (
int ic = 0; ic < nclust; ic++) {
235 if (m_eclClusterArray[ic]->hasHypothesis(usePhotons)) {
236 double eClust = m_eclClusterArray[ic]->getEnergy(usePhotons);
237 if (eClust > maxClustE[0]) {
238 maxClustE[1] = maxClustE[0];
240 maxClustE[0] = eClust;
242 }
else if (eClust > maxClustE[1]) {
243 maxClustE[1] = eClust;
252 if (icMax[0] == -1 || icMax[1] == -1) {
return;}
253 double theta0 = m_eclClusterArray[icMax[0]]->getTheta();
254 double theta1 = m_eclClusterArray[icMax[1]]->getTheta();
255 if (theta0 < thetaLabMin || theta0 > thetaLabMax || theta1 < thetaLabMin || theta1 > thetaLabMax) {
return;}
258 double t0 = m_eclClusterArray[icMax[0]]->getTime();
259 double t990 = m_eclClusterArray[icMax[0]]->getDeltaTime99();
260 double t1 = m_eclClusterArray[icMax[1]]->getTime();
261 double t991 = m_eclClusterArray[icMax[1]]->getDeltaTime99();
262 double taverage = (t0 / (t990 * t990) + t1 / (t991 * t991)) / (1. / (t990 * t990) + 1. / (t991 * t991));
263 if (abs(t0 - taverage) > t990 * m_maxTime || abs(t1 - taverage) > t991 * m_maxTime) {
return;}
269 double phi0 = m_eclClusterArray[icMax[0]]->getPhi();
270 TVector3 p30(0., 0., maxClustE[0]);
271 p30.SetTheta(theta0);
273 const TLorentzVector p40 = cUtil.
Get4MomentumFromCluster(m_eclClusterArray[icMax[0]], clustervertex, usePhotons);
275 double phi1 = m_eclClusterArray[icMax[1]]->getPhi();
276 TVector3 p31(0., 0., maxClustE[1]);
277 p31.SetTheta(theta1);
279 const TLorentzVector p41 = cUtil.
Get4MomentumFromCluster(m_eclClusterArray[icMax[1]], clustervertex, usePhotons);
281 double pairmass = (p40 + p41).M();
282 if (pairmass < m_minPairMass) {
return;}
288 double dphi = abs(p41COM.Phi() - p40COM.Phi()) * TMath::RadToDeg();
289 if (dphi > 180.) {dphi = 360. - dphi;}
290 if (dphi < m_mindPhi) {
return;}
294 int crysIDMax[2] = { -1, -1};
295 for (
int ic = 0; ic < 2; ic++) {
296 crysIDMax[ic] = m_eclClusterArray[icMax[ic]]->getMaxECellId() - 1;
301 memset(&EperCrys[0], 0, EperCrys.size()*
sizeof EperCrys[0]);
302 if (!m_measureTrueEnergy) {
303 for (
auto& eclDigit : m_eclDigitArray) {
304 int crysID = eclDigit.getCellId() - 1;
305 getObjectPtr<TH2F>(
"RawDigitAmpvsCrys")->Fill(crysID + 0.001, eclDigit.getAmp());
308 EperCrys[crysID] = eclDigit.getAmp() * abs(GammaGammaECalib[crysID]) * ElectronicsCalib[crysID];
309 if (EperCrys[crysID] > 0.01) {
310 getObjectPtr<TH2F>(
"RawDigitTimevsCrys")->Fill(crysID + 0.001, eclDigit.getTimeFit());
318 for (
int ic = 0; ic < 2; ic++) {
319 float undoCorrection = m_eclClusterArray[icMax[ic]]->getEnergyRaw() / m_eclClusterArray[icMax[ic]]->getEnergy(
320 ECLCluster::EHypothesisBit::c_nPhotons);
321 EperCrys[crysIDMax[ic]] = undoCorrection * m_eclClusterArray[icMax[ic]]->getEnergyHighestCrystal();
328 for (
int ic = 0; ic < 2; ic++) {
329 if (crysIDMax[ic] >= 0) {
331 getObjectPtr<TH2F>(
"EnVsCrysID")->Fill(crysIDMax[ic] + 0.001, EperCrys[crysIDMax[ic]] / abs(ExpGammaGammaE[crysIDMax[ic]]));
332 getObjectPtr<TH1F>(
"ExpEvsCrys")->Fill(crysIDMax[ic] + 0.001, ExpGammaGammaE[crysIDMax[ic]]);
333 getObjectPtr<TH1F>(
"ElecCalibvsCrys")->Fill(crysIDMax[ic] + 0.001, ElectronicsCalib[crysIDMax[ic]]);
334 getObjectPtr<TH1F>(
"InitialCalibvsCrys")->Fill(crysIDMax[ic] + 0.001, GammaGammaECalib[crysIDMax[ic]]);
335 getObjectPtr<TH1F>(
"CalibEntriesvsCrys")->Fill(crysIDMax[ic] + 0.001);
338 if (crysIDMax[0] >= 0 && crysIDMax[1] >= 0) {
339 getObjectPtr<TH1F>(
"TimeMinusAverage")->Fill((t0 - taverage) / t990);
340 getObjectPtr<TH1F>(
"TimeMinusAverage")->Fill((t1 - taverage) / t991);
Calibration collector module base class.
Class to provide momentum-related information from ECLClusters.
const TLorentzVector Get4MomentumFromCluster(const ECLCluster *cluster, ECLCluster::EHypothesisBit hypo)
Returns four momentum vector.
const TVector3 GetIPPosition()
Returns default IP position from beam parameters.
Provides a type-safe way to pass members of the chargedStableSet set.
EHypothesisBit
The hypothesis bits for this ECLCluster (Connected region (CR) is split using this hypothesis.
unsigned short getNHits() const
Get the total Number of CDC hits in the fit.
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;.
Calibration collector module that uses e+e- --> gamma gamma to do ECL single crystal energy calibrati...
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.