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 TrkPerCrysID =
new TH1F(
"TrkPerCrysID",
"track extrapolations per crystalID;crystal ID", 8736, 0, 8736);
77 registerObject<TH1F>(
"TrkPerCrysID", TrkPerCrysID);
79 auto EnVsCrysID =
new TH2F(
"EnVsCrysID",
"Normalized energy for each crystal;crystal ID;E/Expected", 8736, 0, 8736, 120, 0.1, 2.5);
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 muon pair 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, 250, 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);
107 auto hitCrysVsExtrapolatedCrys =
new TH2F(
"hitCrysVsExtrapolatedCrys",
108 "Crystals with high energy vs extrapolated crystals with no energy;extrapolated crystalID;High crystalID", 8736, 0, 8736, 8736, 0,
110 registerObject<TH2F>(
"hitCrysVsExtrapolatedCrys", hitCrysVsExtrapolatedCrys);
121 B2INFO(
"Input parameters to eclMuMuECollector:");
122 B2INFO(
"minPairMass: " << m_minPairMass);
123 B2INFO(
"minTrackLength: " << m_minTrackLength);
124 B2INFO(
"MaxNeighbourE: " << m_MaxNeighbourE);
125 B2INFO(
"thetaLabMinDeg: " << m_thetaLabMinDeg);
126 B2INFO(
"thetaLabMaxDeg: " << m_thetaLabMaxDeg);
127 if (m_thetaLabMinDeg < 1.) {
128 cotThetaLabMax = 9999.;
129 }
else if (m_thetaLabMinDeg > 179.) {
130 cotThetaLabMax = -9999.;
132 double thetaLabMin = m_thetaLabMinDeg * TMath::Pi() / 180.;
133 cotThetaLabMax = 1. / tan(thetaLabMin);
135 if (m_thetaLabMaxDeg < 1.) {
136 cotThetaLabMin = 9999.;
137 }
else if (m_thetaLabMaxDeg > 179.) {
138 cotThetaLabMin = -9999.;
140 double thetaLabMax = m_thetaLabMaxDeg * TMath::Pi() / 180.;
141 cotThetaLabMin = 1. / tan(thetaLabMax);
143 B2INFO(
"cotThetaLabMin: " << cotThetaLabMin);
144 B2INFO(
"cotThetaLabMax: " << cotThetaLabMax);
145 B2INFO(
"measureTrueEnergy: " << m_measureTrueEnergy);
146 B2INFO(
"requireL1: " << m_requireL1);
149 EperCrys.resize(8736);
153 if (m_ECLExpMuMuE.hasChanged()) {ExpMuMuE = m_ECLExpMuMuE->getCalibVector();}
154 if (m_ElectronicsCalib.hasChanged()) {ElectronicsCalib = m_ElectronicsCalib->getCalibVector();}
155 if (m_MuMuECalib.hasChanged()) {MuMuECalib = m_MuMuECalib->getCalibVector();}
158 for (
int ic = 1; ic < 9000; ic += 1000) {
159 B2INFO(
"DB constants for cellID=" << ic <<
": ExpMuMuE = " << ExpMuMuE[ic - 1] <<
" ElectronicsCalib = " << ElectronicsCalib[ic - 1]
160 <<
" MuMuECalib = " << MuMuECalib[ic - 1]);
164 for (
int crysID = 0; crysID < 8736; crysID++) {
165 if (ElectronicsCalib[crysID] <= 0) {B2FATAL(
"eclMuMuECollector: ElectronicsCalib = " << ElectronicsCalib[crysID] <<
" for crysID = " << crysID);}
166 if (ExpMuMuE[crysID] == 0) {B2FATAL(
"eclMuMuECollector: ExpMuMuE = 0 for crysID = " << crysID);}
167 if (MuMuECalib[crysID] == 0) {B2FATAL(
"eclMuMuECollector: MuMuECalib = 0 for crysID = " << crysID);}
172 m_trackArray.isRequired();
173 m_eclDigitArray.isRequired();
180 void eclMuMuECollectorModule::collect()
185 for (
int crysID = 0; crysID < 8736; crysID++) {
186 getObjectPtr<TH1F>(
"ExpEvsCrys")->Fill(crysID + 0.001, ExpMuMuE[crysID]);
187 getObjectPtr<TH1F>(
"ElecCalibvsCrys")->Fill(crysID + 0.001, ElectronicsCalib[crysID]);
188 getObjectPtr<TH1F>(
"InitialCalibvsCrys")->Fill(crysID + 0.001, MuMuECalib[crysID]);
189 getObjectPtr<TH1F>(
"CalibEntriesvsCrys")->Fill(crysID + 0.001);
193 if (iEvent % 10000 == 0) {B2INFO(
"eclMuMuECollector: iEvent = " << iEvent);}
198 bool newConst =
false;
199 if (m_ECLExpMuMuE.hasChanged()) {
201 B2INFO(
"ECLExpMuMuE has changed, exp = " << m_evtMetaData->getExperiment() <<
" run = " << m_evtMetaData->getRun());
202 ExpMuMuE = m_ECLExpMuMuE->getCalibVector();
204 if (m_ElectronicsCalib.hasChanged()) {
206 B2INFO(
"ECLCrystalElectronics has changed, exp = " << m_evtMetaData->getExperiment() <<
" run = " << m_evtMetaData->getRun());
207 ElectronicsCalib = m_ElectronicsCalib->getCalibVector();
209 if (m_MuMuECalib.hasChanged()) {
211 B2INFO(
"ECLCrystalEnergyMuMu has changed, exp = " << m_evtMetaData->getExperiment() <<
" run = " << m_evtMetaData->getRun());
212 MuMuECalib = m_MuMuECalib->getCalibVector();
216 for (
int ic = 1; ic < 9000; ic += 1000) {
217 B2INFO(
"DB constants for cellID=" << ic <<
": ExpMuMuE = " << ExpMuMuE[ic - 1] <<
" ElectronicsCalib = " <<
218 ElectronicsCalib[ic - 1]
219 <<
" MuMuECalib = " << MuMuECalib[ic - 1]);
223 for (
int crysID = 0; crysID < 8736; crysID++) {
224 if (ElectronicsCalib[crysID] <= 0) {B2FATAL(
"eclMuMuECollector: ElectronicsCalib = " << ElectronicsCalib[crysID] <<
" for crysID = " << crysID);}
225 if (ExpMuMuE[crysID] == 0) {B2FATAL(
"eclMuMuECollector: ExpMuMuE = 0 for crysID = " << crysID);}
226 if (MuMuECalib[crysID] == 0) {B2FATAL(
"eclMuMuECollector: MuMuECalib = 0 for crysID = " << crysID);}
235 unsigned int L1TriggerResults = m_TRGResults->getTRGSummary(0);
236 if (L1TriggerResults == 0) {
return;}
241 int nTrack = m_trackArray.getEntries();
242 if (nTrack < 2) {
return;}
245 double maxpt[2] = {0., 0.};
246 int iTrack[2] = { -1, -1};
247 for (
int it = 0; it < nTrack; it++) {
249 if (not temptrackFit) {
continue;}
251 if (temptrackFit->getChargeSign() == 1) {imu = 1; }
254 double cotThetaLab = temptrackFit->getCotTheta();
255 if (temppt > maxpt[imu] && cotThetaLab > cotThetaLabMin && cotThetaLab < cotThetaLabMax) {
262 if (iTrack[0] == -1 || iTrack[1] == -1) {
return; }
265 TLorentzVector mu0 = m_trackArray[iTrack[0]]->getTrackFitResult(
Const::ChargedStable(211))->get4Momentum();
266 TLorentzVector mu1 = m_trackArray[iTrack[1]]->getTrackFitResult(
Const::ChargedStable(211))->get4Momentum();
267 if ((mu0 + mu1).M() < m_minPairMass) {
return; }
271 int extCrysID[2] = { -1, -1};
273 for (
int imu = 0; imu < 2; imu++) {
274 TVector3 temppos[2] = {};
276 for (
auto& extHit : m_trackArray[iTrack[imu]]->getRelationsTo<ExtHit>()) {
277 int pdgCode = extHit.getPdgCode();
279 int temp0 = extHit.getCopyID();
282 if (detectorID == eclID && TMath::Abs(pdgCode) == Const::muon.getPDGCode() && extHit.getStatus() == EXT_ENTER) {
284 temppos[0] = extHit.getPosition();
288 if (detectorID == eclID && TMath::Abs(pdgCode) == Const::muon.getPDGCode() && extHit.getStatus() == EXT_EXIT && temp0 == IDEnter) {
289 temppos[1] = extHit.getPosition();
292 double trackLength = (temppos[1] - temppos[0]).Mag();
293 if (trackLength > m_minTrackLength) {extCrysID[imu] = temp0;}
300 if (extCrysID[0] == -1 && extCrysID[1] == -1) {
return; }
304 memset(&EperCrys[0], 0, EperCrys.size()*
sizeof EperCrys[0]);
307 const double highEnergyThresh = 0.18;
308 std::vector<int> highECrys;
310 for (
auto& eclDigit : m_eclDigitArray) {
311 int crysID = eclDigit.getCellId() - 1;
312 getObjectPtr<TH2F>(
"RawDigitAmpvsCrys")->Fill(crysID + 0.001, eclDigit.getAmp());
315 EperCrys[crysID] = eclDigit.getAmp() * abs(MuMuECalib[crysID]) * ElectronicsCalib[crysID];
316 if (EperCrys[crysID] > highEnergyThresh) {highECrys.push_back(crysID);}
317 if (EperCrys[crysID] > 0.01) {
318 getObjectPtr<TH2F>(
"RawDigitTimevsCrys")->Fill(crysID + 0.001, eclDigit.getTimeFit());
323 if (m_measureTrueEnergy) {
325 for (
auto& eclCalDigit : m_eclCalDigitArray) {
326 int tempCrysID = eclCalDigit.getCellId() - 1;
327 EperCrys[tempCrysID] = eclCalDigit.getEnergy();
334 for (
int imu = 0; imu < 2; imu++) {
335 int crysID = extCrysID[imu];
336 int cellID = crysID + 1;
339 getObjectPtr<TH1F>(
"TrkPerCrysID")->Fill(crysID + 0.001);
341 bool noNeighbourSignal =
true;
342 bool highNeighourSignal =
false;
343 if (cellID >= firstcellIDN4 && crysID <= lastcellIDN4) {
344 for (
const auto& tempCellID : myNeighbours4->getNeighbours(cellID)) {
345 int tempCrysID = tempCellID - 1;
346 if (tempCellID != cellID && EperCrys[tempCrysID] > m_MaxNeighbourE) {
347 noNeighbourSignal =
false;
348 if (EperCrys[tempCrysID] > highEnergyThresh) {highNeighourSignal =
true;}
352 for (
const auto& tempCellID : myNeighbours8->getNeighbours(cellID)) {
353 int tempCrysID = tempCellID - 1;
354 if (tempCellID != cellID && EperCrys[tempCrysID] > m_MaxNeighbourE) {
355 noNeighbourSignal =
false;
356 if (EperCrys[tempCrysID] > highEnergyThresh) {highNeighourSignal =
true;}
362 if (noNeighbourSignal) {
365 getObjectPtr<TH2F>(
"EnVsCrysID")->Fill(crysID + 0.001, EperCrys[crysID] / abs(ExpMuMuE[crysID]));
366 getObjectPtr<TH1F>(
"ExpEvsCrys")->Fill(crysID + 0.001, ExpMuMuE[crysID]);
367 getObjectPtr<TH1F>(
"ElecCalibvsCrys")->Fill(crysID + 0.001, ElectronicsCalib[crysID]);
368 getObjectPtr<TH1F>(
"InitialCalibvsCrys")->Fill(crysID + 0.001, MuMuECalib[crysID]);
369 getObjectPtr<TH1F>(
"CalibEntriesvsCrys")->Fill(crysID + 0.001);
373 if (highNeighourSignal or (noNeighbourSignal and EperCrys[crysID] < m_MaxNeighbourE)) {
374 for (
auto&
id : highECrys) {
375 getObjectPtr<TH2F>(
"hitCrysVsExtrapolatedCrys")->Fill(crysID + 0.0001,
id + 0.0001);