9 #include <top/modules/collectors/TOPPhotonYieldsCollectorModule.h>
10 #include <top/reconstruction_cpp/TOPTrack.h>
11 #include <top/geometry/TOPGeometryPar.h>
14 #include <framework/gearbox/Unit.h>
15 #include <framework/logging/Logger.h>
42 TOPPhotonYieldsCollectorModule::TOPPhotonYieldsCollectorModule()
45 setDescription(
"A collector for photon pixel yields aimed for PMT ageing studies and for finding optically decoupled PMT's");
46 setPropertyFlags(c_ParallelProcessingCertified);
49 addParam(
"sample", m_sample,
"sample type: one of dimuon or bhabha", std::string(
"dimuon"));
50 addParam(
"deltaEcms", m_deltaEcms,
"c.m.s energy window (half size) if sample is dimuon or bhabha", 0.1);
51 addParam(
"dr", m_dr,
"cut on POCA in r", 2.0);
52 addParam(
"dz", m_dz,
"cut on POCA in abs(z)", 4.0);
53 addParam(
"minThresholdEffi", m_minThresholdEffi,
"threshold efficiency cut to suppress unreliable calibrations", 0.7);
58 void TOPPhotonYieldsCollectorModule::prepare()
61 m_digits.isRequired();
62 m_tracks.isRequired();
63 m_extHits.isRequired();
64 m_recBunch.isRequired();
65 m_asicMask.isRequired();
66 m_associatedPDFs.isRequired();
69 if (m_sample ==
"dimuon" or m_sample ==
"bhabha") {
71 m_selector.setDeltaEcms(m_deltaEcms);
72 m_selector.setCutOnPOCA(m_dr, m_dz);
73 m_selector.setCutOnLocalZ(m_minZ, m_maxZ);
75 B2ERROR(
"Invalid sample type '" << m_sample <<
"'");
80 const int numModules = 16;
81 const int numPixels = 512;
84 auto* timeStamp =
new TProfile(
"timeStamp",
"Time stamp; ; unix time", 1, 0, 1, 0, 1.0e10,
"S");
85 registerObject<TProfile>(
"timeStamp", timeStamp);
88 auto* numTracks =
new TH1F(
"numTracks",
"Number of tracks per slot; slot number; track count", numModules, 0.5, numModules + 0.5);
89 registerObject<TH1F>(
"numTracks", numTracks);
92 for (
int slot = 1; slot <= numModules; slot++) {
93 string name = (slot < 10) ?
"signalHits_0" + to_string(slot) :
"signalHits_" + to_string(slot);
94 string title =
"Hits in signal window for slot " + to_string(slot);
95 auto h =
new TH1F(name.c_str(), title.c_str(), numPixels, 0.5, numPixels + 0.5);
96 h->SetXTitle(
"pixel number");
97 h->SetYTitle(
"hit count");
98 registerObject<TH1F>(name, h);
99 m_signalNames.push_back(name);
103 for (
int slot = 1; slot <= numModules; slot++) {
104 string name = (slot < 10) ?
"bkgHits_0" + to_string(slot) :
"bkgHits_" + to_string(slot);
105 string title =
"Hits in background window for slot " + to_string(slot);
106 auto h =
new TH1F(name.c_str(), title.c_str(), numPixels, 0.5, numPixels + 0.5);
107 h->SetXTitle(
"pixel number");
108 h->SetYTitle(
"hit count");
109 registerObject<TH1F>(name, h);
110 m_bkgNames.push_back(name);
114 for (
int slot = 1; slot <= numModules; slot++) {
115 string name = (slot < 10) ?
"activePixels_0" + to_string(slot) :
"activePixels_" + to_string(slot);
116 string title =
"Active pixels for slot " + to_string(slot);
117 auto h =
new TH1F(name.c_str(), title.c_str(), numPixels, 0.5, numPixels + 0.5);
118 h->SetXTitle(
"pixel number");
119 h->SetYTitle(
"track count");
120 registerObject<TH1F>(name, h);
121 m_activeNames.push_back(name);
125 for (
int slot = 1; slot <= numModules; slot++) {
126 string name = (slot < 10) ?
"alphaLow_0" + to_string(slot) :
"alphaLow_" + to_string(slot);
127 string title =
"Hits w/ low alpha for slot " + to_string(slot);
128 auto h =
new TH1F(name.c_str(), title.c_str(), numPixels, 0.5, numPixels + 0.5);
129 h->SetXTitle(
"pixel number");
130 h->SetYTitle(
"hit count");
131 registerObject<TH1F>(name, h);
132 m_alphaLowNames.push_back(name);
136 for (
int slot = 1; slot <= numModules; slot++) {
137 string name = (slot < 10) ?
"alphaHigh_0" + to_string(slot) :
"alphaHigh_" + to_string(slot);
138 string title =
"Hits w/ high alpha for slot " + to_string(slot);
139 auto h =
new TH1F(name.c_str(), title.c_str(), numPixels, 0.5, numPixels + 0.5);
140 h->SetXTitle(
"pixel number");
141 h->SetYTitle(
"hit count");
142 registerObject<TH1F>(name, h);
143 m_alphaHighNames.push_back(name);
147 for (
int slot = 1; slot <= numModules; slot++) {
148 string name = (slot < 10) ?
"pulseHeights_0" + to_string(slot) :
"pulseHeights_" + to_string(slot);
149 string title =
"Pulse height distributions for slot " + to_string(slot);
150 auto h =
new TH2F(name.c_str(), title.c_str(), numPixels, 0.5, numPixels + 0.5, 200, 0, 2000);
151 h->SetXTitle(
"pixel number");
152 h->SetYTitle(
"pulse height");
153 registerObject<TH2F>(name, h);
154 m_pulseHeightNames.push_back(name);
158 for (
int slot = 1; slot <= numModules; slot++) {
159 string name = (slot < 10) ?
"muonZ_0" + to_string(slot) :
"muonZ_" + to_string(slot);
160 string title =
"Track z-distribution for slot " + to_string(slot);
161 auto h =
new TH1F(name.c_str(), title.c_str(), 100, m_minZ, m_maxZ);
162 h->SetXTitle(
"local z [cm]");
163 h->SetYTitle(
"track count");
164 registerObject<TH1F>(name, h);
165 m_muonZNames.push_back(name);
171 void TOPPhotonYieldsCollectorModule::collect()
175 if (not m_recBunch->isReconstructed())
return;
179 for (
const auto& track : m_tracks) {
182 if (not trk.
isValid())
continue;
183 if (not m_selector.isSelected(trk))
continue;
186 auto timeStamp = getObjectPtr<TProfile>(
"timeStamp");
187 timeStamp->Fill(0.5, m_eventMetaData->getTime() / 1000000000);
190 auto numTracks = getObjectPtr<TH1F>(
"numTracks");
191 numTracks->Fill(slot);
193 auto muonZ = getObjectPtr<TH1F>(m_muonZNames[slot - 1]);
194 muonZ->Fill(m_selector.getLocalPosition().Z());
196 auto signalHits = getObjectPtr<TH1F>(m_signalNames[slot - 1]);
197 auto bkgHits = getObjectPtr<TH1F>(m_bkgNames[slot - 1]);
198 auto pulseHeight = getObjectPtr<TH2F>(m_pulseHeightNames[slot - 1]);
199 for (
const auto& digit : m_digits) {
200 if (digit.getModuleID() != slot)
continue;
201 if (digit.getHitQuality() != TOPDigit::c_Good)
continue;
202 if (not m_thresholdEff->isCalibrated(slot, digit.getChannel()))
continue;
203 double effi = m_thresholdEff->getThrEff(slot, digit.getChannel());
204 if (effi < m_minThresholdEffi)
continue;
205 if (std::abs(digit.getTime()) > m_timeWindow)
continue;
207 if (digit.getTime() > 0) {
208 signalHits->Fill(digit.getPixelID(), 1 / effi);
209 pulseHeight->Fill(digit.getPixelID(), digit.getPulseHeight());
211 bkgHits->Fill(digit.getPixelID(), 1 / effi);
215 auto activePixels = getObjectPtr<TH1F>(m_activeNames[slot - 1]);
216 const auto& chMapper = TOPGeometryPar::Instance()->getChannelMapper();
217 for (
int pixel = 1; pixel <= activePixels->GetNbinsX(); pixel++) {
218 unsigned channel = chMapper.getChannel(pixel);
219 if (not m_thresholdEff->isCalibrated(slot, channel))
continue;
220 if (m_thresholdEff->getThrEff(slot, channel) < m_minThresholdEffi)
continue;
221 if (m_channelMask->isActive(slot, channel) and m_asicMask->isActive(slot, channel)) activePixels->Fill(pixel);
224 if (std::abs(m_selector.getLocalPosition().Z()) > m_excludedZ) {
225 auto alphaLow = getObjectPtr<TH1F>(m_alphaLowNames[slot - 1]);
226 auto alphaHigh = getObjectPtr<TH1F>(m_alphaHighNames[slot - 1]);
227 for (
const auto& digit : m_digits) {
228 if (digit.getModuleID() != slot)
continue;
229 if (digit.getHitQuality() != TOPDigit::c_Good)
continue;
231 if (not pdf)
continue;
232 const auto* peak = pdf->getSinglePeak();
233 if (not peak)
continue;
234 double alpha = acos(std::abs(peak->kzd)) / Unit::deg;
235 if (alpha > 60)
continue;
236 if (alpha < 30) alphaLow->Fill(digit.getPixelID());
237 else alphaHigh->Fill(digit.getPixelID());
Class to store analytic PDF associated with a photon.
Reconstructed track at TOP.
bool isValid() const
Checks if track is successfully constructed.
int getModuleID() const
Returns slot ID.
Utility for the track selection - used in various calibration modules.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Abstract base class for different kinds of events.