Belle II Software  release-08-01-10
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 
17 using namespace std;
18 
19 namespace Belle2 {
24  namespace TOP {
25 
26  TOPAsicShiftsBS13dAlgorithm::TOPAsicShiftsBS13dAlgorithm():
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)
EResult
The result of calibration.
@ c_OK
Finished successfuly =0 in Python.
@ c_NotEnoughData
Needs more data =2 in Python.
const std::vector< Calibration::ExpRun > & getRunList() const
Get the list of runs for which calibration is called.
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.