Belle II Software development
SVDdEdxCalibrationAlgorithm Class Reference

Class implementing the SVD dEdx calibration algorithm. More...

#include <SVDdEdxCalibrationAlgorithm.h>

Inheritance diagram for SVDdEdxCalibrationAlgorithm:
CalibrationAlgorithm

Public Types

enum  EResult {
  c_OK ,
  c_Iterate ,
  c_NotEnoughData ,
  c_Failure ,
  c_Undefined
}
 The result of calibration. More...
 

Public Member Functions

 SVDdEdxCalibrationAlgorithm ()
 Constructor.
 
virtual ~SVDdEdxCalibrationAlgorithm () override
 Destructor.
 
void setMonitoringPlots (bool value=false)
 function to enable plotting
 
void setNumDEdxBins (const int &value)
 set the number of dEdx bins for the payloads
 
void setNumPBins (const int &value)
 set the number of momentum bins for the payloads
 
void setNumBGBins (const int &value)
 set the number of beta*gamma bins for the fits
 
void setDEdxCutoff (const double &value)
 set the upper edge of the dEdx binning for the payloads
 
void setMinEvtsPerTree (const double &value)
 set the upper edge of the dEdx binning for the payloads
 
void setCustomProfile (bool value=true)
 reimplement the profile histogram calculation
 
void setFixUnstableFitParameter (bool value=true)
 In the dEdx:betagamma fit, there is one free parameter that makes fit convergence poor.
 
void setUsePionBGFunctionForEverything (bool value=false)
 use the pion beta*gamma function for other hadrons
 
void setUseProtonBGFunctionForEverything (bool value=false)
 use the proton beta*gamma function for other hadrons
 
const std::string & getPrefix () const
 Get the prefix used for getting calibration data.
 
const std::string & getCollectorName () const
 Alias for prefix.
 
void setPrefix (const std::string &prefix)
 Set the prefix used to identify datastore objects.
 
void setInputFileNames (PyObject *inputFileNames)
 Set the input file names used for this algorithm from a Python list.
 
PyObject * getInputFileNames ()
 Get the input file names used for this algorithm and pass them out as a Python list of unicode strings.
 
std::vector< Calibration::ExpRun > getRunListFromAllData () const
 Get the complete list of runs from inspection of collected data.
 
RunRange getRunRangeFromAllData () const
 Get the complete RunRange from inspection of collected data.
 
IntervalOfValidity getIovFromAllData () const
 Get the complete IoV from inspection of collected data.
 
void fillRunToInputFilesMap ()
 Fill the mapping of ExpRun -> Files.
 
const std::string & getGranularity () const
 Get the granularity of collected data.
 
EResult execute (std::vector< Calibration::ExpRun > runs={}, int iteration=0, IntervalOfValidity iov=IntervalOfValidity())
 Runs calibration over vector of runs for a given iteration.
 
EResult execute (PyObject *runs, int iteration=0, IntervalOfValidity iov=IntervalOfValidity())
 Runs calibration over Python list of runs. Converts to C++ and then calls the other execute() function.
 
std::list< Database::DBImportQuery > & getPayloads ()
 Get constants (in TObjects) for database update from last execution.
 
std::list< Database::DBImportQuery > getPayloadValues () const
 Get constants (in TObjects) for database update from last execution but passed by VALUE.
 
bool commit ()
 Submit constants from last calibration into database.
 
bool commit (std::list< Database::DBImportQuery > payloads)
 Submit constants from a (potentially previous) set of payloads.
 
const std::string & getDescription () const
 Get the description of the algorithm (set by developers in constructor)
 
bool loadInputJson (const std::string &jsonString)
 Load the m_inputJson variable from a string (useful from Python interface). The return bool indicates success or failure.
 
const std::string dumpOutputJson () const
 Dump the JSON string of the output JSON object.
 
const std::vector< Calibration::ExpRun > findPayloadBoundaries (std::vector< Calibration::ExpRun > runs, int iteration=0)
 Used to discover the ExpRun boundaries that you want the Python CAF to execute on. This is optional and only used in some.
 
template<>
std::shared_ptr< TTree > getObjectPtr (const std::string &name, const std::vector< Calibration::ExpRun > &requestedRuns)
 Specialization of getObjectPtr<TTree>.
 

Static Public Member Functions

static bool checkPyExpRun (PyObject *pyObj)
 Checks that a PyObject can be successfully converted to an ExpRun type.
 
static Calibration::ExpRun convertPyExpRun (PyObject *pyObj)
 Performs the conversion of PyObject to ExpRun.
 

Protected Member Functions

virtual EResult calibrate () override
 run algorithm on data
 
void setInputFileNames (const std::vector< std::string > &inputFileNames)
 Set the input file names used for this algorithm.
 
virtual bool isBoundaryRequired (const Calibration::ExpRun &)
 Given the current collector data, make a decision about whether or not this run should be the start of a payload boundary.
 
virtual void boundaryFindingSetup (std::vector< Calibration::ExpRun >, int)
 If you need to make some changes to your algorithm class before 'findPayloadBoundaries' is run, make them in this function.
 
virtual void boundaryFindingTearDown ()
 Put your algorithm back into a state ready for normal execution if you need to.
 
const std::vector< Calibration::ExpRun > & getRunList () const
 Get the list of runs for which calibration is called.
 
int getIteration () const
 Get current iteration.
 
const std::vector< std::string > & getVecInputFileNames () const
 Get the input file names used for this algorithm as a STL vector.
 
template<class T>
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 the overall object.
 
template<class T>
std::shared_ptr< T > getObjectPtr (std::string name)
 Get calibration data object (for all runs the calibration is requested for) This function will only work during or after execute() has been called once.
 
template<>
shared_ptr< TTree > getObjectPtr (const string &name, const vector< ExpRun > &requestedRuns)
 We cheekily cast the TChain to TTree for the returned pointer so that the user never knows Hopefully this doesn't cause issues if people do low level stuff to the tree...
 
std::string getGranularityFromData () const
 Get the granularity of collected data.
 
void saveCalibration (TClonesArray *data, const std::string &name)
 Store DBArray payload with given name with default IOV.
 
void saveCalibration (TClonesArray *data, const std::string &name, const IntervalOfValidity &iov)
 Store DBArray with given name and custom IOV.
 
void saveCalibration (TObject *data)
 Store DB payload with default name and default IOV.
 
void saveCalibration (TObject *data, const IntervalOfValidity &iov)
 Store DB payload with default name and custom IOV.
 
void saveCalibration (TObject *data, const std::string &name)
 Store DB payload with given name with default IOV.
 
void saveCalibration (TObject *data, const std::string &name, const IntervalOfValidity &iov)
 Store DB payload with given name and custom IOV.
 
void setDescription (const std::string &description)
 Set algorithm description (in constructor)
 
void clearCalibrationData ()
 Clear calibration data.
 
void resetInputJson ()
 Clears the m_inputJson member variable.
 
void resetOutputJson ()
 Clears the m_outputJson member variable.
 
template<class T>
void setOutputJsonValue (const std::string &key, const T &value)
 Set a key:value pair for the outputJson object, expected to used internally during calibrate()
 
template<class T>
const T getOutputJsonValue (const std::string &key) const
 Get a value using a key from the JSON output object, not sure why you would want to do this.
 
template<class T>
const T getInputJsonValue (const std::string &key) const
 Get an input JSON value using a key. The normal exceptions are raised when the key doesn't exist.
 
const nlohmann::json & getInputJsonObject () const
 Get the entire top level JSON object. We explicitly say this must be of object type so that we might pick.
 
bool inputJsonKeyExists (const std::string &key) const
 Test for a key in the input JSON object.
 

Static Protected Member Functions

static void updateDBObjPtrs (const unsigned int event, const int run, const int experiment)
 Updates any DBObjPtrs by calling update(event) for DBStore.
 
static Calibration::ExpRun getAllGranularityExpRun ()
 Returns the Exp,Run pair that means 'Everything'. Currently unused.
 

Protected Attributes

std::vector< Calibration::ExpRun > m_boundaries
 When using the boundaries functionality from isBoundaryRequired, this is used to store the boundaries. It is cleared when.
 

Private Member Functions

TTree * LambdaMassFit (std::shared_ptr< TTree > preselTree)
 Mass fit for Lambda->ppi.
 
std::unique_ptr< TList > LambdaHistogramming (TTree *inputTree)
 produce histograms for protons
 
TTree * DstarMassFit (std::shared_ptr< TTree > preselTree)
 Mass fit for D*->Dpi.
 
std::unique_ptr< TList > DstarHistogramming (TTree *inputTree)
 produce histograms for K/pi
 
std::unique_ptr< TList > GammaHistogramming (std::shared_ptr< TTree > preselTree)
 produce histograms for e
 
std::unique_ptr< TList > GenerateNewHistograms (std::shared_ptr< TTree > ttreeLambda, std::shared_ptr< TTree > ttreeDstar, std::shared_ptr< TTree > ttreeGamma, std::shared_ptr< TTree > ttreeGeneric)
 generate high-statistics histograms
 
std::vector< double > CreatePBinningScheme ()
 build the binning scheme for the momentum
 
TH2F * Normalise2DHisto (TH2F *HistoToNormalise)
 Normalise a given dEdx:momentum histogram in each momentum bin, so that sum of entries in each momentum bin is 1.
 
TH2F * PrepareNewHistogram (TH2F *DataHistogram, TString NewName, TF1 *betagamma_function, TF1 *ResolutionFunctionOriginal, double bias_correction)
 Generate a new dEdx:momentum histogram from a function that encodes dEdx:momentum trend and a function that encodes dEdx resolution.
 
TH1D * PrepareProfile (TH2F *DataHistogram, TString NewName)
 Reimplement the Profile histogram calculation for a 2D histogram.
 
std::string getExpRunString (Calibration::ExpRun &expRun) const
 Gets the "exp.run" string repr. of (exp,run)
 
std::string getFullObjectPath (const std::string &name, Calibration::ExpRun expRun) const
 constructs the full TDirectory + Key name of an object in a TFile based on its name and exprun
 

Private Attributes

bool m_isMakePlots
 produce plots for monitoring
 
int m_numDEdxBins = 100
 the number of dEdx bins for the payloads
 
int m_numPBins = 69
 the number of momentum bins for the payloads
 
int m_numBGBins = 69
 the number of beta*gamma bins for the profile and fitting
 
double m_dedxCutoff = 5.e6
 the upper edge of the dEdx binning for the payloads
 
double m_dedxMaxPossible = 7.e6
 the approximate max possible value of dEdx
 
int m_MinEvtsPerTree
 number of events in TTree below which we don't try to fit
 
int m_NToGenerate
 the number of events to be generated in each momentum bin in the new payloads.
 
bool m_CustomProfile = 1
 reimplement profile histogram calculation instead of the ROOT implementation?
 
bool m_UsePionBGFunctionForEverything
 Assume that the dEdx:betagamma trend is the same for all hadrons; use the pion trend as representative.
 
bool m_UseProtonBGFunctionForEverything
 Assume that the dEdx:betagamma trend is the same for all hadrons; use the proton trend as representative.
 
bool m_FixUnstableFitParameter
 In the dEdx:betagamma fit, there is one free parameter that makes fit convergence poor.
 
const double m_ElectronPDGMass = TDatabasePDG::Instance()->GetParticle(11)->Mass()
 PDG mass for the electron.
 
const double m_MuonPDGMass = TDatabasePDG::Instance()->GetParticle(13)->Mass()
 PDG mass for the muon.
 
const double m_PionPDGMass = TDatabasePDG::Instance()->GetParticle(211)->Mass()
 PDG mass for the charged pion.
 
const double m_KaonPDGMass = TDatabasePDG::Instance()->GetParticle(321)->Mass()
 PDG mass for the charged kaon.
 
const double m_ProtonPDGMass = TDatabasePDG::Instance()->GetParticle(2212)->Mass()
 PDG mass for the proton.
 
const double m_DeuteronPDGMass = TDatabasePDG::Instance()->GetParticle(1000010020)->Mass()
 PDG mass for the deuteron.
 
std::vector< std::string > m_inputFileNames
 List of input files to the Algorithm, will initially be user defined but then gets the wildcards expanded during execute()
 
std::map< Calibration::ExpRun, std::vector< std::string > > m_runsToInputFiles
 Map of Runs to input files. Gets filled when you call getRunRangeFromAllData, gets cleared when setting input files again.
 
std::string m_granularityOfData
 Granularity of input data. This only changes when the input files change so it isn't specific to an execution.
 
ExecutionData m_data
 Data specific to a SINGLE execution of the algorithm. Gets reset at the beginning of execution.
 
std::string m_description {""}
 Description of the algorithm.
 
std::string m_prefix {""}
 The name of the TDirectory the collector objects are contained within.
 
nlohmann::json m_jsonExecutionInput = nlohmann::json::object()
 Optional input JSON object used to make decisions about how to execute the algorithm code.
 
nlohmann::json m_jsonExecutionOutput = nlohmann::json::object()
 Optional output JSON object that can be set during the execution by the underlying algorithm code.
 

Static Private Attributes

static const Calibration::ExpRun m_allExpRun = make_pair(-1, -1)
 allExpRun
 

Detailed Description

Class implementing the SVD dEdx calibration algorithm.

Definition at line 28 of file SVDdEdxCalibrationAlgorithm.h.

Member Enumeration Documentation

◆ EResult

enum EResult
inherited

The result of calibration.

Enumerator
c_OK 

Finished successfully =0 in Python.

c_Iterate 

Needs iteration =1 in Python.

c_NotEnoughData 

Needs more data =2 in Python.

c_Failure 

Failed =3 in Python.

c_Undefined 

Not yet known (before execution) =4 in Python.

Definition at line 40 of file CalibrationAlgorithm.h.

40 {
41 c_OK,
42 c_Iterate,
43 c_NotEnoughData,
44 c_Failure,
45 c_Undefined
46 };

Constructor & Destructor Documentation

◆ SVDdEdxCalibrationAlgorithm()

Constructor.

Definition at line 41 of file SVDdEdxCalibrationAlgorithm.cc.

