11 #include <ecl/modules/eclMuMuECollector/eclMuMuECollectorModule.h>
17 #include <framework/gearbox/Const.h>
18 #include <framework/dataobjects/EventMetaData.h>
21 #include <tracking/dataobjects/ExtHit.h>
24 #include <ecl/dataobjects/ECLDigit.h>
25 #include <ecl/dataobjects/ECLCalDigit.h>
26 #include <ecl/geometry/ECLNeighbours.h>
27 #include <ecl/dbobjects/ECLCrystalCalib.h>
30 #include <mdst/dataobjects/Track.h>
31 #include <mdst/dataobjects/TRGSummary.h>
50 m_ElectronicsCalib("ECLCrystalElectronics"), m_MuMuECalib("ECLCrystalEnergyMuMu")
53 setDescription(
"Calibration Collector Module for ECL single crystal energy calibration using muons");
54 setPropertyFlags(c_ParallelProcessingCertified);
55 addParam(
"minPairMass", m_minPairMass,
"minimum invariant mass of the muon pair (GeV/c^2)", 9.0);
56 addParam(
"minTrackLength", m_minTrackLength,
"minimum extrapolated track length in the crystal (cm)", 30.);
57 addParam(
"MaxNeighbourE", m_MaxNeighbourE,
"maximum energy allowed in a neighbouring crystal (GeV)", 0.010);
58 addParam(
"thetaLabMinDeg", m_thetaLabMinDeg,
"miniumum muon theta in lab (degrees)", 17.);
59 addParam(
"thetaLabMaxDeg", m_thetaLabMaxDeg,
"maximum muon theta in lab (degrees)", 150.);
60 addParam(
"measureTrueEnergy", m_measureTrueEnergy,
"use MC events to obtain expected energies",
false);
61 addParam(
"requireL1", m_requireL1,
"only use events that have a level 1 trigger",
true);
66 void eclMuMuECollectorModule::prepare()
72 B2INFO(
"eclMuMuECollector: Experiment = " << m_evtMetaData->getExperiment() <<
" run = " << m_evtMetaData->getRun());
76 auto EnVsCrysID =
new TH2F(
"EnVsCrysID",
"Normalized energy for each crystal;crystal ID;E/Expected", 8736, 0, 8736, 120, 0.1, 2.5);
77 registerObject<TH2F>(
"EnVsCrysID", EnVsCrysID);
79 auto ExpEvsCrys =
new TH1F(
"ExpEvsCrys",
"Sum expected energy vs crystal ID;crystal ID;Energy (GeV)", 8736, 0, 8736);
80 registerObject<TH1F>(
"ExpEvsCrys", ExpEvsCrys);
82 auto ElecCalibvsCrys =
new TH1F(
"ElecCalibvsCrys",
"Sum electronics calib const vs crystal ID;crystal ID;calibration constant",
84 registerObject<TH1F>(
"ElecCalibvsCrys", ElecCalibvsCrys);
86 auto InitialCalibvsCrys =
new TH1F(
"InitialCalibvsCrys",
87 "Sum initial muon pair calib const vs crystal ID;crystal ID;calibration constant", 8736, 0, 8736);
88 registerObject<TH1F>(
"InitialCalibvsCrys", InitialCalibvsCrys);
90 auto CalibEntriesvsCrys =
new TH1F(
"CalibEntriesvsCrys",
"Entries in calib vs crys histograms;crystal ID;Entries per crystal", 8736,
92 registerObject<TH1F>(
"CalibEntriesvsCrys", CalibEntriesvsCrys);
95 auto RawDigitAmpvsCrys =
new TH2F(
"RawDigitAmpvsCrys",
"Digit Amplitude vs crystal ID;crystal ID;Amplitude", 8736, 0, 8736, 250, 0,
97 registerObject<TH2F>(
"RawDigitAmpvsCrys", RawDigitAmpvsCrys);
99 auto RawDigitTimevsCrys =
new TH2F(
"RawDigitTimevsCrys",
"Digit Time vs crystal ID;crystal ID;Time", 8736, 0, 8736, 200, -2000,
101 registerObject<TH2F>(
"RawDigitTimevsCrys", RawDigitTimevsCrys);
112 B2INFO(
"Input parameters to eclMuMuECollector:");
113 B2INFO(
"minPairMass: " << m_minPairMass);
114 B2INFO(
"minTrackLength: " << m_minTrackLength);
115 B2INFO(
"MaxNeighbourE: " << m_MaxNeighbourE);
116 B2INFO(
"thetaLabMinDeg: " << m_thetaLabMinDeg);
117 B2INFO(
"thetaLabMaxDeg: " << m_thetaLabMaxDeg);
118 if (m_thetaLabMinDeg < 1.) {
119 cotThetaLabMax = 9999.;
120 }
else if (m_thetaLabMinDeg > 179.) {
121 cotThetaLabMax = -9999.;
123 double thetaLabMin = m_thetaLabMinDeg * TMath::Pi() / 180.;
124 cotThetaLabMax = 1. / tan(thetaLabMin);
126 if (m_thetaLabMaxDeg < 1.) {
127 cotThetaLabMin = 9999.;
128 }
else if (m_thetaLabMaxDeg > 179.) {
129 cotThetaLabMin = -9999.;
131 double thetaLabMax = m_thetaLabMaxDeg * TMath::Pi() / 180.;
132 cotThetaLabMin = 1. / tan(thetaLabMax);
134 B2INFO(
"cotThetaLabMin: " << cotThetaLabMin);
135 B2INFO(
"cotThetaLabMax: " << cotThetaLabMax);
136 B2INFO(
"measureTrueEnergy: " << m_measureTrueEnergy);
137 B2INFO(
"requireL1: " << m_requireL1);
140 EperCrys.resize(8736);
144 if (m_ECLExpMuMuE.hasChanged()) {ExpMuMuE = m_ECLExpMuMuE->getCalibVector();}
145 if (m_ElectronicsCalib.hasChanged()) {ElectronicsCalib = m_ElectronicsCalib->getCalibVector();}
146 if (m_MuMuECalib.hasChanged()) {MuMuECalib = m_MuMuECalib->getCalibVector();}
149 for (
int ic = 1; ic < 9000; ic += 1000) {
150 B2INFO(
"DB constants for cellID=" << ic <<
": ExpMuMuE = " << ExpMuMuE[ic - 1] <<
" ElectronicsCalib = " << ElectronicsCalib[ic - 1]
151 <<
" MuMuECalib = " << MuMuECalib[ic - 1]);
155 for (
int crysID = 0; crysID < 8736; crysID++) {
156 if (ElectronicsCalib[crysID] <= 0) {B2FATAL(
"eclMuMuECollector: ElectronicsCalib = " << ElectronicsCalib[crysID] <<
" for crysID = " << crysID);}
157 if (ExpMuMuE[crysID] == 0) {B2FATAL(
"eclMuMuECollector: ExpMuMuE = 0 for crysID = " << crysID);}
158 if (MuMuECalib[crysID] == 0) {B2FATAL(
"eclMuMuECollector: MuMuECalib = 0 for crysID = " << crysID);}
163 m_trackArray.isRequired();
164 m_eclDigitArray.isRequired();
171 void eclMuMuECollectorModule::collect()
176 for (
int crysID = 0; crysID < 8736; crysID++) {
177 getObjectPtr<TH1F>(
"ExpEvsCrys")->Fill(crysID + 0.001, ExpMuMuE[crysID]);
178 getObjectPtr<TH1F>(
"ElecCalibvsCrys")->Fill(crysID + 0.001, ElectronicsCalib[crysID]);
179 getObjectPtr<TH1F>(
"InitialCalibvsCrys")->Fill(crysID + 0.001, MuMuECalib[crysID]);
180 getObjectPtr<TH1F>(
"CalibEntriesvsCrys")->Fill(crysID + 0.001);
184 if (iEvent % 10000 == 0) {B2INFO(
"eclMuMuECollector: iEvent = " << iEvent);}
189 bool newConst =
false;
190 if (m_ECLExpMuMuE.hasChanged()) {
192 B2INFO(
"ECLExpMuMuE has changed, exp = " << m_evtMetaData->getExperiment() <<
" run = " << m_evtMetaData->getRun());
193 ExpMuMuE = m_ECLExpMuMuE->getCalibVector();
195 if (m_ElectronicsCalib.hasChanged()) {
197 B2INFO(
"ECLCrystalElectronics has changed, exp = " << m_evtMetaData->getExperiment() <<
" run = " << m_evtMetaData->getRun());
198 ElectronicsCalib = m_ElectronicsCalib->getCalibVector();
200 if (m_MuMuECalib.hasChanged()) {
202 B2INFO(
"ECLCrystalEnergyMuMu has changed, exp = " << m_evtMetaData->getExperiment() <<
" run = " << m_evtMetaData->getRun());
203 MuMuECalib = m_MuMuECalib->getCalibVector();
207 for (
int ic = 1; ic < 9000; ic += 1000) {
208 B2INFO(
"DB constants for cellID=" << ic <<
": ExpMuMuE = " << ExpMuMuE[ic - 1] <<
" ElectronicsCalib = " <<
209 ElectronicsCalib[ic - 1]
210 <<
" MuMuECalib = " << MuMuECalib[ic - 1]);
214 for (
int crysID = 0; crysID < 8736; crysID++) {
215 if (ElectronicsCalib[crysID] <= 0) {B2FATAL(
"eclMuMuECollector: ElectronicsCalib = " << ElectronicsCalib[crysID] <<
" for crysID = " << crysID);}
216 if (ExpMuMuE[crysID] == 0) {B2FATAL(
"eclMuMuECollector: ExpMuMuE = 0 for crysID = " << crysID);}
217 if (MuMuECalib[crysID] == 0) {B2FATAL(
"eclMuMuECollector: MuMuECalib = 0 for crysID = " << crysID);}
226 unsigned int L1TriggerResults = m_TRGResults->getTRGSummary(0);
227 if (L1TriggerResults == 0) {
return;}
232 int nTrack = m_trackArray.getEntries();
233 if (nTrack < 2) {
return;}
236 double maxpt[2] = {0., 0.};
237 int iTrack[2] = { -1, -1};
238 for (
int it = 0; it < nTrack; it++) {
240 if (not temptrackFit) {
continue;}
242 if (temptrackFit->getChargeSign() == 1) {imu = 1; }
245 double cotThetaLab = temptrackFit->getCotTheta();
246 if (temppt > maxpt[imu] && cotThetaLab > cotThetaLabMin && cotThetaLab < cotThetaLabMax) {
253 if (iTrack[0] == -1 || iTrack[1] == -1) {
return; }
256 TLorentzVector mu0 = m_trackArray[iTrack[0]]->getTrackFitResult(
Const::ChargedStable(211))->get4Momentum();
257 TLorentzVector mu1 = m_trackArray[iTrack[1]]->getTrackFitResult(
Const::ChargedStable(211))->get4Momentum();
258 if ((mu0 + mu1).M() < m_minPairMass) {
return; }
262 int extCrysID[2] = { -1, -1};
264 for (
int imu = 0; imu < 2; imu++) {
265 TVector3 temppos[2] = {};
267 for (
auto& extHit : m_trackArray[iTrack[imu]]->getRelationsTo<ExtHit>()) {
268 int pdgCode = extHit.getPdgCode();
270 int temp0 = extHit.getCopyID();
273 if (detectorID == eclID && TMath::Abs(pdgCode) == 13 && extHit.getStatus() == EXT_ENTER) {
275 temppos[0] = extHit.getPosition();
279 if (detectorID == eclID && TMath::Abs(pdgCode) == 13 && extHit.getStatus() == EXT_EXIT && temp0 == IDEnter) {
280 temppos[1] = extHit.getPosition();
283 double trackLength = (temppos[1] - temppos[0]).Mag();
284 if (trackLength > m_minTrackLength) {extCrysID[imu] = temp0;}
291 if (extCrysID[0] == -1 && extCrysID[1] == -1) {
return; }
295 memset(&EperCrys[0], 0, EperCrys.size()*
sizeof EperCrys[0]);
296 for (
auto& eclDigit : m_eclDigitArray) {
297 int crysID = eclDigit.getCellId() - 1;
298 getObjectPtr<TH2F>(
"RawDigitAmpvsCrys")->Fill(crysID + 0.001, eclDigit.getAmp());
301 EperCrys[crysID] = eclDigit.getAmp() * abs(MuMuECalib[crysID]) * ElectronicsCalib[crysID];
302 if (EperCrys[crysID] > 0.01) {
303 getObjectPtr<TH2F>(
"RawDigitTimevsCrys")->Fill(crysID + 0.001, eclDigit.getTimeFit());
308 if (m_measureTrueEnergy) {
310 for (
auto& eclCalDigit : m_eclCalDigitArray) {
311 int tempCrysID = eclCalDigit.getCellId() - 1;
312 EperCrys[tempCrysID] = eclCalDigit.getEnergy();
318 for (
int imu = 0; imu < 2; imu++) {
319 int crysID = extCrysID[imu];
320 int cellID = crysID + 1;
323 bool noNeighbourSignal =
true;
324 if (cellID >= firstcellIDN4 && crysID <= lastcellIDN4) {
325 for (
const auto& tempCellID : myNeighbours4->getNeighbours(cellID)) {
326 int tempCrysID = tempCellID - 1;
327 if (tempCellID != cellID && EperCrys[tempCrysID] > m_MaxNeighbourE) {
328 noNeighbourSignal =
false;
333 for (
const auto& tempCellID : myNeighbours8->getNeighbours(cellID)) {
334 int tempCrysID = tempCellID - 1;
335 if (tempCellID != cellID && EperCrys[tempCrysID] > m_MaxNeighbourE) {
336 noNeighbourSignal =
false;
343 if (noNeighbourSignal) {
346 getObjectPtr<TH2F>(
"EnVsCrysID")->Fill(crysID + 0.001, EperCrys[crysID] / abs(ExpMuMuE[crysID]));
347 getObjectPtr<TH1F>(
"ExpEvsCrys")->Fill(crysID + 0.001, ExpMuMuE[crysID]);
348 getObjectPtr<TH1F>(
"ElecCalibvsCrys")->Fill(crysID + 0.001, ElectronicsCalib[crysID]);
349 getObjectPtr<TH1F>(
"InitialCalibvsCrys")->Fill(crysID + 0.001, MuMuECalib[crysID]);
350 getObjectPtr<TH1F>(
"CalibEntriesvsCrys")->Fill(crysID + 0.001);