Belle II Software development
TOPAsicShiftsBS13dAlgorithm.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <top/calibration/TOPAsicShiftsBS13dAlgorithm.h>
10#include <top/dbobjects/TOPCalAsicShift.h>
11#include <string>
12#include <algorithm>
13#include <math.h>
14#include <TH2F.h>
15#include <TFile.h>
16
17using namespace std;
18
19namespace Belle2 {
24 namespace TOP {
25
27 CalibrationAlgorithm("TOPAsicShiftsBS13dCollector")
28 {
29 setDescription("Calibration algorithm for carrier shifts of BS13d");
30 }
31
32
34 {
35 // get collected histograms
36
37 auto timeReference = getObjectPtr<TH1F>("time_reference");
38 if (not timeReference) {
39 B2ERROR("TOPAsicShiftsBS13dAlgorithm: histogram 'time_reference' not found");
40 return c_NotEnoughData;
41 }
42 if (timeReference->GetSumOfWeights() == 0) {
43 B2ERROR("TOPAsicShiftsBS13dAlgorithm: histogram 'time_reference' is empty");
44 return c_NotEnoughData;
45 }
46
47 std::vector<std::shared_ptr<TH1F> > timeCarriers(4, nullptr);
48 std::vector<int> entries(4, 0);
49 for (unsigned cb = 0; cb < 4; cb++) {
50 string name = "time_carr_" + to_string(cb);
51 auto h = getObjectPtr<TH1F>(name);
52 timeCarriers[cb] = h;
53 if (h) entries[cb] = h->GetSumOfWeights();
54 }
55
56 // set time reference distribution
57 m_timeReference.clear();
58 for (int i = 0; i < timeReference->GetNbinsX(); i++) {
59 m_timeReference.push_back(timeReference->GetBinContent(i + 1));
60 }
61 setWindow();
62
63 // construct file name, open output root file and book output histograms
64
65 const auto& expRun = getRunList();
66 string expNo = to_string(expRun[0].first);
67 while (expNo.length() < 4) expNo.insert(0, "0");
68 string runNo = to_string(expRun[0].second);
69 while (runNo.length() < 5) runNo.insert(0, "0");
70 string outputFileName = "calibrateBS13d-e" + expNo + "-r" + runNo + ".root";
71 auto* file = TFile::Open(outputFileName.c_str(), "recreate");
72
73 int nx = m_shiftEnd - m_shiftBegin;
74 double xmi = m_shiftBegin - 0.5;
75 double xma = m_shiftEnd - 0.5;
76
77 std::vector<TH1F*> chi2Carriers;
78 for (unsigned i = 0; i < 4; i++) {
79 string name = "chi2_carr_" + to_string(i);
80 string title = "chi2 of carrier " + to_string(i);
81 auto* h = new TH1F(name.c_str(), title.c_str(), nx, xmi, xma);
82 h->SetXTitle("shift [127 MHz clk cycles]");
83 h->SetYTitle("-2*logL [arbitrary]");
84 chi2Carriers.push_back(h);
85 }
86
87 auto* shiftClk = new TH1F("shift_clk", "shift in clk units", 4, -0.5, 3.5);
88 shiftClk->SetXTitle("boardstack number");
89 shiftClk->SetYTitle("shift [127 MHz clk cycles]");
90
91 auto* shiftTime = new TH1F("shift_time", "shift in time units", 4, -0.5, 3.5);
92 shiftTime->SetXTitle("boardstack number");
93 shiftTime->SetYTitle("shift [ns]");
94
95 auto* signif = new TH1F("significance", "significance of the result", 4, -0.5, 3.5);
96 signif->SetXTitle("boardstack number");
97 signif->SetYTitle("significance [sigma]");
98
99 // find carrier shifts
100
101 double timeStep = timeReference->GetBinWidth(1);
102 for (unsigned cb = 0; cb < 4; cb++) {
103 auto& h_chi = chi2Carriers[cb];
104 auto& h_time = timeCarriers[cb];
105 if (not h_time) continue;
106 for (int shift = m_shiftBegin; shift < m_shiftEnd; shift++) {
107 double chi2 = -2.0 * logL(h_time, shift);
108 h_chi->SetBinContent(shift - m_shiftBegin + 1, chi2);
109 }
110 double hmin = h_chi->GetMinimum();
111 for (int i = 0; i < h_chi->GetNbinsX(); i++) {
112 h_chi->SetBinContent(i + 1, h_chi->GetBinContent(i + 1) - hmin);
113 }
114 int i0 = h_chi->GetMinimumBin();
115 double x = h_chi->GetBinCenter(i0);
116 shiftClk->SetBinContent(cb + 1, x);
117 shiftTime->SetBinContent(cb + 1, x * timeStep);
118 double s = std::min(h_chi->GetBinContent(i0 - 1), h_chi->GetBinContent(i0 + 1));
119 signif->SetBinContent(cb + 1, sqrt(s));
120 }
121
122 // save results in vectors since histograms are destroyed after file is closed
123
124 std::vector<double> shifts;
125 std::vector<double> significances;
126 for (unsigned cb = 0; cb < 4; cb++) {
127 shifts.push_back(shiftTime->GetBinContent(cb + 1));
128 significances.push_back(signif->GetBinContent(cb + 1));
129 }
130
131 // write the results and close the file
132
133 auto time_vs_BS = getObjectPtr<TH2F>("time_vs_BS");
134 if (time_vs_BS) {
135 time_vs_BS->Write();
136 // make histogram corrected for shifts - for visual validation
137 int Nx = time_vs_BS->GetNbinsX();
138 int Ny = time_vs_BS->GetNbinsY();
139 int step = Nx / 16;
140 if (step * 16 == Nx) {
141 auto* time_vs_BS_corr = (TH2F*) time_vs_BS->Clone("time_vs_BS_corrected");
142 int i0 = (Nx / 4) * 3;
143 for (int i = i0; i < Nx; i++) {
144 int cb = (i - i0) / step;
145 int shift = shiftClk->GetBinContent(cb + 1);
146 if (shift != 0) {
147 for (int k = 0; k < Ny; k++) {
148 double val = 0;
149 int k0 = k + shift;
150 if (k0 < Ny) val = time_vs_BS->GetBinContent(i + 1, k0 + 1);
151 time_vs_BS_corr->SetBinContent(i + 1, k + 1, val);
152 }
153 }
154 }
155 } else {
156 B2ERROR("TOPAsicShiftsBS13dAlgorithm: can't make corrected histogram");
157 }
158 }
159 timeReference->Write();
160 for (auto& h : timeCarriers) {
161 if (h) h->Write();
162 }
163 file->Write();
164 file->Close();
165
166 // check if CB entries have changed if this run is merged with previous one
167
168 if (not m_lastEntries.empty()) { // run is merged
169 for (unsigned cb = 0; cb < 4; cb++) {
170 if (entries[cb] == m_lastEntries[cb] and significances[cb] < m_minSignificance)
171 significances[cb] = 0; // not possible to calibrate this CB
172 }
173 }
174
175 // check result significances and return if too low
176
177 for (auto significance : significances) {
178 if (significance > 0 and significance < m_minSignificance) {
179 m_lastEntries = entries; // save entries
180 return c_NotEnoughData;
181 }
182 }
183
184 // otherwise create and import payload to DB
185
186 auto* asicShift = new TOPCalAsicShift();
187 int moduleID = 13;
188 unsigned bs = 3;
189 for (unsigned cb = 0; cb < 4; cb++) {
190 if (significances[cb] == 0) continue; // no or insufficient data from this BS
191 for (unsigned a = 0; a < 4; a++) {
192 unsigned asic = a + cb * 4 + bs * 16;
193 asicShift->setT0(moduleID, asic, shifts[cb]);
194 }
195 }
196 saveCalibration(asicShift);
197 m_lastEntries.clear();
198
199 return c_OK;
200 }
201
202
204 {
205 int nx = m_timeReference.size();
206 m_i0 = 0;
207 m_i1 = nx - 1;
208 if (m_winSize > nx or m_winSize < 1) return;
209
210 double s = 0;
211 for (int i = 0; i < m_winSize; i++) s += m_timeReference[i];
212
213 double s_max = s;
214 int i0 = 0;
215 for (int i = 0; i < nx - m_winSize; i++) {
217 if (s > s_max) {
218 s_max = s;
219 i0 = i + 1;
220 }
221 }
222 m_i0 = i0;
223 m_i1 = i0 + m_winSize - 1;
224 }
225
226
228 {
229 x = std::min(std::max(x, m_i0), m_i1);
230 return std::max(m_timeReference[x], m_minVal);
231 }
232
233
234 std::vector<double> TOPAsicShiftsBS13dAlgorithm::getPDF(int ishft)
235 {
236 std::vector<double> p;
237 for (size_t i = 0; i < m_timeReference.size(); i++) {
238 p.push_back(fun(i - ishft));
239 }
240 double s = 0;
241 for (auto x : p) s += x;
242 for (auto& x : p) x /= s;
243 return p;
244 }
245
246
247 double TOPAsicShiftsBS13dAlgorithm::logL(std::shared_ptr<TH1F> h, int shift)
248 {
249 if (not h) return 0;
250
251 double logl = 0;
252 auto pdf = getPDF(shift);
253 for (unsigned i = 0; i < pdf.size(); i++) {
254 logl += h->GetBinContent(i + 1) * log(pdf[i]) - pdf[i];
255 }
256 return logl;
257 }
258
259 } // end namespace TOP
261} // end namespace Belle2
Base class for calibration algorithms.
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
void setDescription(const std::string &description)
Set algorithm description (in constructor)
const std::vector< Calibration::ExpRun > & getRunList() const
Get the list of runs for which calibration is called.
EResult
The result of calibration.
@ c_OK
Finished successfuly =0 in Python.
@ c_NotEnoughData
Needs more data =2 in Python.
Calibration constants for ASIC shifts of all 16 modules.
double fun(int x)
Returns measured time distribution at x or minVal for outside-range or empty bins.
void setWindow()
Sets the position of a window containing maximum number of entries of reference time distribution.
std::vector< double > getPDF(int shift)
Returns normalized time distribution at a given shift (PDF)
int m_winSize
size of the window on reference time distribution
std::vector< int > m_lastEntries
number of histogram entries
std::vector< double > m_timeReference
reference time distribution
virtual EResult calibrate() final
algorithm implementation
double m_minSignificance
minimal result significance to declare c_OK
int m_i1
last bin of the window on reference time distribution
double logL(std::shared_ptr< TH1F > h, int shift)
Returns log likelihood of a histogram with respect to PDF at a given shift.
int m_i0
first bin of the window on reference time distribution
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.
STL namespace.