Belle II Software development
eclBhabhaTAlgorithm.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/* Own header. */
10#include <ecl/calibration/eclBhabhaTAlgorithm.h>
11
12/* ECL headers. */
13#include <ecl/dataobjects/ECLElementNumbers.h>
14#include <ecl/dbobjects/ECLCrystalCalib.h>
15#include <ecl/dbobjects/ECLReferenceCrystalPerCrateCalib.h>
16#include <ecl/digitization/EclConfiguration.h>
17#include <ecl/mapper/ECLChannelMapper.h>
18
19/* Basf2 headers. */
20#include <framework/database/DBObjPtr.h>
21#include <framework/database/DBStore.h>
22#include <framework/dataobjects/EventMetaData.h>
23#include <framework/datastore/DataStore.h>
24#include <framework/datastore/StoreObjPtr.h>
25
26/* ROOT headers. */
27#include <TF1.h>
28#include <TFile.h>
29#include <TH2F.h>
30#include <TROOT.h>
31
32using namespace std;
33using namespace Belle2;
34using namespace ECL;
35
37 // Parameters
38 CalibrationAlgorithm("ECLBhabhaTCollector"),
39 cellIDLo(1),
40 cellIDHi(ECLElementNumbers::c_NCrystals),
41 meanCleanRebinFactor(1),
42 meanCleanCutMinFactor(0),
43 crateIDLo(1),
44 crateIDHi(52),
45 savePrevCrysPayload(false),
46 readPrevCrysPayload(false),
47 debugOutput(true),
48 debugFilenameBase("eclBhabhaTAlgorithm"), // base of filename (without ".root")
49 collectorName("ECLBhabhaTCollector"),
50 refCrysPerCrate{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
51 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
52 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
53 -1, -1, -1, -1, -1, -1, -1} //,
54{
55 setDescription("Calculate time offsets from bhabha events by fitting gaussian function to the (t - T0) difference.");
56}
57
58
59
61{
63 gROOT->SetBatch();
64
65
67 B2INFO("eclBhabhaTAlgorithm parameters:");
68 B2INFO("cellIDLo = " << cellIDLo);
69 B2INFO("cellIDHi = " << cellIDHi);
70 B2INFO("meanCleanRebinFactor = " << meanCleanRebinFactor);
71 B2INFO("meanCleanCutMinFactor = " << meanCleanCutMinFactor);
72 B2INFO("crateIDLo = " << crateIDLo);
73 B2INFO("crateIDHi = " << crateIDHi);
74 B2INFO("savePrevCrysPayload = " << savePrevCrysPayload);
75 B2INFO("readPrevCrysPayload = " << readPrevCrysPayload);
76 B2INFO("refCrysPerCrate = {");
77 for (int crateTest = 0; crateTest < 52 - 1; crateTest++) {
78 B2INFO(refCrysPerCrate[crateTest] << ",");
79 }
80 B2INFO(refCrysPerCrate[52 - 1] << "}");
81
82
83 /* Histogram with the data collected by eclBhabhaTCollectorModule */
84
85 auto TimevsCrysPrevCrateCalibPrevCrystCalib = getObjectPtr<TH2F>("TimevsCrysPrevCrateCalibPrevCrystCalib");
86 auto TimevsCratePrevCrateCalibPrevCrystCalib = getObjectPtr<TH2F>("TimevsCratePrevCrateCalibPrevCrystCalib");
87 auto TimevsCrysNoCalibrations = getObjectPtr<TH2F>("TimevsCrysNoCalibrations");
88 auto TimevsCrysPrevCrateCalibNoCrystCalib = getObjectPtr<TH2F>("TimevsCrysPrevCrateCalibNoCrystCalib");
89 auto TimevsCrateNoCrateCalibPrevCrystCalib = getObjectPtr<TH2F>("TimevsCrateNoCrateCalibPrevCrystCalib");
90
91 // Collect other plots just for reference - combines all the runs for these plots.
92 auto cutflow = getObjectPtr<TH1F>("cutflow");
93 auto svdEventT0 = getObjectPtr<TH1D>("svdEventT0");
94
95
96 // Define new plots to make
97 // New calibration constant values minus older values from previous iteration plotted as a function of the crystal or crate id
98 unique_ptr<TH1F> tsNew_MINUS_tsOld__cid(new TH1F("TsNew_MINUS_TsOld__cid",
99 ";cell id; ts(new|bhabha) - ts(previous iteration|merged) [ns]", ECLElementNumbers::c_NCrystals,
101 unique_ptr<TH1F> tcrateNew_MINUS_tcrateOld__crateID(new TH1F("tcrateNew_MINUS_tcrateOld__crateID",
102 ";crate id; tcrate(new | bhabha) - tcrate(previous iteration | merged) [ns]",
103 52, 1, 52 + 1));
104 unique_ptr<TH1F> tsNew_MINUS_tsCustomPrev__cid(new TH1F("TsNew_MINUS_TsCustomPrev__cid",
105 ";cell id; ts(new|bhabha) - ts(old = 'before 1st iter'|merged) [ns]",
107 unique_ptr<TH1F> tsNew_MINUS_tsOldBhabha__cid(new TH1F("TsNew_MINUS_TsOldBhabha__cid",
108 ";cell id; ts(new|bhabha) - ts(previous iteration|bhabha) [ns]", ECLElementNumbers::c_NCrystals,
110
111
112 // Histogram of the new time constant values minus values from previous iteration
113 unique_ptr<TH1F> tsNew_MINUS_tsOld(new TH1F("TsNew_MINUS_TsOld",
114 ";ts(new | bhabha) - ts(previous iteration | merged) [ns];Number of crystals",
115 201, -10.05, 10.05));
116 unique_ptr<TH1F> tcrateNew_MINUS_tcrateOld(new TH1F("tcrateNew_MINUS_tcrateOld",
117 ";tcrate(new) - tcrate(previous iteration) [ns];Number of crates",
118 201, -10.05, 10.05));
119 unique_ptr<TH1F> tsNew_MINUS_tsCustomPrev(new TH1F("TsNew_MINUS_TsCustomPrev",
120 ";ts(new | bhabha) - ts(old = 'before 1st iter' | merged) [ns];Number of crystals",
121 285, -69.5801, 69.5801));
122 unique_ptr<TH1F> tsNew_MINUS_tsOldBhabha(new TH1F("TsNew_MINUS_TsOldBhabha",
123 ";ts(new | bhabha) - ts(previous iteration | bhabha) [ns];Number of crystals",
124 201, -10.05, 10.05));
125
126
127
128 // Histograms just for crates and collecting for all the different runs rather than run by run.
129 unique_ptr<TH1F> tcrateNew_MINUS_tcrateOld_allRuns(new TH1F("tcrateNew_MINUS_tcrateOld_allRuns",
130 "Crate time constant changes over all runs : tcrate(new) uncertainty < 0.1ns;tcrate(new) - tcrate(previous iteration) [ns];Number of crates",
131 201, -10.05, 10.05));
132
133 unique_ptr<TH1F> tcrateNew_MINUS_tcrateOld_allRuns_allCrates(new TH1F("tcrateNew_MINUS_tcrateOld_allRuns_allCrates",
134 "Crate time constant changes over all runs : all crates;tcrate(new) - tcrate(previous iteration) [ns];Number of crates",
135 201, -10.05, 10.05));
136
137 unique_ptr<TH1I> num_tcrates_perRun(new TH1I("num_tcrates_perRun",
138 "Number of good tcrates in each run;Run number;Number of good tcrates",
139 6000, 0, 6000));
140
141 unique_ptr<TH2F> tcrateNew_MINUS_tcrateOld__vs__runNum(new TH2F("tcrateNew_MINUS_tcrateOld__vs__runNum",
142 "Crate time constant changes vs run number : tcrate(new) uncertainty < 0.1ns;Run number;tcrate(new) - tcrate(previous iteration) [ns]",
143 6000, 0, 6000, 21, -10.5, 10.5));
144
145
146
147
148
149 if (!TimevsCrysNoCalibrations) return c_Failure;
150
153 TFile* histfile = 0;
154 TFile* histExtraCrateInfofile = 0; // Only created if needed for crates
155
156
157 unique_ptr<TTree> tree_crystal(new TTree("tree_crystal", "Debug data from bhabha time calibration algorithm for crystals"));
158
159 unique_ptr<TTree> tree_crate(new TTree("tree_crate", "Debug data from bhabha time calibration algorithm for crates"));
160 int tree_cid;
161
162 // Vector of time offsets to be saved in the database.
163 vector<float> t_offsets;
164 // Vector of time offset uncertainties to be saved in the database.
165 vector<float> t_offsets_unc;
166 vector<float> t_offsets_prev; // previous time offsets
167
168
169 int minNumEntries = 40;
170 int minNumEntriesCrateConvergence = 1000;
171
172
173 double mean = 0;
174 double sigma = -1;
175 double mean_unc = 0;
176 int crystalCalibSaved = 0;
177 double tsPrev = 0;
178
179
180 bool minRunNumBool = false;
181 bool maxRunNumBool = false;
182 int minRunNum = -1;
183 int maxRunNum = -1;
184 int minExpNum = -1;
185 int maxExpNum = -1;
186 for (auto expRun : getRunList()) {
187 int expNumber = expRun.first;
188 int runNumber = expRun.second;
189 if (!minRunNumBool) {
190 minExpNum = expNumber;
191 minRunNum = runNumber;
192 minRunNumBool = true;
193 }
194 if (!maxRunNumBool) {
195 maxExpNum = expNumber;
196 maxRunNum = runNumber;
197 maxRunNumBool = true;
198 }
199 if (((minRunNum > runNumber) && (minExpNum >= expNumber)) ||
200 (minExpNum > expNumber)) {
201 minExpNum = expNumber;
202 minRunNum = runNumber;
203 }
204 if (((maxRunNum < runNumber) && (maxExpNum <= expNumber)) ||
205 (maxExpNum < expNumber))
206
207 {
208 maxExpNum = expNumber;
209 maxRunNum = runNumber;
210 }
211 }
212
213 B2INFO("debugFilenameBase = " << debugFilenameBase);
214 string runNumsString = string("_") + to_string(minExpNum) + "_" + to_string(minRunNum) + string("-") +
215 to_string(maxExpNum) + "_" + to_string(maxRunNum);
216 string debugFilename = debugFilenameBase + runNumsString + string(".root");
217 string extraCratedebugFilename = debugFilenameBase + string("_cratesAllRuns.root");
218
219
220 // Need to load information about the event/run/experiment to get the right database information
221 // Will be used for:
222 // * ECLChannelMapper (to map crystal to crates)
223 // * crystal payload updating for iterating crystal and crate fits
224 int eventNumberForCrates = 1;
225
227 // simulate the initialize() phase where we can register objects in the DataStore
229 evtPtr.registerInDataStore();
231 // now construct the event metadata
232 evtPtr.construct(eventNumberForCrates, minRunNum, minExpNum);
233 // and update the database contents
234 DBStore& dbstore = DBStore::Instance();
235 dbstore.update();
236 // this is only needed it the payload might be intra-run dependent,
237 // that is if it might change during one run as well
238 dbstore.updateEvent();
239
240
241 B2INFO("Uploading payload for exp " << minExpNum << ", run " << minRunNum << ", event " << eventNumberForCrates);
242 updateDBObjPtrs(eventNumberForCrates, minRunNum, minExpNum);
243 unique_ptr<ECLChannelMapper> crystalMapper(new ECL::ECLChannelMapper());
244 crystalMapper->initFromDB();
245
246
247 //------------------------------------------------------------------------
248 //..Read payloads from database
249 B2INFO("Reading payloads: ECLCrystalTimeOffset and ECLCrateTimeOffset");
250 DBObjPtr<Belle2::ECLCrystalCalib> crystalTimeObject("ECLCrystalTimeOffset");
251 DBObjPtr<Belle2::ECLCrystalCalib> crateTimeObject("ECLCrateTimeOffset");
252
253 //..Get vectors of values from the payloads
254 vector<float> currentValuesCrys = crystalTimeObject->getCalibVector();
255 vector<float> currentUncCrys = crystalTimeObject->getCalibUncVector();
256 vector<float> currentValuesCrate = crateTimeObject->getCalibVector();
257 vector<float> currentUncCrate = crateTimeObject->getCalibUncVector();
258
259 //..Print out a few values for quality control
260 B2INFO("Values read from database. Write out for their values for comparison against those from tcol");
261 for (int ic = 0; ic < ECLElementNumbers::c_NCrystals; ic += 500) {
262 B2INFO("ts: cellID " << ic + 1 << " " << currentValuesCrys[ic] << " +/- " << currentUncCrys[ic]);
263 B2INFO("tcrate: cellID " << ic + 1 << " " << currentValuesCrate[ic] << " +/- " << currentUncCrate[ic]);
264 }
265
266
267 //..Read in the previous crystal payload values
268 vector<float> prevValuesCrys(ECLElementNumbers::c_NCrystals);
270 DBObjPtr<Belle2::ECLCrystalCalib> customPrevCrystalTimeObject("ECLCrystalTimeOffsetPreviousValues");
271 //..Get vectors of values from the payloads
272 prevValuesCrys = customPrevCrystalTimeObject->getCalibVector();
273
274 //..Print out a few values for quality control
275 B2INFO("Previous values read from database. Write out for their values for comparison against those from tcol");
276 for (int ic = 0; ic < ECLElementNumbers::c_NCrystals; ic += 500) {
277 B2INFO("ts custom previous payload: cellID " << ic + 1 << " " << prevValuesCrys[ic]);
278 }
279 }
280
281
282 //..Read bhabha payloads from database
283 B2INFO("Reading payloads: ECLCrystalTimeOffsetBhabha");
284 DBObjPtr<Belle2::ECLCrystalCalib> crystalBhabhaTimeObject("ECLCrystalTimeOffsetBhabha");
285
286 //..Get vectors of values from the payloads
287 vector<float> currentBhabhaValuesCrys = crystalBhabhaTimeObject->getCalibVector();
288 vector<float> currentBhabhaUncCrys = crystalBhabhaTimeObject->getCalibUncVector();
289
290 //..Print out a few values for quality control
291 for (int ic = 0; ic < ECLElementNumbers::c_NCrystals; ic += 500) {
292 B2INFO("ts bhabha: cellID " << ic + 1 << " " << currentBhabhaValuesCrys[ic] << " +/- " << currentBhabhaUncCrys[ic]);
293 }
294
295
296 //------------------------------------------------------------------------
297 //..Get the reference crystal information
298 auto refCrysIDzeroingCrate = getObjectPtr<TH1F>("refCrysIDzeroingCrate");
299
300 // crystal index for the crystals (one per crate) that is used as the reference crystal. This one has
301 // ts defined as zero. The crystal id runs 1...8636, not starting at 0.
302 B2INFO("Extract reference crystals from collector histogram.");
303 vector <short> crystalIDreferenceUntested;
304 for (int bin = 1; bin <= ECLElementNumbers::c_NCrystals; bin++) {
305 if (refCrysIDzeroingCrate->GetBinContent(bin) > 0.5) {
306 crystalIDreferenceUntested.push_back(bin);
307 }
308 }
309
310 // Output for the user the crystal id to be used as a reference
311 // and also state which crate the crystal is in.
312 B2INFO("Reference crystals to define as having ts=0. Base 1 counting for both crates and crystals");
313 for (long unsigned int crysRefCounter = 0; crysRefCounter < crystalIDreferenceUntested.size(); crysRefCounter++) {
314 int crys_id = crystalIDreferenceUntested[crysRefCounter] ;
315 int crate_id_from_crystal = crystalMapper->getCrateID(crys_id);
316 B2INFO(" crystal " << crys_id << " is a reference for crate " << crate_id_from_crystal);
317 }
318
319 // Check that the reference crystals make sense. There should be exactly one per crate but
320 // since the crystal calibration executes over multiple runs, it is possible that the
321 // reference crystals could change but we don't want to allow this.
322 B2INFO("Checking number of reference crystals");
323 B2INFO("Number of reference crystals = " << crystalIDreferenceUntested.size());
324
325 // Check that there are exactly 52 reference crystals
326 if (crystalIDreferenceUntested.size() != 52) {
327 B2FATAL("The number of reference crystals does not equal 52, which is one per crate");
328 return c_Failure;
329 } else {
330 B2INFO("Number of reference crystals is 52 as required");
331 }
332
333 // Count the number of reference crystals for each crate to make sure that there is exactly
334 // one reference crystal for each crate as defined by the payload/database.
335 // also fill the final vector that maps the crate id to the reference crystal id
336 vector <short> crateIDsNumRefCrystalsUntested(52, 0);
337 vector <short> crystalIDReferenceForZeroTs(52, 0);
338
339 for (long unsigned int crysRefCounter = 0; crysRefCounter < crystalIDreferenceUntested.size(); crysRefCounter++) {
340 int crys_id = crystalIDreferenceUntested[crysRefCounter] ;
341 int crate_id_from_crystal = crystalMapper->getCrateID(crys_id);
342 crateIDsNumRefCrystalsUntested[crate_id_from_crystal - 1]++;
343 crystalIDReferenceForZeroTs[crate_id_from_crystal - 1] = crys_id;
344 }
345 B2INFO("crystalIDReferenceForZeroTs = {");
346 for (int crateTest = 0; crateTest < 52 - 1; crateTest++) {
347 B2INFO(crystalIDReferenceForZeroTs[crateTest] << ",");
348 }
349 B2INFO(crystalIDReferenceForZeroTs[52 - 1] << "}");
350
351
352 // Make sure that there is only one reference crystal per crate as defined by the payload/database
353 for (int crateTest = 0; crateTest < 52; crateTest++) {
354 if (crateIDsNumRefCrystalsUntested[crateTest] != 1) {
355 B2FATAL("Crate " << crateTest + 1 << " (base 1) has " << crateIDsNumRefCrystalsUntested[crateTest] << " reference crystals");
356 return c_Failure;
357 }
358 }
359 B2INFO("All reference crystals are reasonably mapped one crystal to one crate for all crates");
360
361
362
363 B2INFO("Extract reference crystals from algorithm steering script if provided. If user inputs custom values via steering script for this algorithm, they are only applied after all the tests are performed on the values from the histogram and override the histogram valuees. User can adjust just a single crystal if desired. Use -1 to indicate that a crystal is not to be modified. Position of crystal in list determines the crate to which the crystal is meant to be associated.");
364
365 /* Test if the user wants to modify the reference crystals. This will probably be done very rarely,
366 perhaps less than once per year. If the user does want to change one or more reference
367 crystals then perform the checks again to make sure that there is still just one reference crystal
368 per crate after the modifications to the payload values with the user values.*/
369 bool userSetRefCrysPerCrate = false ;
370 for (int crateTest = 0; crateTest < 52; crateTest++) {
371 if (refCrysPerCrate[crateTest] != -1) {
372 crystalIDReferenceForZeroTs[crateTest] = refCrysPerCrate[crateTest] ;
373 B2INFO("Crate " << crateTest + 1 << " (base 1) new reference crystal = " << crystalIDReferenceForZeroTs[crateTest]);
374 userSetRefCrysPerCrate = true ;
375 }
376 }
377 if (userSetRefCrysPerCrate) {
378 B2INFO("User changed reference crystals via steering script");
379
380 // Validate crystals per crate again with the new user set values
381 fill(crateIDsNumRefCrystalsUntested.begin(), crateIDsNumRefCrystalsUntested.end(), 0);
382 for (long unsigned int crysRefCounter = 0; crysRefCounter < 52; crysRefCounter++) {
383 int crys_id = crystalIDReferenceForZeroTs[crysRefCounter] ;
384 int crate_id_from_crystal = crystalMapper->getCrateID(crys_id);
385 crateIDsNumRefCrystalsUntested[crate_id_from_crystal - 1]++;
386 }
387 for (int crateTest = 0; crateTest < 52; crateTest++) {
388 if (crateIDsNumRefCrystalsUntested[crateTest] != 1) {
389 B2FATAL("Crate " << crateTest + 1 << " (base 1) has " << crateIDsNumRefCrystalsUntested[crateTest] << " reference crystals");
390 return c_Failure;
391 }
392 }
393 B2INFO("All reference crystals are reasonably mapped one crystal to one crate for all crates after changes made by user steering script.");
394
395 // Save the information to the payload if there is at least one crate
396 // reference crystal that has been modified by the user steering file
398 refCrystalsCalib->setCalibVector(crystalIDReferenceForZeroTs);
399 saveCalibration(refCrystalsCalib, "ECLReferenceCrystalPerCrateCalib");
400 B2INFO("Created reference crystal per crate payload: ECLReferenceCrystalPerCrateCalib");
401 } else {
402 B2INFO("User did not change reference crystals via steering script");
403 }
404
405
406 //------------------------------------------------------------------------
407 //..Start looking at timing information
408
409 B2INFO("Debug output rootfile: " << debugFilename);
410 histfile = new TFile(debugFilename.c_str(), "recreate");
411
412
413 TimevsCrysPrevCrateCalibPrevCrystCalib ->Write();
414 TimevsCratePrevCrateCalibPrevCrystCalib->Write();
415 TimevsCrysNoCalibrations ->Write();
416 TimevsCrysPrevCrateCalibNoCrystCalib ->Write();
417 TimevsCrateNoCrateCalibPrevCrystCalib ->Write();
418
419 cutflow->Write();
420 svdEventT0->Write();
421
422
423 if (debugOutput) {
424 tree_crystal->Branch("cid", &tree_cid)->SetTitle("Cell ID, 1..8736");
425 tree_crystal->Branch("ts", &mean)->SetTitle("Time offset mean, ts, ns");
426 tree_crystal->Branch("tsUnc", &mean_unc)->SetTitle("Error of time ts mean, ns.");
427 tree_crystal->Branch("tsSigma", &sigma)->SetTitle("Sigma of time ts distribution, ns");
428 tree_crystal->Branch("crystalCalibSaved",
429 &crystalCalibSaved)->SetTitle("0=crystal skipped, 1=crystal calib saved (num entries based)");
430 tree_crystal->Branch("tsPrev", &tsPrev)->SetTitle("Previous crystal time offset, ts, ns");
431 tree_crystal->SetAutoSave(10);
432 }
433
434
435 double hist_tmin = TimevsCrysNoCalibrations->GetYaxis()->GetXmin();
436 double hist_tmax = TimevsCrysNoCalibrations->GetYaxis()->GetXmax();
437
438 double time_fit_min = hist_tmax; // Set min value to largest possible value so that it gets reset
439 double time_fit_max = hist_tmin; // Set max value to smallest possible value so that it gets reset
440
441 B2INFO("hist_tmin = " << hist_tmin);
442 B2INFO("hist_tmax = " << hist_tmax);
443
444 /* 1/(4fRF) = 0.4913 ns/clock tick, where fRF is the accelerator RF frequency.
445 Same for all crystals. */
446 const double TICKS_TO_NS = 1.0 / (4.0 * EclConfiguration::getRF()) * 1e3;
447
448 // The ts and tcrate database values are filled once per tcol instance so count the number of times that the database values
449 // were summed together by the histogram merging process and extract out the original values again.
450 auto databaseCounter = getObjectPtr<TH1I>("databaseCounter");
451 float numTimesFilled = databaseCounter->GetBinContent(1);
452 B2INFO("Number of times database histograms were merged = " << numTimesFilled);
453
454
455 auto TsDatabase = getObjectPtr<TH1F>("TsDatabase");
456 auto TsDatabaseUnc = getObjectPtr<TH1F>("TsDatabaseUnc");
457 for (int i = 1; i <= ECLElementNumbers::c_NCrystals; i++) {
458 t_offsets.push_back(TsDatabase->GetBinContent(i) / numTimesFilled);
459 t_offsets_prev.push_back(TsDatabase->GetBinContent(i) / numTimesFilled);
460
461 B2INFO("t_offsets_prev (last iter) at crysID " << i << " = " << t_offsets_prev[i - 1]);
462
463 t_offsets_unc.push_back(TsDatabaseUnc->GetBinContent(i) / numTimesFilled);
464 }
465
466
467 /* CRYSTAL CORRECTIONS */
468
469 /* Make a 1D histogram of the number of hits per crystal. This will help with the validations
470 to make sure that all the crystals had enough hits and to look for problems.*/
471 TH1D* h_crysHits = TimevsCrysPrevCrateCalibNoCrystCalib->ProjectionX("h_crysHits");
472 h_crysHits->SetTitle("Hits per crystal;Crystal id");
473
474 histfile->WriteTObject(h_crysHits, "h_crysHits");
475
476
477 // Loop over all the crystals for doing the crystal calibation
478 for (int crys_id = cellIDLo; crys_id <= cellIDHi; crys_id++) {
479 crystalCalibSaved = 0;
480
481 double database_mean = 0;
482 double database_mean_unc = 0;
483
484 B2INFO("Crystal id = " << crys_id);
485
486
487 vector<bool> ts_new_was_set(ECLElementNumbers::c_NCrystals, false);
488
489
490 /* Determining which bins to mask out for mean calculation
491 */
492
493 TH1D* h_time = TimevsCrysPrevCrateCalibNoCrystCalib->ProjectionY((string("h_time_psi__") + to_string(crys_id)).c_str(),
494 crys_id, crys_id);
495 TH1D* h_timeMask = (TH1D*)h_time->Clone();
496 TH1D* h_timeMasked = (TH1D*)h_time->Clone((string("h_time_psi_masked__") + to_string(crys_id)).c_str());
497 TH1D* h_timeRebin = (TH1D*)h_time->Clone();
498
499 // Do rebinning and cleaning of some bins but only if the user selection values call for it since it slows the code down
501
502 h_timeRebin->Rebin(meanCleanRebinFactor);
503
504 h_timeMask->Scale(0.0); // set all bins to being masked off
505
506 time_fit_min = hist_tmax; // Set min value to largest possible value so that it gets reset
507 time_fit_max = hist_tmin; // Set max value to smallest possible value so that it gets reset
508
509 // Find value of bin with max value
510 double histRebin_max = h_timeRebin->GetMaximum();
511
512 bool maskedOutNonZeroBin = false;
513 // Loop over all bins to find those with content less than a certain threshold. Mask the non-rebinned histogram for the corresponding bins
514 for (int bin = 1; bin <= h_timeRebin->GetNbinsX(); bin++) {
515 for (int rebinCounter = 1; rebinCounter <= meanCleanRebinFactor; rebinCounter++) {
516 int nonRebinnedBinNumber = (bin - 1) * meanCleanRebinFactor + rebinCounter;
517 if (nonRebinnedBinNumber < h_time->GetNbinsX()) {
518 if (h_timeRebin->GetBinContent(bin) >= histRebin_max * meanCleanCutMinFactor) {
519 h_timeMask->SetBinContent(nonRebinnedBinNumber, 1);
520
521 // Save the lower and upper edges of the rebin histogram time range for fitting purposes
522 double x_lower = h_timeRebin->GetXaxis()->GetBinLowEdge(bin);
523 double x_upper = h_timeRebin->GetXaxis()->GetBinUpEdge(bin);
524 if (x_lower < time_fit_min) {
525 time_fit_min = x_lower;
526 }
527 if (x_upper > time_fit_max) {
528 time_fit_max = x_upper;
529 }
530
531 } else {
532 if (h_time->GetBinContent(nonRebinnedBinNumber) > 0) {
533 B2DEBUG(22, "Setting bin " << nonRebinnedBinNumber << " from " << h_timeMasked->GetBinContent(nonRebinnedBinNumber) << " to 0");
534 maskedOutNonZeroBin = true;
535 }
536 h_timeMasked->SetBinContent(nonRebinnedBinNumber, 0);
537 }
538 }
539 }
540 }
541 B2INFO("Bins with non-zero values have been masked out: " << maskedOutNonZeroBin);
542 h_timeMasked->ResetStats();
543 h_timeMask->ResetStats();
544
545 }
546
547 // Calculate mean from masked histogram
548 double default_meanMasked = h_timeMasked->GetMean();
549 //double default_meanMasked_unc = h_timeMasked->GetMeanError();
550 B2INFO("default_meanMasked = " << default_meanMasked);
551
552
553 // Get the overall mean and standard deviation of the distribution within the plot. This doesn't require a fit.
554 double default_mean = h_time->GetMean();
555 double default_mean_unc = h_time->GetMeanError();
556 double default_sigma = h_time->GetStdDev();
557
558 B2INFO("Fitting crystal between " << time_fit_min << " and " << time_fit_max);
559
560 // gaus(0) is a substitute for [0]*exp(-0.5*((x-[1])/[2])**2)
561 TF1* gaus = new TF1("func", "gaus(0)", time_fit_min, time_fit_max);
562 gaus->SetParNames("numCrystalHitsNormalization", "mean", "sigma");
563 /*
564 gaus->ReleaseParameter(0); // number of crystals
565 gaus->ReleaseParameter(1); // mean
566 gaus->ReleaseParameter(2); // standard deviation
567 */
568
569 double hist_max = h_time->GetMaximum();
570
571 //=== Estimate initial value of sigma as std dev.
572 double stddev = h_time->GetStdDev();
573 sigma = stddev;
574 mean = default_mean;
575
576 //=== Setting parameters for initial iteration
577 gaus->SetParameter(0, hist_max / 2.);
578 gaus->SetParameter(1, mean);
579 gaus->SetParameter(2, sigma);
580 // L -- Use log likelihood method
581 // I -- Use integral of function in bin instead of value at bin center // not using
582 // R -- Use the range specified in the function range
583 // B -- Fix one or more parameters with predefined function // not using
584 // Q -- Quiet mode
585
586 h_timeMasked->Fit(gaus, "LQR"); // L for likelihood, R for x-range, Q for fit quiet mode
587
588 double fit_mean = gaus->GetParameter(1);
589 double fit_mean_unc = gaus->GetParError(1);
590 double fit_sigma = gaus->GetParameter(2);
591
592 double meanDiff = fit_mean - default_mean;
593 double meanUncDiff = fit_mean_unc - default_mean_unc;
594 double sigmaDiff = fit_sigma - default_sigma;
595
596 bool good_fit = false;
597
598 if ((fabs(meanDiff) > 10) ||
599 (fabs(meanUncDiff) > 10) ||
600 (fabs(sigmaDiff) > 10) ||
601 (fit_mean_unc > 0.09) ||
602 (fit_sigma < 0.1) ||
603 (fit_mean < time_fit_min) ||
604 (fit_mean > time_fit_max)) {
605 B2INFO("Crystal id = " << crys_id);
606 B2INFO("fit mean, default mean = " << fit_mean << ", " << default_mean);
607 B2INFO("fit mean unc, default mean unc = " << fit_mean_unc << ", " << default_mean_unc);
608 B2INFO("fit sigma, default sigma = " << fit_sigma << ", " << default_sigma);
609
610 B2INFO("crystal fit mean - hist mean = " << meanDiff);
611 B2INFO("fit mean unc. - hist mean unc. = " << meanUncDiff);
612 B2INFO("fit sigma - hist sigma = " << sigmaDiff);
613
614 B2INFO("fit_mean = " << fit_mean);
615 B2INFO("time_fit_min = " << time_fit_min);
616 B2INFO("time_fit_max = " << time_fit_max);
617
618 if (fabs(meanDiff) > 10) B2INFO("fit mean diff too large");
619 if (fabs(meanUncDiff) > 10) B2INFO("fit mean unc diff too large");
620 if (fabs(sigmaDiff) > 10) B2INFO("fit mean sigma diff too large");
621 if (fit_mean_unc > 0.09) B2INFO("fit mean unc too large");
622 if (fit_sigma < 0.1) B2INFO("fit sigma too small");
623
624 } else {
625 good_fit = true;
626 }
627
628
629
630 // Set the tree_crystal values - ignore fit values !!!!!!!!!!!!!!!!
631 sigma = default_sigma;
632
633
634 int numEntries = h_time->GetEntries();
635 /* If number of entries in histogram is greater than X then use the statistical information from the data otherwise
636 leave crystal uncalibrated. Histograms are still shown though. ALSO require the that fits are good.*/
637 if ((numEntries >= minNumEntries) && good_fit) {
638 crystalCalibSaved = 1;
639 database_mean = fit_mean;
640 database_mean_unc = fit_mean_unc;
641 } else {
642 database_mean = default_mean;
643 database_mean_unc = -fabs(default_mean_unc);
644 }
645
646 if (numEntries < minNumEntries) B2INFO("Number of entries less than minimum");
647 if (numEntries == 0) B2INFO("Number of entries == 0");
648
649
650 tree_cid = crys_id;
651
652 // For the database, convert back from ns to ADC ticks.
653 t_offsets[crys_id - 1] = database_mean / TICKS_TO_NS;
654 t_offsets_unc[crys_id - 1] = database_mean_unc / TICKS_TO_NS;
655
656
657 histfile->WriteTObject(h_time, (string("h_time_psi") + to_string(crys_id)).c_str());
658 histfile->WriteTObject(h_timeMasked, (string("h_time_psi_masked") + to_string(crys_id)).c_str());
659
660 mean = database_mean;
661 mean_unc = database_mean_unc;
662
663 tsPrev = t_offsets_prev[crys_id - 1] * TICKS_TO_NS;
664
665 delete gaus;
666 tree_crystal->Fill();
667 }
668
669
670 // Shift the crystal time calibration constants by the reference crystal calibration constant values
671 if (cellIDLo <= cellIDHi) {
672 vector <double> tsRefCID ;
673 B2INFO("crystal times before shift");
674 for (int crate_id = 1; crate_id <= 52; crate_id++) {
675 tsRefCID.push_back(t_offsets[ crystalIDReferenceForZeroTs[crate_id - 1] - 1 ]);
676 B2INFO("crystal time [crystal = " << crystalIDReferenceForZeroTs[crate_id - 1] << ", crate = " << crate_id << " (base 1)] = " <<
677 t_offsets[ crystalIDReferenceForZeroTs[crate_id - 1] - 1 ] << " ticks");
678 }
679
680 B2INFO("crystal times after shift wrt reference crystal");
681 for (int crys_id = 1; crys_id <= ECLElementNumbers::c_NCrystals; crys_id++) {
682 int crate_id_from_crystal = crystalMapper->getCrateID(crys_id);
683 B2INFO("crystal time before shift [crystal = " << crys_id << ", crate = " << crate_id_from_crystal << " (base 1)] = " <<
684 t_offsets[crys_id - 1] << " +- " << t_offsets_unc[crys_id - 1] << " ticks");
685
686 /* Shift the crystal time constant by that of the reference crystal, but only if
687 there were values to shift. If there were no entries, ts=0 and ts_unc=0, which
688 are special values so do not shift these crystals. */
689 if (t_offsets[crys_id - 1] == 0 && t_offsets_unc[crys_id - 1] == 0) {
690 B2INFO("crystal time after shift [crystal = " << crys_id << ", crate = " << crate_id_from_crystal << " (base 1)] = " <<
691 t_offsets[crys_id - 1] << " ticks. No change because ts=0 and ts_unc=0 (no entries).");
692 } else {
693 t_offsets[crys_id - 1] = t_offsets[crys_id - 1] - tsRefCID[crate_id_from_crystal - 1];
694 B2INFO("crystal time after shift [crystal = " << crys_id << ", crate = " << crate_id_from_crystal << " (base 1)] = " <<
695 t_offsets[crys_id - 1] << " ticks");
696 }
697
698
699 // Fill histograms with the difference in the ts values between iterations
700 double tsDiff_ns = (t_offsets[crys_id - 1] - t_offsets_prev[crys_id - 1]) * TICKS_TO_NS;
701 double tsDiffBhabha_ns = -999;
703 tsDiffBhabha_ns = (t_offsets[crys_id - 1] - currentBhabhaValuesCrys[crys_id - 1]) * TICKS_TO_NS;
704 }
705
706 B2INFO("Crystal " << crys_id << ": ts new bhabha - old merged = (" <<
707 t_offsets[crys_id - 1] << " - " << t_offsets_prev[crys_id - 1] <<
708 ") ticks * " << TICKS_TO_NS << " ns/tick = " << tsDiff_ns << " ns");
709 B2INFO("Crystal " << crys_id << ": ts new bhabha - old bhabha = (" <<
710 t_offsets[crys_id - 1] << " - " << currentBhabhaValuesCrys[crys_id - 1] <<
711 ") ticks * " << TICKS_TO_NS << " ns/tick = " << tsDiffBhabha_ns << " ns");
712
713 tsNew_MINUS_tsOld__cid->SetBinContent(crys_id, tsDiff_ns);
714 tsNew_MINUS_tsOld__cid->SetBinError(crys_id, 0);
715 tsNew_MINUS_tsOld__cid->ResetStats();
716
717 tsNew_MINUS_tsOld->Fill(tsDiff_ns);
718
719
720 tsNew_MINUS_tsOldBhabha__cid->SetBinContent(crys_id, tsDiffBhabha_ns);
721 tsNew_MINUS_tsOldBhabha__cid->SetBinError(crys_id, 0);
722 tsNew_MINUS_tsOldBhabha__cid->ResetStats();
723
724 tsNew_MINUS_tsOldBhabha->Fill(tsDiffBhabha_ns);
725
726
727
728 /* Fill histograms with the difference in the ts values from this iteration
729 and the previous values read in from the payload. */
730 double tsDiffCustomOld_ns = -999;
732 tsDiffCustomOld_ns = (t_offsets[crys_id - 1] - prevValuesCrys[crys_id - 1]) * TICKS_TO_NS;
733 B2INFO("Crystal " << crys_id << ": ts new bhabha - 'before 1st iter' merged = (" <<
734 t_offsets[crys_id - 1] << " - " << prevValuesCrys[crys_id - 1] <<
735 ") ticks * " << TICKS_TO_NS << " ns/tick = " << tsDiffCustomOld_ns << " ns");
736 }
737 tsNew_MINUS_tsCustomPrev__cid->SetBinContent(crys_id, tsDiffCustomOld_ns);
738 tsNew_MINUS_tsCustomPrev__cid->SetBinError(crys_id, 0);
739 tsNew_MINUS_tsCustomPrev__cid->ResetStats();
740
741 tsNew_MINUS_tsCustomPrev->Fill(tsDiffCustomOld_ns);
742
743 }
744
745 // Save the histograms to the output root file
746 histfile->WriteTObject(tsNew_MINUS_tsOld__cid.get(), "tsNew_MINUS_tsOld__cid");
747 histfile->WriteTObject(tsNew_MINUS_tsOld.get(), "tsNew_MINUS_tsOld");
748
749 histfile->WriteTObject(tsNew_MINUS_tsCustomPrev__cid.get(), "tsNew_MINUS_tsCustomPrev__cid");
750 histfile->WriteTObject(tsNew_MINUS_tsCustomPrev.get(), "tsNew_MINUS_tsCustomPrev");
751
752 histfile->WriteTObject(tsNew_MINUS_tsOldBhabha__cid.get(), "tsNew_MINUS_tsOldBhabha__cid");
753 histfile->WriteTObject(tsNew_MINUS_tsOldBhabha.get(), "tsNew_MINUS_tsOldBhabha");
754 }
755
756
757 //..Store previous crystal calibration constants to payload under different
758 // names so that they can be read in for comparison later. These are temporary
759 // payloads that are only used for plotting purposes while running the calibration
760 // and does not need to be added to any global tag.
762 ECLCrystalCalib* crysTCalib_prev = new ECLCrystalCalib();
763 crysTCalib_prev->setCalibVector(currentValuesCrys, currentUncCrys);
764
765 ECLCrystalCalib* crysBhabhaTCalib_prev = new ECLCrystalCalib();
766 crysBhabhaTCalib_prev->setCalibVector(currentBhabhaValuesCrys, currentBhabhaUncCrys);
767
768
769 // Save the information to the payload if there is at least one crystal
770 // begin calibrated.
771 if (cellIDLo <= cellIDHi) {
772 saveCalibration(crysTCalib_prev, "ECLCrystalTimeOffsetPreviousValues");
773 B2INFO("Previous overall crystal payload made");
774
775 saveCalibration(crysBhabhaTCalib_prev, "ECLCrystalTimeOffsetBhabhaPreviousValues");
776 B2INFO("Previous bhabha crystal payload made");
777 }
778 }
779
780
781 ECLCrystalCalib* BhabhaTCalib = new ECLCrystalCalib();
782 BhabhaTCalib->setCalibVector(t_offsets, t_offsets_unc);
783
784 // Save the information to the payload if there is at least one crystal
785 // begin calibrated.
786 if (cellIDLo <= cellIDHi) {
787 saveCalibration(BhabhaTCalib, "ECLCrystalTimeOffset");
788 saveCalibration(BhabhaTCalib, "ECLCrystalTimeOffsetBhabha");
789 B2DEBUG(22, "crystal payload made");
790 }
791
792
793 B2DEBUG(22, "end of crystal start of crate corrections .....");
794
795
796 //==============================================================
797 /* CRATE CORRECTIONS */
798
799 hist_tmin = TimevsCrateNoCrateCalibPrevCrystCalib->GetYaxis()->GetXmin();
800 hist_tmax = TimevsCrateNoCrateCalibPrevCrystCalib->GetYaxis()->GetXmax();
801
802 B2DEBUG(22, "Found min/max of X axis of TimevsCrateNoCrateCalibPrevCrystCalib");
803
804 // Vector of time offsets to be saved in the database.
805
806 auto TcrateDatabase = getObjectPtr<TH1F>("TcrateDatabase");
807
808
809 B2DEBUG(22, "Retrieved Ts and Tcrate histograms from tcol root file");
810
811
812 vector<float> tcrate_mean_new(52, 0.0);
813 vector<float> tcrate_mean_unc_new(52, 0.0);
814 vector<float> tcrate_sigma_new(52, 0.0);
815 vector<float> tcrate_mean_prev(52, 0.0);
816 // vector<float> tcrate_sigma_prev(52, 0.0); // currently not used
817 vector<bool> tcrate_new_was_set(52, false);
818 vector<bool> tcrate_new_goodQuality(52, false);
819
820 B2DEBUG(22, "crate vectors set");
821
822
823
824 // Crate time calibration constants are saved per crystal so read them per crystal
825 // and save as one entry per crate in the array
826 for (int crys_id = 1; crys_id <= ECLElementNumbers::c_NCrystals; crys_id++) {
827 int crate_id_from_crystal = crystalMapper->getCrateID(crys_id);
828 tcrate_mean_prev[crate_id_from_crystal - 1] = TcrateDatabase->GetBinContent(crys_id) / numTimesFilled;
829 }
830
831
832 B2INFO("Print out previous crate time calibration constants to make sure they match from the two different sources.");
833 for (int crate_id = 1; crate_id <= 52; crate_id++) {
834 B2INFO("tcrate_mean_prev[crate " << crate_id << " (base 1)] = " << tcrate_mean_prev[crate_id - 1]);
835
836 int thisRefCellID = crystalIDReferenceForZeroTs[crate_id - 1];
837 B2INFO("tcrate from payload: ref cellID " << thisRefCellID << " " << currentValuesCrate[thisRefCellID - 1] << " +/- " <<
838 currentUncCrate[thisRefCellID - 1]);
839 }
840
841
842 /* Read in the histogram about the crate calibration constant differences between iterations
843 if it exists. This way the histograms can be updated after each run.*/
844 if (crateIDLo <= crateIDHi) {
845 TFile* histExtraCrateInfofile_dummy = 0; // Only created if needed for crates
846 B2INFO("Debug output rootfile used for crate iterations: " << extraCratedebugFilename);
847 histExtraCrateInfofile_dummy = new TFile(extraCratedebugFilename.c_str(), "UPDATE");
848
849
850 // If the histogram already exists then read it in and recreate the file so that we can save an updated version of the histogram.
851 TKey* key = histExtraCrateInfofile_dummy->FindKey("tcrateNew_MINUS_tcrateOld_allRuns");
852 if (key != 0) {
853 TH1F* h = (TH1F*)histExtraCrateInfofile_dummy->Get("tcrateNew_MINUS_tcrateOld_allRuns");
854 tcrateNew_MINUS_tcrateOld_allRuns->Add(h);
855 }
856
857 key = histExtraCrateInfofile_dummy->FindKey("tcrateNew_MINUS_tcrateOld_allRuns_allCrates");
858 if (key != 0) {
859 TH1F* h = (TH1F*)histExtraCrateInfofile_dummy->Get("tcrateNew_MINUS_tcrateOld_allRuns_allCrates");
860 tcrateNew_MINUS_tcrateOld_allRuns_allCrates->Add(h);
861 }
862
863 key = histExtraCrateInfofile_dummy->FindKey("num_tcrates_perRun");
864 if (key != 0) {
865 TH1F* h = (TH1F*)histExtraCrateInfofile_dummy->Get("num_tcrates_perRun");
866 num_tcrates_perRun->Add(h);
867 }
868
869 key = histExtraCrateInfofile_dummy->FindKey("tcrateNew_MINUS_tcrateOld__vs__runNum");
870 if (key != 0) {
871 TH1F* h = (TH1F*)histExtraCrateInfofile_dummy->Get("tcrateNew_MINUS_tcrateOld__vs__runNum");
872 tcrateNew_MINUS_tcrateOld__vs__runNum->Add(h);
873 }
874
875 histExtraCrateInfofile_dummy->Close();
876
877 /* After reading in all the histograms, recreate the root file from empty so that the
878 histograms can be made again with the updated values.*/
879 histExtraCrateInfofile = new TFile(extraCratedebugFilename.c_str(), "recreate");
880 }
881
882
883
884 for (int crate_id = crateIDLo; crate_id <= crateIDHi; crate_id++) {
885
886 B2DEBUG(22, "Start of crate id = " << crate_id);
887
888 TH1D* h_time_crate = TimevsCrateNoCrateCalibPrevCrystCalib->ProjectionY("h_time_psi_crate", crate_id, crate_id);
889 TH1D* h_time_crate_mask = (TH1D*)h_time_crate->Clone();
890 TH1D* h_time_crate_masked = (TH1D*)h_time_crate->Clone();
891 TH1D* h_time_crate_rebin = (TH1D*)h_time_crate->Clone();
892
893
894 // Do rebinning and cleaning of some bins but only if the user selection values call for it since it slows the code down
896
897 h_time_crate_rebin->Rebin(meanCleanRebinFactor);
898 h_time_crate_mask->Scale(0.0); // set all bins to being masked off
899
900 time_fit_min = hist_tmax; // Set min value to largest possible value so that it gets reset
901 time_fit_max = hist_tmin; // Set max value to smallest possible value so that it gets reset
902
903 // Find value of bin with max value
904 double histRebin_max = h_time_crate_rebin->GetMaximum();
905
906 bool maskedOutNonZeroBin = false;
907 // Loop over all bins to find those with content less than a certain threshold. Mask the non-rebinned histogram for the corresponding bins
908 for (int bin = 1; bin <= h_time_crate_rebin->GetNbinsX(); bin++) {
909 for (int rebinCounter = 1; rebinCounter <= meanCleanRebinFactor; rebinCounter++) {
910 int nonRebinnedBinNumber = (bin - 1) * meanCleanRebinFactor + rebinCounter;
911 if (nonRebinnedBinNumber < h_time_crate->GetNbinsX()) {
912 if (h_time_crate_rebin->GetBinContent(bin) >= histRebin_max * meanCleanCutMinFactor) {
913 h_time_crate_mask->SetBinContent(nonRebinnedBinNumber, 1);
914
915 // Save the lower and upper edges of the rebin histogram time range for fitting purposes
916 double x_lower = h_time_crate_rebin->GetXaxis()->GetBinLowEdge(bin);
917 double x_upper = h_time_crate_rebin->GetXaxis()->GetBinUpEdge(bin);
918 if (x_lower < time_fit_min) {
919 time_fit_min = x_lower;
920 }
921 if (x_upper > time_fit_max) {
922 time_fit_max = x_upper;
923 }
924 } else {
925 if (h_time_crate->GetBinContent(nonRebinnedBinNumber) > 0) {
926 B2DEBUG(22, "Setting bin " << nonRebinnedBinNumber << " from " << h_time_crate_masked->GetBinContent(
927 nonRebinnedBinNumber) << " to 0");
928 maskedOutNonZeroBin = true;
929 }
930 h_time_crate_masked->SetBinContent(nonRebinnedBinNumber, 0);
931 }
932 }
933 }
934 }
935 B2INFO("Bins with non-zero values have been masked out: " << maskedOutNonZeroBin);
936 h_time_crate_masked->ResetStats();
937 h_time_crate_mask->ResetStats();
938
939 }
940
941
942
943 B2DEBUG(22, "crate loop - projected h_time_psi_crate");
944
945
946 double default_mean_crate = h_time_crate_masked->GetMean();
947 double default_mean_crate_unc = h_time_crate_masked->GetMeanError();
948 double default_sigma_crate = h_time_crate_masked->GetStdDev();
949 B2INFO("Fitting crate between " << time_fit_min << " and " << time_fit_max);
950 TF1* gaus = new TF1("func", "gaus(0)", time_fit_min, time_fit_max);
951 gaus->SetParNames("numCrateHisNormalization", "mean", "sigma");
952 double hist_max = h_time_crate->GetMaximum();
953 double stddev = h_time_crate->GetStdDev();
954 double sigma_crate = stddev;
955 double mean_crate = default_mean_crate;
956 gaus->SetParameter(0, hist_max / 2.);
957 gaus->SetParameter(1, mean_crate);
958 gaus->SetParameter(2, sigma_crate);
959
960 h_time_crate_masked->Fit(gaus, "LQR"); // L for likelihood, R for x-range, Q for fit quiet mode
961
962 double fit_mean_crate = gaus->GetParameter(1);
963 double fit_mean_crate_unc = gaus->GetParError(1);
964 double fit_sigma_crate = gaus->GetParameter(2);
965
966 double meanDiff = fit_mean_crate - default_mean_crate;
967 double meanUncDiff = fit_mean_crate_unc - default_mean_crate_unc;
968 double sigmaDiff = fit_sigma_crate - default_sigma_crate;
969
970 bool good_fit = false;
971
972 B2DEBUG(22, "Crate id = " << crate_id << " with crate mean = " << default_mean_crate << " +- " << fit_mean_crate_unc);
973
974 if ((fabs(meanDiff) > 7) ||
975 (fabs(meanUncDiff) > 7) ||
976 (fabs(sigmaDiff) > 7) ||
977 (fit_mean_crate_unc > 3) ||
978 (fit_sigma_crate < 0.1) ||
979 (fit_mean_crate < time_fit_min) ||
980 (fit_mean_crate > time_fit_max)) {
981 B2INFO("Crate id = " << crate_id);
982 B2INFO("fit mean, default mean = " << fit_mean_crate << ", " << default_mean_crate);
983 B2INFO("fit sigma, default sigma = " << fit_sigma_crate << ", " << default_sigma_crate);
984
985 B2INFO("crate fit mean - hist mean = " << meanDiff);
986 B2INFO("fit mean unc. - hist mean unc. = " << meanUncDiff);
987 B2INFO("fit sigma - hist sigma = " << sigmaDiff);
988 B2INFO("fit_mean_crate = " << fit_mean_crate);
989 B2INFO("time_fit_min = " << time_fit_min);
990 B2INFO("time_fit_max = " << time_fit_max);
991 } else {
992 good_fit = true;
993 }
994
995 int numEntries = h_time_crate->GetEntries();
996 B2INFO("Number entries = " << numEntries);
997 double database_mean_crate = 0;
998 double database_mean_crate_unc = 0;
999 if ((numEntries >= minNumEntries) && good_fit) {
1000 database_mean_crate = fit_mean_crate;
1001 database_mean_crate_unc = fit_mean_crate_unc;
1002
1003 if ((numEntries >= minNumEntriesCrateConvergence) && (fit_mean_crate_unc < 0.1)) {
1004 tcrate_new_goodQuality[crate_id - 1] = true;
1005 }
1006 } else {
1007 database_mean_crate = default_mean_crate;
1008 database_mean_crate_unc = default_mean_crate_unc;
1009 }
1010 if (numEntries == 0) {
1011 database_mean_crate = 0;
1012 database_mean_crate_unc = 0;
1013 }
1014
1015 tcrate_mean_new[crate_id - 1] = database_mean_crate;
1016 tcrate_mean_unc_new[crate_id - 1] = database_mean_crate_unc;
1017 tcrate_sigma_new[crate_id - 1] = fit_sigma_crate;
1018 tcrate_new_was_set[crate_id - 1] = true;
1019
1020
1021 histfile->WriteTObject(h_time_crate, (string("h_time_psi_crate") + to_string(crate_id)).c_str());
1022 histfile->WriteTObject(h_time_crate_masked, (string("h_time_psi_crate_masked") + to_string(crate_id)).c_str());
1023 histfile->WriteTObject(h_time_crate_rebin, (string("h_time_psi_crate_rebinned") + to_string(crate_id)).c_str());
1024
1025 delete gaus;
1026 }
1027
1028 B2DEBUG(22, "crate histograms made");
1029
1030
1031 // Save database for crates
1032 // Vector of time offsets to be saved in the database.
1033 vector<float> t_offsets_crate;
1034 // Vector of time offset uncertainties to be saved in the database.
1035 vector<float> t_offsets_crate_unc;
1036 for (int i = 1; i <= ECLElementNumbers::c_NCrystals; i++) {
1037 t_offsets_crate.push_back(0);
1038 t_offsets_crate_unc.push_back(0);
1039 }
1040
1041
1042 for (int crys_id = 1; crys_id <= ECLElementNumbers::c_NCrystals; crys_id++) {
1043 int crate_id_from_crystal = crystalMapper->getCrateID(crys_id);
1044 if (tcrate_new_was_set[crate_id_from_crystal - 1]) {
1045 t_offsets_crate[crys_id - 1] = tcrate_mean_new[crate_id_from_crystal - 1] / TICKS_TO_NS;
1046 t_offsets_crate_unc[crys_id - 1] = tcrate_mean_unc_new[crate_id_from_crystal - 1] / TICKS_TO_NS;
1047
1048 } else {
1049 t_offsets_crate[crys_id - 1] = tcrate_mean_prev[crate_id_from_crystal - 1];
1050 B2INFO("used old crate mean but zeroed uncertainty since not saved in root file");
1051 }
1052 }
1053
1054
1055 // Fill histograms with the difference in the tcrate values
1056 if (crateIDLo <= crateIDHi) {
1057 for (int crate_id = crateIDLo; crate_id <= crateIDHi; crate_id++) {
1058 // tcrate_mean_new already in ns, but tcrate_mean_prev in ticks.
1059 double tCrateDiff_ns = tcrate_mean_new[crate_id - 1] - (tcrate_mean_prev[crate_id - 1] * TICKS_TO_NS);
1060 B2INFO("Crate " << crate_id << ": tcrate new - previous iteration = "
1061 << tcrate_mean_new[crate_id - 1]
1062 << " - " << tcrate_mean_prev[crate_id - 1] * TICKS_TO_NS
1063 << " = " << tCrateDiff_ns << " ns");
1064 tcrateNew_MINUS_tcrateOld__crateID->SetBinContent(crate_id, tCrateDiff_ns);
1065 tcrateNew_MINUS_tcrateOld__crateID->SetBinError(crate_id, 0);
1066 tcrateNew_MINUS_tcrateOld__crateID->ResetStats();
1067
1068 tcrateNew_MINUS_tcrateOld->Fill(tCrateDiff_ns);
1069
1070 // Save the histograms monitoring the change between iterations
1071 tcrateNew_MINUS_tcrateOld_allRuns_allCrates->Fill(tCrateDiff_ns);
1072 if (tcrate_new_goodQuality[crate_id - 1]) {
1073 tcrateNew_MINUS_tcrateOld_allRuns->Fill(tCrateDiff_ns);
1074 num_tcrates_perRun->Fill(minRunNum);
1075 tcrateNew_MINUS_tcrateOld__vs__runNum->Fill(minRunNum, tCrateDiff_ns);
1076 }
1077 }
1078
1079 // Save the histograms to the output root file
1080 histfile->WriteTObject(tcrateNew_MINUS_tcrateOld__crateID.get(), "tcrateNew_MINUS_tcrateOld__crateID");
1081 histfile->WriteTObject(tcrateNew_MINUS_tcrateOld.get(), "tcrateNew_MINUS_tcrateOld");
1082
1083 // Save the histograms to the crate iterations file
1084 histExtraCrateInfofile->WriteTObject(tcrateNew_MINUS_tcrateOld_allRuns.get(), "tcrateNew_MINUS_tcrateOld_allRuns");
1085 histExtraCrateInfofile->WriteTObject(tcrateNew_MINUS_tcrateOld_allRuns_allCrates.get(),
1086 "tcrateNew_MINUS_tcrateOld_allRuns_allCrates");
1087 histExtraCrateInfofile->WriteTObject(num_tcrates_perRun.get(), "num_tcrates_perRun");
1088 histExtraCrateInfofile->WriteTObject(tcrateNew_MINUS_tcrateOld__vs__runNum.get(), "tcrateNew_MINUS_tcrateOld__vs__runNum");
1089 }
1090
1091
1092 ECLCrystalCalib* BhabhaTCrateCalib = new ECLCrystalCalib();
1093 BhabhaTCrateCalib->setCalibVector(t_offsets_crate, t_offsets_crate_unc);
1094
1095
1096 // Save the information to the payload if there is at least one crate
1097 // begin calibrated.
1098 if (crateIDLo <= crateIDHi) {
1099 saveCalibration(BhabhaTCrateCalib, "ECLCrateTimeOffset");
1100 B2DEBUG(22, "crate payload made");
1101
1102 histExtraCrateInfofile->Close();
1103 }
1104
1105
1106 int tree_crateid;
1107 int tree_runNum;
1108 double tree_tcrate_mean;
1109 double tree_tcrate_mean_unc;
1110 double tree_tcrate_sigma;
1111 double tree_tcrate_meanPrev;
1112
1113 tree_crate->Branch("runNum", &tree_runNum)->SetTitle("Run number, 0..infinity and beyond!");
1114 tree_crate->Branch("crateid", &tree_crateid)->SetTitle("Crate id, 1..52");
1115 tree_crate->Branch("tcrate", &tree_tcrate_mean)->SetTitle("Crate time offset mean, tcrate, ns");
1116 tree_crate->Branch("tcratePrev", &tree_tcrate_meanPrev)->SetTitle("Previous crate time offset mean, tcrate, ns");
1117 tree_crate->Branch("tcrate_unc", &tree_tcrate_mean_unc)->SetTitle("Error of time tcrate mean, ns.");
1118 tree_crate->Branch("tcrate_sigma", &tree_tcrate_sigma)->SetTitle("Sigma of time tcrate distribution, ns");
1119 tree_crate->SetAutoSave(10);
1120
1121
1122 for (auto expRun : getRunList()) {
1123 // Key command to make sure your DBObjPtrs are correct
1124 B2INFO("run num, exp num: " << expRun.second << ", " << expRun.first);
1125 int runNumber = expRun.second;
1126
1127 for (int crate_id = 1; crate_id <= 52; crate_id++) {
1128 if (tcrate_new_was_set[crate_id - 1]) {
1129 tree_runNum = runNumber;
1130 tree_crateid = crate_id;
1131 tree_tcrate_mean = tcrate_mean_new[crate_id - 1];
1132 tree_tcrate_mean_unc = tcrate_mean_unc_new[crate_id - 1];
1133 tree_tcrate_sigma = tcrate_sigma_new[crate_id - 1];
1134 tree_tcrate_meanPrev = tcrate_mean_prev[crate_id - 1] * TICKS_TO_NS;
1135 tree_crate->Fill();
1136 }
1137 }
1138 }
1139
1140 B2DEBUG(22, "end of crate corrections .....");
1141
1142 tree_crystal->Write();
1143 tree_crate->Write();
1144
1145 histfile->Close();
1146
1147 B2INFO("Finished talgorithm");
1148 return c_OK;
1149}
1150
Base class for calibration algorithms.
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
void updateDBObjPtrs(const unsigned int event, const int run, const int experiment)
Updates any DBObjPtrs by calling update(event) for DBStore.
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 successfully =0 in Python.
@ c_Failure
Failed =3 in Python.
Class for accessing objects in the database.
Definition: DBObjPtr.h:21
Singleton class to cache database objects.
Definition: DBStore.h:31
static DataStore & Instance()
Instance of singleton Store.
Definition: DataStore.cc:53
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition: DataStore.cc:93
General DB object to store one calibration number per ECL crystal.
void setCalibVector(const std::vector< float > &CalibConst, const std::vector< float > &CalibConstUnc)
Set vector of constants with uncertainties.
General DB object to store one reference crystal per per ECL crate for calibration purposes.
void setCalibVector(const std::vector< short > &refCrystals)
Set vector of constants with uncertainties.
This class provides access to ECL channel map that is either a) Loaded from the database (see ecl/dbo...
static double getRF()
See m_rf.
int crateIDHi
Fit crates with crateID0 in the inclusive range [crateIDLo,crateIDHi].
int cellIDHi
Fit crystals with cellID0 in the inclusive range [cellIDLo,cellIDHi].
int cellIDLo
Fit crystals with cellID0 in the inclusive range [cellIDLo,cellIDHi].
bool debugOutput
Save every histogram and fitted function to debugFilename.
double meanCleanRebinFactor
Rebinning factor for mean calculation.
int crateIDLo
Fit crates with crateID0 in the inclusive range [crateIDLo,crateIDHi].
double meanCleanCutMinFactor
After rebinning, create a mask for bins that have values less than meanCleanCutMinFactor times the ma...
bool savePrevCrysPayload
Save the previous crystal payload values for comparison.
bool readPrevCrysPayload
Read the previous crystal payload values for comparison.
EResult calibrate() override
..Run algorithm on events
int refCrysPerCrate[52]
List of crystals, one per crate, used as reference time for crystal time calibration.
std::string debugFilenameBase
Name of file with debug output, eclBhabhaTAlgorithm.root by default.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
bool construct(Args &&... params)
Construct an object of type T in this StoreObjPtr, using the provided constructor arguments.
Definition: StoreObjPtr.h:118
static DBStore & Instance()
Instance of a singleton DBStore.
Definition: DBStore.cc:26
void updateEvent()
Updates all intra-run dependent objects.
Definition: DBStore.cc:140
void update()
Updates all objects that are outside their interval of validity.
Definition: DBStore.cc:77
const int c_NCrystals
Number of crystals.
Abstract base class for different kinds of events.
STL namespace.