41 : CalibrationAlgorithm("SVDdEdxCollector"),
42 m_isMakePlots(true)
43{
44 setDescription("SVD dE/dx calibration algorithm");
45}
void setDescription(const std::string &description)
Set algorithm description (in constructor)
CalibrationAlgorithm(const std::string &collectorModuleName)
Constructor - sets the prefix for collected objects (won't be accesses until execute(....
bool m_isMakePlots
produce plots for monitoring

◆ ~SVDdEdxCalibrationAlgorithm()

virtual ~SVDdEdxCalibrationAlgorithm ( )
inlineoverridevirtual

Destructor.

Definition at line 40 of file SVDdEdxCalibrationAlgorithm.h.

40{}

Member Function Documentation

◆ boundaryFindingSetup()

virtual void boundaryFindingSetup ( std::vector< Calibration::ExpRun > ,
int  )
inlineprotectedvirtualinherited

If you need to make some changes to your algorithm class before 'findPayloadBoundaries' is run, make them in this function.

Reimplemented in PXDAnalyticGainCalibrationAlgorithm, PXDValidationAlgorithm, SVD3SampleCoGTimeCalibrationAlgorithm, SVD3SampleELSTimeCalibrationAlgorithm, SVDClusterAbsoluteTimeShifterAlgorithm, SVDCoGTimeCalibrationAlgorithm, TestBoundarySettingAlgorithm, and TestCalibrationAlgorithm.

Definition at line 252 of file CalibrationAlgorithm.h.

252{};

◆ boundaryFindingTearDown()

virtual void boundaryFindingTearDown ( )
inlineprotectedvirtualinherited

Put your algorithm back into a state ready for normal execution if you need to.

Definition at line 257 of file CalibrationAlgorithm.h.

257{};

◆ calibrate()

CalibrationAlgorithm::EResult calibrate ( )
overrideprotectedvirtual

run algorithm on data

Implements CalibrationAlgorithm.

Definition at line 48 of file SVDdEdxCalibrationAlgorithm.cc.

49{
50 gROOT->SetBatch(true);
51
52 const auto exprun = getRunList()[0];
53 B2INFO("ExpRun used for calibration: " << exprun.first << " " << exprun.second);
54
55 auto payload = new Belle2::SVDdEdxPDFs();
56
57 // Get data objects
58 auto ttreeLambda = getObjectPtr<TTree>("Lambda");
59 auto ttreeDstar = getObjectPtr<TTree>("Dstar");
60 auto ttreeGamma = getObjectPtr<TTree>("Gamma");
61 auto ttreeGeneric = getObjectPtr<TTree>("Generic");
62
63 if ((ttreeLambda->GetEntries() < m_MinEvtsPerTree) || (ttreeDstar->GetEntries() < m_MinEvtsPerTree)
64 || (ttreeGamma->GetEntries() < m_MinEvtsPerTree)) {
65 B2WARNING("Not enough data for calibration.");
66 return c_NotEnoughData;
67 }
68
69 // call the calibration function
70 std::unique_ptr<TList> GeneratedList = GenerateNewHistograms(ttreeLambda, ttreeDstar, ttreeGamma, ttreeGeneric);
71
72 TH2F* histoE = static_cast<TH2F*>(GeneratedList->FindObject("Electron2DHistogramNew"));
73 TH2F* histoMu = static_cast<TH2F*>(GeneratedList->FindObject("Muon2DHistogramNew"));
74 TH2F* histoPi = static_cast<TH2F*>(GeneratedList->FindObject("Pion2DHistogramNew"));
75 TH2F* histoK = static_cast<TH2F*>(GeneratedList->FindObject("Kaon2DHistogramNew"));
76 TH2F* histoP = static_cast<TH2F*>(GeneratedList->FindObject("Proton2DHistogramNew"));
77 TH2F* histoDeut = static_cast<TH2F*>(GeneratedList->FindObject("Deuteron2DHistogramNew"));
78
79 std::vector<double> pbins = CreatePBinningScheme();
80 TH2F hEmpty("hEmpty", "A histogram returned if we cannot calibrate", m_numPBins, pbins.data(), m_numDEdxBins, 0, m_dedxCutoff);
81 for (int pbin = 0; pbin <= m_numPBins + 1; pbin++) {
82 for (int dedxbin = 0; dedxbin <= m_numDEdxBins + 1; dedxbin++) {
83 hEmpty.SetBinContent(pbin, dedxbin, 0.01);
84 };
85 }
86
87 B2INFO("Histograms are ready, proceed to creating the payload object...");
88 std::vector<TH2F*> hDedxPDFs(6);
89
90 std::array<std::string, 6> part = {"Electron", "Muon", "Pion", "Kaon", "Proton", "Deuteron"};
91
92 std::unique_ptr<TCanvas> candEdx(new TCanvas("candEdx", "SVD dEdx payloads", 1200, 700));
93 candEdx->Divide(3, 2);
94 gStyle->SetOptStat(11);
95
96 for (bool trunmean : {false, true}) {
97 for (int iPart = 0; iPart < 6; iPart++) {
98 if (iPart == 0 && trunmean) {
99 hDedxPDFs[iPart] = histoE;
100 hDedxPDFs[iPart]->SetName("hist_d1_11_trunc");
101 } else if (iPart == 1 && trunmean) {
102 hDedxPDFs[iPart] = histoMu;
103 hDedxPDFs[iPart]->SetName("hist_d1_13_trunc");
104 } else if (iPart == 2 && trunmean) {
105 hDedxPDFs[iPart] = histoPi;
106 hDedxPDFs[iPart]->SetName("hist_d1_211_trunc");
107 } else if (iPart == 3 && trunmean) {
108 hDedxPDFs[iPart] = histoK;
109 hDedxPDFs[iPart]->SetName("hist_d1_321_trunc");
110 } else if (iPart == 4 && trunmean) {
111 hDedxPDFs[iPart] = histoP;
112 hDedxPDFs[iPart]->SetName("hist_d1_2212_trunc");
113 } else if (iPart == 5 && trunmean) {
114 hDedxPDFs[iPart] = histoDeut;
115 hDedxPDFs[iPart]->SetName("hist_d1_1000010020_trunc");
116 } else if (iPart == 0 && !trunmean) {
117 hDedxPDFs[iPart] = &hEmpty;
118 hDedxPDFs[iPart]->SetName("hist_d1_11");
119 } else if (iPart == 1 && !trunmean) {
120 hDedxPDFs[iPart] = &hEmpty;
121 hDedxPDFs[iPart]->SetName("hist_d1_13");
122 } else if (iPart == 2 && !trunmean) {
123 hDedxPDFs[iPart] = &hEmpty;
124 hDedxPDFs[iPart]->SetName("hist_d1_211");
125 } else if (iPart == 3 && !trunmean) {
126 hDedxPDFs[iPart] = &hEmpty;
127 hDedxPDFs[iPart]->SetName("hist_d1_321");
128 } else if (iPart == 4 && !trunmean) {
129 hDedxPDFs[iPart] = &hEmpty;
130 hDedxPDFs[iPart]->SetName("hist_d1_2212");
131 } else if (iPart == 5 && !trunmean) {
132 hDedxPDFs[iPart] = &hEmpty;
133 hDedxPDFs[iPart]->SetName("hist_d1_1000010020");
134 } else
135 hDedxPDFs[iPart] = &hEmpty;
136 payload->setPDF(*hDedxPDFs[iPart], iPart, trunmean);
137
138 candEdx->cd(iPart + 1);
139 hDedxPDFs[iPart]->SetTitle(Form("%s; p(GeV/c) of %s; dE/dx", hDedxPDFs[iPart]->GetTitle(), part[iPart].data()));
140 hDedxPDFs[iPart]->DrawCopy("colz");
141 }
142
143 if (m_isMakePlots) {
144 candEdx->SaveAs("PlotsSVDdEdxPDFs_wTruncMean.pdf");
145 std::unique_ptr<TList> l(new TList());
146 for (int iPart = 0; iPart < 6; iPart++) {
147 l->Add(hDedxPDFs[iPart]);
148 }
149
150 TFile SVDdEdxPDFsPlotFile("PlotsSVDdEdxPDFs_wTruncMean.root", "RECREATE");
151 l->Write("histlist", TObject::kSingleKey);
152 SVDdEdxPDFsPlotFile.Close();
153 }
154
155 // candEdx->SetTitle(Form("Likehood dist. of charged particles from %s, trunmean = %s", idet.data(), check.str().data()));
156 }
157
158 saveCalibration(payload, "SVDdEdxPDFs");
159 B2INFO("SVD dE/dx calibration done!");
160
161 return c_OK;
162}
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
const std::vector< Calibration::ExpRun > & getRunList() const
Get the list of runs for which calibration is called.
@ c_OK
Finished successfully =0 in Python.
@ c_NotEnoughData
Needs more data =2 in Python.
int m_numPBins
the number of momentum bins for the payloads
std::vector< double > CreatePBinningScheme()
build the binning scheme for the momentum
int m_MinEvtsPerTree
number of events in TTree below which we don't try to fit
int m_numDEdxBins
the number of dEdx bins for the payloads
std::unique_ptr< TList > GenerateNewHistograms(std::shared_ptr< TTree > ttreeLambda, std::shared_ptr< TTree > ttreeDstar, std::shared_ptr< TTree > ttreeGamma, std::shared_ptr< TTree > ttreeGeneric)
generate high-statistics histograms
double m_dedxCutoff
the upper edge of the dEdx binning for the payloads
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...

◆ checkPyExpRun()

bool checkPyExpRun ( PyObject * pyObj)
staticinherited

Checks that a PyObject can be successfully converted to an ExpRun type.

Checks if the PyObject can be converted to ExpRun.

Definition at line 28 of file CalibrationAlgorithm.cc.

29{
30 // Is it a sequence?
31 if (PySequence_Check(pyObj)) {
32 Py_ssize_t nObj = PySequence_Length(pyObj);
33 // Does it have 2 objects in it?
34 if (nObj != 2) {
35 B2DEBUG(29, "ExpRun was a Python sequence which didn't have exactly 2 entries!");
36 return false;
37 }
38 PyObject* item1, *item2;
39 item1 = PySequence_GetItem(pyObj, 0);
40 item2 = PySequence_GetItem(pyObj, 1);
41 // Did the GetItem work?
42 if ((item1 == NULL) || (item2 == NULL)) {
43 B2DEBUG(29, "A PyObject pointer was NULL in the sequence");
44 return false;
45 }
46 // Are they longs?
47 if (PyLong_Check(item1) && PyLong_Check(item2)) {
48 long value1, value2;
49 value1 = PyLong_AsLong(item1);
50 value2 = PyLong_AsLong(item2);
51 if (((value1 == -1) || (value2 == -1)) && PyErr_Occurred()) {
52 B2DEBUG(29, "An error occurred while converting the PyLong to long");
53 return false;
54 }
55 } else {
56 B2DEBUG(29, "One or more of the PyObjects in the ExpRun wasn't a long");
57 return false;
58 }
59 // Make sure to kill off the reference GetItem gave us responsibility for
60 Py_DECREF(item1);
61 Py_DECREF(item2);
62 } else {
63 B2DEBUG(29, "ExpRun was not a Python sequence.");
64 return false;
65 }
66 return true;
67}

◆ clearCalibrationData()

void clearCalibrationData ( )
inlineprotectedinherited

Clear calibration data.

Definition at line 324 of file CalibrationAlgorithm.h.

324{m_data.clearCalibrationData();}

◆ commit() [1/2]

bool commit ( )
inherited

Submit constants from last calibration into database.

Definition at line 302 of file CalibrationAlgorithm.cc.

303{
304 if (getPayloads().empty())
305 return false;
306 list<Database::DBImportQuery> payloads = getPayloads();
307 B2INFO("Committing " << payloads.size() << " payloads to database.");
308 return Database::Instance().storeData(payloads);
309}
std::list< Database::DBImportQuery > & getPayloads()
Get constants (in TObjects) for database update from last execution.
static Database & Instance()
Instance of a singleton Database.
Definition Database.cc:42
bool storeData(const std::string &name, TObject *object, const IntervalOfValidity &iov)
Store an object in the database.
Definition Database.cc:141

◆ commit() [2/2]

bool commit ( std::list< Database::DBImportQuery > payloads)
inherited

Submit constants from a (potentially previous) set of payloads.

Definition at line 312 of file CalibrationAlgorithm.cc.

313{
314 if (payloads.empty())
315 return false;
316 return Database::Instance().storeData(payloads);
317}

◆ convertPyExpRun()

ExpRun convertPyExpRun ( PyObject * pyObj)
staticinherited

Performs the conversion of PyObject to ExpRun.

Converts the PyObject to an ExpRun. We've preoviously checked the object so this assumes a lot about the PyObject.

Definition at line 70 of file CalibrationAlgorithm.cc.

71{
72 ExpRun expRun;
73 PyObject* itemExp, *itemRun;
74 itemExp = PySequence_GetItem(pyObj, 0);
75 itemRun = PySequence_GetItem(pyObj, 1);
76 expRun.first = PyLong_AsLong(itemExp);
77 Py_DECREF(itemExp);
78 expRun.second = PyLong_AsLong(itemRun);
79 Py_DECREF(itemRun);
80 return expRun;
81}

◆ CreatePBinningScheme()

std::vector< double > CreatePBinningScheme ( )
inlineprivate

build the binning scheme for the momentum

Definition at line 135 of file SVDdEdxCalibrationAlgorithm.h.

136 {
137 std::vector<double> pbins;
138 pbins.reserve(m_numPBins + 1);
139 pbins.push_back(0.0);
140 pbins.push_back(0.05);
141
142 for (int iBin = 2; iBin <= m_numPBins; iBin++) {
143 if (iBin <= 19)
144 pbins.push_back(0.025 + 0.025 * iBin);
145 else if (iBin <= 59)
146 pbins.push_back(pbins.at(19) + 0.05 * (iBin - 19));
147 else
148 pbins.push_back(pbins.at(59) + 0.3 * (iBin - 59));
149 }
150
151 return pbins;
152 }

◆ DstarHistogramming()

std::unique_ptr< TList > DstarHistogramming ( TTree * inputTree)
private

produce histograms for K/pi

Definition at line 525 of file SVDdEdxCalibrationAlgorithm.cc.

526{
527 gROOT->SetBatch(true);
528 inputTree->SetEstimate(-1);
529 std::vector<double> pbins = CreatePBinningScheme();
530
531 TH2F* hDstarKMomentum = new TH2F("hist_d1_321_truncMomentum", "hist_d1_321_trunc;Momentum [GeV/c];dEdx [arb. units]", m_numPBins,
532 pbins.data(),
534 // the pion payload
535 TH2F* hDstarPiMomentum = new TH2F("hist_d1_211_truncMomentum", "hist_d1_211_trunc;Momentum [GeV/c];dEdx [arb. units]", m_numPBins,
536 pbins.data(),
538
539 inputTree->Draw("KaonSVDdEdx:KaonSVDdEdxTrackMomentum>>hist_d1_321_truncMomentum",
540 "nSignalDstar_sw * (KaonSVDdEdx>0) * (KaonnSVDHits>4)", "goff");
541 // the pion one will be built from both pions in the Dstar decay tree
542 TH2F* hDstarPiPart1Momentum = static_cast<TH2F*>(hDstarPiMomentum->Clone("hist_d1_211_truncPart1Momentum"));
543 TH2F* hDstarPiPart2Momentum = static_cast<TH2F*>(hDstarPiMomentum->Clone("hist_d1_211_truncPart2Momentum"));
544
545 inputTree->Draw("PionDSVDdEdx:PionDSVDdEdxTrackMomentum>>hist_d1_211_truncPart1Momentum",
546 "nSignalDstar_sw * (PionDSVDdEdx>0) * (PionDnSVDHits>4)",
547 "goff");
548 inputTree->Draw("SlowPionSVDdEdx:SlowPionSVDdEdxTrackMomentum>>hist_d1_211_truncPart2Momentum",
549 "nSignalDstar_sw * (SlowPionSVDdEdx>0) * (SlowPionnSVDHits>4)",
550 "goff");
551 hDstarPiMomentum->Add(hDstarPiPart1Momentum);
552 hDstarPiMomentum->Add(hDstarPiPart2Momentum);
553
554 inputTree->Draw(Form("KaonSVDdEdxTrackMomentum/%f", m_KaonPDGMass), "", "goff",
555 ((inputTree->GetEntries()) / m_numBGBins)*m_numBGBins);
556 double* KaonMomentumDataset = inputTree->GetV1();
557 TKDTreeBinning* kdBinsK = new TKDTreeBinning(((inputTree->GetEntries()) / m_numBGBins)*m_numBGBins, 1, KaonMomentumDataset,
559 const double* binsMinEdgesKOriginal = kdBinsK->SortOneDimBinEdges();
560 double* binsMinEdgesK = const_cast<double*>(binsMinEdgesKOriginal);
561 binsMinEdgesK[0] = 0.1;
562 binsMinEdgesK[m_numBGBins + 1] = 50.;
563
564// get a distribution that contains both pions to get a typical kinematics for the binning scheme
565 inputTree->Draw(Form("SlowPionSVDdEdxTrackMomentum/%f * (event %% 2 == 0) + PionDSVDdEdxTrackMomentum/%f * (event %% 2 ==1)",
566 m_PionPDGMass, m_PionPDGMass), "", "goff",
567 ((inputTree->GetEntries()) / m_numBGBins)*m_numBGBins);
568 double* PionMomentumDataset = inputTree->GetV1();
569
570 TKDTreeBinning* kdBinsPi = new TKDTreeBinning(((inputTree->GetEntries()) / m_numBGBins)*m_numBGBins, 1, PionMomentumDataset,
572 const double* binsMinEdgesPiOriginal = kdBinsPi->SortOneDimBinEdges();
573 double* binsMinEdgesPi = const_cast<double*>(binsMinEdgesPiOriginal);
574 binsMinEdgesPi[0] = 0.1;
575 binsMinEdgesPi[m_numBGBins + 1] = 50.;
576
577 TH2F* hDstarKBetaGamma = new TH2F("hist_d1_321_truncBetaGamma", "hist_d1_321_truncBetaGamma;#beta*#gamma;dEdx [arb. units]",
579 binsMinEdgesK,
581 // the pion payload
582 TH2F* hDstarPiBetaGamma = new TH2F("hist_d1_211_truncBetaGamma", "hist_d1_211_truncBetaGamma;#beta*#gamma;dEdx [arb. units]",
584 binsMinEdgesPi,
586
587 inputTree->Draw(Form("KaonSVDdEdx:KaonSVDdEdxTrackMomentum/%f>>hist_d1_321_truncBetaGamma", m_KaonPDGMass),
588 "nSignalDstar_sw * (KaonSVDdEdx>0) * (KaonnSVDHits>4)", "goff");
589 // the pion one will be built from both pions in the Dstar decay tree
590 TH2F* hDstarPiPart1BetaGamma = static_cast<TH2F*>(hDstarPiBetaGamma->Clone("hist_d1_211_truncPart1BetaGamma"));
591 TH2F* hDstarPiPart2BetaGamma = static_cast<TH2F*>(hDstarPiBetaGamma->Clone("hist_d1_211_truncPart2BetaGamma"));
592
593 inputTree->Draw(Form("PionDSVDdEdx:PionDSVDdEdxTrackMomentum/%f>>hist_d1_211_truncPart1BetaGamma", m_PionPDGMass),
594 "nSignalDstar_sw * (PionDSVDdEdx>0) * (PionDnSVDHits>4)",
595 "goff");
596 inputTree->Draw(Form("SlowPionSVDdEdx:SlowPionSVDdEdxTrackMomentum/%f>>hist_d1_211_truncPart2BetaGamma", m_PionPDGMass),
597 "nSignalDstar_sw * (SlowPionSVDdEdx>0) * (SlowPionnSVDHits>4)", "goff");
598 hDstarPiBetaGamma->Add(hDstarPiPart1BetaGamma);
599 hDstarPiBetaGamma->Add(hDstarPiPart2BetaGamma);
600
601
602
603 // produce the 1D profiles
604
605
606 TH1D* PionProfileMomentum = static_cast<TH1D*>(hDstarPiMomentum->ProfileX("PionProfileMomentum"));
607 PionProfileMomentum->SetTitle("PionProfile");
608 PionProfileMomentum->GetYaxis()->SetRangeUser(0, m_dedxCutoff);
609 PionProfileMomentum->GetXaxis()->SetTitle("Momentum, GeV/c");
610 PionProfileMomentum->GetYaxis()->SetTitle("dE/dx");
611 PionProfileMomentum->SetLineColor(kRed);
612
613 TH1D* PionProfileBetaGamma = static_cast<TH1D*>(hDstarPiBetaGamma->ProfileX("PionProfileBetaGamma"));
614 if (m_CustomProfile) {
615 PionProfileBetaGamma = PrepareProfile(hDstarPiBetaGamma, "PionProfileBetaGamma");
616 }
617 PionProfileBetaGamma->SetTitle("PionProfile");
618 PionProfileBetaGamma->GetYaxis()->SetRangeUser(0, m_dedxCutoff);
619 PionProfileBetaGamma->GetXaxis()->SetTitle("#beta*#gamma");
620 PionProfileBetaGamma->GetYaxis()->SetTitle("dE/dx");
621 PionProfileBetaGamma->SetLineColor(kRed);
622
623
624 TH1D* KaonProfileMomentum = static_cast<TH1D*>(hDstarKMomentum->ProfileX("KaonProfileMomentum"));
625 KaonProfileMomentum->SetTitle("KaonProfile");
626 KaonProfileMomentum->GetYaxis()->SetRangeUser(0, m_dedxCutoff);
627 KaonProfileMomentum->GetXaxis()->SetTitle("Momentum, GeV/c");
628 KaonProfileMomentum->GetYaxis()->SetTitle("dE/dx");
629 KaonProfileMomentum->SetLineColor(kRed);
630
631
632 TH1D* KaonProfileBetaGamma = static_cast<TH1D*>(hDstarKBetaGamma->ProfileX("KaonProfileBetaGamma"));
633 if (m_CustomProfile) {
634 KaonProfileBetaGamma = PrepareProfile(hDstarKBetaGamma, "KaonProfileBetaGamma");
635 }
636 KaonProfileBetaGamma->SetTitle("KaonProfile");
637
638 KaonProfileBetaGamma->GetYaxis()->SetRangeUser(0, m_dedxCutoff);
639 KaonProfileBetaGamma->GetXaxis()->SetTitle("#beta*#gamma");
640 KaonProfileBetaGamma->GetYaxis()->SetTitle("dE/dx");
641 KaonProfileBetaGamma->SetLineColor(kRed);
642
643
644
645 // normalisation
646 hDstarKMomentum->Sumw2();
647 hDstarKMomentum = Normalise2DHisto(hDstarKMomentum);
648
649 hDstarPiMomentum->Sumw2();
650 hDstarPiMomentum = Normalise2DHisto(hDstarPiMomentum);
651
652 std::unique_ptr<TList> histList(new TList);
653 histList->Add(KaonProfileMomentum);
654 histList->Add(KaonProfileBetaGamma);
655 histList->Add(hDstarKMomentum);
656
657 histList->Add(PionProfileMomentum);
658 histList->Add(PionProfileBetaGamma);
659 histList->Add(hDstarPiMomentum);
660
661 if (m_isMakePlots) {
662 TFile DstarHistogrammingPlotFile("SVDdEdxCalibrationDstarHistogramming.root", "RECREATE");
663 histList->Write();
664 DstarHistogrammingPlotFile.Close();
665 }
666
667 return histList;
668}
TH2F * Normalise2DHisto(TH2F *HistoToNormalise)
Normalise a given dEdx:momentum histogram in each momentum bin, so that sum of entries in each moment...
int m_numBGBins
the number of beta*gamma bins for the profile and fitting
double m_dedxMaxPossible
the approximate max possible value of dEdx
TH1D * PrepareProfile(TH2F *DataHistogram, TString NewName)
Reimplement the Profile histogram calculation for a 2D histogram.
const double m_KaonPDGMass
PDG mass for the charged kaon.
bool m_CustomProfile
reimplement profile histogram calculation instead of the ROOT implementation?
const double m_PionPDGMass
PDG mass for the charged pion.

◆ DstarMassFit()

TTree * DstarMassFit ( std::shared_ptr< TTree > preselTree)
private

Mass fit for D*->Dpi.

Definition at line 386 of file SVDdEdxCalibrationAlgorithm.cc.

387{
388 B2INFO("Configuring the Dstar fit...");
389 gROOT->SetBatch(true);
390 RooMsgService::instance().setGlobalKillBelow(RooFit::WARNING);
391
392 RooRealVar deltaM("deltaM", "m(D*)-m(D^{0})", 0.139545, 0.151, "GeV/c^{2}");
393
394 RooRealVar KaonMomentum("KaonMomentum", "momentum for Kaon (GeV)", -1.e8, 1.e8);
395 RooRealVar KaonSVDdEdxTrackMomentum("KaonSVDdEdxTrackMomentum", "momentum for Kaon (GeV), from the track", -1.e8, 1.e8);
396 RooRealVar KaonSVDdEdx("KaonSVDdEdx", "", -1.e8, 1.e8);
397 RooRealVar PionDMomentum("PionDMomentum", "momentum for pion (GeV)", -1.e8, 1.e8);
398 RooRealVar PionDSVDdEdxTrackMomentum("PionDSVDdEdxTrackMomentum", "momentum for pion (GeV), from the track", -1.e8, 1.e8);
399 RooRealVar PionDSVDdEdx("PionDSVDdEdx", "", -1.e8, 1.e8);
400 RooRealVar SlowPionMomentum("SlowPionMomentum", "momentum for slow pion (GeV)", -1.e8, 1.e8);
401 RooRealVar SlowPionSVDdEdxTrackMomentum("SlowPionSVDdEdxTrackMomentum", "momentum for slow pion (GeV), from the track", -1.e8,
402 1.e8);
403 RooRealVar SlowPionSVDdEdx("SlowPionSVDdEdx", "", -1.e8, 1.e8);
404 RooRealVar KaonnSVDHits("KaonnSVDHits", "", -1.e8, 1.e8);
405 RooRealVar PionDnSVDHits("PionDnSVDHits", "", -1.e8, 1.e8);
406 RooRealVar SlowPionnSVDHits("SlowPionnSVDHits", "", -1.e8, 1.e8);
407
408 RooRealVar exp("exp", "experiment number", 0, 1.e5);
409 RooRealVar run("run", "run number", 0, 1.e8);
410 RooRealVar event("event", "event number", 0, 1.e10);
411
412 auto variables = new RooArgSet();
413 variables->add(deltaM);
414 variables->add(KaonMomentum);
415 variables->add(KaonSVDdEdxTrackMomentum);
416 variables->add(KaonSVDdEdx);
417 variables->add(PionDMomentum);
418 variables->add(PionDSVDdEdxTrackMomentum);
419 variables->add(PionDSVDdEdx);
420 variables->add(SlowPionMomentum);
421 variables->add(SlowPionSVDdEdxTrackMomentum);
422 variables->add(SlowPionSVDdEdx);
423 variables->add(KaonnSVDHits);
424 variables->add(PionDnSVDHits);
425 variables->add(SlowPionnSVDHits);
426 variables->add(exp);
427 variables->add(run);
428 variables->add(event);
429
430 RooDataSet* DstarDataset = new RooDataSet("DstarDataset", "DstarDataset", *variables, Import(*preselTree));
431
432 if (DstarDataset->sumEntries() == 0) {
433 B2FATAL("The Dstar dataset is empty, stopping here");
434 }
435
436 RooPlot* DstarFitFrame = DstarDataset->plotOn(deltaM.frame());
437
438 RooRealVar GaussMean("GaussMean", "GaussMean", 0.145, 0.140, 0.150);
439 RooRealVar GaussSigma1("GaussSigma1", "GaussSigma1", 0.01, 1.e-4, 1.0);
440 RooGaussian DstarGauss1("DstarGauss1", "DstarGauss1", deltaM, GaussMean, GaussSigma1);
441 RooRealVar GaussSigma2("GaussSigma2", "GaussSigma2", 0.001, 1.e-4, 1.0);
442 RooGaussian DstarGauss2("DstarGauss2", "DstarGauss2", deltaM, GaussMean, GaussSigma2);
443 RooRealVar fracGaussYield("fracGaussYield", "Fraction of two Gaussians", 0.75, 0.0, 1.0);
444 RooAddPdf DstarSignalPDF("DstarSignalPDF", "DstarGauss1+DstarGauss2", RooArgList(DstarGauss1, DstarGauss2), fracGaussYield);
445
446 RooRealVar dm0Bkg("dm0Bkg", "dm0", 0.13957018, 0.130, 0.140);
447 RooRealVar aBkg("aBkg", "a", -0.0784, -0.08, 3.0);
448 RooRealVar bBkg("bBkg", "b", -0.444713, -0.5, 0.4);
449 RooRealVar cBkg("cBkg", "c", 0.3);
450 RooDstD0BG DstarBkgPDF("DstarBkgPDF", "DstarBkgPDF", deltaM, dm0Bkg, cBkg, aBkg, bBkg);
451 RooRealVar nSignalDstar("nSignalDstar", "signal yield", 0.5 * preselTree->GetEntries(), 0, preselTree->GetEntries());
452 RooRealVar nBkgDstar("nBkgDstar", "background yield", 0.5 * preselTree->GetEntries(), 0, preselTree->GetEntries());
453 RooAddPdf totalPDFDstar("totalPDFDstar", "totalPDFDstar pdf", RooArgList(DstarSignalPDF, DstarBkgPDF),
454 RooArgList(nSignalDstar, nBkgDstar));
455
456 B2INFO("Dstar: Start fitting...");
457 RooFitResult* DstarFitResult = totalPDFDstar.fitTo(*DstarDataset, Save(kTRUE), PrintLevel(-1));
458
459 int status = DstarFitResult->status();
460 int covqual = DstarFitResult->covQual();
461 double diff = nSignalDstar.getValV() + nBkgDstar.getValV() - DstarDataset->sumEntries();
462
463 B2INFO("Dstar: Fit status: " << status << "; covariance quality: " << covqual);
464 // if the fit is not healthy, try again once before giving up, with a slightly different setup:
465 if ((status > 0) || (TMath::Abs(diff) > 1.) || (nSignalDstar.getError() < sqrt(nSignalDstar.getValV()))
466 || (nSignalDstar.getError() > (nSignalDstar.getValV()))) {
467
468 DstarFitResult = totalPDFDstar.fitTo(*DstarDataset, Save(), Strategy(2), Offset(1));
469 status = DstarFitResult->status();
470 covqual = DstarFitResult->covQual();
471 diff = nSignalDstar.getValV() + nBkgDstar.getValV() - DstarDataset->sumEntries();
472 B2INFO("Dstar: Updated fit status: " << status << "; covariance quality: " << covqual);
473 }
474
475 if ((status > 0) || (TMath::Abs(diff) > 1.) || (nSignalDstar.getError() < sqrt(nSignalDstar.getValV()))
476 || (nSignalDstar.getError() > (nSignalDstar.getValV()))) {
477 B2WARNING("Dstar: Fit problem: fit status " << status << "; sum of component yields minus the dataset yield is " << diff <<
478 "; signal yield is " << nSignalDstar.getValV() << ", while its uncertainty is " << nSignalDstar.getError());
479 }
480 if (covqual < 2) {
481 B2INFO("Dstar: Fit warning: covariance quality " << covqual);
482 }
483
484 totalPDFDstar.plotOn(DstarFitFrame, LineColor(TColor::GetColor("#4575b4")));
485
486 double chisquare = DstarFitFrame->chiSquare();
487 B2INFO("Dstar: Fit chi2 = " << chisquare);
488 totalPDFDstar.paramOn(DstarFitFrame, Layout(0.63, 0.96, 0.93), Format("NEU", AutoPrecision(2)));
489 DstarFitFrame->getAttText()->SetTextSize(0.03);
490
491 totalPDFDstar.plotOn(DstarFitFrame, Components("DstarSignalPDF"), LineColor(TColor::GetColor("#d73027")));
492 totalPDFDstar.plotOn(DstarFitFrame, Components("DstarBkgPDF"), LineColor(TColor::GetColor("#fc8d59")));
493 totalPDFDstar.plotOn(DstarFitFrame, LineColor(TColor::GetColor("#4575b4")));
494
495 DstarFitFrame->GetXaxis()->SetTitle("#Deltam [GeV/c^{2}]");
496 if (m_isMakePlots) {
497 std::unique_ptr<TCanvas> canvDstar(new TCanvas("canvDstar", "canvDstar"));
498 canvDstar->cd();
499
500 DstarFitFrame->Draw();
501
502 canvDstar->Print("SVDdEdxCalibrationFitDstar.pdf");
503 TFile DstarFitPlotFile("SVDdEdxCalibrationDstarFitPlotFile.root", "RECREATE");
504 canvDstar->Write();
505 DstarFitPlotFile.Close();
506 }
507
509
510 RooStats::SPlot* sPlotDatasetDstar = new RooStats::SPlot("sData", "An SPlot", *DstarDataset, &totalPDFDstar,
511 RooArgList(nSignalDstar, nBkgDstar));
512
513 for (int iEvt = 0; iEvt < 5; iEvt++) {
514 if (TMath::Abs(sPlotDatasetDstar->GetSWeight(iEvt, "nSignalDstar") + sPlotDatasetDstar->GetSWeight(iEvt, "nBkgDstar") - 1) > 5.e-3)
515 B2FATAL("Dstar: sPlot error: sum of weights not equal to 1");
516 }
517
518 TTree* treeDstarSWeighted = DstarDataset->GetClonedTree();
519 treeDstarSWeighted->SetName("treeDstarSWeighted");
520
521 B2INFO("Dstar: sPlot done. Proceed to histogramming");
522 return treeDstarSWeighted;
523}
double sqrt(double a)
sqrt for double
Definition beamHelpers.h:28

◆ dumpOutputJson()

const std::string dumpOutputJson ( ) const
inlineinherited

Dump the JSON string of the output JSON object.

Definition at line 223 of file CalibrationAlgorithm.h.

223{return m_jsonExecutionOutput.dump();}

◆ execute() [1/2]

CalibrationAlgorithm::EResult execute ( PyObject * runs,
int iteration = 0,
IntervalOfValidity iov = IntervalOfValidity() )
inherited

Runs calibration over Python list of runs. Converts to C++ and then calls the other execute() function.

Definition at line 83 of file CalibrationAlgorithm.cc.

84{
85 B2DEBUG(29, "Running execute() using Python Object as input argument");
86 // Reset the execution specific data in case the algorithm was previously called
87 m_data.reset();
88 m_data.setIteration(iteration);
89 vector<ExpRun> vecRuns;
90 // Is it a list?
91 if (PySequence_Check(runs)) {
92 boost::python::handle<> handle(boost::python::borrowed(runs));
93 boost::python::list listRuns(handle);
94
95 int nList = boost::python::len(listRuns);
96 for (int iList = 0; iList < nList; ++iList) {
97 boost::python::object pyExpRun(listRuns[iList]);
98 if (!checkPyExpRun(pyExpRun.ptr())) {
99 B2ERROR("Received Python ExpRuns couldn't be converted to C++");
100 m_data.setResult(c_Failure);
101 return c_Failure;
102 } else {
103 vecRuns.push_back(convertPyExpRun(pyExpRun.ptr()));
104 }
105 }
106 } else {
107 B2ERROR("Tried to set the input runs but we didn't receive a Python sequence object (list,tuple).");
108 m_data.setResult(c_Failure);
109 return c_Failure;
110 }
111 return execute(vecRuns, iteration, iov);
112}
static bool checkPyExpRun(PyObject *pyObj)
Checks that a PyObject can be successfully converted to an ExpRun type.
EResult execute(std::vector< Calibration::ExpRun > runs={}, int iteration=0, IntervalOfValidity iov=IntervalOfValidity())
Runs calibration over vector of runs for a given iteration.
static Calibration::ExpRun convertPyExpRun(PyObject *pyObj)
Performs the conversion of PyObject to ExpRun.
ExecutionData m_data
Data specific to a SINGLE execution of the algorithm. Gets reset at the beginning of execution.

◆ execute() [2/2]

CalibrationAlgorithm::EResult execute ( std::vector< Calibration::ExpRun > runs = {},
int iteration = 0,
IntervalOfValidity iov = IntervalOfValidity() )
inherited

Runs calibration over vector of runs for a given iteration.

You can also specify the IoV to save the database payload as. By default the Algorithm will create an IoV from your requested ExpRuns, or from the overall ExpRuns of the input data if you haven't specified ExpRuns in this function.

No checks are performed to make sure that a IoV you specify matches the data you ran over, it simply labels the IoV to commit to the database later.

Definition at line 114 of file CalibrationAlgorithm.cc.

115{
116 // Check if we are calling this function directly and need to reset, or through Python where it was already done.
117 if (m_data.getResult() != c_Undefined) {
118 m_data.reset();
119 m_data.setIteration(iteration);
120 }
121
122 if (m_inputFileNames.empty()) {
123 B2ERROR("There aren't any input files set. Please use CalibrationAlgorithm::setInputFiles()");
124 m_data.setResult(c_Failure);
125 return c_Failure;
126 }
127
128 // Did we receive runs to execute over explicitly?
129 if (!(runs.empty())) {
130 for (auto expRun : runs) {
131 B2DEBUG(29, "ExpRun requested = (" << expRun.first << ", " << expRun.second << ")");
132 }
133 // We've asked explicitly for certain runs, but we should check if the data granularity is 'run'
134 if (strcmp(getGranularity().c_str(), "all") == 0) {
135 B2ERROR(("The data is collected with granularity=all (exp=-1,run=-1), but you seem to request calibration for specific runs."
136 " We'll continue but using ALL the input data given instead of the specific runs requested."));
137 }
138 } else {
139 // If no runs are provided, infer the runs from all collected data
140 runs = getRunListFromAllData();
141 // Let's check that we have some now
142 if (runs.empty()) {
143 B2ERROR("No collected data in input files.");
144 m_data.setResult(c_Failure);
145 return c_Failure;
146 }
147 for (auto expRun : runs) {
148 B2DEBUG(29, "ExpRun requested = (" << expRun.first << ", " << expRun.second << ")");
149 }
150 }
151
152 m_data.setRequestedRuns(runs);
153 if (iov.empty()) {
154 // If no user specified IoV we use the IoV from the executed run list
155 iov = IntervalOfValidity(runs[0].first, runs[0].second, runs[runs.size() - 1].first, runs[runs.size() - 1].second);
156 }
157 m_data.setRequestedIov(iov);
158 // After here, the getObject<...>(...) helpers start to work
159
161 m_data.setResult(result);
162 return result;
163}
std::vector< Calibration::ExpRun > getRunListFromAllData() const
Get the complete list of runs from inspection of collected data.
std::vector< std::string > m_inputFileNames
List of input files to the Algorithm, will initially be user defined but then gets the wildcards expa...
EResult
The result of calibration.
@ c_Undefined
Not yet known (before execution) =4 in Python.
const std::string & getGranularity() const
Get the granularity of collected data.
virtual EResult calibrate()=0
Run algo on data - pure virtual: needs to be implemented.

◆ fillRunToInputFilesMap()

void fillRunToInputFilesMap ( )
inherited

Fill the mapping of ExpRun -> Files.

Definition at line 331 of file CalibrationAlgorithm.cc.

332{
333 m_runsToInputFiles.clear();
334 // Save TDirectory to change back at the end
335 TDirectory* dir = gDirectory;
336 RunRange* runRange;
337 // Construct the TDirectory name where we expect our objects to be
338 string runRangeObjName(getPrefix() + "/" + RUN_RANGE_OBJ_NAME);
339 for (const auto& fileName : m_inputFileNames) {
340 //Open TFile to get the objects
341 unique_ptr<TFile> f;
342 f.reset(TFile::Open(fileName.c_str(), "READ"));
343 runRange = dynamic_cast<RunRange*>(f->Get(runRangeObjName.c_str()));
344 if (runRange) {
345 // Insert or extend the run -> file mapping for this ExpRun
346 auto expRuns = runRange->getExpRunSet();
347 for (const auto& expRun : expRuns) {
348 auto runFiles = m_runsToInputFiles.find(expRun);
349 if (runFiles != m_runsToInputFiles.end()) {
350 (runFiles->second).push_back(fileName);
351 } else {
352 m_runsToInputFiles.insert(std::make_pair(expRun, std::vector<std::string> {fileName}));
353 }
354 }
355 } else {
356 B2WARNING("Missing a RunRange object for file: " << fileName);
357 }
358 }
359 dir->cd();
360}
const std::string & getPrefix() const
Get the prefix used for getting calibration data.
std::map< Calibration::ExpRun, std::vector< std::string > > m_runsToInputFiles
Map of Runs to input files. Gets filled when you call getRunRangeFromAllData, gets cleared when setti...
const std::set< Calibration::ExpRun > & getExpRunSet()
Get access to the stored set.
Definition RunRange.h:64

◆ findPayloadBoundaries()

const std::vector< ExpRun > findPayloadBoundaries ( std::vector< Calibration::ExpRun > runs,
int iteration = 0 )
inherited

Used to discover the ExpRun boundaries that you want the Python CAF to execute on. This is optional and only used in some.

Definition at line 521 of file CalibrationAlgorithm.cc.

522{
523 m_boundaries.clear();
524 if (m_inputFileNames.empty()) {
525 B2ERROR("There aren't any input files set. Please use CalibrationAlgorithm::setInputFiles()");
526 return m_boundaries;
527 }
528 // Reset the internal execution data just in case something is hanging around
529 m_data.reset();
530 if (runs.empty()) {
531 // Want to loop over all runs we could possibly know about
532 runs = getRunListFromAllData();
533 }
534 // Let's check that we have some now
535 if (runs.empty()) {
536 B2ERROR("No collected data in input files.");
537 return m_boundaries;
538 }
539 // In order to find run boundaries we must have collected with data granularity == 'run'
540 if (strcmp(getGranularity().c_str(), "all") == 0) {
541 B2ERROR("The data is collected with granularity='all' (exp=-1,run=-1), and we can't use that to find run boundaries.");
542 return m_boundaries;
543 }
544 m_data.setIteration(iteration);
545 // User defined setup function
546 boundaryFindingSetup(runs, iteration);
547 std::vector<ExpRun> runList;
548 // Loop over run list and call derived class "isBoundaryRequired" member function
549 for (auto currentRun : runs) {
550 runList.push_back(currentRun);
551 m_data.setRequestedRuns(runList);
552 // After here, the getObject<...>(...) helpers start to work
553 if (isBoundaryRequired(currentRun)) {
554 m_boundaries.push_back(currentRun);
555 }
556 // Only want run-by-run
557 runList.clear();
558 // Don't want memory hanging around
559 m_data.clearCalibrationData();
560 }
561 m_data.reset();
563 return m_boundaries;
564}
std::vector< Calibration::ExpRun > m_boundaries
When using the boundaries functionality from isBoundaryRequired, this is used to store the boundaries...
virtual void boundaryFindingTearDown()
Put your algorithm back into a state ready for normal execution if you need to.
virtual void boundaryFindingSetup(std::vector< Calibration::ExpRun >, int)
If you need to make some changes to your algorithm class before 'findPayloadBoundaries' is run,...
virtual bool isBoundaryRequired(const Calibration::ExpRun &)
Given the current collector data, make a decision about whether or not this run should be the start o...

◆ GammaHistogramming()

std::unique_ptr< TList > GammaHistogramming ( std::shared_ptr< TTree > preselTree)
private

produce histograms for e

Definition at line 671 of file SVDdEdxCalibrationAlgorithm.cc.

672{
673 B2INFO("Histogramming the converted photon selection...");
674 gROOT->SetBatch(true);
675
676
677 if (preselTree->GetEntries() == 0) {
678 B2FATAL("The Gamma tree is empty, stopping here");
679 }
680 preselTree->SetEstimate(-1);
681 std::vector<double> pbins = CreatePBinningScheme();
682
683
684 TH2F* hGammaEMomentum = new TH2F("hist_d1_11_truncMomentum", "hist_d1_11_trunc;Momentum [GeV/c];dEdx [arb. units]", m_numPBins,
685 pbins.data(), m_numDEdxBins, 0, m_dedxCutoff);
686
687 TH2F* hGammaEPart1Momentum = static_cast<TH2F*>(hGammaEMomentum->Clone("hist_d1_11_truncPart1Momentum"));
688 TH2F* hGammaEPart2Momentum = static_cast<TH2F*>(hGammaEMomentum->Clone("hist_d1_11_truncPart2Momentum"));
689
690 preselTree->Draw("FirstElectronSVDdEdx:FirstElectronSVDdEdxTrackMomentum>>hist_d1_11_truncPart1Momentum",
691 "FirstElectronSVDdEdx>0 && FirstElectronnSVDHits>4 && DIRA>0.995 && dr>1.2", "goff");
692 preselTree->Draw("SecondElectronSVDdEdx:SecondElectronSVDdEdxTrackMomentum>>hist_d1_11_truncPart2Momentum",
693 "SecondElectronSVDdEdx>0 && SecondElectronnSVDHits>4 && DIRA>0.995 && dr>1.2", "goff");
694 hGammaEMomentum->Add(hGammaEPart1Momentum);
695 hGammaEMomentum->Add(hGammaEPart2Momentum);
696
697// get a distribution that contains both pions to get a typical kinematics for the binning scheme
698 preselTree->Draw(
699 Form("FirstElectronSVDdEdxTrackMomentum/%f* (event %% 2==0) + SecondElectronSVDdEdxTrackMomentum/%f* (event %% 2==1)",
701 "", "goff", ((preselTree->GetEntries()) / m_numBGBins)*m_numBGBins);
702 double* ElectronMomentumDataset = preselTree->GetV1();
703
704 TKDTreeBinning* kdBinsE = new TKDTreeBinning(((preselTree->GetEntries()) / m_numBGBins)*m_numBGBins, 1, ElectronMomentumDataset,
706 const double* binsMinEdgesEOriginal = kdBinsE->SortOneDimBinEdges();
707 double* binsMinEdgesE = const_cast<double*>(binsMinEdgesEOriginal);
708 binsMinEdgesE[0] = 0.;
709 binsMinEdgesE[m_numBGBins + 1] = 10000.;
710
711
712 TH2F* hGammaEBetaGamma = new TH2F("hist_d1_11_truncBetaGamma", "hist_d1_11_truncBetaGamma;#beta*#gamma;dEdx [arb. units]",
714 binsMinEdgesE,
716 TH2F* hGammaEPart1BetaGamma = static_cast<TH2F*>(hGammaEBetaGamma->Clone("hist_d1_11_truncPart1BetaGamma"));
717 TH2F* hGammaEPart2BetaGamma = static_cast<TH2F*>(hGammaEBetaGamma->Clone("hist_d1_11_truncPart2BetaGamma"));
718
719 preselTree->Draw(Form("FirstElectronSVDdEdx:FirstElectronSVDdEdxTrackMomentum/%f>>hist_d1_11_truncPart1BetaGamma",
721 "FirstElectronSVDdEdx>0 && FirstElectronnSVDHits>4 && DIRA>0.995 && dr>1.2 && FirstElectronSVDdEdx<1.8e6", "goff");
722 preselTree->Draw(Form("SecondElectronSVDdEdx:SecondElectronSVDdEdxTrackMomentum/%f>>hist_d1_11_truncPart2BetaGamma",
724 "SecondElectronSVDdEdx>0 && SecondElectronnSVDHits>4 && DIRA>0.995 && dr>1.2 && SecondElectronSVDdEdx<1.8e6", "goff");
725 hGammaEBetaGamma->Add(hGammaEPart1BetaGamma);
726 hGammaEBetaGamma->Add(hGammaEPart2BetaGamma);
727
728
729 // produce the 1D profile (for data-MC comparisons)
730 TH1D* ElectronProfileMomentum = static_cast<TH1D*>(hGammaEMomentum->ProfileX("ElectronProfileMomentum"));
731 ElectronProfileMomentum->SetTitle("ElectronProfile");
732 ElectronProfileMomentum->GetYaxis()->SetRangeUser(0, m_dedxCutoff);
733 ElectronProfileMomentum->GetXaxis()->SetTitle("Momentum, GeV/c");
734 ElectronProfileMomentum->GetYaxis()->SetTitle("dE/dx");
735 ElectronProfileMomentum->SetLineColor(kRed);
736
737// beta*gamma profile for the fit
738 TH1D* ElectronProfileBetaGamma = static_cast<TH1D*>(hGammaEBetaGamma->ProfileX("ElectronProfileBetaGamma"));
739 if (m_CustomProfile) {
740 ElectronProfileBetaGamma = PrepareProfile(hGammaEBetaGamma, "ElectronProfileBetaGamma");
741 }
742 ElectronProfileBetaGamma->SetTitle("ElectronProfile");
743
744 ElectronProfileBetaGamma->GetYaxis()->SetRangeUser(0, m_dedxCutoff);
745 ElectronProfileBetaGamma->GetXaxis()->SetTitle("#beta*#gamma");
746 ElectronProfileBetaGamma->GetYaxis()->SetTitle("dE/dx");
747 ElectronProfileBetaGamma->SetLineColor(kRed);
748
749
750 hGammaEMomentum = Normalise2DHisto(hGammaEMomentum);
751
752 std::unique_ptr<TList> histList(new TList);
753 histList->Add(ElectronProfileMomentum);
754 histList->Add(ElectronProfileBetaGamma);
755 histList->Add(hGammaEMomentum);
756
757 if (m_isMakePlots) {
758 TFile GammaHistogrammingPlotFile("SVDdEdxCalibrationGammaHistogramming.root", "RECREATE");
759 histList->Write();
760 GammaHistogrammingPlotFile.Close();
761 }
762
763 return histList;
764
765}
const double m_ElectronPDGMass
PDG mass for the electron.

◆ GenerateNewHistograms()

std::unique_ptr< TList > GenerateNewHistograms ( std::shared_ptr< TTree > ttreeLambda,
std::shared_ptr< TTree > ttreeDstar,
std::shared_ptr< TTree > ttreeGamma,
std::shared_ptr< TTree > ttreeGeneric )
private

generate high-statistics histograms

Definition at line 767 of file SVDdEdxCalibrationAlgorithm.cc.

770{
771 gROOT->SetBatch(true);
772 gStyle->SetOptStat(0);
773// run the background subtraction and histogramming parts
774 TTree* treeLambda = LambdaMassFit(ttreeLambda);
775 std::unique_ptr<TList> HistListLambda = LambdaHistogramming(treeLambda);
776 TH1D* ProtonProfileBetaGamma = static_cast<TH1D*>(HistListLambda->FindObject("ProtonProfileBetaGamma"));
777 TH2F* Proton2DHistogram = static_cast<TH2F*>(HistListLambda->FindObject("hist_d1_2212_truncMomentum"));
778
779 TTree* treeDstar = DstarMassFit(ttreeDstar);
780 std::unique_ptr<TList> HistListDstar = DstarHistogramming(treeDstar);
781 TH1D* PionProfileBetaGamma = static_cast<TH1D*>(HistListDstar->FindObject("PionProfileBetaGamma"));
782 TH2F* Pion2DHistogram = static_cast<TH2F*>(HistListDstar->FindObject("hist_d1_211_truncMomentum"));
783 TH1D* KaonProfileBetaGamma = static_cast<TH1D*>(HistListDstar->FindObject("KaonProfileBetaGamma"));
784 TH2F* Kaon2DHistogram = static_cast<TH2F*>(HistListDstar->FindObject("hist_d1_321_truncMomentum"));
785
786 std::unique_ptr<TList> HistListGamma = GammaHistogramming(ttreeGamma);
787 TH1D* ElectronProfileBetaGamma = static_cast<TH1D*>(HistListGamma->FindObject("ElectronProfileBetaGamma"));
788 TH2F* Electron2DHistogram = static_cast<TH2F*>(HistListGamma->FindObject("hist_d1_11_truncMomentum"));
789
790 int cred = TColor::GetColor("#e31a1c");
791 PionProfileBetaGamma->SetMarkerSize(4);
792 PionProfileBetaGamma->SetLineWidth(2);
793 PionProfileBetaGamma->SetMarkerColor(cred);
794 PionProfileBetaGamma->SetLineColor(cred);
795
796 int cpink = TColor::GetColor("#807dba");
797 KaonProfileBetaGamma->SetMarkerSize(4);
798 KaonProfileBetaGamma->SetLineWidth(2);
799 KaonProfileBetaGamma->SetMarkerColor(cpink);
800 KaonProfileBetaGamma->SetLineColor(cpink);
801
802 int cblue = TColor::GetColor("#084594");
803 ProtonProfileBetaGamma->SetMarkerSize(4);
804 ProtonProfileBetaGamma->SetLineWidth(2);
805 ProtonProfileBetaGamma->SetMarkerColor(cblue);
806 ProtonProfileBetaGamma->SetLineColor(cblue);
807
808 int cgreen = TColor::GetColor("#238b45");
809 ElectronProfileBetaGamma->SetMarkerSize(4);
810 ElectronProfileBetaGamma->SetLineWidth(2);
811 ElectronProfileBetaGamma->SetMarkerColor(cgreen);
812 ElectronProfileBetaGamma->SetLineColor(cgreen);
813
814// prepare the fitting
815
816 PionProfileBetaGamma->GetYaxis()->SetRangeUser(5.e5, 5.5e6);
817 KaonProfileBetaGamma->GetYaxis()->SetRangeUser(5.e5, 5.5e6);
818 ProtonProfileBetaGamma->GetYaxis()->SetRangeUser(5.e5, 5.5e6);
819
820// enhance the proton histogram (which ends at beta*gamma around 3) by adding pion data above this value – otherwise the fit is very unstable
821 auto PionEdges = PionProfileBetaGamma->GetXaxis()->GetXbins()->GetArray();
822 auto ProtonEdges = ProtonProfileBetaGamma->GetXaxis()->GetXbins()->GetArray();
823
824 std::vector<float> CombinedEdgesVector;
825
826 double borderline = 3.;
827
828 for (int i = 0; i < ProtonProfileBetaGamma->GetNbinsX() + 1; i++)
829 if (ProtonEdges[i] < borderline) CombinedEdgesVector.push_back(ProtonEdges[i]);
830
831
832 for (int i = 0; i < PionProfileBetaGamma->GetNbinsX() + 1; i++)
833 if (PionEdges[i] > borderline) CombinedEdgesVector.push_back(PionEdges[i]);
834
835
836 TH1D* CombinedHistogramPAndPi = new TH1D("CombinedHistogramPAndPi", "histo_for_fit", CombinedEdgesVector.size() - 1,
837 CombinedEdgesVector.data());
838
839 int iterator = 1;
840 for (int i = 1; i < ProtonProfileBetaGamma->GetNbinsX() + 1; i++)
841 if (ProtonEdges[i - 1] < borderline) {
842 CombinedHistogramPAndPi->SetBinContent(i, ProtonProfileBetaGamma->GetBinContent(i));
843 CombinedHistogramPAndPi->SetBinError(i, ProtonProfileBetaGamma->GetBinError(i));
844 iterator++;
845 }
846
847 for (int i = 1; i < PionProfileBetaGamma->GetNbinsX() + 1; i++)
848 if (PionEdges[i - 1] > borderline) {
849
850 CombinedHistogramPAndPi->SetBinContent(iterator, PionProfileBetaGamma->GetBinContent(i));
851 CombinedHistogramPAndPi->SetBinError(iterator, PionProfileBetaGamma->GetBinError(i));
852 iterator++;
853 }
854
855// define the beta*gamma vs momentum function
856 TF1* BetaGammaFunctionPion = new TF1("BetaGammaFunctionPion", "[0] + [1] * x/[2] + [5]/(x^2/[2]^2 + [3])**[4] + [6]* (x/[2])**0.5",
857 0.01, 25.);
858
859 BetaGammaFunctionPion->SetNpx(1000);
860
861 BetaGammaFunctionPion->SetParameters(5.e5, 2.e3, 1, 0.15, 1.2, 6.e5, 3.e5);
862
863 BetaGammaFunctionPion->SetParLimits(0, 3.e5, 7.e5);
864 BetaGammaFunctionPion->SetParLimits(1, -3.e4, 1.e4);
865 BetaGammaFunctionPion->SetParLimits(3, 0.1, 0.2);
866 BetaGammaFunctionPion->SetParLimits(4, 0.9, 1.6);
867 BetaGammaFunctionPion->SetParLimits(5, 3.e5, 7.e5);
868 BetaGammaFunctionPion->SetParLimits(6, 0., 1.e6);
869 BetaGammaFunctionPion->FixParameter(2, 1);
870 if (m_FixUnstableFitParameter) BetaGammaFunctionPion->FixParameter(3, 0.15);
871
872// fit it to the pion data
873 ROOT::Math::MinimizerOptions::SetDefaultMinimizer("Minuit2", "Migrad");
874 auto FitResultBetaGammaPion = PionProfileBetaGamma->Fit("BetaGammaFunctionPion", "0SI", "", 0.4, 25);
875
876 if ((FitResultBetaGammaPion->Status() > 1) || (BetaGammaFunctionPion->Eval(1) < 5.e5) || (BetaGammaFunctionPion->Eval(1) > 5.e6)) {
877 BetaGammaFunctionPion->FixParameter(3, 0.15);
878 FitResultBetaGammaPion = PionProfileBetaGamma->Fit("BetaGammaFunctionPion", "0SI", "", 0.4, 25);
879 }
880 if ((FitResultBetaGammaPion->Status() > 1) || (BetaGammaFunctionPion->Eval(1) < 5.e5) || (BetaGammaFunctionPion->Eval(1) > 5.e6)) {
881 BetaGammaFunctionPion->FixParameter(3, 0.15);
882 FitResultBetaGammaPion = PionProfileBetaGamma->Fit("BetaGammaFunctionPion", "0SI", "", 0.45, 25);
883 }
884 if ((FitResultBetaGammaPion->Status() > 1) || (BetaGammaFunctionPion->Eval(1) < 5.e5) || (BetaGammaFunctionPion->Eval(1) > 5.e6)) {
885 BetaGammaFunctionPion->FixParameter(3, 0.15);
886 FitResultBetaGammaPion = PionProfileBetaGamma->Fit("BetaGammaFunctionPion", "0S", "", 0.5, 25);
887 }
888
889 B2INFO("BetaGamma fit for pions done. Fit status: " << FitResultBetaGammaPion->Status());
890 // B2INFO(FitResultBetaGammaPion->Print(Belle2::LogConfig::c_Info));
891 B2INFO("Fit parameters:");
892 B2INFO("p0: " << BetaGammaFunctionPion->GetParameter(0) << " +- " << BetaGammaFunctionPion->GetParError(0));
893 B2INFO("p1: " << BetaGammaFunctionPion->GetParameter(1) << " +- " << BetaGammaFunctionPion->GetParError(1));
894 B2INFO("p2: " << BetaGammaFunctionPion->GetParameter(2) << " +- " << BetaGammaFunctionPion->GetParError(2));
895 B2INFO("p3: " << BetaGammaFunctionPion->GetParameter(3) << " +- " << BetaGammaFunctionPion->GetParError(3));
896 B2INFO("p4: " << BetaGammaFunctionPion->GetParameter(4) << " +- " << BetaGammaFunctionPion->GetParError(4));
897 B2INFO("p5: " << BetaGammaFunctionPion->GetParameter(5) << " +- " << BetaGammaFunctionPion->GetParError(5));
898 B2INFO("p6: " << BetaGammaFunctionPion->GetParameter(6) << " +- " << BetaGammaFunctionPion->GetParError(6));
899
900 // repeat the same for kaons
901 TF1* BetaGammaFunctionKaon = new TF1("BetaGammaFunctionKaon", "[0] + [1] * x/[2] + [5]/(x^2/[2]^2 + [3])**[4]+ [6]* (x/[2])**0.5",
902 0.01, 25.);
903
904 BetaGammaFunctionKaon->SetNpx(1000);
905 BetaGammaFunctionKaon->SetParameters(5.e5, 2.e3, 1, 0.15, 1.2, 6.e5, 3.e5);
906
907 BetaGammaFunctionKaon->SetParLimits(0, 3.e5, 7.e5);
908 BetaGammaFunctionKaon->SetParLimits(1, -3.e4, 1.e4);
909 BetaGammaFunctionKaon->SetParLimits(3, 0.1, 0.2);
910 BetaGammaFunctionKaon->SetParLimits(4, 0.9, 1.6);
911 BetaGammaFunctionKaon->SetParLimits(5, 3.e5, 7.e5);
912 BetaGammaFunctionKaon->SetParLimits(6, 0., 1.e6);
913
914 BetaGammaFunctionKaon->FixParameter(2, 1);
915 if (m_FixUnstableFitParameter) BetaGammaFunctionKaon->FixParameter(3, 0.15);
916
917 BetaGammaFunctionKaon->SetLineColor(KaonProfileBetaGamma->GetMarkerColor());
918
919 auto FitResultBetaGammaKaon = KaonProfileBetaGamma->Fit("BetaGammaFunctionKaon", "0SI", "", 0.4, 8.5);
920
921 if ((FitResultBetaGammaKaon->Status() > 1) || (BetaGammaFunctionKaon->Eval(1) < 5.e5) || (BetaGammaFunctionKaon->Eval(1) > 5.e6)) {
922 BetaGammaFunctionKaon->FixParameter(3, 0.15);
923 FitResultBetaGammaKaon = KaonProfileBetaGamma->Fit("BetaGammaFunctionKaon", "0SI", "", 0.4, 8.5);
924 }
925 if ((FitResultBetaGammaKaon->Status() > 1) || (BetaGammaFunctionKaon->Eval(1) < 5.e5) || (BetaGammaFunctionKaon->Eval(1) > 5.e6)) {
926 BetaGammaFunctionKaon->FixParameter(3, 0.15);
927 FitResultBetaGammaKaon = KaonProfileBetaGamma->Fit("BetaGammaFunctionKaon", "0SI", "", 0.45, 8);
928 }
929 if ((FitResultBetaGammaKaon->Status() > 1) || (BetaGammaFunctionKaon->Eval(1) < 5.e5) || (BetaGammaFunctionKaon->Eval(1) > 5.e6)) {
930 BetaGammaFunctionKaon->FixParameter(3, 0.15);
931 FitResultBetaGammaKaon = KaonProfileBetaGamma->Fit("BetaGammaFunctionKaon", "0S", "", 0.5, 8);
932 }
933
934 B2INFO("BetaGamma fit for kaons done. Fit status: " << FitResultBetaGammaKaon->Status());
935 B2INFO("Fit parameters:");
936 B2INFO("p0: " << BetaGammaFunctionKaon->GetParameter(0) << " +- " << BetaGammaFunctionKaon->GetParError(0));
937 B2INFO("p1: " << BetaGammaFunctionKaon->GetParameter(1) << " +- " << BetaGammaFunctionKaon->GetParError(1));
938 B2INFO("p2: " << BetaGammaFunctionKaon->GetParameter(2) << " +- " << BetaGammaFunctionKaon->GetParError(2));
939 B2INFO("p3: " << BetaGammaFunctionKaon->GetParameter(3) << " +- " << BetaGammaFunctionKaon->GetParError(3));
940 B2INFO("p4: " << BetaGammaFunctionKaon->GetParameter(4) << " +- " << BetaGammaFunctionKaon->GetParError(4));
941 B2INFO("p5: " << BetaGammaFunctionKaon->GetParameter(5) << " +- " << BetaGammaFunctionKaon->GetParError(5));
942 B2INFO("p6: " << BetaGammaFunctionKaon->GetParameter(6) << " +- " << BetaGammaFunctionKaon->GetParError(6));
943
944 // repeat the same for protons
945 TF1* BetaGammaFunctionProton = new TF1("BetaGammaFunctionProton",
946 "[0] + [1] * x/[2] + [5]/(x^2/[2]^2 + [3])**[4]+ [6]* (x/[2])**0.5", 0.01, 25.);
947
948 BetaGammaFunctionProton->SetNpx(1000);
949
950 BetaGammaFunctionProton->SetParameters(5.e5, 2.e3, 1, 0.15, 1.2, 6.e5, 3.e5);
951
952 BetaGammaFunctionProton->SetParLimits(0, 3.e5, 7.e5);
953 BetaGammaFunctionProton->SetParLimits(1, -3.e4, 1.e4);
954 BetaGammaFunctionProton->SetParLimits(3, 0.1, 0.2);
955 BetaGammaFunctionProton->SetParLimits(4, 0.9, 1.6);
956 BetaGammaFunctionProton->SetParLimits(5, 3.e5, 7.e5);
957 BetaGammaFunctionProton->SetParLimits(6, 0., 1.e6);
958
959 BetaGammaFunctionProton->FixParameter(2, 1);
960 if (m_FixUnstableFitParameter) BetaGammaFunctionProton->FixParameter(3, 0.15);
961
962 BetaGammaFunctionProton->SetLineColor(ProtonProfileBetaGamma->GetMarkerColor());
963
964 auto FitResultBetaGammaProton = CombinedHistogramPAndPi->Fit("BetaGammaFunctionProton", "0SI", "", 0.45, 15);
965
966 if ((FitResultBetaGammaProton->Status() > 1) || (BetaGammaFunctionProton->Eval(1) < 5.e5)
967 || (BetaGammaFunctionProton->Eval(1) > 5.e6)) {
968 BetaGammaFunctionProton->FixParameter(3, 0.15);
969 FitResultBetaGammaProton = CombinedHistogramPAndPi->Fit("BetaGammaFunctionProton", "0SI", "", 0.45, 15);
970 }
971 if ((FitResultBetaGammaProton->Status() > 1) || (BetaGammaFunctionProton->Eval(1) < 5.e5)
972 || (BetaGammaFunctionProton->Eval(1) > 5.e6)) {
973 BetaGammaFunctionProton->FixParameter(3, 0.15);
974 FitResultBetaGammaProton = CombinedHistogramPAndPi->Fit("BetaGammaFunctionProton", "0SI", "", 0.45, 10);
975 }
976 if ((FitResultBetaGammaProton->Status() > 1) || (BetaGammaFunctionProton->Eval(1) < 5.e5)
977 || (BetaGammaFunctionProton->Eval(1) > 5.e6)) {
978 BetaGammaFunctionProton->FixParameter(3, 0.15);
979 FitResultBetaGammaProton = CombinedHistogramPAndPi->Fit("BetaGammaFunctionProton", "0S", "", 0.5, 10);
980 }
981
982 B2INFO("BetaGamma fit for protons done. Fit status: " << FitResultBetaGammaProton->Status());
983 B2INFO("Fit parameters:");
984 B2INFO("p0: " << BetaGammaFunctionProton->GetParameter(0) << " +- " << BetaGammaFunctionProton->GetParError(0));
985 B2INFO("p1: " << BetaGammaFunctionProton->GetParameter(1) << " +- " << BetaGammaFunctionProton->GetParError(1));
986 B2INFO("p2: " << BetaGammaFunctionProton->GetParameter(2) << " +- " << BetaGammaFunctionProton->GetParError(2));
987 B2INFO("p3: " << BetaGammaFunctionProton->GetParameter(3) << " +- " << BetaGammaFunctionProton->GetParError(3));
988 B2INFO("p4: " << BetaGammaFunctionProton->GetParameter(4) << " +- " << BetaGammaFunctionProton->GetParError(4));
989 B2INFO("p5: " << BetaGammaFunctionProton->GetParameter(5) << " +- " << BetaGammaFunctionProton->GetParError(5));
990 B2INFO("p6: " << BetaGammaFunctionProton->GetParameter(6) << " +- " << BetaGammaFunctionProton->GetParError(6));
991
992 if (m_isMakePlots) {
993// plot a summary of all beta*gamma fits for hadrons
994 std::unique_ptr<TCanvas> CombinedCanvasHadrons(new TCanvas("CombinedCanvasHadrons", "Hadron beta*gamma fits", 10, 10, 1000, 700));
995 gStyle->SetOptFit(1111);
996
997 PionProfileBetaGamma->Draw();
998 PionProfileBetaGamma->GetListOfFunctions()->Add(BetaGammaFunctionPion);
999 KaonProfileBetaGamma->Draw("SAME");
1000 KaonProfileBetaGamma->GetListOfFunctions()->Add(BetaGammaFunctionKaon);
1001 ProtonProfileBetaGamma->Draw("SAME");
1002 ProtonProfileBetaGamma->GetListOfFunctions()->Add(BetaGammaFunctionProton);
1003// BetaGammaFunctionPion->Draw("SAME");
1004// BetaGammaFunctionKaon->Draw("SAME");
1005// BetaGammaFunctionProton->Draw("SAME");
1006 auto legend = new TLegend(0.4, 0.7, 0.65, 0.9);
1007 legend->AddEntry(PionProfileBetaGamma, "Pions", "lep");
1008 legend->AddEntry(KaonProfileBetaGamma, "Kaons", "lep");
1009 legend->AddEntry(ProtonProfileBetaGamma, "Protons", "lep");
1010 legend->Draw();
1011
1012 gPad->SetLogx();
1013 gPad->SetLogy();
1014
1015 CombinedCanvasHadrons->Print("HadronBetaGammaFits.pdf");
1016 TFile HadronFitPlotFile("SVDdEdxCalibrationHadronFitPlotFile.root", "RECREATE");
1017 PionProfileBetaGamma->Write();
1018 KaonProfileBetaGamma->Write();
1019 ProtonProfileBetaGamma->Write();
1020 CombinedHistogramPAndPi->Write();
1021 BetaGammaFunctionPion->Write();
1022 BetaGammaFunctionKaon->Write();
1023 BetaGammaFunctionProton->Write();
1024 CombinedCanvasHadrons->Write();
1025 HadronFitPlotFile.Close();
1026 }
1027
1028
1029 // in case we assume that all hadrons are equal
1031 BetaGammaFunctionKaon = static_cast<TF1*>(BetaGammaFunctionPion->Clone("BetaGammaFunctionKaon"));
1032 BetaGammaFunctionProton = static_cast<TF1*>(BetaGammaFunctionPion->Clone("BetaGammaFunctionProton"));
1033 }
1035 BetaGammaFunctionKaon = static_cast<TF1*>(BetaGammaFunctionProton->Clone("BetaGammaFunctionKaon"));
1036 BetaGammaFunctionPion = static_cast<TF1*>(BetaGammaFunctionProton->Clone("BetaGammaFunctionPion"));
1037 }
1038
1039 // sanity checks: are all fits ok?
1040 if ((FitResultBetaGammaProton->Status() > 1) || (BetaGammaFunctionProton->Eval(1) < 5.e5)
1041 || (BetaGammaFunctionProton->Eval(1) > 5.e6)) {
1042 if (FitResultBetaGammaPion->Status() == 0) {
1043 BetaGammaFunctionProton = static_cast<TF1*>(BetaGammaFunctionPion->Clone("BetaGammaFunctionProton"));
1044 } else if (FitResultBetaGammaKaon->Status() == 0) {
1045 BetaGammaFunctionProton = static_cast<TF1*>(BetaGammaFunctionKaon->Clone("BetaGammaFunctionProton"));
1046 } else {
1047 B2WARNING("Problem with the beta*gamma fit for protons, reverting to the default values");
1048 BetaGammaFunctionProton->SetParameters(450258, -10900.8, 1, 0.126797, 1.155, 641907, 86304.5);
1049 }
1050 }
1051
1052 if ((FitResultBetaGammaKaon->Status() > 1) || (BetaGammaFunctionKaon->Eval(1) < 5.e5) || (BetaGammaFunctionKaon->Eval(1) > 5.e6)) {
1053 if (FitResultBetaGammaProton->Status() == 0) {
1054 BetaGammaFunctionKaon = static_cast<TF1*>(BetaGammaFunctionProton->Clone("BetaGammaFunctionKaon"));
1055 } else if (FitResultBetaGammaPion->Status() == 0) {
1056 BetaGammaFunctionKaon = static_cast<TF1*>(BetaGammaFunctionPion->Clone("BetaGammaFunctionKaon"));
1057 } else {
1058 B2WARNING("Problem with the beta*gamma fit for kaons, reverting to the default values");
1059 BetaGammaFunctionKaon->SetParameters(543386, 3013.81, 1, 0.135517, 1.19742, 619509, 15484.4);
1060 }
1061 }
1062
1063 if ((FitResultBetaGammaPion->Status() > 1) || (BetaGammaFunctionPion->Eval(1) < 5.e5) || (BetaGammaFunctionPion->Eval(1) > 5.e6)) {
1064 if (FitResultBetaGammaKaon->Status() == 0) {
1065 BetaGammaFunctionPion = static_cast<TF1*>(BetaGammaFunctionKaon->Clone("BetaGammaFunctionPion"));
1066 } else if (FitResultBetaGammaProton->Status() == 0) {
1067 BetaGammaFunctionPion = static_cast<TF1*>(BetaGammaFunctionProton->Clone("BetaGammaFunctionPion"));
1068 } else {
1069 B2WARNING("Problem with the beta*gamma fit for pions, reverting to the default values");
1070 BetaGammaFunctionPion->SetParameters(537623, -1937.62, 1, 0.15292, 1.23803, 623678, 30400.9);
1071 }
1072 }
1073
1074
1075// electrons
1076
1077 TF1* BetaGammaFunctionElectron = new TF1("BetaGammaFunctionElectron", "[0] + [1]* x", 1, 10000.);
1078 BetaGammaFunctionElectron->SetParameters(6.e5, -1);
1079 BetaGammaFunctionElectron->SetParLimits(0, 3.e5, 8.e5);
1080 BetaGammaFunctionElectron->SetParLimits(1, -1.e5, 1.e5);
1081 auto FitResultBetaGammaElectron = ElectronProfileBetaGamma->Fit("BetaGammaFunctionElectron", "0SI", "", 100, 8000);
1082
1083
1084 if ((FitResultBetaGammaElectron->Status() > 1) || (BetaGammaFunctionElectron->Eval(1) < 3.e5)
1085 || (BetaGammaFunctionElectron->Eval(1) > 5.e6)) {
1086 FitResultBetaGammaElectron = ElectronProfileBetaGamma->Fit("BetaGammaFunctionElectron", "0S", "", 100, 10000);
1087 }
1088 B2INFO("BetaGamma fit for electrons done. Fit status: " << FitResultBetaGammaElectron->Status());
1089 B2INFO("Fit parameters:");
1090 B2INFO("p0: " << BetaGammaFunctionElectron->GetParameter(0) << " +- " << BetaGammaFunctionElectron->GetParError(0));
1091 B2INFO("p1: " << BetaGammaFunctionElectron->GetParameter(1) << " +- " << BetaGammaFunctionElectron->GetParError(1));
1092
1093
1094 ElectronProfileBetaGamma->SetMarkerSize(4);
1095 ElectronProfileBetaGamma->SetLineWidth(2);
1096 ElectronProfileBetaGamma->GetYaxis()->SetRangeUser(5e5, 1e6);
1097 ElectronProfileBetaGamma->GetListOfFunctions()->Add(BetaGammaFunctionElectron);
1098
1099 if (m_isMakePlots) {
1100 std::unique_ptr<TCanvas> ElectronCanvas(new TCanvas("ElectronCanvas", "Electron histogram", 10, 10, 1000, 700));
1101 ElectronProfileBetaGamma->Draw();
1102
1103 gPad->SetLogx();
1104
1105 ElectronCanvas->Print("ElectronBetaGammaFits.pdf");
1106 TFile ElectronFitPlotFile("SVDdEdxCalibrationElectronFitPlotFile.root", "RECREATE");
1107 ElectronProfileBetaGamma->Write();
1108 BetaGammaFunctionElectron->Write();
1109 ElectronCanvas->Write();
1110 ElectronFitPlotFile.Close();
1111 }
1112
1113 TF1* MomentumFunctionElectron = static_cast<TF1*>(BetaGammaFunctionElectron->Clone("MomentumFunctionElectron"));
1114 MomentumFunctionElectron->SetParameter(2, m_ElectronPDGMass);
1115 MomentumFunctionElectron->SetRange(0.01, 5.5);
1116 MomentumFunctionElectron->SetLineColor(kRed);
1117 MomentumFunctionElectron->SetLineWidth(4);
1118
1119 TF1* MomentumFunctionPion = static_cast<TF1*>(BetaGammaFunctionPion->Clone("MomentumFunctionPion"));
1120 MomentumFunctionPion->SetParameter(2, m_PionPDGMass);
1121 MomentumFunctionPion->SetRange(0.01, 5.5);
1122 MomentumFunctionPion->SetLineColor(kRed);
1123 MomentumFunctionPion->SetLineWidth(4);
1124
1125 TF1* MomentumFunctionProton = static_cast<TF1*>(BetaGammaFunctionProton->Clone("MomentumFunctionProton"));
1126 MomentumFunctionProton->SetParameter(2, m_ProtonPDGMass);
1127 MomentumFunctionProton->SetRange(0.01, 5.5);
1128 MomentumFunctionProton->SetLineColor(kRed);
1129 MomentumFunctionProton->SetLineWidth(4);
1130
1131 TF1* MomentumFunctionKaon = static_cast<TF1*>(BetaGammaFunctionKaon->Clone("MomentumFunctionKaon"));
1132 MomentumFunctionKaon->SetParameter(2, m_KaonPDGMass);
1133 MomentumFunctionKaon->SetRange(0.01, 5.5);
1134 MomentumFunctionKaon->SetLineColor(kRed);
1135 MomentumFunctionKaon->SetLineWidth(4);
1136
1137 gStyle->SetOptFit(1111);
1138 std::unique_ptr<TCanvas> CanvasOverlays(new TCanvas("CanvasOverlays", "overlays", 1300, 1000));
1139 CanvasOverlays->Divide(2, 2);
1140 CanvasOverlays->cd(1); Electron2DHistogram->Draw(); MomentumFunctionElectron->Draw("SAME");
1141 CanvasOverlays->cd(2); Pion2DHistogram->Draw(); MomentumFunctionPion->Draw("SAME");
1142 CanvasOverlays->cd(3); Kaon2DHistogram->Draw(); MomentumFunctionKaon->Draw("SAME");
1143 CanvasOverlays->cd(4); Proton2DHistogram->Draw(); MomentumFunctionProton->Draw("SAME");
1144 CanvasOverlays->Print("SVDdEdxOverlaysFitsHistos.pdf");
1145
1146 TF1* MomentumFunctionDeuteron = static_cast<TF1*>(BetaGammaFunctionProton->Clone("MomentumFunctionDeuteron"));
1147 MomentumFunctionDeuteron->SetParameter(2, m_DeuteronPDGMass);
1148 MomentumFunctionDeuteron->SetRange(0.01, 5.5);
1149 MomentumFunctionDeuteron->SetLineColor(kRed);
1150
1151 TF1* MomentumFunctionMuon = static_cast<TF1*>(BetaGammaFunctionPion->Clone("MomentumFunctionMuon"));
1152 MomentumFunctionMuon->SetParameter(2, m_MuonPDGMass);
1153 MomentumFunctionMuon->SetRange(0.01, 5.5);
1154 MomentumFunctionMuon->SetLineColor(kRed);
1155
1156// overlay all fits in one plot
1157
1158 std::unique_ptr<TCanvas> OverlayAllTracksCanvas(new TCanvas("OverlayAllTracksCanvas", "The Ultimate Plot", 10, 10, 1000, 700));
1159
1160 TH2F* AllTracksHistogram = new TH2F("AllTracksHistogram", "AllTracksHistogram;Momentum [GeV/c];dEdx [arb. units]", 1000, 0.05, 5,
1161 1000, 2.e5, 6.e6);
1162
1163 ttreeGeneric->Draw("TrackSVDdEdx:TrackSVDdEdxTrackMomentum>>AllTracksHistogram", "TracknSVDHits>7", "goff");
1164 AllTracksHistogram->Draw("COLZ");
1165 AllTracksHistogram->GetXaxis()->SetTitle("Momentum [GeV/c]");
1166 AllTracksHistogram->GetYaxis()->SetTitle("dE/dx [arbitrary units]");
1167 MomentumFunctionElectron->Draw("SAME");
1168 MomentumFunctionMuon->Draw("SAME");
1169 MomentumFunctionPion->Draw("SAME");
1170 MomentumFunctionKaon->Draw("SAME");
1171 MomentumFunctionProton->Draw("SAME");
1172 MomentumFunctionDeuteron->Draw("SAME");
1173 OverlayAllTracksCanvas->SetLogx();
1174 OverlayAllTracksCanvas->SetLogz();
1175
1176 OverlayAllTracksCanvas->Print("SVDdEdxAllTracksWithFits.pdf");
1177 TFile OverlayAllTracksPlotFile("SVDdEdxCalibrationOverlayAllTracks.root", "RECREATE");
1178 AllTracksHistogram->Write();
1179 MomentumFunctionElectron->Write();
1180 MomentumFunctionMuon->Write();
1181 MomentumFunctionPion->Write();
1182 MomentumFunctionKaon->Write();
1183 MomentumFunctionProton->Write();
1184 MomentumFunctionDeuteron->Write();
1185 OverlayAllTracksCanvas->Write();
1186 OverlayAllTracksPlotFile.Close();
1187
1188
1189// resolution studies //
1190
1191// For resolution measurement, we need to take a ProjectionY of the data histograms in the momentum range where the dEdx is flat vs momentum. We use our educated guess of the flat range (e.g. 0.6-1 GeV for pions) and FindBin to figure out which bin numbers those momentum values correspond to.
1192 double PionRangeMin = 0.6;
1193 double PionRangeMax = 1.;
1194 double KaonRangeMin = 1.9;
1195 double KaonRangeMax = 3;
1196 double ElectronRangeMin = 1.;
1197 double ElectronRangeMax = 1.4;
1198
1199 auto PionResolutionHistogram = Pion2DHistogram->ProjectionY("PionResolutionHistogram",
1200 Pion2DHistogram->GetXaxis()->FindBin(PionRangeMin),
1201 Pion2DHistogram->GetXaxis()->FindBin(PionRangeMax));
1202 auto ElectronResolutionHistogram = Electron2DHistogram->ProjectionY("ElectronResolutionHistogram",
1203 Electron2DHistogram->GetXaxis()->FindBin(ElectronRangeMin), Electron2DHistogram->GetXaxis()->FindBin(ElectronRangeMax));
1204 auto KaonResolutionHistogram = Kaon2DHistogram->ProjectionY("KaonResolutionHistogram",
1205 Kaon2DHistogram->GetXaxis()->FindBin(KaonRangeMin),
1206 Kaon2DHistogram->GetXaxis()->FindBin(KaonRangeMax));
1207// for protons, there is not enough data in the flat range.
1208
1209
1210 TF1* PionResolutionFunction = new TF1("PionResolutionFunction",
1211 "[0]*TMath::Landau(x, [1], [1]*[2])*TMath::Gaus(x, [1], [1]*[2]*[4]) + [3]*TMath::Gaus(x, [1], [1]*[2]*[5])", 100e3, 1500e3);
1212// parameter [1] is the mean of the Landau
1213// parameter [2] is the relative resolution (w.r.t. the mean) of the Landau
1214// parameters [4]-[5] are the relative resolution of Gauss contributions w.r.t. that of Landau
1215// parameters [0] and [3] are fractions of the two components
1216 PionResolutionFunction->SetParameters(1, 6.e5, 0.1, 0.5, 2, 1);
1217 PionResolutionFunction->SetParLimits(0, 0, 500);
1218 PionResolutionFunction->SetParLimits(1, 3.e5, 8.e5);
1219 PionResolutionFunction->SetParLimits(2, 0, 1);
1220 PionResolutionFunction->SetParLimits(3, 0, 500);
1221 PionResolutionFunction->SetParLimits(4, 0, 7);
1222 PionResolutionFunction->SetParLimits(5, 1, 7);
1223 PionResolutionFunction->SetNpx(1000);
1224 auto FitResultResolutionPion = PionResolutionHistogram->Fit(PionResolutionFunction, "RSI");
1225
1226 B2INFO("relative resolution for pions: " << PionResolutionFunction->GetParameter(2));
1227 B2INFO("resolution for pions: fit status" << FitResultResolutionPion->Status());
1228
1229 TF1* KaonResolutionFunction = new TF1("KaonResolutionFunction",
1230 "[0]*TMath::Landau(x, [1], [1]*[2])*TMath::Gaus(x, [1], [1]*[2]*[4]) + [3]*TMath::Gaus(x, [1], [1]*[2]*[5])", 100e3, 1500e3);
1231
1232
1233 KaonResolutionFunction->SetParameters(1, 6.e5, 0.1, 0.5, 2, 1);
1234 KaonResolutionFunction->SetParLimits(0, 0, 500);
1235 KaonResolutionFunction->SetParLimits(1, 3.e5, 8.e5);
1236 KaonResolutionFunction->SetParLimits(2, 0, 1);
1237 KaonResolutionFunction->SetParLimits(3, 0, 500);
1238 KaonResolutionFunction->SetParLimits(4, 0, 7);
1239 KaonResolutionFunction->SetParLimits(5, 1, 7);
1240 KaonResolutionFunction->SetNpx(1000);
1241 auto FitResultResolutionKaon = KaonResolutionHistogram->Fit(KaonResolutionFunction, "RSI");
1242
1243 B2INFO("relative resolution for kaons: " << KaonResolutionFunction->GetParameter(2));
1244 B2INFO("resolution for kaons: fit status" << FitResultResolutionKaon->Status());
1245
1246 if ((FitResultResolutionKaon->Status() > 1)
1247 && (FitResultResolutionPion->Status() <= 1)) KaonResolutionFunction = static_cast<TF1*>
1248 (PionResolutionFunction->Clone("KaonResolutionFunction"));
1249
1250
1251
1252
1253 TF1* ElectronResolutionFunction = new TF1("ElectronResolutionFunction",
1254 "[0]*TMath::Landau(x, [1], [1]*[2])*TMath::Gaus(x, [1], [1]*[2]*[4]) + [3]*TMath::Gaus(x, [1], [1]*[2]*[5])", 50e3, 1500e3);
1255
1256
1257 ElectronResolutionFunction->SetParameters(1, 6.e5, 0.1, 0.5, 2, 1);
1258 ElectronResolutionFunction->SetParLimits(0, 0, 500);
1259 ElectronResolutionFunction->SetParLimits(1, 3.e5, 8.e5);
1260 ElectronResolutionFunction->SetParLimits(2, 0, 1);
1261 ElectronResolutionFunction->SetParLimits(3, 0, 500);
1262 ElectronResolutionFunction->SetParLimits(4, 0, 7);
1263 ElectronResolutionFunction->SetParLimits(5, 1, 7);
1264 ElectronResolutionFunction->SetNpx(1000);
1265 auto FitResultResolutionElectron = ElectronResolutionHistogram->Fit(ElectronResolutionFunction, "RSI");
1266
1267 B2INFO("relative resolution for electrons: " << ElectronResolutionFunction->GetParameter(2));
1268 B2INFO("resolution for electrons: fit status" << FitResultResolutionElectron->Status());
1269
1270 // plot all the resolution fits
1271 if (m_isMakePlots) {
1272 TCanvas* CanvasResolutions = new TCanvas("CanvasResolutions", "Resolutions", 1200, 650);
1273 CanvasResolutions->Divide(3, 1);
1274 CanvasResolutions->cd(1); PionResolutionHistogram->Draw();
1275 CanvasResolutions->cd(2); KaonResolutionHistogram->Draw();
1276 CanvasResolutions->cd(3); ElectronResolutionHistogram->Draw();
1277
1278 CanvasResolutions->Print("SVDdEdxResolutions.pdf");
1279 TFile OverlayResolutionsPlotFile("SVDdEdxCalibrationResolutions.root", "RECREATE");
1280 PionResolutionHistogram->Write();
1281 KaonResolutionHistogram->Write();
1282 ElectronResolutionHistogram->Write();
1283 CanvasResolutions->Write();
1284 OverlayResolutionsPlotFile.Close();
1285 }
1286
1287// evaluate the bias correction:
1288// difference between the MomentumFunction prediction and the mean of the resolution function in the flat part
1289// it should be of the order -1e4, i.e. about -1% of the absolute dEdx value
1290 double BiasCorrectionPion = PionResolutionFunction->GetParameter(1) - MomentumFunctionPion->Eval((
1291 PionRangeMax + PionRangeMin) / 2.);
1292 B2INFO("BiasCorrectionPion = " << BiasCorrectionPion);
1293
1294// generate a new pion payload using the MomentumFunctionPion, PionResolutionFunction and the bias correction
1295 TH2F* Pion2DHistogramNew = PrepareNewHistogram(Pion2DHistogram, Form("%sNew", Pion2DHistogram->GetName()), MomentumFunctionPion,
1296 PionResolutionFunction, BiasCorrectionPion);
1297
1298// sanity check: residual between the generated distribution and the data one
1299 TH2F* Pion2DHistogramResidual = static_cast<TH2F*>(Pion2DHistogram->Clone("Pion2DHistogramResidual"));
1300 Pion2DHistogramResidual->Add(Pion2DHistogramNew, Pion2DHistogram, 1, -1);
1301 Pion2DHistogramResidual->SetMinimum(-0.15);
1302 Pion2DHistogramResidual->SetMaximum(0.15);
1303
1304 // repeat, for kaons
1305 double BiasCorrectionKaon = KaonResolutionFunction->GetParameter(1) - MomentumFunctionKaon->Eval((
1306 KaonRangeMax + KaonRangeMin) / 2.);
1307 B2INFO("BiasCorrectionKaon = " << BiasCorrectionKaon);
1308
1309 // for protons, we compare the flat part of the MomentumFunction (~3 GeV) with the mean of the kaon resolution function
1310 // as there's not enough stats in the flat part to extract proton resolution from data
1311 double BiasCorrectionProton = KaonResolutionFunction->GetParameter(1) - MomentumFunctionProton->Eval(3.);
1312 B2INFO("BiasCorrectionProton = " << BiasCorrectionProton);
1313
1314 if ((BiasCorrectionProton / BiasCorrectionKaon) > 1.5) BiasCorrectionProton =
1315 BiasCorrectionKaon; // probably something went wrong due to low statistics
1316
1317 // back to kaons: generate a new payload
1318 TH2F* Kaon2DHistogramNew = PrepareNewHistogram(Kaon2DHistogram, Form("%sNew", Kaon2DHistogram->GetName()), MomentumFunctionKaon,
1319 KaonResolutionFunction, BiasCorrectionKaon);
1320// residual generated - data for kaons
1321 TH2F* Kaon2DHistogramResidual = static_cast<TH2F*>(Kaon2DHistogram->Clone("Kaon2DHistogramResidual"));
1322 Kaon2DHistogramResidual->Add(Kaon2DHistogramNew, Kaon2DHistogram, 1, -1);
1323 Kaon2DHistogramResidual->SetMinimum(-0.15);
1324 Kaon2DHistogramResidual->SetMaximum(0.15);
1325
1326 // same for protons (we use the kaon resolution function as explained above)
1327 TH2F* Proton2DHistogramNew = PrepareNewHistogram(Proton2DHistogram, Form("%sNew", Proton2DHistogram->GetName()),
1328 MomentumFunctionProton,
1329 KaonResolutionFunction, BiasCorrectionProton);
1330
1331// residual for protons
1332 TH2F* Proton2DHistogramResidual = static_cast<TH2F*>(Proton2DHistogram->Clone("Proton2DHistogramResidual"));
1333 Proton2DHistogramResidual->Add(Proton2DHistogramNew, Proton2DHistogram, 1, -1);
1334 Proton2DHistogramResidual->SetMinimum(-0.15);
1335 Proton2DHistogramResidual->SetMaximum(0.15);
1336
1337// deuterons: same as protons, but use the MomentumFunctionDeuteron
1338 TH2F* Deuteron2DHistogramNew = PrepareNewHistogram(Proton2DHistogram, "Deuteron2DHistogramNew", MomentumFunctionDeuteron,
1339 KaonResolutionFunction,
1340 BiasCorrectionKaon);
1341 Deuteron2DHistogramNew->SetTitle("hist_d1_1000010020_trunc");
1342
1343// muons: same as pions, but use the MomentumFunctionMuon
1344 TH2F* Muon2DHistogramNew = PrepareNewHistogram(Pion2DHistogram, "Muon2DHistogramNew", MomentumFunctionMuon, PionResolutionFunction,
1345 BiasCorrectionPion);
1346 Muon2DHistogramNew->SetTitle("hist_d1_13_trunc");
1347
1348// same for electrons
1349 double BiasCorrectionElectron = ElectronResolutionFunction->GetParameter(1) - MomentumFunctionElectron->Eval((
1350 ElectronRangeMax + ElectronRangeMin) / 2.);
1351 B2INFO("BiasCorrectionElectron = " << BiasCorrectionElectron);
1352 TH2F* Electron2DHistogramNew = PrepareNewHistogram(Electron2DHistogram, Form("%sNew", Electron2DHistogram->GetName()),
1353 MomentumFunctionElectron,
1354 ElectronResolutionFunction, BiasCorrectionElectron);
1355
1356 TH2F* Electron2DHistogramResidual = static_cast<TH2F*>(Electron2DHistogram->Clone("Electron2DHistogramResidual"));
1357 Electron2DHistogramResidual->Add(Electron2DHistogramNew, Electron2DHistogram, 1, -1);
1358 Electron2DHistogramResidual->SetMinimum(-0.15);
1359 Electron2DHistogramResidual->SetMaximum(0.15);
1360
1361 Electron2DHistogramNew->SetName("Electron2DHistogramNew");
1362 Muon2DHistogramNew->SetName("Muon2DHistogramNew");
1363 Pion2DHistogramNew->SetName("Pion2DHistogramNew");
1364 Kaon2DHistogramNew->SetName("Kaon2DHistogramNew");
1365 Proton2DHistogramNew->SetName("Proton2DHistogramNew");
1366 Deuteron2DHistogramNew->SetName("Deuteron2DHistogramNew");
1367
1368// plot the summary of all the distributions
1369 if (m_isMakePlots) {
1370 TCanvas* CanvasSummaryGenerated = new TCanvas("CanvasSummaryGenerated", "Generated payloads", 1700, 850);
1371 CanvasSummaryGenerated->Divide(3, 2);
1372 CanvasSummaryGenerated->cd(1); Electron2DHistogramNew->Draw("COLZ");
1373 CanvasSummaryGenerated->cd(2); Muon2DHistogramNew->Draw("COLZ");
1374 CanvasSummaryGenerated->cd(3); Pion2DHistogramNew->Draw("COLZ");
1375 CanvasSummaryGenerated->cd(4); Kaon2DHistogramNew->Draw("COLZ");
1376 CanvasSummaryGenerated->cd(5); Proton2DHistogramNew->Draw("COLZ");
1377 CanvasSummaryGenerated->cd(6); Deuteron2DHistogramNew->Draw("COLZ");
1378
1379 CanvasSummaryGenerated->Print("SVDdEdxGeneratedPayloads.pdf");
1380 TFile SummaryGeneratedPlotFile("SVDdEdxCalibrationSummaryGenerated.root", "RECREATE");
1381 Electron2DHistogramNew->Write();
1382 Muon2DHistogramNew->Write();
1383 Pion2DHistogramNew->Write();
1384 Kaon2DHistogramNew->Write();
1385 Proton2DHistogramNew->Write();
1386 Deuteron2DHistogramNew->Write();
1387 SummaryGeneratedPlotFile.Close();
1388
1389
1390 TCanvas* CanvasSummaryData = new TCanvas("CanvasSummaryData", "Data distributions", 1700, 850);
1391 CanvasSummaryData->Divide(3, 2);
1392 CanvasSummaryData->cd(1); Electron2DHistogram->Draw("COLZ");
1393 CanvasSummaryData->cd(3); Pion2DHistogram->Draw("COLZ");
1394 CanvasSummaryData->cd(4); Kaon2DHistogram->Draw("COLZ");
1395 CanvasSummaryData->cd(5); Proton2DHistogram->Draw("COLZ");
1396
1397 CanvasSummaryData->Print("SVDdEdxDataDistributions.pdf");
1398 TFile SummaryDataPlotFile("SVDdEdxCalibrationSummaryData.root", "RECREATE");
1399 Electron2DHistogram->Write();
1400 Pion2DHistogram->Write();
1401 Kaon2DHistogram->Write();
1402 Proton2DHistogram->Write();
1403 SummaryDataPlotFile.Close();
1404
1405
1406 TCanvas* CanvasSummaryResiduals = new TCanvas("CanvasSummaryResiduals", "Residuals", 1700, 850);
1407 CanvasSummaryResiduals->Divide(3, 2);
1408 CanvasSummaryResiduals->cd(1); Electron2DHistogramResidual->Draw("COLZ");
1409 CanvasSummaryResiduals->cd(3); Pion2DHistogramResidual->Draw("COLZ");
1410 CanvasSummaryResiduals->cd(4); Kaon2DHistogramResidual->Draw("COLZ");
1411 CanvasSummaryResiduals->cd(5); Proton2DHistogramResidual->Draw("COLZ");
1412
1413
1414 CanvasSummaryResiduals->Print("SVDdEdxResiduals.pdf");
1415 TFile SummaryResidualsPlotFile("SVDdEdxCalibrationSummaryResiduals.root", "RECREATE");
1416 Electron2DHistogramResidual->Write();
1417 Pion2DHistogramResidual->Write();
1418 Kaon2DHistogramResidual->Write();
1419 Proton2DHistogramResidual->Write();
1420 SummaryResidualsPlotFile.Close();
1421 }
1422
1423
1424 // return all the generated payloads
1425 std::unique_ptr<TList> histList(new TList);
1426 histList->Add(Electron2DHistogramNew);
1427 histList->Add(Muon2DHistogramNew);
1428 histList->Add(Pion2DHistogramNew);
1429 histList->Add(Kaon2DHistogramNew);
1430 histList->Add(Proton2DHistogramNew);
1431 histList->Add(Deuteron2DHistogramNew);
1432
1433 return histList;
1434
1435}
const double m_MuonPDGMass
PDG mass for the muon.
bool m_FixUnstableFitParameter
In the dEdx:betagamma fit, there is one free parameter that makes fit convergence poor.
const double m_DeuteronPDGMass
PDG mass for the deuteron.
bool m_UseProtonBGFunctionForEverything
Assume that the dEdx:betagamma trend is the same for all hadrons; use the proton trend as representat...
std::unique_ptr< TList > DstarHistogramming(TTree *inputTree)
produce histograms for K/pi
TTree * LambdaMassFit(std::shared_ptr< TTree > preselTree)
Mass fit for Lambda->ppi.
std::unique_ptr< TList > LambdaHistogramming(TTree *inputTree)
produce histograms for protons
TH2F * PrepareNewHistogram(TH2F *DataHistogram, TString NewName, TF1 *betagamma_function, TF1 *ResolutionFunctionOriginal, double bias_correction)
Generate a new dEdx:momentum histogram from a function that encodes dEdx:momentum trend and a functio...
std::unique_ptr< TList > GammaHistogramming(std::shared_ptr< TTree > preselTree)
produce histograms for e
TTree * DstarMassFit(std::shared_ptr< TTree > preselTree)
Mass fit for D*->Dpi.
bool m_UsePionBGFunctionForEverything
Assume that the dEdx:betagamma trend is the same for all hadrons; use the pion trend as representativ...
const double m_ProtonPDGMass
PDG mass for the proton.

◆ getAllGranularityExpRun()

static Calibration::ExpRun getAllGranularityExpRun ( )
inlinestaticprotectedinherited

Returns the Exp,Run pair that means 'Everything'. Currently unused.

Definition at line 327 of file CalibrationAlgorithm.h.

327{return m_allExpRun;}

◆ getCollectorName()

const std::string & getCollectorName ( ) const
inlineinherited

Alias for prefix.

For convenience and less writing, we say developers to set this to default collector module name in constructor of base class. One can however use the dublets of collector+algorithm multiple times with different settings. To bind these together correctly, the prefix has to be set the same for algo and collector. So we call the setter setPrefix rather than setModuleName or whatever. This getter will work out of the box for default cases -> return the name of module you have to add to your path to collect data for this algorithm.

Definition at line 164 of file CalibrationAlgorithm.h.

164{return getPrefix();}

◆ getDescription()

const std::string & getDescription ( ) const
inlineinherited

Get the description of the algorithm (set by developers in constructor)

Definition at line 216 of file CalibrationAlgorithm.h.

216{return m_description;}

◆ getExpRunString()

string getExpRunString ( Calibration::ExpRun & expRun) const
privateinherited

Gets the "exp.run" string repr. of (exp,run)

Definition at line 254 of file CalibrationAlgorithm.cc.

255{
256 string expRunString;
257 expRunString += to_string(expRun.first);
258 expRunString += ".";
259 expRunString += to_string(expRun.second);
260 return expRunString;
261}

◆ getFullObjectPath()

string getFullObjectPath ( const std::string & name,
Calibration::ExpRun expRun ) const
privateinherited

constructs the full TDirectory + Key name of an object in a TFile based on its name and exprun

Definition at line 263 of file CalibrationAlgorithm.cc.

264{
265 string dirName = getPrefix() + "/" + name;
266 string objName = name + "_" + getExpRunString(expRun);
267 return dirName + "/" + objName;
268}
std::string getExpRunString(Calibration::ExpRun &expRun) const
Gets the "exp.run" string repr. of (exp,run)

◆ getGranularity()

const std::string & getGranularity ( ) const
inlineinherited

Get the granularity of collected data.

Definition at line 188 of file CalibrationAlgorithm.h.

188{return m_granularityOfData;};

◆ getGranularityFromData()

string getGranularityFromData ( ) const
protectedinherited

Get the granularity of collected data.

Definition at line 384 of file CalibrationAlgorithm.cc.

385{
386 // Save TDirectory to change back at the end
387 TDirectory* dir = gDirectory;
388 const RunRange* runRange;
389 string runRangeObjName(getPrefix() + "/" + RUN_RANGE_OBJ_NAME);
390 // We only check the first file
391 string fileName = m_inputFileNames[0];
392 unique_ptr<TFile> f;
393 f.reset(TFile::Open(fileName.c_str(), "READ"));
394 runRange = dynamic_cast<RunRange*>(f->Get(runRangeObjName.c_str()));
395 if (!runRange) {
396 B2FATAL("The input file " << fileName << " does not contain a RunRange object at "
397 << runRangeObjName << ". Please set your input files to exclude it.");
398 return "";
399 }
400 string granularity = runRange->getGranularity();
401 dir->cd();
402 return granularity;
403}
const std::string & getGranularity() const
Gets the m_granularity.
Definition RunRange.h:110

◆ getInputFileNames()

PyObject * getInputFileNames ( )
inherited

Get the input file names used for this algorithm and pass them out as a Python list of unicode strings.

Definition at line 245 of file CalibrationAlgorithm.cc.

246{
247 PyObject* objInputFileNames = PyList_New(m_inputFileNames.size());
248 for (size_t i = 0; i < m_inputFileNames.size(); ++i) {
249 PyList_SetItem(objInputFileNames, i, Py_BuildValue("s", m_inputFileNames[i].c_str()));
250 }
251 return objInputFileNames;
252}

◆ getInputJsonObject()

const nlohmann::json & getInputJsonObject ( ) const
inlineprotectedinherited

Get the entire top level JSON object. We explicitly say this must be of object type so that we might pick.

Definition at line 357 of file CalibrationAlgorithm.h.

357{return m_jsonExecutionInput;}

◆ getInputJsonValue()

template<class T>
const T getInputJsonValue ( const std::string & key) const
inlineprotectedinherited

Get an input JSON value using a key. The normal exceptions are raised when the key doesn't exist.

Definition at line 350 of file CalibrationAlgorithm.h.

351 {
352 return m_jsonExecutionInput.at(key);
353 }

◆ getIovFromAllData()

IntervalOfValidity getIovFromAllData ( ) const
inherited

Get the complete IoV from inspection of collected data.

Definition at line 326 of file CalibrationAlgorithm.cc.

327{
329}
RunRange getRunRangeFromAllData() const
Get the complete RunRange from inspection of collected data.
IntervalOfValidity getIntervalOfValidity()
Make IntervalOfValidity from the set, spanning all runs. Works because sets are sorted by default.
Definition RunRange.h:70

◆ getIteration()

int getIteration ( ) const
inlineprotectedinherited

Get current iteration.

Definition at line 269 of file CalibrationAlgorithm.h.

269{ return m_data.getIteration(); }

◆ getObjectPtr()

template<class T>
std::shared_ptr< T > getObjectPtr ( std::string name)
inlineprotectedinherited

Get calibration data object (for all runs the calibration is requested for) This function will only work during or after execute() has been called once.

Definition at line 285 of file CalibrationAlgorithm.h.

286 {
287 if (m_runsToInputFiles.size() == 0)
288 fillRunToInputFilesMap();
289 return getObjectPtr<T>(name, m_data.getRequestedRuns());
290 }

◆ getOutputJsonValue()

template<class T>
const T getOutputJsonValue ( const std::string & key) const
inlineprotectedinherited

Get a value using a key from the JSON output object, not sure why you would want to do this.

Definition at line 342 of file CalibrationAlgorithm.h.

343 {
344 return m_jsonExecutionOutput.at(key);
345 }

◆ getPayloads()

std::list< Database::DBImportQuery > & getPayloads ( )
inlineinherited

Get constants (in TObjects) for database update from last execution.

Definition at line 204 of file CalibrationAlgorithm.h.

204{return m_data.getPayloads();}

◆ getPayloadValues()

std::list< Database::DBImportQuery > getPayloadValues ( ) const
inlineinherited

Get constants (in TObjects) for database update from last execution but passed by VALUE.

Definition at line 207 of file CalibrationAlgorithm.h.

207{return m_data.getPayloadValues();}

◆ getPrefix()

const std::string & getPrefix ( ) const
inlineinherited

Get the prefix used for getting calibration data.

Definition at line 146 of file CalibrationAlgorithm.h.

146{return m_prefix;}

◆ getRunList()

const std::vector< Calibration::ExpRun > & getRunList ( ) const
inlineprotectedinherited

Get the list of runs for which calibration is called.

Definition at line 266 of file CalibrationAlgorithm.h.

266{return m_data.getRequestedRuns();}

◆ getRunListFromAllData()

vector< ExpRun > getRunListFromAllData ( ) const
inherited

Get the complete list of runs from inspection of collected data.

Definition at line 319 of file CalibrationAlgorithm.cc.

320{
321 RunRange runRange = getRunRangeFromAllData();
322 set<ExpRun> expRunSet = runRange.getExpRunSet();
323 return vector<ExpRun>(expRunSet.begin(), expRunSet.end());
324}

◆ getRunRangeFromAllData()

RunRange getRunRangeFromAllData ( ) const
inherited

Get the complete RunRange from inspection of collected data.

Definition at line 362 of file CalibrationAlgorithm.cc.

363{
364 // Save TDirectory to change back at the end
365 TDirectory* dir = gDirectory;
366 RunRange runRange;
367 // Construct the TDirectory name where we expect our objects to be
368 string runRangeObjName(getPrefix() + "/" + RUN_RANGE_OBJ_NAME);
369 for (const auto& fileName : m_inputFileNames) {
370 //Open TFile to get the objects
371 unique_ptr<TFile> f;
372 f.reset(TFile::Open(fileName.c_str(), "READ"));
373 const RunRange* runRangeOther = dynamic_cast<RunRange*>(f->Get(runRangeObjName.c_str()));
374 if (runRangeOther) {
375 runRange.merge(runRangeOther);
376 } else {
377 B2WARNING("Missing a RunRange object for file: " << fileName);
378 }
379 }
380 dir->cd();
381 return runRange;
382}
virtual void merge(const RunRange *other)
Implementation of merging - other is added to the set (union)
Definition RunRange.h:52

◆ getVecInputFileNames()

const std::vector< std::string > & getVecInputFileNames ( ) const
inlineprotectedinherited

Get the input file names used for this algorithm as a STL vector.

Definition at line 275 of file CalibrationAlgorithm.h.

275{return m_inputFileNames;}

◆ inputJsonKeyExists()

bool inputJsonKeyExists ( const std::string & key) const
inlineprotectedinherited

Test for a key in the input JSON object.

Definition at line 360 of file CalibrationAlgorithm.h.

360{return m_jsonExecutionInput.count(key);}

◆ isBoundaryRequired()

virtual bool isBoundaryRequired ( const Calibration::ExpRun & )
inlineprotectedvirtualinherited

Given the current collector data, make a decision about whether or not this run should be the start of a payload boundary.

Reimplemented in PXDAnalyticGainCalibrationAlgorithm, PXDValidationAlgorithm, SVD3SampleCoGTimeCalibrationAlgorithm, SVD3SampleELSTimeCalibrationAlgorithm, SVDClusterAbsoluteTimeShifterAlgorithm, SVDCoGTimeCalibrationAlgorithm, TestBoundarySettingAlgorithm, and TestCalibrationAlgorithm.

Definition at line 243 of file CalibrationAlgorithm.h.

244 {
245 B2ERROR("You didn't implement a isBoundaryRequired() member function in your CalibrationAlgorithm but you are calling it!");
246 return false;
247 }

◆ LambdaHistogramming()

std::unique_ptr< TList > LambdaHistogramming ( TTree * inputTree)
private

produce histograms for protons

Definition at line 310 of file SVDdEdxCalibrationAlgorithm.cc.

311{
312 gROOT->SetBatch(true);
313 inputTree->SetEstimate(-1);
314 std::vector<double> pbins = CreatePBinningScheme();
315
316 TH2F* hLambdaPMomentum = new TH2F("hist_d1_2212_truncMomentum", "hist_d1_2212_trunc;Momentum [GeV/c];dEdx [arb. units]",
317 m_numPBins, pbins.data(), m_numDEdxBins, 0,
319
320 inputTree->Draw("ProtonSVDdEdx:ProtonSVDdEdxTrackMomentum>>hist_d1_2212_truncMomentum",
321 "nSignalLambda_sw * (ProtonSVDdEdx>0) * (ProtonnSVDHits>4) * (ProtonSVDdEdxTrackMomentum>0.13)", "goff");
322
323// create isopopulated beta*gamma binning
324 inputTree->Draw(Form("ProtonSVDdEdxTrackMomentum/%f", m_ProtonPDGMass), "", "goff",
325 ((inputTree->GetEntries()) / m_numBGBins)*m_numBGBins);
326 double* ProtonMomentumDataset = inputTree->GetV1();
327
328 TKDTreeBinning* kdBinsP = new TKDTreeBinning(((inputTree->GetEntries()) / m_numBGBins)*m_numBGBins, 1, ProtonMomentumDataset,
330 const double* binsMinEdgesP_pointer = kdBinsP->SortOneDimBinEdges();
331 double* binsMinEdgesP = const_cast<double*>(binsMinEdgesP_pointer);
332
333
334 binsMinEdgesP[0] = 0.1;
335 binsMinEdgesP[m_numBGBins + 1] = 50.;
336
337
338 TH2F* hLambdaPBetaGamma = new TH2F("hist_d1_2212_truncBetaGamma", "hist_d1_2212_truncBetaGamma;#beta*#gamma;dEdx [arb. units]",
339 m_numBGBins, binsMinEdgesP, m_numDEdxBins,
340 0,
342
343 inputTree->Draw(Form("ProtonSVDdEdx:ProtonSVDdEdxTrackMomentum/%f>>hist_d1_2212_truncBetaGamma", m_ProtonPDGMass),
344 "nSignalLambda_sw * (ProtonSVDdEdx>0) * (ProtonnSVDHits>4) * (ProtonSVDdEdxTrackMomentum>0.13) * (ProtonSVDdEdx>1.2e6 - 1.e6*ProtonSVDdEdxTrackMomentum)",
345 "goff");
346
347 // produce the 1D profile
348 // momentum: for data-MC comparisons
349
350 TH1D* ProtonProfileMomentum = static_cast<TH1D*>(hLambdaPMomentum->ProfileX("ProtonProfileMomentum"));
351 ProtonProfileMomentum->SetTitle("ProtonProfile");
352 ProtonProfileMomentum->GetYaxis()->SetRangeUser(0, m_dedxCutoff);
353 ProtonProfileMomentum->GetXaxis()->SetTitle("Momentum, GeV/c");
354 ProtonProfileMomentum->GetYaxis()->SetTitle("dE/dx");
355 ProtonProfileMomentum->SetLineColor(kRed);
356
357 //beta*gamma: for the fit
358 TH1D* ProtonProfileBetaGamma = static_cast<TH1D*>(hLambdaPBetaGamma->ProfileX("ProtonProfileBetaGamma"));
359 if (m_CustomProfile) {
360 ProtonProfileBetaGamma = PrepareProfile(hLambdaPBetaGamma, "ProtonProfileBetaGamma");
361 }
362 ProtonProfileBetaGamma->SetTitle("ProtonProfile");
363 ProtonProfileBetaGamma->GetYaxis()->SetRangeUser(0, m_dedxCutoff);
364 ProtonProfileBetaGamma->GetXaxis()->SetTitle("#beta*#gamma");
365 ProtonProfileBetaGamma->GetYaxis()->SetTitle("dE/dx");
366 ProtonProfileBetaGamma->SetLineColor(kRed);
367
368
369 // for each momentum bin, normalize the pdf
370 hLambdaPMomentum = Normalise2DHisto(hLambdaPMomentum);
371
372 std::unique_ptr<TList> histList(new TList);
373 histList->Add(ProtonProfileMomentum);
374 histList->Add(ProtonProfileBetaGamma);
375 histList->Add(hLambdaPMomentum);
376
377 if (m_isMakePlots) {
378 TFile LambdaHistogrammingPlotFile("SVDdEdxCalibrationLambdaHistogramming.root", "RECREATE");
379 histList->Write();
380 LambdaHistogrammingPlotFile.Close();
381 }
382
383 return histList;
384}

◆ LambdaMassFit()

TTree * LambdaMassFit ( std::shared_ptr< TTree > preselTree)
private

Mass fit for Lambda->ppi.

Definition at line 164 of file SVDdEdxCalibrationAlgorithm.cc.

165{
166 B2INFO("Configuring the Lambda fit...");
167 gROOT->SetBatch(true);
168 RooMsgService::instance().setGlobalKillBelow(RooFit::WARNING);
169
170 RooRealVar InvM("InvM", "m(p^{+}#pi^{-})", 1.1, 1.13, "GeV/c^{2}");
171
172 RooRealVar ProtonMomentum("ProtonMomentum", "momentum for p", -1.e8, 1.e8);
173 RooRealVar ProtonSVDdEdxTrackMomentum("ProtonSVDdEdxTrackMomentum", "momentum for p", -1.e8, 1.e8);
174 RooRealVar ProtonSVDdEdx("ProtonSVDdEdx", "", -1.e8, 1.e8);
175 RooRealVar ProtonSVDdEdxTrackCosTheta("ProtonSVDdEdxTrackCosTheta", "", -10., 10.);
176 RooRealVar ProtonnSVDHits("ProtonnSVDHits", "", -1.e8, 1.e8);
177
178 RooRealVar exp("exp", "experiment number", 0, 1.e5);
179 RooRealVar run("run", "run number", 0, 1.e7);
180
181 auto variables = new RooArgSet();
182
183 variables->add(InvM);
184
185 variables->add(ProtonMomentum);
186 variables->add(ProtonSVDdEdxTrackMomentum);
187 variables->add(ProtonSVDdEdx);
188 variables->add(ProtonSVDdEdxTrackCosTheta);
189 variables->add(ProtonnSVDHits);
190 variables->add(exp);
191 variables->add(run);
192
193 RooDataSet* LambdaDataset = new RooDataSet("LambdaDataset", "LambdaDataset", *variables, Import(*preselTree));
194
195 if (LambdaDataset->sumEntries() == 0) {
196 B2FATAL("The Lambda dataset is empty, stopping here");
197 }
198
199 // the signal PDF; might be revisited at a later point
200
201 RooRealVar GaussMean("GaussMean", " GaussMean", 1.116, 1.111, 1.12);
202 RooRealVar GaussSigma("GaussSigma", "#sigma_{1}", 3.e-3, 3.e-5, 10.e-3);
203 RooGaussian LambdaGauss("LambdaGauss", "LambdaGauss", InvM, GaussMean, GaussSigma);
204
205 /* temporary RooRealVar sigmaBifurGaussL1 and sigmaBifurGaussR1 to replace
206 * RooRealVar resolutionParamL("resolutionParamL", "resolutionParamL", 0.4, 5.e-4, 1.0);
207 * RooRealVar resolutionParamR("resolutionParamR", "resolutionParamR", 0.4, 5.e-4, 1.0);
208 * RooFormulaVar sigmaBifurGaussL1("sigmaBifurGaussL1", "resolutionParamL*GaussSigma", RooArgSet(resolutionParamL, GaussSigma));
209 * RooFormulaVar sigmaBifurGaussR1("sigmaBifurGaussR1", "resolutionParamR*GaussSigma", RooArgSet(resolutionParamR, GaussSigma));
210 */
211 RooRealVar sigmaBifurGaussL1("sigmaBifurGaussL1", "sigma left", 0.4 * 3.e-3, 3.e-5, 10.e-3);
212 RooRealVar sigmaBifurGaussR1("sigmaBifurGaussR1", "sigma right", 0.4 * 3.e-3, 3.e-5, 10.e-3);
213 RooBifurGauss LambdaBifurGauss("LambdaBifurGauss", "LambdaBifurGauss", InvM, GaussMean, sigmaBifurGaussL1, sigmaBifurGaussR1);
214
215 /* temporary RooRealVar sigmaBifurGaussL2 to replace
216 * RooRealVar resolutionParam2("resolutionParam2", "resolutionParam2", 0.2, 5.e-4, 1.0);
217 * sigmaBifurGaussL2("sigmaBifurGaussL2", "resolutionParam2*GaussSigma", RooArgSet(resolutionParam2, GaussSigma));
218 */
219 RooRealVar sigmaBifurGaussL2("sigmaBifurGaussL2", "sigmaBifurGaussL2", 0.2 * 3.e-3, 3.e-5, 10.e-3);
220 RooGaussian LambdaBifurGauss2("LambdaBifurGauss2", "LambdaBifurGauss2", InvM, GaussMean, sigmaBifurGaussL2);
221
222 RooRealVar fracBifurGaussYield("fracBifurGaussYield", "fracBifurGaussYield", 0.3, 5.e-4, 1.0);
223 RooRealVar fracGaussYield("fracGaussYield", "fracGaussYield", 0.8, 5.e-4, 1.0);
224
225 RooAddPdf LambdaCombinedBifurGauss("LambdaCombinedBifurGauss", "LambdaBifurGauss + LambdaBifurGauss2 ", RooArgList(LambdaBifurGauss,
226 LambdaBifurGauss2), RooArgList(fracBifurGaussYield));
227
228 RooAddPdf LambdaSignalPDF("LambdaSignalPDF", "LambdaCombinedBifurGauss + LambdaGauss", RooArgList(LambdaCombinedBifurGauss,
229 LambdaGauss), RooArgList(fracGaussYield));
230
231 // Background PDF
232 RooRealVar BkgPolyCoef0("BkgPolyCoef0", "BkgPolyCoef0", 0.1, 0., 1.5);
233 RooRealVar BkgPolyCoef1("BkgPolyCoef1", "BkgPolyCoef1", -0.5, -1.5, -1.e-3);
234 RooChebychev BkgPolyPDF("BkgPolyPDF", "BkgPolyPDF", InvM, RooArgList(BkgPolyCoef0, BkgPolyCoef1));
235
236 RooRealVar nSignalLambda("nSignalLambda", "nSignalLambda", 0.6 * preselTree->GetEntries(), 0., 0.99 * preselTree->GetEntries());
237 RooRealVar nBkgLambda("nBkgLambda", "nBkgLambda", 0.4 * preselTree->GetEntries(), 0., 0.99 * preselTree->GetEntries());
238 RooAddPdf totalPDFLambda("totalPDFLambda", "totalPDFLambda pdf", RooArgList(LambdaSignalPDF, BkgPolyPDF),
239 RooArgList(nSignalLambda, nBkgLambda));
240
241 B2INFO("Lambda: Start fitting...");
242 RooFitResult* LambdaFitResult = totalPDFLambda.fitTo(*LambdaDataset, Save(kTRUE), PrintLevel(-1));
243
244 int status = LambdaFitResult->status();
245 int covqual = LambdaFitResult->covQual();
246 double diff = nSignalLambda.getValV() + nBkgLambda.getValV() - LambdaDataset->sumEntries();
247
248 B2INFO("Lambda: Fit status: " << status << "; covariance quality: " << covqual);
249 // if the fit is not healthy, try again once before giving up, with a slightly different setup:
250 if ((status > 0) || (TMath::Abs(diff) > 1.) || (nSignalLambda.getError() < sqrt(nSignalLambda.getValV()))
251 || (nSignalLambda.getError() > (nSignalLambda.getValV()))) {
252
253 LambdaFitResult = totalPDFLambda.fitTo(*LambdaDataset, Save(), Strategy(2), Offset(1));
254 status = LambdaFitResult->status();
255 covqual = LambdaFitResult->covQual();
256 diff = nSignalLambda.getValV() + nBkgLambda.getValV() - LambdaDataset->sumEntries();
257 B2INFO("Lambda: updated fit status: " << status << "; covariance quality: " << covqual);
258 }
259
260 if ((status > 0) || (TMath::Abs(diff) > 1.) || (nSignalLambda.getError() < sqrt(nSignalLambda.getValV()))
261 || (nSignalLambda.getError() > (nSignalLambda.getValV()))) {
262 B2WARNING("Lambda: Fit problem: fit status " << status << "; sum of component yields minus the dataset yield is " << diff <<
263 "; signal yield is " << nSignalLambda.getValV() << ", while its uncertainty is " << nSignalLambda.getError());
264 }
265 if (covqual < 2) {
266 B2INFO("Lambda: Fit warning: covariance quality " << covqual);
267 }
268
269 if (m_isMakePlots) {
270 std::unique_ptr<TCanvas> canvLambda(new TCanvas("canvLambda", "canvLambda"));
271 canvLambda->cd();
272 RooPlot* LambdaFitFrame = LambdaDataset->plotOn(InvM.frame(130));
273 totalPDFLambda.plotOn(LambdaFitFrame, LineColor(TColor::GetColor("#4575b4")));
274
275 double chisquare = LambdaFitFrame->chiSquare();
276 B2INFO("Lambda: Fit chi2 = " << chisquare);
277 totalPDFLambda.paramOn(LambdaFitFrame, Layout(0.6, 0.96, 0.93), Format("NEU", AutoPrecision(2)));
278 LambdaFitFrame->getAttText()->SetTextSize(0.03);
279
280 totalPDFLambda.plotOn(LambdaFitFrame, Components("LambdaSignalPDF"), LineColor(TColor::GetColor("#d73027")));
281 totalPDFLambda.plotOn(LambdaFitFrame, Components("BkgPolyPDF"), LineColor(TColor::GetColor("#fc8d59")));
282 totalPDFLambda.plotOn(LambdaFitFrame, LineColor(TColor::GetColor("#4575b4")));
283
284 LambdaFitFrame->GetXaxis()->SetTitle("m(p#pi^{-}) (GeV/c^{2})");
285
286 LambdaFitFrame->Draw();
287
288
289 canvLambda->Print("SVDdEdxCalibrationFitLambda.pdf");
290 TFile LambdaFitPlotFile("SVDdEdxCalibrationLambdaFitPlotFile.root", "RECREATE");
291 canvLambda->Write();
292 LambdaFitPlotFile.Close();
293 }
294 RooStats::SPlot* sPlotDatasetLambda = new RooStats::SPlot("sData", "An SPlot", *LambdaDataset, &totalPDFLambda,
295 RooArgList(nSignalLambda, nBkgLambda));
296
297 for (int iEvt = 0; iEvt < 5; iEvt++) {
298 if (TMath::Abs(sPlotDatasetLambda->GetSWeight(iEvt, "nSignalLambda") + sPlotDatasetLambda->GetSWeight(iEvt,
299 "nBkgLambda") - 1) > 5.e-3)
300 B2FATAL("Lambda: sPlot error: sum of weights not equal to 1");
301 }
302
303 TTree* treeLambdaSWeighted = LambdaDataset->GetClonedTree();
304 treeLambdaSWeighted->SetName("treeLambdaSWeighted");
305
306 B2INFO("Lambda: sPlot done. Proceed to histogramming");
307 return treeLambdaSWeighted;
308}

◆ loadInputJson()

bool loadInputJson ( const std::string & jsonString)
inherited

Load the m_inputJson variable from a string (useful from Python interface). The return bool indicates success or failure.

Definition at line 503 of file CalibrationAlgorithm.cc.

504{
505 try {
506 auto jsonInput = nlohmann::json::parse(jsonString);
507 // Input string has an object (dict) as the top level object?
508 if (jsonInput.is_object()) {
509 m_jsonExecutionInput = jsonInput;
510 return true;
511 } else {
512 B2ERROR("JSON input string isn't an object type i.e. not a '{}' at the top level.");
513 return false;
514 }
515 } catch (nlohmann::json::parse_error&) {
516 B2ERROR("Parsing of JSON input string failed");
517 return false;
518 }
519}
nlohmann::json m_jsonExecutionInput
Optional input JSON object used to make decisions about how to execute the algorithm code.

◆ Normalise2DHisto()

TH2F * Normalise2DHisto ( TH2F * HistoToNormalise)
inlineprivate

Normalise a given dEdx:momentum histogram in each momentum bin, so that sum of entries in each momentum bin is 1.

Note that this accounts for entries in the underflow/overflow bins.

Definition at line 158 of file SVDdEdxCalibrationAlgorithm.h.

159 {
160 for (int pbin = 0; pbin <= m_numPBins + 1; pbin++) {
161 for (int dedxbin = 0; dedxbin <= m_numDEdxBins + 1; dedxbin++) {
162 // get rid of the bins with negative weights
163 if (HistoToNormalise->GetBinContent(pbin, dedxbin) <= 1) {
164 HistoToNormalise->SetBinContent(pbin, dedxbin, 0);
165 };
166 }
167 // create a projection (1D histogram) in a given momentum bin
168
169 TH1D* MomentumSlice = static_cast<TH1D*>(HistoToNormalise->ProjectionY("slice_tr", pbin, pbin));
170 // normalise, but ignore the cases with empty histograms
171 if (MomentumSlice->Integral(0, m_numDEdxBins + 1) > 0) {
172 MomentumSlice->Scale(1. / MomentumSlice->Integral(0, m_numDEdxBins + 1));
173 }
174 // fill back the 2D histogram with the result
175 for (int dedxbin = 0; dedxbin <= m_numDEdxBins + 1; dedxbin++) {
176 HistoToNormalise->SetBinContent(pbin, dedxbin, MomentumSlice->GetBinContent(dedxbin));
177 HistoToNormalise->SetBinError(pbin, dedxbin, MomentumSlice->GetBinError(dedxbin));
178 }
179 }
180 return HistoToNormalise;
181 }

◆ PrepareNewHistogram()

TH2F * PrepareNewHistogram ( TH2F * DataHistogram,
TString NewName,
TF1 * betagamma_function,
TF1 * ResolutionFunctionOriginal,
double bias_correction )
inlineprivate

Generate a new dEdx:momentum histogram from a function that encodes dEdx:momentum trend and a function that encodes dEdx resolution.

Definition at line 186 of file SVDdEdxCalibrationAlgorithm.h.

188 {
189 TF1* ResolutionFunction = static_cast<TF1*>(ResolutionFunctionOriginal->Clone(Form("%sClone",
190 ResolutionFunctionOriginal->GetName()))); // to avoid modifying the resolution function
191 ResolutionFunction->SetRange(0, m_dedxMaxPossible); // allow the function to take values outside the histogram range
192 TH2F* DataHistogramNew = static_cast<TH2F*>(DataHistogram->Clone(NewName));
193
194 DataHistogramNew->Reset();
195
196 for (int pbin = 1; pbin <= m_numPBins + 1; pbin++) {
197 double mean_dEdx_value = betagamma_function->Eval(DataHistogramNew->GetXaxis()->GetBinCenter(pbin));
198 ResolutionFunction->FixParameter(1, mean_dEdx_value + bias_correction);
199
200 // create a projection (1D histogram) in a given momentum bin
201 TH1D* MomentumSlice = static_cast<TH1D*>(DataHistogramNew->ProjectionY("slice", pbin, pbin));
202
203 // fill manually (instead of FillRandom) to also preserve events in the overflow bin
204 // this is needed for the correct normalisation
205 for (int iEvent = 0; iEvent < m_NToGenerate; iEvent++) {
206 MomentumSlice->Fill(ResolutionFunction->GetRandom());
207 }
208
209 // get rid of the empty bins: set their bin content to 0.5 (i.e. smaller than 1 event)
210 // this is to allow for a well-defined log-likelihood calculation
211 for (int dedxbin = 0; dedxbin <= m_numDEdxBins + 1; dedxbin++) {
212 if (MomentumSlice->GetBinContent(dedxbin) < 1) {
213 MomentumSlice->SetBinContent(dedxbin, 0.5);
214 };
215 }
216
217 // normalise each momentum slice to unity, but ignore the cases with empty histograms
218 if (MomentumSlice->Integral(0, m_numDEdxBins + 1) > 0) {
219 MomentumSlice->Scale(1. / MomentumSlice->Integral(0, m_numDEdxBins + 1));
220 }
221 // fill back the 2D histo with the result
222 for (int dedxbin = 0; dedxbin <= m_numDEdxBins + 1; dedxbin++) {
223 DataHistogramNew->SetBinContent(pbin, dedxbin, MomentumSlice->GetBinContent(dedxbin));
224 DataHistogramNew->SetBinError(pbin, dedxbin, MomentumSlice->GetBinError(dedxbin));
225 }
226 }
227
228 return DataHistogramNew;
229
230 }

◆ PrepareProfile()

TH1D * PrepareProfile ( TH2F * DataHistogram,
TString NewName )
inlineprivate

Reimplement the Profile histogram calculation for a 2D histogram.

The standard ROOT implementation takes the mean Y at a given X, which produces biased results in case of rapidly-rising distributions with non-Gaussian resolutions. We fit in slices to extract the mean more precisely.

Definition at line 235 of file SVDdEdxCalibrationAlgorithm.h.

236 {
237// define our resolution function: Crystal Ball. Parameter [1] is the mean and [2] is the relative width.
238 TF1* ResolutionFunction = new TF1("ResolutionFunction", "[0]*ROOT::Math::crystalball_function(x,[4],[3],[2]*[1],[1])", 100e3,
239 7000e3);
240
241
242 ResolutionFunction->SetNpx(1000);
243
244 ResolutionFunction->SetParameters(1000, 6.e5, 0.1, 1, 1);
245 ResolutionFunction->SetParLimits(0, 0, 1.e6);
246 ResolutionFunction->SetParLimits(1, 3.e5, 7.e6);
247 ResolutionFunction->SetParLimits(2, 0, 10);
248 ResolutionFunction->SetParLimits(3, 0.01, 100);
249 ResolutionFunction->SetParLimits(4, 0.01, 100);
250
251 ResolutionFunction->SetRange(0, m_dedxMaxPossible); // allow the function to take values outside the histogram range
252
253 TH1D* DataHistogramNew = static_cast<TH1D*>(DataHistogram->ProfileX()->ProjectionX());
254 TH1D* DataHistogramClone = static_cast<TH1D*>(DataHistogramNew->Clone(Form("%sClone",
255 DataHistogramNew->GetName()))); // preserve the original profile for uncertainty cross-checks
256 DataHistogramNew->SetName(NewName);
257 DataHistogramNew->SetTitle(NewName);
258 DataHistogramNew->Reset();
259
260 for (int pbin = 1; pbin <= m_numBGBins; pbin++) {
261 // create a projection (1D histogram) in a given momentum bin
262 TH1D* MomentumSlice = static_cast<TH1D*>(DataHistogram->ProjectionY("slice", pbin, pbin));
263
264 if (MomentumSlice->Integral() < 1) continue;
265// guesstimate the starting fit values
266 ResolutionFunction->SetParameter(1, MomentumSlice->GetMean());
267 ResolutionFunction->SetParameter(2, MomentumSlice->GetStdDev() / MomentumSlice->GetMean());
268 ResolutionFunction->SetRange(MomentumSlice->GetMean() * 0.2, MomentumSlice->GetMean() * 1.75);
269// fit each slice to extract the mean
270 MomentumSlice->Fit(ResolutionFunction, "RQI");
271
272 double stat_error = DataHistogramClone->GetBinError(pbin);
273// fill back the 1D histo with the result
274 double bincontent = ResolutionFunction->GetParameter(1);
275 double binerror = ResolutionFunction->GetParError(1);
276
277 binerror = std::max(binerror, stat_error);
278
279 DataHistogramNew->SetBinContent(pbin, bincontent);
280 DataHistogramNew->SetBinError(pbin, binerror);
281 }
282
283 return DataHistogramNew;
284
285 }

◆ resetInputJson()

void resetInputJson ( )
inlineprotectedinherited

Clears the m_inputJson member variable.

Definition at line 330 of file CalibrationAlgorithm.h.

330{m_jsonExecutionInput.clear();}

◆ resetOutputJson()

void resetOutputJson ( )
inlineprotectedinherited

Clears the m_outputJson member variable.

Definition at line 333 of file CalibrationAlgorithm.h.

333{m_jsonExecutionOutput.clear();}

◆ saveCalibration() [1/6]

void saveCalibration ( TClonesArray * data,
const std::string & name )
protectedinherited

Store DBArray payload with given name with default IOV.

Definition at line 297 of file CalibrationAlgorithm.cc.

298{
299 saveCalibration(data, name, m_data.getRequestedIov());
300}

◆ saveCalibration() [2/6]

void saveCalibration ( TClonesArray * data,
const std::string & name,
const IntervalOfValidity & iov )
protectedinherited

Store DBArray with given name and custom IOV.

Definition at line 276 of file CalibrationAlgorithm.cc.

277{
278 B2DEBUG(29, "Saving calibration TClonesArray '" << name << "' to payloads list.");
279 getPayloads().emplace_back(name, data, iov);
280}

◆ saveCalibration() [3/6]

void saveCalibration ( TObject * data)
protectedinherited

Store DB payload with default name and default IOV.

Definition at line 287 of file CalibrationAlgorithm.cc.

288{
289 saveCalibration(data, DataStore::objectName(data->IsA(), ""));
290}
static std::string objectName(const TClass *t, const std::string &name)
Return the storage name for an object of the given TClass and name.
Definition DataStore.cc:150

◆ saveCalibration() [4/6]

void saveCalibration ( TObject * data,
const IntervalOfValidity & iov )
protectedinherited

Store DB payload with default name and custom IOV.

Definition at line 282 of file CalibrationAlgorithm.cc.

283{
284 saveCalibration(data, DataStore::objectName(data->IsA(), ""), iov);
285}

◆ saveCalibration() [5/6]

void saveCalibration ( TObject * data,
const std::string & name )
protectedinherited

Store DB payload with given name with default IOV.

Definition at line 292 of file CalibrationAlgorithm.cc.

293{
294 saveCalibration(data, name, m_data.getRequestedIov());
295}

◆ saveCalibration() [6/6]

void saveCalibration ( TObject * data,
const std::string & name,
const IntervalOfValidity & iov )
protectedinherited

Store DB payload with given name and custom IOV.

Definition at line 270 of file CalibrationAlgorithm.cc.

271{
272 B2DEBUG(29, "Saving calibration TObject = '" << name << "' to payloads list.");
273 getPayloads().emplace_back(name, data, iov);
274}

◆ setCustomProfile()

void setCustomProfile ( bool value = true)
inline

reimplement the profile histogram calculation

Definition at line 75 of file SVDdEdxCalibrationAlgorithm.h.

75{ m_CustomProfile = value; }

◆ setDEdxCutoff()

void setDEdxCutoff ( const double & value)
inline

set the upper edge of the dEdx binning for the payloads

Definition at line 65 of file SVDdEdxCalibrationAlgorithm.h.

65{ m_dedxCutoff = value; }

◆ setDescription()

void setDescription ( const std::string & description)
inlineprotectedinherited

Set algorithm description (in constructor)

Definition at line 321 of file CalibrationAlgorithm.h.

321{m_description = description;}

◆ setFixUnstableFitParameter()

void setFixUnstableFitParameter ( bool value = true)
inline

In the dEdx:betagamma fit, there is one free parameter that makes fit convergence poor.

It is ok to fix it, unless the dEdx behavior changes radically with time.

Definition at line 80 of file SVDdEdxCalibrationAlgorithm.h.

80{ m_FixUnstableFitParameter = value; }

◆ setInputFileNames() [1/2]

void setInputFileNames ( const std::vector< std::string > & inputFileNames)
protectedinherited

Set the input file names used for this algorithm.

Set the input file names used for this algorithm and resolve the wildcards.

Definition at line 194 of file CalibrationAlgorithm.cc.

195{
196 // A lot of code below is tweaked from RootInputModule::initialize,
197 // since we're basically copying the functionality anyway.
198 if (inputFileNames.empty()) {
199 B2WARNING("You have called setInputFileNames() with an empty list. Did you mean to do that?");
200 return;
201 }
202 auto tmpInputFileNames = RootIOUtilities::expandWordExpansions(inputFileNames);
203
204 // We'll use a set to enforce sorted unique file paths as we check them
205 set<string> setInputFileNames;
206 // Check that files exist and convert to absolute paths
207 for (auto path : tmpInputFileNames) {
208 string fullPath = fs::absolute(path).string();
209 if (fs::exists(fullPath)) {
210 setInputFileNames.insert(fs::canonical(fullPath).string());
211 } else {
212 B2WARNING("Couldn't find the file " << path);
213 }
214 }
215
216 if (setInputFileNames.empty()) {
217 B2WARNING("No valid files specified!");
218 return;
219 } else {
220 // Reset the run -> files map as our files are likely different
221 m_runsToInputFiles.clear();
222 }
223
224 // Open TFile to check they can be accessed by ROOT
225 TDirectory* dir = gDirectory;
226 for (const string& fileName : setInputFileNames) {
227 unique_ptr<TFile> f;
228 try {
229 f.reset(TFile::Open(fileName.c_str(), "READ"));
230 } catch (logic_error&) {
231 //this might happen for ~invaliduser/foo.root
232 //actually undefined behaviour per standard, reported as ROOT-8490 in JIRA
233 }
234 if (!f || !f->IsOpen()) {
235 B2FATAL("Couldn't open input file " + fileName);
236 }
237 }
238 dir->cd();
239
240 // Copy the entries of the set to a vector
241 m_inputFileNames = vector<string>(setInputFileNames.begin(), setInputFileNames.end());
243}
std::string m_granularityOfData
Granularity of input data. This only changes when the input files change so it isn't specific to an e...
void setInputFileNames(PyObject *inputFileNames)
Set the input file names used for this algorithm from a Python list.
std::string getGranularityFromData() const
Get the granularity of collected data.
std::vector< std::string > expandWordExpansions(const std::vector< std::string > &filenames)
Performs wildcard expansion using wordexp(), returns matches.

◆ setInputFileNames() [2/2]

void setInputFileNames ( PyObject * inputFileNames)
inherited

Set the input file names used for this algorithm from a Python list.

Set the input file names used for this algorithm and resolve the wildcards.

Definition at line 166 of file CalibrationAlgorithm.cc.

167{
168 // The reasoning for this very 'manual' approach to extending the Python interface
169 // (instead of using boost::python) is down to my fear of putting off final users with
170 // complexity on their side.
171 //
172 // I didn't want users that inherit from this class to be forced to use boost and
173 // to have to define a new python module just to use the CAF. A derived class from
174 // from a boost exposed class would need to have its own boost python module definition
175 // to allow access from a steering file and to the base class functions (I think).
176 // I also couldn't be bothered to write a full framework to get around the issue in a similar
177 // way to Module()...maybe there's an easy way.
178 //
179 // But this way we can allow people to continue using their ROOT implemented classes and inherit
180 // easily from this one. But add in a few helper functions that work with Python objects
181 // created in their steering file i.e. instead of being forced to use STL objects as input
182 // to the algorithm.
183 if (PyList_Check(inputFileNames)) {
184 boost::python::handle<> handle(boost::python::borrowed(inputFileNames));
185 boost::python::list listInputFileNames(handle);
186 auto vecInputFileNames = PyObjConvUtils::convertPythonObject(listInputFileNames, vector<string>());
187 setInputFileNames(vecInputFileNames);
188 } else {
189 B2ERROR("Tried to set the input files but we didn't receive a Python list.");
190 }
191}
Scalar convertPythonObject(const boost::python::object &pyObject, Scalar)
Convert from Python to given type.

◆ setMinEvtsPerTree()

void setMinEvtsPerTree ( const double & value)
inline

set the upper edge of the dEdx binning for the payloads

Definition at line 70 of file SVDdEdxCalibrationAlgorithm.h.

70{ m_MinEvtsPerTree = value; }

◆ setMonitoringPlots()

void setMonitoringPlots ( bool value = false)
inline

function to enable plotting

Definition at line 45 of file SVDdEdxCalibrationAlgorithm.h.

45{ m_isMakePlots = value; }

◆ setNumBGBins()

void setNumBGBins ( const int & value)
inline

set the number of beta*gamma bins for the fits

Definition at line 60 of file SVDdEdxCalibrationAlgorithm.h.

60{ m_numBGBins = value; }

◆ setNumDEdxBins()

void setNumDEdxBins ( const int & value)
inline

set the number of dEdx bins for the payloads

Definition at line 50 of file SVDdEdxCalibrationAlgorithm.h.

50{ m_numDEdxBins = value; }

◆ setNumPBins()

void setNumPBins ( const int & value)
inline

set the number of momentum bins for the payloads

Definition at line 55 of file SVDdEdxCalibrationAlgorithm.h.

55{ m_numPBins = value; }

◆ setOutputJsonValue()

template<class T>
void setOutputJsonValue ( const std::string & key,
const T & value )
inlineprotectedinherited

Set a key:value pair for the outputJson object, expected to used internally during calibrate()

Definition at line 337 of file CalibrationAlgorithm.h.

337{m_jsonExecutionOutput[key] = value;}

◆ setPrefix()

void setPrefix ( const std::string & prefix)
inlineinherited

Set the prefix used to identify datastore objects.

Definition at line 167 of file CalibrationAlgorithm.h.

167{m_prefix = prefix;}

◆ setUsePionBGFunctionForEverything()

void setUsePionBGFunctionForEverything ( bool value = false)
inline

use the pion beta*gamma function for other hadrons

Definition at line 85 of file SVDdEdxCalibrationAlgorithm.h.

85{ m_UsePionBGFunctionForEverything = value; }

◆ setUseProtonBGFunctionForEverything()

void setUseProtonBGFunctionForEverything ( bool value = false)
inline

use the proton beta*gamma function for other hadrons

Definition at line 90 of file SVDdEdxCalibrationAlgorithm.h.

90{ m_UseProtonBGFunctionForEverything = value; }

◆ updateDBObjPtrs()

void updateDBObjPtrs ( const unsigned int event,
const int run,
const int experiment )
staticprotectedinherited

Updates any DBObjPtrs by calling update(event) for DBStore.

Definition at line 405 of file CalibrationAlgorithm.cc.

406{
407 // Construct an EventMetaData object but NOT in the Datastore
408 EventMetaData emd(event, run, experiment);
409 // Explicitly update while avoiding registering a Datastore object
411 // Also update the intra-run objects to the event at the same time (maybe unnecessary...)
413}
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

Member Data Documentation

◆ m_allExpRun

const ExpRun m_allExpRun = make_pair(-1, -1)
staticprivateinherited

allExpRun

Definition at line 364 of file CalibrationAlgorithm.h.

◆ m_boundaries

std::vector<Calibration::ExpRun> m_boundaries
protectedinherited

When using the boundaries functionality from isBoundaryRequired, this is used to store the boundaries. It is cleared when.

Definition at line 261 of file CalibrationAlgorithm.h.

◆ m_CustomProfile

bool m_CustomProfile = 1
private

reimplement profile histogram calculation instead of the ROOT implementation?

Definition at line 117 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_data

ExecutionData m_data
privateinherited

Data specific to a SINGLE execution of the algorithm. Gets reset at the beginning of execution.

Definition at line 382 of file CalibrationAlgorithm.h.

◆ m_dedxCutoff

double m_dedxCutoff = 5.e6
private

the upper edge of the dEdx binning for the payloads

Definition at line 111 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_dedxMaxPossible

double m_dedxMaxPossible = 7.e6
private

the approximate max possible value of dEdx

Definition at line 112 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_description

std::string m_description {""}
privateinherited

Description of the algorithm.

Definition at line 385 of file CalibrationAlgorithm.h.

385{""};

◆ m_DeuteronPDGMass

const double m_DeuteronPDGMass = TDatabasePDG::Instance()->GetParticle(1000010020)->Mass()
private

PDG mass for the deuteron.

Definition at line 130 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_ElectronPDGMass

const double m_ElectronPDGMass = TDatabasePDG::Instance()->GetParticle(11)->Mass()
private

PDG mass for the electron.

Definition at line 125 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_FixUnstableFitParameter

bool m_FixUnstableFitParameter
private
Initial value:
=
1

In the dEdx:betagamma fit, there is one free parameter that makes fit convergence poor.

It is ok to fix it, unless the dEdx behavior changes radically with time.

Definition at line 122 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_granularityOfData

std::string m_granularityOfData
privateinherited

Granularity of input data. This only changes when the input files change so it isn't specific to an execution.

Definition at line 379 of file CalibrationAlgorithm.h.

◆ m_inputFileNames

std::vector<std::string> m_inputFileNames
privateinherited

List of input files to the Algorithm, will initially be user defined but then gets the wildcards expanded during execute()

Definition at line 373 of file CalibrationAlgorithm.h.

◆ m_isMakePlots

bool m_isMakePlots
private

produce plots for monitoring

Definition at line 99 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_jsonExecutionInput

nlohmann::json m_jsonExecutionInput = nlohmann::json::object()
privateinherited

Optional input JSON object used to make decisions about how to execute the algorithm code.

Definition at line 397 of file CalibrationAlgorithm.h.

◆ m_jsonExecutionOutput

nlohmann::json m_jsonExecutionOutput = nlohmann::json::object()
privateinherited

Optional output JSON object that can be set during the execution by the underlying algorithm code.

Definition at line 403 of file CalibrationAlgorithm.h.

◆ m_KaonPDGMass

const double m_KaonPDGMass = TDatabasePDG::Instance()->GetParticle(321)->Mass()
private

PDG mass for the charged kaon.

Definition at line 128 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_MinEvtsPerTree

int m_MinEvtsPerTree
private
Initial value:
=
100

number of events in TTree below which we don't try to fit

Definition at line 113 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_MuonPDGMass

const double m_MuonPDGMass = TDatabasePDG::Instance()->GetParticle(13)->Mass()
private

PDG mass for the muon.

Definition at line 126 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_NToGenerate

int m_NToGenerate
private
Initial value:
=
5e6

the number of events to be generated in each momentum bin in the new payloads.

Please do not change this number unless it's really needed. It is crucial that this is consistent between data and MC payloads, as it affects the minimal possible PID probability value after normalisation.

Definition at line 115 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_numBGBins

int m_numBGBins = 69
private

the number of beta*gamma bins for the profile and fitting

Definition at line 110 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_numDEdxBins

int m_numDEdxBins = 100
private

the number of dEdx bins for the payloads

Definition at line 108 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_numPBins

int m_numPBins = 69
private

the number of momentum bins for the payloads

Definition at line 109 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_PionPDGMass

const double m_PionPDGMass = TDatabasePDG::Instance()->GetParticle(211)->Mass()
private

PDG mass for the charged pion.

Definition at line 127 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_prefix

std::string m_prefix {""}
privateinherited

The name of the TDirectory the collector objects are contained within.

Definition at line 388 of file CalibrationAlgorithm.h.

388{""};

◆ m_ProtonPDGMass

const double m_ProtonPDGMass = TDatabasePDG::Instance()->GetParticle(2212)->Mass()
private

PDG mass for the proton.

Definition at line 129 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_runsToInputFiles

std::map<Calibration::ExpRun, std::vector<std::string> > m_runsToInputFiles
privateinherited

Map of Runs to input files. Gets filled when you call getRunRangeFromAllData, gets cleared when setting input files again.

Definition at line 376 of file CalibrationAlgorithm.h.

◆ m_UsePionBGFunctionForEverything

bool m_UsePionBGFunctionForEverything
private
Initial value:
=
0

Assume that the dEdx:betagamma trend is the same for all hadrons; use the pion trend as representative.

Definition at line 118 of file SVDdEdxCalibrationAlgorithm.h.

◆ m_UseProtonBGFunctionForEverything

bool m_UseProtonBGFunctionForEverything
private
Initial value:
=
0

Assume that the dEdx:betagamma trend is the same for all hadrons; use the proton trend as representative.

Definition at line 120 of file SVDdEdxCalibrationAlgorithm.h.


The documentation for this class was generated from the following files: