Belle II Software  release-06-01-15
TOPValidationAlgorithm.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/TOPValidationAlgorithm.h>
10 #include <top/utilities/Chi2MinimumFinder1D.h>
11 
12 #include <TFile.h>
13 #include <TH1F.h>
14 #include <TH1D.h>
15 #include <TH2F.h>
16 
17 #include <string>
18 #include <vector>
19 #include <map>
20 #include <set>
21 #include <cmath>
22 
23 using namespace std;
24 
25 namespace Belle2 {
30  namespace TOP {
31 
32  TOPValidationAlgorithm::TOPValidationAlgorithm():
33  CalibrationAlgorithm("TOPValidationCollector")
34  {
35  setDescription("Calibration algorithm for automatic validation of the calibration");
36  }
37 
38 
40  {
41  // open output root file
42 
43  auto* file = TFile::Open("TOPCalValidation.root", "recreate");
44 
45  // write-out the histograms that are ready
46 
47  B2INFO("TOPValidationAlgorithm: get basic histograms");
48 
49  double scaleFactor = 1; // scaling factor for module and common T0 uncertainties
50  auto h1 = getObjectPtr<TH1F>("moduleT0_pulls");
51  if (h1) {
52  if (h1->GetEntries() > 1) scaleFactor = h1->GetRMS();
53  h1->Write();
54  }
55 
56  std::vector<string> slotNames;
57  for (unsigned slot = 1; slot <= c_numModules; slot++) {
58  string slotName = "slot";
59  if (slot < 10) slotName += "0";
60  slotName += to_string(slot);
61  slotNames.push_back(slotName);
62  }
63 
64  for (unsigned slot = 0; slot < c_numModules; slot++) {
65  string name = "hits_" + slotNames[slot];
66  auto h = getObjectPtr<TH2F>(name);
67  if (h) h->Write();
68  }
69 
70  // channelT0 residuals: determine Chi2 minima and save the results into histograms
71 
72  B2INFO("TOPValidationAlgorithm: determine channel T0 residuals");
73 
74  for (unsigned slot = 0; slot < c_numModules; slot++) {
75  string name = "chi2_" + slotNames[slot];
76  auto h = getObjectPtr<TH2F>(name);
77  if (not h) continue;
78 
79  int nx = h->GetNbinsX();
80  string nameOut = "channelT0_" + slotNames[slot];
81  string title = "ChannelT0, " + slotNames[slot] + "; channel; residuals [ns]";
82  auto* h0 = new TH1F(nameOut.c_str(), title.c_str(), nx, 0, nx);
83 
84  for (int ibin = 1; ibin <= nx; ibin++) {
85  Chi2MinimumFinder1D finder(std::shared_ptr<TH1D>(h->ProjectionY("py", ibin, ibin)));
86  const auto& minimum = finder.getMinimum();
87  if (not minimum.valid) continue;
88  h0->SetBinContent(ibin, minimum.position);
89  h0->SetBinError(ibin, minimum.error);
90  }
91  }
92 
93  // moduleT0, commonT0 and others: get input tree and set branch addresses
94 
95  B2INFO("TOPValidationAlgorithm: get input tree");
96 
97  auto inputTree = getObjectPtr<TTree>("tree");
98  if (not inputTree) {
99  B2ERROR("TOPValidationAlgorithm: input tree not found");
100  file->Write();
101  file->Close();
102  return c_Failure;
103  }
104  inputTree->SetBranchAddress("expNo", &m_treeEntry.expNo);
105  inputTree->SetBranchAddress("runNo", &m_treeEntry.runNo);
106  inputTree->SetBranchAddress("numTracks", &m_treeEntry.numTracks);
107  inputTree->SetBranchAddress("commonT0", &m_treeEntry.commonT0);
108  inputTree->SetBranchAddress("commonT0Err", &m_treeEntry.commonT0Err);
109  inputTree->SetBranchAddress("moduleT0", &m_treeEntry.moduleT0);
110  inputTree->SetBranchAddress("moduleT0Err", &m_treeEntry.moduleT0Err);
111  inputTree->SetBranchAddress("numTBCalibrated", &m_treeEntry.numTBCalibrated);
112  inputTree->SetBranchAddress("numT0Calibrated", &m_treeEntry.numT0Calibrated);
113  inputTree->SetBranchAddress("numActive", &m_treeEntry.numActive);
114  inputTree->SetBranchAddress("numActiveCalibrated", &m_treeEntry.numActiveCalibrated);
115  inputTree->SetBranchAddress("thrEffi", &m_treeEntry.thrEffi);
116  inputTree->SetBranchAddress("asicShifts", &m_treeEntry.asicShifts);
117 
118  // sort input tree entries according to exp/run
119 
120  B2INFO("TOPValidationAlgorithm: sort input tree entries");
121 
122  std::multimap<int, ValidationTreeStruct> sortedEntries;
123  std::set<int> sortedRuns;
124  for (int iev = 0; iev < inputTree->GetEntries(); iev++) {
125  inputTree->GetEntry(iev);
126  int expRun = (m_treeEntry.expNo << 16) + m_treeEntry.runNo;
127  sortedEntries.emplace(expRun, m_treeEntry);
128  sortedRuns.insert(expRun);
129  }
130 
131  // merge input entries of the same exp/run and rescale the errors
132 
133  B2INFO("TOPValidationAlgorithm: merge input tree entries");
134 
135  std::vector<ValidationTreeStruct> mergedEntries;
136  for (auto expRun : sortedRuns) {
137  ValidationTreeStruct mergedEntry;
138  const auto range = sortedEntries.equal_range(expRun);
139  for (auto it = range.first; it != range.second; ++it) {
140  mergedEntry.merge(it->second);
141  }
142  mergedEntry.rescaleErrors(scaleFactor);
143  mergedEntries.push_back(mergedEntry);
144  }
145 
146  // make histograms vs. run index
147 
148  int nx = mergedEntries.size();
149  if (nx == 0) {
150  B2ERROR("TOPValidationAlgorithm: input tree is empty");
151  file->Write();
152  file->Close();
153  return c_Failure;
154  }
155 
156  file->cd();
157 
158  std::set<int> sortedExps;
159  for (auto& entry : mergedEntries) sortedExps.insert(entry.expNo);
160  std::string titleIndex = "Experiment";
161  if (sortedExps.size() > 1) titleIndex += "s";
162  for (auto expNo : sortedExps) titleIndex += " " + to_string(expNo) + ",";
163  titleIndex.pop_back();
164  auto* h_index = new TH1F("runIndex", (titleIndex + "; run index; run number").c_str(), nx, 0, nx);
165  for (int i = 0; i < nx; i++) {
166  h_index->SetBinContent(i + 1, mergedEntries[i].runNo);
167  }
168 
169  auto* h_numTracks = new TH1F("numTracks", "Number of tracks; run index; number of tracks", nx, 0, nx);
170  for (int i = 0; i < nx; i++) {
171  h_numTracks->SetBinContent(i + 1, mergedEntries[i].numTracks);
172  }
173 
174  auto* h_numMerged = new TH1F("numMerged", "Number of merged entries; run index; number of merged", nx, 0, nx);
175  for (int i = 0; i < nx; i++) {
176  h_numMerged->SetBinContent(i + 1, mergedEntries[i].numMerged);
177  }
178 
179  auto* h_commonT0 = new TH1F("commonT0", "commonT0; run index; residuals [ns]", nx, 0, nx);
180  for (int i = 0; i < nx; i++) {
181  h_commonT0->SetBinContent(i + 1, mergedEntries[i].commonT0);
182  h_commonT0->SetBinError(i + 1, mergedEntries[i].commonT0Err);
183  }
184 
185  for (unsigned slot = 0; slot < c_numModules; slot++) {
186  string name = "moduleT0_" + slotNames[slot];
187  string title = "moduleT0, " + slotNames[slot] + "; run index; residuals [ns]";
188  auto* h = new TH1F(name.c_str(), title.c_str(), nx, 0, nx);
189  for (int i = 0; i < nx; i++) {
190  h->SetBinContent(i + 1, mergedEntries[i].moduleT0[slot]);
191  h->SetBinError(i + 1, mergedEntries[i].moduleT0Err[slot]);
192  }
193  }
194 
195  for (unsigned slot = 0; slot < c_numModules; slot++) {
196  string name = "numTBCalibrated_" + slotNames[slot];
197  string title = "Time base calibrated, " + slotNames[slot] + "; run index; fraction";
198  auto* h = new TH1F(name.c_str(), title.c_str(), nx, 0, nx);
199  for (int i = 0; i < nx; i++) {
200  h->SetBinContent(i + 1, mergedEntries[i].numTBCalibrated[slot] / 512.0);
201  }
202  }
203 
204  for (unsigned slot = 0; slot < c_numModules; slot++) {
205  string name = "numT0Calibrated_" + slotNames[slot];
206  string title = "channel T0 calibrated, " + slotNames[slot] + "; run index; fraction";
207  auto* h = new TH1F(name.c_str(), title.c_str(), nx, 0, nx);
208  for (int i = 0; i < nx; i++) {
209  h->SetBinContent(i + 1, mergedEntries[i].numT0Calibrated[slot] / 512.0);
210  }
211  }
212 
213  for (unsigned slot = 0; slot < c_numModules; slot++) {
214  string name = "numActive_" + slotNames[slot];
215  string title = "Active, " + slotNames[slot] + "; run index; fraction";
216  auto* h = new TH1F(name.c_str(), title.c_str(), nx, 0, nx);
217  for (int i = 0; i < nx; i++) {
218  h->SetBinContent(i + 1, mergedEntries[i].numActive[slot] / 512.0);
219  }
220  }
221 
222  for (unsigned slot = 0; slot < c_numModules; slot++) {
223  string name = "numActiveCalibrated_" + slotNames[slot];
224  string title = "Active and calibrated, " + slotNames[slot] + "; run index; fraction";
225  auto* h = new TH1F(name.c_str(), title.c_str(), nx, 0, nx);
226  for (int i = 0; i < nx; i++) {
227  h->SetBinContent(i + 1, mergedEntries[i].numActiveCalibrated[slot] / 512.0);
228  }
229  }
230 
231  for (unsigned slot = 0; slot < c_numModules; slot++) {
232  string name = "thrEffi_" + slotNames[slot];
233  string title = "Threshold efficiency, " + slotNames[slot] + "; run index; efficiency";
234  auto* h = new TH1F(name.c_str(), title.c_str(), nx, 0, nx);
235  for (int i = 0; i < nx; i++) {
236  h->SetBinContent(i + 1, mergedEntries[i].thrEffi[slot]);
237  }
238  }
239 
240  for (unsigned carrier = 0; carrier < 4; carrier++) {
241  string name = "asicShifts_" + to_string(carrier);
242  string title = "BS13d, carrier " + to_string(carrier) + "; run index; shift [ns]";
243  auto* h = new TH1F(name.c_str(), title.c_str(), nx, 0, nx);
244  for (int i = 0; i < nx; i++) {
245  auto y = mergedEntries[i].asicShifts[carrier];
246  if (isnan(y)) {
247  h->SetBinError(i + 1, 0);
248  } else {
249  h->SetBinContent(i + 1, y);
250  h->SetBinError(i + 1, 0.001);
251  }
252  }
253  }
254 
255  // write-out the results
256 
257  B2INFO("TOPValidationAlgorithm: write the results");
258 
259  file->Write();
260  file->Close();
261 
262  return c_OK;
263  }
264 
265  } // end namespace TOP
267 } // end namespace Belle2
Base class for calibration algorithms.
void setDescription(const std::string &description)
Set algorithm description (in constructor)
EResult
The result of calibration.
@ c_OK
Finished successfuly =0 in Python.
@ c_Failure
Failed =3 in Python.
Minimum finder using tabulated chi^2 values in one dimension.
virtual EResult calibrate() final
algorithm implementation
ValidationTreeStruct m_treeEntry
input tree entry
Abstract base class for different kinds of events.
Calibration validation tree structure.
int numTBCalibrated[c_numModules]
number of timebase calibrated channels, index = slot - 1
void rescaleErrors(double scaleFactor)
Rescale errors.
int numTracks
number of selected tracks
int numActive[c_numModules]
number of active channels, index = slot - 1
void merge(const ValidationTreeStruct &other)
Merge two structures.
float commonT0Err
common T0 uncertainty (not scaled)
float thrEffi[c_numModules]
threshold efficiency: average over active calibrated channels, index = slot - 1
float moduleT0[c_numModules]
module T0 residuals, index = slot - 1
int numActiveCalibrated[c_numModules]
number of active calibrated channels, index = slot - 1
float moduleT0Err[c_numModules]
module T0 uncertainties (not scaled), index = slot - 1
float asicShifts[4]
carrier shifts of BS13d, index = carrier number
int numT0Calibrated[c_numModules]
number of channel T0 calibrated channels, index = slot - 1