Belle II Software development
CDCDedxHadBGAlgorithm.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 <cdc/calibration/CDCdEdx/CDCDedxHadBGAlgorithm.h>
10
11using namespace Belle2;
12
13//-----------------------------------------------------------------
14// Implementation
15//-----------------------------------------------------------------
17 CalibrationAlgorithm("CDCDedxHadronCollector"),
18 m_ismakePlots(true),
19 m_suffix("")
20{
21 // Set module properties
22 setDescription("A calibration algorithm for CDC dE/dx hadron Beta Gamma curve and resolution fitting");
23}
24
25//-----------------------------------------------------------------
26// Run the calibration
27//-----------------------------------------------------------------
29{
30
31 gROOT->SetBatch();
33
34 //existing hadron bg mean and reso payload for merging
35 if (!m_DBMeanPars.isValid() || !m_DBSigmaPars.isValid())
36 B2FATAL("There is no valid payload for Beta-Gamma saturation");
37
38 // particle list
39 std::vector< std::string > particles = {"muon", "kaon", "proton", "pion", "electron"};
40
41 // check we have enough data
42 for (int i = 0; i < int(particles.size()); i++) {
43 std::string p = particles[i];
44 auto tree = getObjectPtr<TTree>(Form("%s", p.data()));
45 if (!tree) return c_NotEnoughData;
46 }
47
48 gSystem->Exec("mkdir -p plots/HadronPrep");
49 gSystem->Exec("mkdir -p plots/HadronCal/BGfits");
50 gSystem->Exec("mkdir -p plots/HadronCal/Resofits");
51 gSystem->Exec("mkdir -p plots/HadronCal/Monitoring");
52
53 // Write beta-gamma curve mean and resolution parameters in text file
55 mg.setParameters();
56 mg.printParameters("parameters.inital.curve");
57
59 sg.setParameters();
60 sg.printParameters("parameters.inital.sigma");
61
62 m_bgcurve = "parameters.inital.curve";
63 m_bgsigma = "parameters.inital.sigma";
64
65 HadronCalibration hadcal;
66 std::string filename = " ";
67
68 for (int iter = 0; iter < m_iter; ++iter) {
69
70 const bool isFirstIteration = (iter == 0);
71 const bool isFinalIteration = (iter == m_iter - 1);
72
73 const bool makeIterationSummary = m_ismakePlots && (isFirstIteration || isFinalIteration);
74
75 std::string sfx = Form("%s_iter%d", m_suffix.data(), iter);
76 filename = Form("widget_corrected_NewHSpars_1D_%s.root", sfx.data());
77
78 // prepare sample to perform bg curve fittting and draw the monitoring plots
79 prepareSample(particles, filename, sfx, false);
80
81 // create the HadronCalibration object and fit the prepared samples
82 // if(makeIterationSummary) hadcal.plotBGMonitoring(particles, filename, sfx);
83
84 //bg fit
85 hadcal.fitBGCurve(particles, filename, m_bgcurve, sfx, makeIterationSummary);
86 m_bgcurve = "parameters.bgcurve.fit";
87
88 //dedx reso vs ionz fit
89 hadcal.fitSigmavsIonz(particles, filename, m_bgsigma, sfx, makeIterationSummary);
90 m_bgsigma = "parameters.ionz.fit";
91
92 //dedx reso vs nHits fit
93 SigmaFits(particles, sfx, "nhit", makeIterationSummary);
94 m_bgsigma = "parameters.sigmanhit.fit";
95
96 //dedx reso vs costh fit
97 SigmaFits(particles, sfx, "costh", makeIterationSummary);
98 m_bgsigma = "parameters.sigmacos.fit";
99
100 }
101
102 filename = Form("widget_corrected_NewHSpars_1D_%s_final.root", m_suffix.data());
103 prepareSample(particles, filename, Form("%s_final", m_suffix.data()), true);
104 hadcal.plotBGMonitoring(particles, filename, Form("%s_final", m_suffix.data()));
105
106 B2INFO("Saving calibration for: " << m_suffix << "");
108
109 return c_OK;
110}
111
112
113//------------------------------------
115{
116 int cruns = 0;
117 for (auto expRun : getRunList()) {
118 if (cruns == 0)B2INFO("CDCDedxHadBGAlgorithm: start exp " << expRun.first << " and run " << expRun.second << "");
119 cruns++;
120 }
121
122 const auto erStart = getRunList()[0];
123 int estart = erStart.first;
124 int rstart = erStart.second;
125
126 updateDBObjPtrs(1, erStart.second, erStart.first);
127
128 m_suffix = Form("e%dr%d", estart, rstart);
129 B2INFO("tool exp = " << estart << ", run = " << rstart << ", m_suffix = " << m_suffix << "");
130}
131
132//--------------------------
134{
135
136 std::ifstream fins("parameters.sigmacos.fit"), fin("parameters.bgcurve.fit");
137
138 if (!fin.good()) B2FATAL("\t WARNING: CANNOT FIND parameters.bgcurve.fit!");
139 if (!fins.good()) B2FATAL("\tWARNING: CANNOT FIND parameters.sigmacos.fit!");
140
141 int par;
142 double meanpars, sigmapars;
143 std::vector<double> v_meanpars, v_sigmapars;
144
145 B2INFO("\t --> Curve parameters");
146 for (int i = 0; i < 15; ++i) {
147 fin >> par >> meanpars;
148 v_meanpars.push_back(meanpars);
149 B2INFO("\t\t (" << i << ")" << v_meanpars[i]);
150 }
151
152 fin.close();
153
154 B2INFO("\t --> Sigma parameters");
155 for (int i = 0; i < 17; ++i) {
156 fins >> par >> sigmapars;
157 v_sigmapars.push_back(sigmapars);
158 B2INFO("\t\t (" << i << ")" << v_sigmapars[i]);
159 }
160 fins.close();
161
162 B2INFO("dE/dx Calibration done for " << v_meanpars.size() << " CDC Beta Gamma curve");
163 CDCDedxMeanPars* gains = new CDCDedxMeanPars(0, v_meanpars);
164 saveCalibration(gains, "CDCDedxMeanPars");
165
166
167 B2INFO("dE/dx Calibration done for " << v_sigmapars.size() << " CDC Beta Gamma resolution");
168 CDCDedxSigmaPars* sgains = new CDCDedxSigmaPars(0, v_sigmapars);
169 saveCalibration(sgains, "CDCDedxSigmaPars");
170}
171
172void CDCDedxHadBGAlgorithm::prepareSample(const std::vector< std::string >& particles, const std::string& filename,
173 const std::string& sfx, const bool makeIterationSummary)
174{
175
176 TFile* outfile = new TFile(filename.data(), "RECREATE");
177
178 for (int i = 0; i < int(particles.size()); ++i) {
179
180 std::string p = particles[i];
181 auto tree = getObjectPtr<TTree>(Form("%s", p.data()));
182
183 HadronBgPrep prep(m_bgpar[p][0], m_bgpar[p][1], m_bgpar[p][2], 8, -1.0, 1.0, m_injpar[p][0], m_injpar[p][1],
185
186 prep.prepareSample(tree, outfile, sfx, m_bgcurve, m_bgsigma, p, makeIterationSummary);
187 }
188 outfile->Close();
189
190}
191
192void CDCDedxHadBGAlgorithm::SigmaFits(const std::vector< std::string >& particles, const std::string& sfx, const std::string& svar,
193 const bool makeIterationSummary)
194{
195 // only the muon samples are used for the sigma fits
196 HadronCalibration hadcal;
197
198 std::string filename = Form("widget_%s_1D_%s.root", svar.data(), sfx.data());
199
200 TFile* outfile = new TFile(filename.data(), "RECREATE");
201 outfile->cd();
202
203 for (int ip = 0; ip < int(particles.size()); ++ip) {
204
205 std::string particle = particles[ip];
206 auto hadron = getObjectPtr<TTree>(Form("%s", particle.data()));
207
208 HadronBgPrep prep(m_bgpar[particle][0], m_bgpar[particle][1], m_bgpar[particle][2], m_cospar[particle], m_cosMin, m_cosMax,
209 m_injpar[particle][0],
210 m_injpar[particle][1], m_injpar[particle][2], m_nhitBins, m_nhitMin, m_nhitMax, m_cut);
211
212 double mass = prep.getParticleMass(particle);
213 if (mass == 0.0) B2FATAL("Mass of particle " << particle.data() << " is zero");
214 // --------------------------------------------------
215 // INITIALIZE CONTAINERS
216 // --------------------------------------------------
217 double dedxnosat; // dE/dx without hadron saturation correction
218 double p; // track momentum
219 double costh; // cosine of track polar angle
220 double timereso;
221 int nhits; // number of hits on this track
222
223 hadron->SetBranchAddress("dedxnosat", &dedxnosat);
224 hadron->SetBranchAddress("p", &p);
225 hadron->SetBranchAddress("costh", &costh);
226 hadron->SetBranchAddress("timereso", &timereso);
227 hadron->SetBranchAddress("nhits", &nhits);
228
229 int nbins = m_nhitBins;
230 double lower = m_nhitMin;
231 double upper = m_nhitMax;
232 double nstep = (upper - lower + 1) / nbins;
233
234 if (svar == "costh") {
235 nbins = m_cospar[particle];
236 lower = m_cosMin, upper = m_cosMax;
237 nstep = (upper - lower) / nbins;
238 }
239
240 // Create the histograms to be fit
241 std::vector<TH1F*> hdedx_var;
242
243 //define histograms
244 prep.defineHisto(hdedx_var, "chi", svar, particle);
245
246 // Create some containers to calculate averages
247 std::vector<double> sumvar(nbins);
248 std::vector<int> sumsize(nbins);
249 for (int i = 0; i < nbins; ++i) {
250 sumvar[i] = 0;
251 sumsize[i] = 0;
252 }
253
254 // get the hadron saturation parameters
255 CDCDedxMeanPred mgpar;
256 CDCDedxSigmaPred sgpar;
257
260
261 CDCDedxHadSat had;
262 had.setParameters("sat-pars.fit.txt");
263 // --------------------------------------------------
264 // LOOP OVER EVENTS AND FILL CONTAINERS
265 // --------------------------------------------------
266 // Fill the histograms to be fitted
267
268 for (unsigned int index = 0; index < hadron->GetEntries(); ++index) {
269
270 hadron->GetEntry(index);
271 double bg = std::fabs(p) / mass;
272
273 if (std::fabs(p) > 8.0) continue; // unphysical tracks
274
275 if (svar == "nhit") {
276 if (nhits < lower || nhits > upper) continue;
277 } else if (svar == "costh") {
278 if (costh > upper || costh < lower) continue;
279 }
280
281 if (dedxnosat <= 0) continue;
282 if (!(costh == costh)) continue; // NaN check
283
284 if (particle == "proton") {
285 if ((dedxnosat - 0.45) * std::abs(p) * std::abs(p) < m_cut) continue;
286 }
287
288 if (particle == "electron" || particle == "muon") {
289 if (std::fabs(p) > 2.0) continue;
290 }
291
292 double dedx_new = had.D2I(costh, had.I2D(costh, 1.0) * dedxnosat);
293 double dedx_cur = mgpar.getMean(bg);
294
295 if (svar == "nhit") {
296 double res_cor = sgpar.cosPrediction(costh) * sgpar.ionzPrediction(dedx_cur) * timereso;
297 int nhitBin = static_cast<int>((std::fabs(nhits) - lower) / nstep);
298
299 if (nhitBin < 0) nhitBin = 0;
300 else if (nhitBin >= nbins) nhitBin = nbins - 1;
301
302 if (res_cor != 0)
303 hdedx_var[nhitBin]->Fill((dedx_new - dedx_cur) / res_cor);
304
305 sumvar[nhitBin] += nhits;
306 sumsize[nhitBin] += 1;
307
308 } else { // costh
309 double denom = (upper - lower);
310 int cosBin = static_cast<int>((costh - lower) / denom * nbins);
311
312 if (cosBin < 0) cosBin = 0;
313 else if (cosBin >= nbins) cosBin = nbins - 1;
314
315 double res_cor = sgpar.nhitPrediction(nhits) * sgpar.ionzPrediction(dedx_cur) * timereso;
316 if (res_cor != 0) hdedx_var[cosBin]->Fill((dedx_new - dedx_cur) / res_cor);
317 sumvar[cosBin] += costh;
318 sumsize[cosBin] += 1;
319 }
320 }
321
322 // --------------------------------------------------
323 // FIT IN BINS OF NHIT
324 // --------------------------------------------------
325 // fit the histograms with Gaussian functions
326 // and extract the means and errors
327
328
329 TTree* tTree = new TTree(Form("%s_%s", particle.data(), svar.data()), "chi m_means and m_errors");
330 double avg, mean, mean_err, sigma, sigma_err;
331
332 tTree->Branch("avg", &avg, "avg/D");
333 tTree->Branch("chimean", &mean, "chimean/D");
334 tTree->Branch("chimean_err", &mean_err, "chimean_err/D");
335 tTree->Branch("chisigma", &sigma, "chisigma/D");
336 tTree->Branch("chisigma_err", &sigma_err, "chisigma_err/D");
337
338 double avg_sigma = 0.0;
339 std::vector<double> var(nbins), varres(nbins), varreserr(nbins), varmean(nbins), varmeanerr(nbins);
340
341 int count_bins = 0;
342 for (int i = 0; i < nbins; ++i) {
343
344 varres[i] = 0.0, varmean[i] = 0.0;
345 varreserr[i] = 0.0, varmeanerr[i] = 0.0;
346 var[i] = (sumsize[i] > 0) ? (sumvar[i] / sumsize[i]) : 0.0;
347
348 // fit the dE/dx distribution in bins of injection time'
349 if (hdedx_var[i]->Integral() > 100) {
350 gstatus stats;
351 prep.fit(hdedx_var[i], particle, stats);
352 if (stats == OK) {
353 varmean[i] = hdedx_var[i]->GetFunction("gaus")->GetParameter(1);
354 varmeanerr[i] = hdedx_var[i]->GetFunction("gaus")->GetParError(1);
355 varres[i] = hdedx_var[i]->GetFunction("gaus")->GetParameter(2);;
356 varreserr[i] = hdedx_var[i]->GetFunction("gaus")->GetParError(2);
357 }
358 count_bins++;
359 avg_sigma += varres[i];
360
361 }
362 }
363 if (count_bins > 0) avg_sigma /= count_bins;
364 for (int i = 0; i < nbins; ++i) {
365
366 if (avg_sigma > 0) {
367 sigma = varres[i] / avg_sigma;
368 sigma_err = varreserr[i] / avg_sigma;
369 }
370 mean = varmean[i];
371 mean_err = varmeanerr[i];
372 avg = var[i];
373 tTree->Fill();
374 }
375
376 tTree->Write();
377
378 if (makeIterationSummary) prep.plotDist(hdedx_var, Form("fits_chi_%s_%s_%s", svar.data(), sfx.data(), particle.data()), nbins);
379
380 prep.deleteHistos(hdedx_var);
381 }
382 outfile->Close();
383
384 if (svar == "costh") hadcal.fitSigmaVsCos(particles, filename, m_bgsigma, sfx, makeIterationSummary);
385 else hadcal.fitSigmaVsNHit(particles, filename, m_bgsigma, sfx, makeIterationSummary);
386
387}
388
389
DBObjPtr< CDCDedxMeanPars > m_DBMeanPars
db object for dE/dx mean parameters
std::map< std::string, std::array< double, 3 > > m_bgpar
bg bins, min, max for different particles
void getExpRunInfo()
function to get exp/run information (payload object, plotting)
double m_cosMax
max range of cosine
std::map< std::string, double > m_cospar
cos bins for different particles
std::string m_bgcurve
string for mean parameter file names
bool m_ismakePlots
produce plots for monitoring
int m_iter
set number of iteration
std::string m_suffix
string suffix for object names
void prepareSample(const std::vector< std::string > &particles, const std::string &filename, const std::string &sfx, const bool makeIterationSummary)
function to prepare sample for bgcurve fitting, sigma vs ionzation fitting and monitoring plots
CDCDedxHadBGAlgorithm()
Constructor: Sets the description, the properties and the parameters of the algorithm.
double m_nhitMax
max range of nhits
DBObjPtr< CDCDedxSigmaPars > m_DBSigmaPars
db object for dE/dx resolution parameters
std::string m_bgsigma
string for sigma parameter file names
double m_cosMin
min range of cosine
double m_cut
cut to clean protons
virtual EResult calibrate() override
CDC dE/dx Beta Gamma curve and resolution algorithm.
double m_nhitMin
min range of nhits
std::map< std::string, std::array< double, 3 > > m_injpar
injection time bins, min, max for different particles
void createPayload()
function to store payloads after full calibration
void SigmaFits(const std::vector< std::string > &particles, const std::string &sfx, const std::string &svar, const bool makeIterationSummary)
function to do the sigma vs nhit or cos fits and store parameters
Class to hold the hadron saturation functions.
double I2D(double cosTheta, double I) const
hadron saturation parameterization part 2
double D2I(double cosTheta, double D) const
hadron saturation parameterization part 1
void setParameters()
set the parameters
dE/dx mean (curve versus beta-gamma) parameterization constants
Class to hold the prediction of mean as a function of beta-gamma (bg)
void setParameters(const std::string &infile)
set the parameters from file
double getMean(double bg)
Return the predicted mean value as a function of beta-gamma (bg)
void printParameters(const std::string &infile)
write the parameters in file
dE/dx sigma (versus beta-gamma) parameterization constants
Class to hold the prediction of resolution depending dE/dx, nhit, and cos(theta)
double ionzPrediction(double dedx)
Return sigma from the ionization parameterization.
double cosPrediction(double cos)
Return sigma from the cos parameterization.
void setParameters(const std::string &infile)
set the parameters from file
double nhitPrediction(double nhit)
Return sigma from the nhit parameterization.
void printParameters(const std::string &infile)
write the parameters in file
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
static 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_NotEnoughData
Needs more data =2 in Python.
CalibrationAlgorithm(const std::string &collectorModuleName)
Constructor - sets the prefix for collected objects (won't be accesses until execute(....
Class to prepare sample for fitting in beta gamma bins.
static void fit(TH1F *&hist, const std::string &pdg, gstatus &status)
function to fit the histograms
void defineHisto(std::vector< TH1F * > &htemp, const std::string &svar, const std::string &stype, const std::string &pdg)
function to define histograms
static void plotDist(std::map< int, std::vector< TH1F * > > &hist, const std::string &suffix, int bins)
function to plot the map of histograms
static double getParticleMass(const std::string &particle)
function to get the particle mass
static void deleteHistos(std::vector< TH1F * > &htemp)
function to delete the histograms
void prepareSample(std::shared_ptr< TTree > hadron, TFile *&outfile, const std::string &suffix, const std::string &bgcurvefile, const std::string &bgsigmafile, const std::string &pdg, bool ismakePlots)
function to prepare sample for monitoring plots, bg curve fitting and sigma vs ionz fitting
Class to perform the fitting in beta gamma bins.
void plotBGMonitoring(const std::vector< std::string > &particles, const std::string &filename, const std::string &suffix)
plots mean and width after fitting
static void fitSigmaVsNHit(const std::vector< std::string > &particles, const std::string &filename, const std::string &paramsigma, const std::string &suffx, const bool makeIterationSummary)
fit sigma vs.
void fitSigmavsIonz(const std::vector< std::string > &particles, const std::string &filename, const std::string &paramfile, const std::string &suffix, const bool makeIterationSummary)
fit sigma vs.
void fitBGCurve(const std::vector< std::string > &particles, const std::string &filename, const std::string &paramfile, const std::string &suffx, const bool makeIterationSummary)
fit the beta-gamma curve
static void fitSigmaVsCos(const std::vector< std::string > &particles, const std::string &filename, const std::string &paramfile, const std::string &suffx, const bool makeIterationSummary)
fit sigma vs.
std::shared_ptr< T > getObjectPtr(const std::string &name, const std::vector< Calibration::ExpRun > &requestedRuns)
Get calibration data object by name and list of runs, the Merge function will be called to generate t...
Abstract base class for different kinds of events.