9 #include <top/modules/TOPChannelT0Calibrator/TOPChannelT0CalibratorModule.h>
10 #include <top/geometry/TOPGeometryPar.h>
11 #include <top/reconstruction_cpp/TOPTrack.h>
12 #include <top/reconstruction_cpp/PDFConstructor.h>
13 #include <top/reconstruction_cpp/TOPRecoManager.h>
14 #include <framework/dataobjects/EventMetaData.h>
15 #include <framework/gearbox/Const.h>
16 #include <framework/logging/Logger.h>
42 setDescription(
"Alternative channel T0 calibration with dimuons or bhabhas. "
43 "This module can also be used to check the calibration "
44 "(channel, module and common T0).\n"
45 "Note: after this kind of calibration one cannot do the alignment.");
49 addParam(
"numBins", m_numBins,
"number of bins of the search region", 200);
50 addParam(
"timeRange", m_timeRange,
51 "time range in which to search for the minimum [ns]", 10.0);
52 addParam(
"sigmaSmear", m_sigmaSmear,
53 "sigma in [ns] for additional smearing of PDF", 0.0);
54 addParam(
"sample", m_sample,
55 "sample type: one of dimuon, bhabha or cosmics", std::string(
"dimuon"));
56 addParam(
"minMomentum", m_minMomentum,
57 "minimal track momentum if sample is cosmics", 1.0);
58 addParam(
"deltaEcms", m_deltaEcms,
59 "c.m.s energy window (half size) if sample is dimuon or bhabha", 0.1);
60 addParam(
"dr", m_dr,
"cut on POCA in r", 2.0);
61 addParam(
"dz", m_dz,
"cut on POCA in abs(z)", 4.0);
62 addParam(
"minZ", m_minZ,
63 "minimal local z of extrapolated hit", -130.0);
64 addParam(
"maxZ", m_maxZ,
65 "maximal local z of extrapolated hit", 130.0);
66 addParam(
"outputFileName", m_outFileName,
67 "Root output file name containing calibration results. "
68 "File name can include *'s; "
69 "they will be replaced with a run number from the first input file",
70 std::string(
"calibrationT0_r*.root"));
71 addParam(
"pdfOption", m_pdfOption,
72 "PDF option, one of 'rough', 'fine', 'optimal'", std::string(
"rough"));
76 void TOPChannelT0CalibratorModule::initialize()
79 m_digits.isRequired();
80 m_tracks.isRequired();
81 m_extHits.isRequired();
82 m_recBunch.isOptional();
85 if (m_pdfOption ==
"rough") {
86 m_PDFOption = PDFConstructor::c_Rough;
87 }
else if (m_pdfOption ==
"fine") {
88 m_PDFOption = PDFConstructor::c_Fine;
89 }
else if (m_pdfOption ==
"optimal") {
90 m_PDFOption = PDFConstructor::c_Optimal;
92 B2ERROR(
"TOPPDFDebuggerModule: unknown PDF option '" << m_pdfOption <<
"'");
97 m_selector.setMinMomentum(m_minMomentum);
98 m_selector.setDeltaEcms(m_deltaEcms);
99 m_selector.setCutOnPOCA(m_dr, m_dz);
100 m_selector.setCutOnLocalZ(m_minZ, m_maxZ);
103 double tmin = -m_timeRange / 2;
104 double tmax = m_timeRange / 2;
105 for (
unsigned i = 0; i < 2; i++) {
106 for (
unsigned m = 0; m < c_numModules; m++) {
107 for (
unsigned c = 0; c < c_numChannels; c++) {
114 auto pos = m_outFileName.find(
"*");
115 if (pos != std::string::npos) {
117 auto run = std::to_string(evtMetaData->getRun());
118 while (run.size() < 5) run =
"0" + run;
119 while (pos != std::string::npos) {
120 m_outFileName.replace(pos, 1, run);
121 pos = m_outFileName.find(
"*");
126 m_file = TFile::Open(m_outFileName.c_str(),
"RECREATE");
128 B2ERROR(
"Cannot open output file '" << m_outFileName <<
"'");
133 for (
unsigned module = 0; module < c_numModules; module++) {
134 int moduleID = module + 1;
136 std::string slotNum = std::to_string(moduleID);
137 if (moduleID < 10) slotNum =
"0" + slotNum;
139 std::string name =
"numHits_slot" + slotNum;
140 std::string title =
"Number of hits per channel for slot " + slotNum;
141 TH1F h1(name.c_str(), title.c_str(), c_numChannels, 0, c_numChannels);
142 h1.SetXTitle(
"channel number");
143 h1.SetYTitle(
"hits per channel");
144 m_hits1D.push_back(h1);
146 name =
"timeHits_slot" + slotNum;
147 title =
"hit time vs. channel for slot " + slotNum;
148 TH2F h2(name.c_str(), title.c_str(), c_numChannels, 0, c_numChannels,
150 h2.SetXTitle(
"channel number");
151 h2.SetYTitle(
"time [ns]");
152 m_hits2D.push_back(h2);
157 m_tree =
new TTree(
"tree",
"Channel T0 calibration results");
158 m_tree->Branch(
"slot", &m_moduleID);
159 m_tree->Branch(
"numPhotons", &m_numPhotons);
160 m_tree->Branch(
"x", &m_x);
161 m_tree->Branch(
"y", &m_y);
162 m_tree->Branch(
"z", &m_z);
163 m_tree->Branch(
"p", &m_p);
164 m_tree->Branch(
"theta", &m_theta);
165 m_tree->Branch(
"phi", &m_phi);
166 m_tree->Branch(
"r_poca", &m_pocaR);
167 m_tree->Branch(
"z_poca", &m_pocaZ);
168 m_tree->Branch(
"x_poca", &m_pocaX);
169 m_tree->Branch(
"y_poca", &m_pocaY);
170 m_tree->Branch(
"Ecms", &m_cmsE);
171 m_tree->Branch(
"charge", &m_charge);
172 m_tree->Branch(
"PDG", &m_PDG);
176 void TOPChannelT0CalibratorModule::event()
183 if (m_recBunch.isValid()) {
184 if (not m_recBunch->isReconstructed())
return;
187 TOPRecoManager::setDefaultTimeWindow();
188 double timeMin = TOPRecoManager::getMinTime();
189 double timeMax = TOPRecoManager::getMaxTime();
190 const auto& chMapper = TOPGeometryPar::Instance()->getChannelMapper();
194 for (
const auto& track : m_tracks) {
198 if (not trk.
isValid())
continue;
200 if (not m_selector.isSelected(trk))
continue;
203 PDFConstructor pdfConstructor(trk, m_selector.getChargedStable(), m_PDFOption);
204 if (not pdfConstructor.
isValid())
continue;
208 if (module >= c_numModules)
continue;
209 int sub = gRandom->Integer(2);
210 auto& finders = m_finders[sub][module];
211 const auto& binCenters = finders[0].getBinCenters();
212 for (
unsigned ibin = 0; ibin < binCenters.size(); ibin++) {
213 double t0 = binCenters[ibin];
214 const auto& pixelLogLs = pdfConstructor.
getPixelLogLs(t0, m_sigmaSmear);
215 for (
unsigned channel = 0; channel < c_numChannels; channel++) {
216 int pix = chMapper.getPixelID(channel) - 1;
217 finders[channel].add(ibin, -2 * pixelLogLs[pix].logL);
223 for (
const auto& digit : m_digits) {
224 if (digit.getHitQuality() != TOPDigit::c_Good)
continue;
225 if (digit.getModuleID() != trk.
getModuleID())
continue;
226 if (digit.getTime() < timeMin)
continue;
227 if (digit.getTime() > timeMax)
continue;
229 auto& h1 = m_hits1D[module];
230 h1.Fill(digit.getChannel());
231 auto& h2 = m_hits2D[module];
232 h2.Fill(digit.getChannel(), digit.getTime());
237 const auto& localPosition = m_selector.getLocalPosition();
238 m_x = localPosition.X();
239 m_y = localPosition.Y();
240 m_z = localPosition.Z();
241 const auto& localMomentum = m_selector.getLocalMomentum();
242 m_p = localMomentum.Mag();
243 m_theta = localMomentum.Theta();
244 m_phi = localMomentum.Phi();
245 const auto& pocaPosition = m_selector.getPOCAPosition();
246 m_pocaR = pocaPosition.Perp();
247 m_pocaZ = pocaPosition.Z();
248 m_pocaX = pocaPosition.X();
249 m_pocaY = pocaPosition.Y();
250 m_cmsE = m_selector.getCMSEnergy();
259 void TOPChannelT0CalibratorModule::terminate()
264 TH1F h_pulls(
"pulls",
"Pulls of the two statistically independent results",
266 h_pulls.SetXTitle(
"pulls");
267 for (
unsigned module = 0; module < c_numModules; module++) {
268 for (
unsigned channel = 0; channel < c_numChannels; channel++) {
269 std::vector<double> pos, err;
270 for (
int i = 0; i < 2; i++) {
271 const auto& minimum = m_finders[i][module][channel].getMinimum();
272 if (not minimum.valid)
continue;
273 pos.push_back(minimum.position);
274 err.push_back(minimum.error);
276 if (pos.size() < 2)
continue;
277 double pull = (pos[0] - pos[1]) / sqrt(err[0] * err[0] + err[1] * err[1]);
282 double scaleError = h_pulls.GetRMS();
286 for (
unsigned module = 0; module < c_numModules; module++) {
287 int moduleID = module + 1;
289 std::string slotNum = std::to_string(moduleID);
290 if (moduleID < 10) slotNum =
"0" + slotNum;
292 std::string name =
"channelT0_slot" + slotNum;
293 std::string title =
"Relative channel T0 for slot " + slotNum;
294 TH1F h_channelT0(name.c_str(), title.c_str(), c_numChannels, 0, c_numChannels);
295 h_channelT0.SetXTitle(
"channel number");
296 h_channelT0.SetYTitle(
"relative channel T0 [ns]");
298 for (
unsigned channel = 0; channel < c_numChannels; channel++) {
299 auto& finder = m_finders[0][module][channel].add(m_finders[1][module][channel]);
300 const auto& minimum = finder.getMinimum();
302 h_channelT0.SetBinContent(channel + 1, minimum.position);
303 h_channelT0.SetBinError(channel + 1, minimum.error * scaleError);
313 TH1F h_moduleT0(
"moduleT0",
"Relative module T0",
314 c_numModules, 0.5, c_numModules + 0.5);
315 h_moduleT0.SetXTitle(
"slot number");
316 h_moduleT0.SetYTitle(
"relative module T0 [ns]");
317 auto finderCommon = m_finders[0][0][0];
318 finderCommon.clear();
319 for (
unsigned module = 0; module < c_numModules; module++) {
320 auto finder = m_finders[0][module][0];
322 for (
unsigned channel = 0; channel < c_numChannels; channel++) {
323 finder.add(m_finders[0][module][channel]);
325 finderCommon.add(finder);
326 const auto& minimum = finder.getMinimum();
328 h_moduleT0.SetBinContent(module + 1, minimum.position);
329 h_moduleT0.SetBinError(module + 1, minimum.error * scaleError);
336 TH1F h_commonT0(
"commonT0",
"Relative common T0", 1, 0, 1);
337 h_commonT0.SetYTitle(
"relative common T0 [ns]");
338 const auto& minimum = finderCommon.getMinimum();
340 h_commonT0.SetBinContent(1, minimum.position);
341 h_commonT0.SetBinError(1, minimum.error * scaleError);
347 for (
auto& h : m_hits1D) h.Write();
348 for (
auto& h : m_hits2D) h.Write();
353 B2RESULT(
"Results available in " << m_outFileName);
Type-safe access to single objects in the data store.
A module for alternative channel T0 calibration with collision data Note: after this kind of calibrat...
Minimum finder using tabulated chi^2 values in one dimension.
PDF construction and log likelihood determination for a given track and particle hypothesis.
bool isValid() const
Checks the object status.
const std::vector< LogL > & getPixelLogLs(double t0, double sigt=0) const
Returns extended log likelihoods in pixels for PDF shifted in time.
Reconstructed track at TOP.
int getPDGCode() const
Returns PDG code of associated MCParticle (returns 0 if none)
double getCharge() const
Returns charge.
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.