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