Belle II Software  release-08-01-10
TOPCommonT0LLAlgorithm.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/TOPCommonT0LLAlgorithm.h>
10 #include <top/dbobjects/TOPCalCommonT0.h>
11 #include <top/utilities/Chi2MinimumFinder1D.h>
12 
13 #include <math.h>
14 #include <TFile.h>
15 #include <TTree.h>
16 #include <TH1F.h>
17 #include <TH1D.h>
18 #include <TH2F.h>
19 
20 #include <string>
21 #include <vector>
22 
23 using namespace std;
24 
25 namespace Belle2 {
30  namespace TOP {
31 
32  TOPCommonT0LLAlgorithm::TOPCommonT0LLAlgorithm():
33  CalibrationAlgorithm("TOPCommonT0LLCollector")
34  {
35  setDescription("Calibration algorithm for common T0 calibration "
36  "with neg. log likelihood minimization (method LL)");
37  }
38 
40  {
41 
42  // get histograms
43 
44  auto h1 = getObjectPtr<TH1F>("tracks_per_set");
45  if (not h1) {
46  B2ERROR("TOPCommonT0LLAlgorithm: histogram 'tracks_per_set' not found");
47  return c_NotEnoughData;
48  }
49  unsigned numSets = h1->GetNbinsX();
50 
51  vector<Chi2MinimumFinder1D> finders;
52  for (unsigned set = 0; set < numSets; set++) {
53  string name = "chi2_set" + to_string(set);
54  auto h = getObjectPtr<TH1D>(name);
55  if (not h) continue;
56  finders.push_back(Chi2MinimumFinder1D(h));
57  }
58  if (finders.size() != numSets) {
59  B2ERROR("TOPCommonT0LLAlgorithm: got number of chi2 scans not as expected"
60  << LogVar("expected", numSets)
61  << LogVar("found", finders.size()));
62  return c_NotEnoughData;
63  }
64 
65  // bunch separation in time
66 
67  auto h4 = getObjectPtr<TH1F>("offset");
68  if (not h4) {
69  B2ERROR("TOPCommonT0LLAlgorithm: histogram 'offset' not found");
70  return c_NotEnoughData;
71  }
72  double bunchTimeSep = h4->GetXaxis()->GetXmax() - h4->GetXaxis()->GetXmin();
73 
74  // construct file name, open output root file and book output tree
75 
76  const auto& expRun = getRunList();
77  string expNo = to_string(expRun[0].first);
78  while (expNo.length() < 4) expNo.insert(0, "0");
79  string runNo = to_string(expRun[0].second);
80  while (runNo.length() < 5) runNo.insert(0, "0");
81  string outputFileName = "commonT0-e" + expNo + "-r" + runNo + ".root";
82  auto* file = TFile::Open(outputFileName.c_str(), "recreate");
83 
84  auto* tree = new TTree("tree", "common T0 calibration results");
85  tree->Branch<int>("expNum", &m_expNo);
86  tree->Branch<int>("runNum", &m_runNo);
87  tree->Branch<int>("runLast", &m_runLast);
88  tree->Branch<float>("fitted_offset", &m_fittedOffset);
89  tree->Branch<float>("offset", &m_offset);
90  tree->Branch<float>("offsetErr", &m_offsetError);
91  tree->Branch<float>("errorScaling", &m_errorScaling);
92  tree->Branch<int>("nTracks", &m_numTracks);
93  tree->Branch<int>("nEvt", &m_numEvents);
94  tree->Branch<int>("fitStatus", &m_fitStatus);
95 
96  m_expNo = expRun[0].first;
97  m_runNo = expRun[0].second;
98  m_runLast = expRun.back().second;
99 
100  // determine scaling factor for the error from statistically independent results
101 
102  auto h_pulls = new TH1F("pulls", "Pulls of statistically independent results",
103  200, -15.0, 15.0);
104  h_pulls->SetXTitle("pulls");
105  std::vector<double> pos, err;
106  for (auto& finder : finders) {
107  const auto& minimum = finder.getMinimum();
108  if (not minimum.valid) continue;
109  pos.push_back(minimum.position);
110  err.push_back(minimum.error);
111  }
112  for (unsigned i = 0; i < pos.size(); i++) {
113  for (unsigned j = i + 1; j < pos.size(); j++) {
114  double pull = (pos[i] - pos[j]) / sqrt(err[i] * err[i] + err[j] * err[j]);
115  h_pulls->Fill(pull);
116  }
117  }
118  double scaleError = 1;
119  if (h_pulls->GetEntries() > 1) scaleError = h_pulls->GetRMS();
120 
121  // merge statistically independent finders and store results into histograms
122 
123  auto finder = finders[0];
124  for (unsigned i = 1; i < numSets; i++) {
125  finder.add(finders[i]);
126  }
127 
128  auto h_commonT0 = new TH1F("commonT0", "Common T0", 1, 0, 1);
129  h_commonT0->SetYTitle("common T0 [ns]");
130 
131  const auto& minimum = finder.getMinimum();
132  if (minimum.valid) {
133  m_fittedOffset = minimum.position;
134  m_offset = m_fittedOffset - round(m_fittedOffset / bunchTimeSep) * bunchTimeSep;
135  m_offsetError = minimum.error * scaleError;
136  m_fitStatus = 0;
137  h_commonT0->SetBinContent(1, m_offset);
138  h_commonT0->SetBinError(1, m_offsetError);
139  } else {
140  m_fittedOffset = 0;
141  m_offset = 0;
142  m_offsetError = 0;
143  m_fitStatus = 1;
144  }
145  m_errorScaling = scaleError;
146  m_numTracks = h1->GetSumOfWeights();
147  m_numEvents = h4->GetEntries();
148  tree->Fill();
149 
150  // write the results and close the file
151 
152  file->Write();
153  auto h = finder.getHistogram("chi2", "chi2 scan; t0 [ns]; -2 logL");
154  h.Write();
155  h1->Write();
156  auto h2 = getObjectPtr<TH1F>("numHits");
157  if (h2) h2->Write();
158  auto h3 = getObjectPtr<TH2F>("timeHits");
159  if (h3) h3->Write();
160  h4->Write();
161  file->Close();
162 
163  // check the results and return if not good enough
164 
165  if (m_fitStatus != 0 or m_offsetError > m_minError) return c_NotEnoughData;
166 
167  // otherwise create and import payload to DB
168 
169  auto* commonT0 = new TOPCalCommonT0(m_offset, m_offsetError);
170  saveCalibration(commonT0);
171 
172  return c_OK;
173  }
174 
175  } // end namespace TOP
177 } // 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.
Common T0 calibration constant.
Minimum finder using tabulated chi^2 values in one dimension.
float m_offsetError
error on fitted offset
float m_offset
wrap-around of fitted offset (= common T0)
virtual EResult calibrate() final
algorithm implementation
float m_errorScaling
factor used for scaling the error
double m_minError
minimal commonT0 uncertainty [ns] to declare c_OK
Class to store variables with their name which were sent to the logging service.
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.