9 #include <top/modules/TOPCommonT0Calibrator/TOPCommonT0CalibratorModule.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/logging/Logger.h>
41 setDescription(
"Common T0 calibration with dimuons or bhabhas.");
45 addParam(
"numBins", m_numBins,
"number of bins of the search region", 200);
46 addParam(
"timeRange", m_timeRange,
47 "time range in which to search for the minimum [ns]", 10.0);
48 addParam(
"sigmaSmear", m_sigmaSmear,
49 "sigma in [ns] for additional smearing of PDF", 0.0);
50 addParam(
"sample", m_sample,
51 "sample type: one of dimuon, bhabha or cosmics", std::string(
"dimuon"));
52 addParam(
"minMomentum", m_minMomentum,
53 "minimal track momentum if sample is cosmics", 1.0);
54 addParam(
"deltaEcms", m_deltaEcms,
55 "c.m.s energy window (half size) if sample is dimuon or bhabha", 0.1);
56 addParam(
"dr", m_dr,
"cut on POCA in r", 2.0);
57 addParam(
"dz", m_dz,
"cut on POCA in abs(z)", 4.0);
58 addParam(
"minZ", m_minZ,
59 "minimal local z of extrapolated hit", -130.0);
60 addParam(
"maxZ", m_maxZ,
61 "maximal local z of extrapolated hit", 130.0);
62 addParam(
"outputFileName", m_outFileName,
63 "Root output file name containing calibration results. "
64 "File name can include *'s; "
65 "they will be replaced with a run number from the first input file",
66 std::string(
"commonT0_r*.root"));
67 addParam(
"pdfOption", m_pdfOption,
68 "PDF option, one of 'rough', 'fine', 'optimal'", std::string(
"rough"));
73 void TOPCommonT0CalibratorModule::initialize()
76 m_digits.isRequired();
77 m_tracks.isRequired();
78 m_extHits.isRequired();
79 m_recBunch.isOptional();
83 const auto* geo = TOPGeometryPar::Instance()->getGeometry();
84 m_bunchTimeSep = geo->getNominalTDC().getSyncTimeBase() / 24;
87 if (m_pdfOption ==
"rough") {
88 m_PDFOption = PDFConstructor::c_Rough;
89 }
else if (m_pdfOption ==
"fine") {
90 m_PDFOption = PDFConstructor::c_Fine;
91 }
else if (m_pdfOption ==
"optimal") {
92 m_PDFOption = PDFConstructor::c_Optimal;
94 B2ERROR(
"TOPPDFDebuggerModule: unknown PDF option '" << m_pdfOption <<
"'");
99 m_selector.setMinMomentum(m_minMomentum);
100 m_selector.setDeltaEcms(m_deltaEcms);
101 m_selector.setCutOnPOCA(m_dr, m_dz);
102 m_selector.setCutOnLocalZ(m_minZ, m_maxZ);
105 double tmin = -m_timeRange / 2;
106 double tmax = m_timeRange / 2;
107 for (
unsigned i = 0; i < c_numSets; i++) {
112 auto pos = m_outFileName.find(
"*");
113 if (pos != std::string::npos) {
115 auto run = std::to_string(evtMetaData->getRun());
116 while (run.size() < 5) run =
"0" + run;
117 while (pos != std::string::npos) {
118 m_outFileName.replace(pos, 1, run);
119 pos = m_outFileName.find(
"*");
124 m_file = TFile::Open(m_outFileName.c_str(),
"RECREATE");
126 B2ERROR(
"Cannot open output file '" << m_outFileName <<
"'");
131 m_hits1D = TH1F(
"numHits",
"Number of photons per slot",
132 c_numModules, 0.5, c_numModules + 0.5);
133 m_hits1D.SetXTitle(
"slot number");
134 m_hits1D.SetYTitle(
"hits per slot");
136 m_hits2D = TH2F(
"timeHits",
"Photon times vs. boardstacks",
137 c_numModules * 4, 0.5, c_numModules + 0.5, 200, 0.0, 20.0);
138 m_hits2D.SetXTitle(
"slot number");
139 m_hits2D.SetYTitle(
"time [ns]");
142 m_tree =
new TTree(
"tree",
"Channel T0 calibration results");
143 m_tree->Branch(
"slot", &m_moduleID);
144 m_tree->Branch(
"numPhotons", &m_numPhotons);
145 m_tree->Branch(
"x", &m_x);
146 m_tree->Branch(
"y", &m_y);
147 m_tree->Branch(
"z", &m_z);
148 m_tree->Branch(
"p", &m_p);
149 m_tree->Branch(
"theta", &m_theta);
150 m_tree->Branch(
"phi", &m_phi);
151 m_tree->Branch(
"r_poca", &m_pocaR);
152 m_tree->Branch(
"z_poca", &m_pocaZ);
153 m_tree->Branch(
"x_poca", &m_pocaX);
154 m_tree->Branch(
"y_poca", &m_pocaY);
155 m_tree->Branch(
"Ecms", &m_cmsE);
156 m_tree->Branch(
"charge", &m_charge);
157 m_tree->Branch(
"PDG", &m_PDG);
162 void TOPCommonT0CalibratorModule::event()
169 if (m_recBunch.isValid()) {
170 if (not m_recBunch->isReconstructed())
return;
173 TOPRecoManager::setDefaultTimeWindow();
174 double timeMin = TOPRecoManager::getMinTime();
175 double timeMax = TOPRecoManager::getMaxTime();
179 if (isRunningOffsetSubtracted()) {
180 B2ERROR(
"Running offset subtracted in TOPDigits: common T0 will not be correct");
185 for (
const auto& track : m_tracks) {
189 if (not trk.
isValid())
continue;
191 if (not m_selector.isSelected(trk))
continue;
194 PDFConstructor pdfConstructor(trk, m_selector.getChargedStable(), m_PDFOption);
195 if (not pdfConstructor.
isValid())
continue;
198 int sub = gRandom->Integer(c_numSets);
199 auto& finder = m_finders[sub];
200 const auto& binCenters = finder.getBinCenters();
201 for (
unsigned ibin = 0; ibin < binCenters.size(); ibin++) {
202 double t0 = binCenters[ibin];
203 finder.add(ibin, -2 * pdfConstructor.
getLogL(t0, m_sigmaSmear).
logL);
208 for (
const auto& digit : m_digits) {
209 if (digit.getHitQuality() != TOPDigit::c_Good)
continue;
210 if (digit.getModuleID() != trk.
getModuleID())
continue;
211 if (digit.getTime() < timeMin)
continue;
212 if (digit.getTime() > timeMax)
continue;
214 m_hits1D.Fill(digit.getModuleID());
215 int bs = digit.getBoardstackNumber();
216 m_hits2D.Fill((digit.getModuleID() * 4 + bs - 1.5) / 4.0 , digit.getTime());
221 const auto& localPosition = m_selector.getLocalPosition();
222 m_x = localPosition.X();
223 m_y = localPosition.Y();
224 m_z = localPosition.Z();
225 const auto& localMomentum = m_selector.getLocalMomentum();
226 m_p = localMomentum.Mag();
227 m_theta = localMomentum.Theta();
228 m_phi = localMomentum.Phi();
229 const auto& pocaPosition = m_selector.getPOCAPosition();
230 m_pocaR = pocaPosition.Perp();
231 m_pocaZ = pocaPosition.Z();
232 m_pocaX = pocaPosition.X();
233 m_pocaY = pocaPosition.Y();
234 m_cmsE = m_selector.getCMSEnergy();
243 void TOPCommonT0CalibratorModule::terminate()
248 TH1F h_pulls(
"pulls",
"Pulls of statistically independent results",
250 h_pulls.SetXTitle(
"pulls");
251 std::vector<double> pos, err;
252 for (
int i = 0; i < c_numSets; i++) {
253 const auto& minimum = m_finders[i].getMinimum();
254 if (not minimum.valid)
continue;
255 pos.push_back(minimum.position);
256 err.push_back(minimum.error);
258 for (
unsigned i = 0; i < pos.size(); i++) {
259 for (
unsigned j = i + 1; j < pos.size(); j++) {
260 double pull = (pos[i] - pos[j]) / sqrt(err[i] * err[i] + err[j] * err[j]);
265 double scaleError = 1;
266 if (h_pulls.GetEntries() > 1) scaleError = h_pulls.GetRMS();
270 auto finder = m_finders[0];
271 for (
int i = 1; i < c_numSets; i++) {
272 finder.add(m_finders[i]);
275 TH1F h_relCommonT0(
"relCommonT0",
"relative common T0", 1, 0, 1);
276 h_relCommonT0.SetYTitle(
"common T0 residual [ns]");
277 TH1F h_commonT0(
"commonT0",
"Common T0", 1, 0, 1);
278 h_commonT0.SetYTitle(
"common T0 [ns]");
280 const auto& minimum = finder.getMinimum();
281 auto h = finder.getHistogram(
"chi2",
"chi2");
284 h_relCommonT0.SetBinContent(1, minimum.position);
285 h_relCommonT0.SetBinError(1, minimum.error * scaleError);
286 double T0 = minimum.position;
287 if (m_commonT0->isCalibrated()) T0 += m_commonT0->getT0();
288 T0 -= round(T0 / m_bunchTimeSep) * m_bunchTimeSep;
289 h_commonT0.SetBinContent(1, T0);
290 h_commonT0.SetBinError(1, minimum.error * scaleError);
292 h_relCommonT0.Write();
302 B2RESULT(
"Results available in " << m_outFileName);
305 bool TOPCommonT0CalibratorModule::isRunningOffsetSubtracted()
307 for (
const auto& digit : m_digits) {
308 if (digit.hasStatus(TOPDigit::c_BunchOffsetSubtracted))
return true;
Type-safe access to single objects in the data store.
A module for common T0 calibration with collision data (dimuons or bhabhas)
Minimum finder using tabulated chi^2 values in one dimension.
PDF construction and log likelihood determination for a given track and particle hypothesis.
LogL getLogL() const
Returns extended log likelihood (using the default time window)
bool isValid() const
Checks the object status.
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.
double logL
extended log likelihood