Belle II Software  release-08-01-10
eclCosmicEAlgorithm Class Reference

class eclCosmiEAlgorithm. More...

#include <eclCosmicEAlgorithm.h>

Inheritance diagram for eclCosmicEAlgorithm:
Collaboration diagram for eclCosmicEAlgorithm:

Public Types

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

Public Member Functions

 eclCosmicEAlgorithm ()
 Constructor.
 
virtual ~eclCosmicEAlgorithm ()
 Destructor.
 
std::string getPrefix () const
 Get the prefix used for getting calibration data.
 
bool checkPyExpRun (PyObject *pyObj)
 Checks that a PyObject can be successfully converted to an ExpRun type. More...
 
Calibration::ExpRun convertPyExpRun (PyObject *pyObj)
 Performs the conversion of PyObject to ExpRun. More...
 
std::string getCollectorName () const
 Alias for prefix. More...
 
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. More...
 
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.
 
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. More...
 
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::DBImportQuerygetPayloadValues ()
 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 algoithm (set by developers in constructor)
 
bool loadInputJson (const std::string &jsonString)
 Load the m_inputJson variable from a string (useful from Python interface). The rturn 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>.
 

Public Attributes

int cellIDLo
 Parameters to control Novosibirsk fit to signal measured in each crystal. More...
 
int cellIDHi
 Last cellID to be fit.
 
int minEntries
 All crystals to be fit must have at least minEntries events in the fit range.
 
int maxIterations
 no more than maxIteration iterations
 
double tRatioMin
 Fit range is adjusted so that fit at upper endpoint is between tRatioMin and tRatioMax of peak.
 
double tRatioMax
 Fit range is adjusted so that fit at upper endpoint is between tRatioMin and tRatioMax of peak.
 
bool performFits
 if false, input histograms are copied to output, but no fits are done.
 
bool findExpValues
 if true, fits are used to find expected energy deposit for each crystal instead of the calibration constant
 
int storeConst
 controls which values are written to the database. More...
 

Protected Member Functions

virtual EResult calibrate () override
 Run algorithm on events. More...
 
void setInputFileNames (std::vector< std::string > inputFileNames)
 Set the input file names used for this algorithm. More...
 
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.
 
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 updateDBObjPtrs (const unsigned int event, const int run, const int experiment)
 Updates any DBObjPtrs by calling update(event) for DBStore.
 
void setDescription (const std::string &description)
 Set algorithm description (in constructor)
 
void clearCalibrationData ()
 Clear calibration data.
 
Calibration::ExpRun getAllGranularityExpRun () const
 Returns the Exp,Run pair that means 'Everything'. Currently unused.
 
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 interally 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.
 

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

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

int fitOK = 16
 fit is OK
 
int iterations = 8
 fit reached max number of iterations, but is useable
 
int atLimit = 4
 a parameter is at the limit; fit not useable
 
int poorFit = 3
 low chi square; fit not useable
 
int noPeak = 2
 Novosibirsk component of fit is negligible; fit not useable.
 
int notFit = -1
 no fit performed
 
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 eclCosmiEAlgorithm.

Analyze histograms of normalized energy for each ECL crystal from cosmic ray events. Code can either find most-likely energy deposit for each crystal using CRY MC or calibration constant for each crystal (data)

Definition at line 24 of file eclCosmicEAlgorithm.h.

Member Enumeration Documentation

◆ EResult

enum EResult
inherited

The result of calibration.

Enumerator
c_OK 

Finished successfuly =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.

Member Function Documentation

◆ calibrate()

CalibrationAlgorithm::EResult calibrate ( )
overrideprotectedvirtual

Run algorithm on events.


..ranges of various fit parameters, and tolerance to determine that fit is at the limit

..Put root into batch mode so that we don't try to open a graphics window


..Clean up existing histograms if necessary


..Histograms containing the data collected by eclCosmicECollectorModule


..Record the number of entries per crystal in each of the two normalized energy histograms and average the constants obtained from DB


..Write out the basic histograms in all cases


..If we have not been asked to do fits, we can quit now


..Check that every crystal has enough entries. If we are finding calibration constants (normal data mode), at least 1 histogram must have sufficient statistics. If we are finding expected values (used with MC), both must have sufficient statistics.


Insufficient data. Quit if we are required to have a successful fit for every crystal


..Some prep for the many fits about to follow

..1D summary histograms

..Histograms to store results for DB


..Loop over specified crystals and performs fits to the two normalized energy distributions

..Extract the 1D normalized energy distribution from the appropriate 2D histogram

..Fit function (xmin, xmax, nparameters) for this histogram

..Estimate initial parameters. For peak, use maximum bin in the allowed range

..Fit range is histogram low edge plus a few bins to peak + 2.5*effective sigma

..Constant from lower edge of plot

..Eta is nominal

..parameters to control iterations. dIter checks if we are stuck in a loop


..Iterate from this point if needed

..Set the initial parameters

..Perform the fit and note the resulting parameters

..The upper fit range should correspond to 20-25% of the peak. Iterate if necessary.

..Check if we are oscillating between two end points

..Many iterations may mean we are stuck in a loop. Try a different end point.

..Set the constant term to 0 if we are close to the limit

..No more than specified number of iterations


..Calculate fit probability. Same as P option in fit, which cannot be used with L


..Fit status

No peak; normalization of Novo component is too small

..poor fit, or relatively poor fit with too many iterations

..parameter at limit

..Store the fit results

..Write out the fit distribution


..Find expected energies from MC, if requested

..Write out expected energies if status is adequate. Check that every crystal has at least one good fit


..Otherwise, find calibration constants

..Find calibration constant separately for the two normalized energy distributions for each crystal

..Peak and uncertainty; assume uncertainties on expected energy and elec calib are negligible

..Find the weighted average of the two constants and store in the histogram

..If both fits failed, use the negative of the initial "same" calibration constant


..Write output to DB if requested and successful

..Store expected energy for each crystal and neighbour type from CRY MC

..Store calibration constant for each crystal (nominally real data)

..Write out some diagnostic histograms

..Histograms containing values written to DB


..Clean up histograms in case Algorithm is called again


..Set the return code appropriately

Implements CalibrationAlgorithm.

Definition at line 64 of file eclCosmicEAlgorithm.cc.

65 {
66 
69  double limitTol = 0.0005; /*< tolerance for checking if a parameter is at the limit */
70  double minFitLimit = 1e-25; /*< cut off for labeling a fit as poor */
71  double minFitProbIter = 1e-8; /*< cut off for labeling a fit as poor if it also has many iterations */
72  double constRatio = 0.5; /*< Novosibirsk normalization must be greater than constRatio x constant term */
73  double peakMin(0.5), peakMax(1.75); /*< range for peak of measured energy distribution */
74  double peakTol = limitTol * (peakMax - peakMin); /*< fit is at limit if it is within peakTol of min or max */
75  double effSigMin(0.08), effSigMax(0.5); /*< range for effective sigma of measured energy distribution */
76  double effSigTol = limitTol * (effSigMax - effSigMin);
77  double etaMin(-3.), etaMax(1.); /*< Novosibirsk tail parameter range */
78  double etaNom(-0.41); /*< Nominal tail parameter */
79  double etaTol = limitTol * (etaMax - etaMin);
80  double constTol = 0.1; /*< if constant is less than constTol, it will be fixed to 0 */
81 
83  gROOT->SetBatch();
84 
87  TH1F* dummy;
88  dummy = (TH1F*)gROOT->FindObject("EnvsCrysSameRing");
89  if (dummy) {delete dummy;}
90  dummy = (TH1F*)gROOT->FindObject("EnvsCrysDifferentRing");
91  if (dummy) {delete dummy;}
92  dummy = (TH1F*)gROOT->FindObject("IntegralVsCrysSame");
93  if (dummy) {delete dummy;}
94  dummy = (TH1F*)gROOT->FindObject("IntegralVsCrysDifferent");
95  if (dummy) {delete dummy;}
96  dummy = (TH1F*)gROOT->FindObject("AverageExpECrysSame");
97  if (dummy) {delete dummy;}
98  dummy = (TH1F*)gROOT->FindObject("AverageExpECrysDifferent");
99  if (dummy) {delete dummy;}
100  dummy = (TH1F*)gROOT->FindObject("AverageElecCalibSame");
101  if (dummy) {delete dummy;}
102  dummy = (TH1F*)gROOT->FindObject("AverageElecCalibDifferent");
103  if (dummy) {delete dummy;}
104  dummy = (TH1F*)gROOT->FindObject("AverageInitialCalibSame");
105  if (dummy) {delete dummy;}
106  dummy = (TH1F*)gROOT->FindObject("AverageInitialCalibDifferent");
107  if (dummy) {delete dummy;}
108 
111  std::vector<std::shared_ptr<TH2F>> EnvsCrys;
112  EnvsCrys.push_back(getObjectPtr<TH2F>("EnvsCrysSameRing"));
113  EnvsCrys.push_back(getObjectPtr<TH2F>("EnvsCrysDifferentRing"));
114 
115  std::vector<std::shared_ptr<TH1F>> ExpEvsCrys;
116  ExpEvsCrys.push_back(getObjectPtr<TH1F>("ExpEvsCrysSameRing"));
117  ExpEvsCrys.push_back(getObjectPtr<TH1F>("ExpEvsCrysDifferentRing"));
118 
119  std::vector<std::shared_ptr<TH1F>> ElecCalibvsCrys;
120  ElecCalibvsCrys.push_back(getObjectPtr<TH1F>("ElecCalibvsCrysSameRing"));
121  ElecCalibvsCrys.push_back(getObjectPtr<TH1F>("ElecCalibvsCrysDifferentRing"));
122 
123  std::vector<std::shared_ptr<TH1F>> InitialCalibvsCrys;
124  InitialCalibvsCrys.push_back(getObjectPtr<TH1F>("InitialCalibvsCrysSameRing"));
125  InitialCalibvsCrys.push_back(getObjectPtr<TH1F>("InitialCalibvsCrysDifferentRing"));
126 
127  std::vector<std::shared_ptr<TH1F>> CalibEntriesvsCrys;
128  CalibEntriesvsCrys.push_back(getObjectPtr<TH1F>("CalibEntriesvsCrysSameRing"));
129  CalibEntriesvsCrys.push_back(getObjectPtr<TH1F>("CalibEntriesvsCrysDifferentRing"));
130 
131  auto RawDigitAmpvsCrys = getObjectPtr<TH2F>("RawDigitAmpvsCrys");
132 
136  TH1F* IntegralVsCrys[2];
137  IntegralVsCrys[0] = new TH1F("IntegralVsCrysSame", "Integral of EnVsCrys for each crystal, same theta ring;Crystal ID",
140  IntegralVsCrys[1] = new TH1F("IntegralVsCrysDifferent", "Integral of EnVsCrys for each crystal, different theta rings;Crystal ID",
142 
143  TH1F* AverageExpECrys[2];
144  AverageExpECrys[0] = new TH1F("AverageExpECrysSame",
145  "Average expected E per crys from collector, same theta ring;Crystal ID;Energy (GeV)", ECLElementNumbers::c_NCrystals, 0,
147  AverageExpECrys[1] = new TH1F("AverageExpECrysDifferent",
148  "Average expected E per crys from collector, different theta ring;Crystal ID;Energy (GeV)", ECLElementNumbers::c_NCrystals, 0,
150 
151  TH1F* AverageElecCalib[2];
152  AverageElecCalib[0] = new TH1F("AverageElecCalibSame",
153  "Average electronics calib const vs crys, same theta ring;Crystal ID;Calibration constant", ECLElementNumbers::c_NCrystals, 0,
155  AverageElecCalib[1] = new TH1F("AverageElecCalibDifferent",
156  "Average electronics calib const vs crys, different theta rings;Crystal ID;Calibration constant", ECLElementNumbers::c_NCrystals, 0,
158 
159  TH1F* AverageInitialCalib[2];
160  AverageInitialCalib[0] = new TH1F("AverageInitialCalibSame",
161  "Average initial cosmic calib const vs crys, same theta ring;Crystal ID;Calibration constant", ECLElementNumbers::c_NCrystals, 0,
163  AverageInitialCalib[1] = new TH1F("AverageInitialCalibDifferent",
164  "Average initial cosmic calib const vs crys, different theta rings;Crystal ID;Calibration constant", ECLElementNumbers::c_NCrystals,
166 
167  for (int crysID = 0; crysID < ECLElementNumbers::c_NCrystals; crysID++) {
168  int histbin = crysID + 1;
169  for (int idir = 0; idir < 2; idir++) {
170  TH1D* hEnergy = EnvsCrys[idir]->ProjectionY("hEnergy", histbin, histbin);
171  int Integral = hEnergy->Integral();
172  IntegralVsCrys[idir]->SetBinContent(histbin, Integral);
173 
174  double TotEntries = CalibEntriesvsCrys[idir]->GetBinContent(histbin);
175 
176  double expectedE = 0.;
177  if (TotEntries > 0.) {expectedE = ExpEvsCrys[idir]->GetBinContent(histbin) / TotEntries;}
178  AverageExpECrys[idir]->SetBinContent(histbin, expectedE);
179  AverageExpECrys[idir]->SetBinError(histbin, 0.);
180 
181  double calibconst = 0.;
182  if (TotEntries > 0.) {calibconst = ElecCalibvsCrys[idir]->GetBinContent(histbin) / TotEntries;}
183  AverageElecCalib[idir]->SetBinContent(histbin, calibconst);
184  AverageElecCalib[idir]->SetBinError(histbin, 0);
185 
186  calibconst = 0.;
187  if (TotEntries > 0.) {calibconst = InitialCalibvsCrys[idir]->GetBinContent(histbin) / TotEntries;}
188  AverageInitialCalib[idir]->SetBinContent(histbin, calibconst);
189  AverageInitialCalib[idir]->SetBinError(histbin, 0);
190  }
191  }
192 
195  TFile* histfile = new TFile("eclCosmicEAlgorithm.root", "recreate");
196  for (int idir = 0; idir < 2; idir++) {
197  EnvsCrys[idir]->Write();
198  IntegralVsCrys[idir]->Write();
199  AverageExpECrys[idir]->Write();
200  AverageElecCalib[idir]->Write();
201  AverageInitialCalib[idir]->Write();
202  }
203  RawDigitAmpvsCrys->Write();
204 
207  if (!performFits) {
208  B2INFO("eclCosmicEAlgorithm has not been asked to perform fits; copying input histograms and quitting");
209  histfile->Close();
210  return c_NotEnoughData;
211  }
212 
217  bool sufficientData = true;
218  for (int crysID = cellIDLo - 1; crysID < cellIDHi; crysID++) {
219  int histbin = crysID + 1;
220  bool SameLow = IntegralVsCrys[0]->GetBinContent(histbin) < minEntries;
221  bool DifferentLow = IntegralVsCrys[1]->GetBinContent(histbin) < minEntries;
222  if ((SameLow && DifferentLow) || (findExpValues && (SameLow || DifferentLow))) {
223  if (storeConst == 1) {B2INFO("eclCosmicEAlgorithm: cellID " << histbin << " has insufficient statistics: " << IntegralVsCrys[0]->GetBinContent(histbin) << " and " << IntegralVsCrys[1]->GetBinContent(histbin) << ". Requirement is " << minEntries);}
224  sufficientData = false;
225  break;
226  }
227  }
228 
231  if (!sufficientData && storeConst == 1) {
232  histfile->Close();
233  return c_NotEnoughData;
234  }
235 
238  const TString preName[2] = {"SameRing", "DifferentRing"};
239 
240  TH1F* PeakperCrys[2];
241  PeakperCrys[0] = new TH1F("PeakperCrysSame", "Fit peak per crystal, same theta ring;Crystal ID;Peak normalized energy",
244  PeakperCrys[1] = new TH1F("PeakperCrysDifferent", "Fit peak per crystal, different theta ring;Crystal ID;Peak normalized energy",
246 
247  TH1F* SigmaperCrys[2];
248  SigmaperCrys[0] = new TH1F("SigmaperCrysSame", "Fit sigma per crysal, same theta ring;Crystal ID;Sigma (ADC)",
250  SigmaperCrys[1] = new TH1F("SigmaperCrysDifferent", "Fit sigma per crysal, different theta ring;Crystal ID;Sigma (ADC)",
253 
254  TH1F* EtaperCrys[2];
255  EtaperCrys[0] = new TH1F("EtaperCrysSame", "Fit eta per crysal, same theta ring;Crystal ID;Eta", ECLElementNumbers::c_NCrystals, 0,
257  EtaperCrys[1] = new TH1F("EtaperCrysDifferent", "Fit eta per crysal, different theta ring;Crystal ID;Eta",
259 
260  TH1F* ConstperCrys[2];
261  ConstperCrys[0] = new TH1F("ConstperCrysSame", "Fit constant per crystal, same theta ring;Crystal ID;Constant",
263  ConstperCrys[1] = new TH1F("ConstperCrysDifferent", "Fit constant per crystal, different theta ring;Crystal ID;Constant",
266 
267  TH1F* StatusperCrys[2];
268  StatusperCrys[0] = new TH1F("StatusperCrysSame", "Fit status, same theta ring;Crystal ID;Status", ECLElementNumbers::c_NCrystals, 0,
270  StatusperCrys[1] = new TH1F("StatusperCrysDifferent", "Fit status, different theta ring;Crystal ID;Status",
272 
274  TH1F* hStatus[2];
275  hStatus[0] = new TH1F("StatusSame", "Fit status, same theta ring", 25, -5, 20);
276  hStatus[1] = new TH1F("StatusDifferent", "Fit status, different theta ring", 25, -5, 20);
277 
278  TH1F* fracPeakUnc[2];
279  fracPeakUnc[0] = new TH1F("fracPeakUncSame", "Fractional uncertainty on peak location, same theta ring", 100, 0, 0.1);
280  fracPeakUnc[1] = new TH1F("fracPeakUncDifferent", "Fractional uncertainty on peak location, different theta ring", 100, 0, 0.1);
281 
282  TH1F* hfitProb[2];
283  hfitProb[0] = new TH1F("fitProbSame", "Probability of fit, same theta ring", 200, 0, 0.02);
284  hfitProb[1] = new TH1F("fitProbDifferent", "Probability of fit, different theta ring", 200, 0, 0.02);
285 
287  TH1F* ExpEnergyperCrys[2];
288  ExpEnergyperCrys[0] = new TH1F("ExpEnergyperCrysSame", "Expected energy per crystal, same theta ring;Crystal ID;Peak energy (GeV)",
290  ExpEnergyperCrys[1] = new TH1F("ExpEnergyperCrysDifferent",
291  "Expected energy per crystal, different theta ring;Crystal ID;Peak energy (GeV)", ECLElementNumbers::c_NCrystals, 0,
293 
294  TH1F* CalibvsCrys = new TH1F("CalibvsCrys", "Energy calibration constant from cosmics;Crystal ID;Calibration constant",
297 
300  bool allFitsOK = true;
301  for (int crysID = cellIDLo - 1; crysID < cellIDHi; crysID++) {
302  int histbin = crysID + 1;
303  for (int idir = 0; idir < 2; idir++) {
304 
306  TString hname = preName[idir];
307  hname += "Enormalized";
308  hname += crysID;
309  TH1D* hEnergy = EnvsCrys[idir]->ProjectionY(hname, histbin, histbin);
310 
312  double histMin = hEnergy->GetXaxis()->GetXmin();
313  double histMax = hEnergy->GetXaxis()->GetXmax();
314  TF1* func = new TF1("eclCosmicNovoConst", eclCosmicNovoConst, histMin, histMax, 5);
315  func->SetParNames("normalization", "peak", "effSigma", "eta", "const");
316  func->SetParLimits(1, peakMin, peakMax);
317  func->SetParLimits(2, effSigMin, effSigMax);
318  func->SetParLimits(3, etaMin, etaMax);
319 
321  hEnergy->GetXaxis()->SetRangeUser(peakMin, peakMax);
322  int maxBin = hEnergy->GetMaximumBin();
323  double peakE = hEnergy->GetBinLowEdge(maxBin);
324  double peakEUnc = 0.;
325  double normalization = hEnergy->GetMaximum();
326  double effSigma = hEnergy->GetRMS();
327  double sigmaUnc = 0.;
328  hEnergy->GetXaxis()->SetRangeUser(histMin, histMax);
329 
331  double fitlow = 0.25;
332  double fithigh = peakE + 2.5 * effSigma;
333 
335  int il0 = hEnergy->GetXaxis()->FindBin(fitlow);
336  int il1 = hEnergy->GetXaxis()->FindBin(fitlow + 0.1);
337  double constant = hEnergy->Integral(il0, il1) / (1 + il1 - il0);
338  double constUnc = 0.;
339 
341  double eta = etaNom;
342  double etaUnc = 0.;
343 
345  double dIter = 0.1 * (histMax - histMin) / hEnergy->GetNbinsX();
346  double highold(0.), higholdold(0.);
347  double fitProb(0.);
348  double fitProbDefault(0.);
349  bool fitHist = IntegralVsCrys[idir]->GetBinContent(histbin) >= minEntries; /* fit only if enough events */
350  bool fixConst = false;
351  int nIter = 0;
352 
355  while (fitHist) {
356  nIter++;
357 
359  func->SetParameters(normalization, peakE, effSigma, eta, constant);
360  if (fixConst) { func->FixParameter(4, 0); }
361 
363  hEnergy->Fit(func, "LIQ", "", fitlow, fithigh);
364  normalization = func->GetParameter(0);
365  peakE = func->GetParameter(1);
366  peakEUnc = func->GetParError(1);
367  effSigma = func->GetParameter(2);
368  sigmaUnc = func->GetParError(2);
369  eta = func->GetParameter(3);
370  etaUnc = func->GetParError(3);
371  constant = func->GetParameter(4);
372  constUnc = func->GetParError(4);
373  fitProbDefault = func->GetProb();
374 
376  fitHist = false;
377  double peak = func->Eval(peakE) - constant;
378  double tRatio = (func->Eval(fithigh) - constant) / peak;
379  if (tRatio < tRatioMin || tRatio > tRatioMax) {
380  double targetY = constant + 0.5 * (tRatioMin + tRatioMax) * peak;
381  higholdold = highold;
382  highold = fithigh;
383  fithigh = func->GetX(targetY, peakE, histMax);
384  fitHist = true;
385 
387  if (abs(fithigh - higholdold) < dIter) {fithigh = 0.5 * (highold + higholdold); }
388 
390  if (nIter > maxIterations - 3) {fithigh = 0.33333 * (fithigh + highold + higholdold); }
391  }
392 
394  if (constant < constTol && !fixConst) {
395  constant = 0;
396  fixConst = true;
397  fitHist = true;
398  }
399 
401  if (nIter == maxIterations) {fitHist = false;}
402  B2DEBUG(200, "cellID = " << histbin << " " << nIter << " " << preName[idir] << " " << peakE << " " << constant << " " << tRatio <<
403  " " << fithigh);
404 
405  }
406 
409  fitProb = 0.;
410  if (nIter > 0) {
411  int lowbin = hEnergy->GetXaxis()->FindBin(fitlow);
412  int highbin = hEnergy->GetXaxis()->FindBin(fithigh);
413  int npar = 5;
414  if (fixConst) {npar = 4;}
415  int ndeg = (highbin - lowbin) + 1 - npar;
416  double chisq = 0.;
417  double halfbinwidth = 0.5 * hEnergy->GetBinWidth(1);
418  for (int ib = lowbin; ib <= highbin; ib++) {
419  double yexp = func->Eval(hEnergy->GetBinLowEdge(ib) + halfbinwidth);
420  double yobs = hEnergy->GetBinContent(ib);
421  double dchi2 = (yexp - yobs) * (yexp - yobs) / yexp;
422  chisq += dchi2;
423  }
424  fitProb = 0.5 * (TMath::Prob(chisq, ndeg) + fitProbDefault);
425  }
426 
429  int iStatus = fitOK; // success
430  if (nIter == maxIterations) {iStatus = iterations;} // too many iterations
431 
433  if (normalization < constRatio * constant) {iStatus = noPeak;}
434 
436  if (fitProb <= minFitLimit || (fitProb < minFitProbIter && iStatus == iterations)) {iStatus = poorFit;}
437 
439  if ((peakE < peakMin + peakTol) || (peakE > peakMax - peakTol)) {iStatus = atLimit;}
440  if ((effSigma < effSigMin + effSigTol) || (effSigma > effSigMax - effSigTol)) {iStatus = atLimit;}
441  if ((eta < etaMin + etaTol) || (eta > etaMax - etaTol)) {iStatus = atLimit;}
442 
443  //**..No fit
444  if (nIter == 0) {iStatus = notFit;} // not fit
445 
447  PeakperCrys[idir]->SetBinContent(histbin, peakE);
448  PeakperCrys[idir]->SetBinError(histbin, peakEUnc);
449  SigmaperCrys[idir]->SetBinContent(histbin, effSigma);
450  SigmaperCrys[idir]->SetBinError(histbin, sigmaUnc);
451  EtaperCrys[idir]->SetBinContent(histbin, eta);
452  EtaperCrys[idir]->SetBinError(histbin, etaUnc);
453  ConstperCrys[idir]->SetBinContent(histbin, constant);
454  ConstperCrys[idir]->SetBinError(histbin, constUnc);
455  StatusperCrys[idir]->SetBinContent(histbin, iStatus);
456  hStatus[idir]->Fill(iStatus);
457  fracPeakUnc[idir]->Fill(peakEUnc / peakE);
458  hfitProb[idir]->Fill(fitProb);
459 
461  B2INFO("cellID " << histbin << " " << preName[idir] << " status = " << iStatus << " fit probability = " << fitProb);
462  histfile->cd();
463  hEnergy->Write();
464  }
465  }
466 
469  if (findExpValues) {
470 
472  for (int crysID = 0; crysID < ECLElementNumbers::c_NCrystals; crysID++) {
473  int histbin = crysID + 1;
474  bool atLeastOneOK = false;
475  for (int idir = 0; idir < 2; idir++) {
476  double fitstatus = StatusperCrys[idir]->GetBinContent(histbin);
477  double peakE = PeakperCrys[idir]->GetBinContent(histbin);
478  double peakEUnc = PeakperCrys[idir]->GetBinError(histbin);
479 
480  //**..For failed fits, store the negative of the input expected energy */
481  if (fitstatus < iterations) {
482  if (histbin >= cellIDLo && histbin <= cellIDHi) {
483  B2INFO("eclCosmicEAlgorithm: crystal " << crysID << " " << preName[idir] << " is not a successful fit. Status = " << fitstatus);
484  }
485  peakE = -1.;
486  peakEUnc = 0.;
487  } else {
488  atLeastOneOK = true;
489  }
490  double inputExpE = abs(AverageExpECrys[idir]->GetBinContent(histbin));
491  ExpEnergyperCrys[idir]->SetBinContent(histbin, inputExpE * peakE);
492  ExpEnergyperCrys[idir]->SetBinError(histbin, inputExpE * peakEUnc / peakE);
493  }
494  if (!atLeastOneOK) {allFitsOK = false;}
495  }
496 
499  } else {
500 
502  for (int crysID = 0; crysID < ECLElementNumbers::c_NCrystals; crysID++) {
503  int histbin = crysID + 1;
504  double calibConst[2] = {};
505  double calibConstUnc[2] = {999999., 999999.};
506  double weight[2] = {};
507  bool bothFitsBad = true;
508  for (int idir = 0; idir < 2; idir++) {
509 
511  double peakE = PeakperCrys[idir]->GetBinContent(histbin);
512  double fracPeakEUnc = PeakperCrys[idir]->GetBinError(histbin) / peakE;
513  double inputConst = AverageInitialCalib[idir]->GetBinContent(histbin);
514  double fitstatus = StatusperCrys[idir]->GetBinContent(histbin);
515  double inputExpE = AverageExpECrys[idir]->GetBinContent(histbin);
516  if (fitstatus >= iterations && inputConst == 0) {B2FATAL("eclCosmicEAlgorithm: input calibration = 0 for idir = " << idir << " and crysID = " << crysID);}
517 
518  //** Find constant only if fit was successful and we have a value for the expected energy */
519  if (fitstatus >= iterations && inputExpE > 0.) {
520  calibConst[idir] = abs(inputConst) / peakE;
521  calibConstUnc[idir] = calibConst[idir] * fracPeakEUnc / peakE;
522  weight[idir] = 1. / (calibConstUnc[idir] * calibConstUnc[idir]);
523  bothFitsBad = false;
524  }
525  if (fitstatus < iterations && histbin >= cellIDLo && histbin <= cellIDHi) {
526  B2INFO("eclCosmicEAlgorithm: cellID " << histbin << " " << preName[idir] << " is not a successful fit. Status = " << fitstatus);
527  } else if (inputExpE < 0. && histbin >= cellIDLo && histbin <= cellIDHi) {
528  B2WARNING("eclCosmicEAlgorithm: cellID " << histbin << " " << preName[idir] << " has no expected energy. Status = " << fitstatus);
529  }
530  }
531 
532 
534  double averageConst;
535  double averageConstUnc;
536 
538  if (bothFitsBad) {
539  if (histbin >= cellIDLo && histbin <= cellIDHi) {B2INFO("eclCosmicEAlgorithm: no constant found for cellID = " << histbin << " status = " << StatusperCrys[0]->GetBinContent(histbin) << " and " << StatusperCrys[1]->GetBinContent(histbin));}
540  averageConst = -1.*abs(AverageInitialCalib[0]->GetBinContent(histbin));
541  averageConstUnc = 0.;
542  } else {
543  averageConst = (calibConst[0] * weight[0] + calibConst[1] * weight[1]) / (weight[0] + weight[1]);
544  averageConstUnc = 1. / sqrt(weight[0] + weight[1]);
545  }
546  CalibvsCrys->SetBinContent(histbin, averageConst);
547  CalibvsCrys->SetBinError(histbin, averageConstUnc);
548  }
549  }
550 
553  bool DBsuccess = false;
554  if (storeConst == 0 || (storeConst == 1 && allFitsOK)) {
555  DBsuccess = true;
556 
558  if (findExpValues) {
559  std::vector<std::string> DBname = {"ECLExpCosmicESame", "ECLExpCosmicEDifferent"};
560  for (int idir = 0; idir < 2; idir++) {
561  std::vector<float> tempE;
562  std::vector<float> tempUnc;
563  for (int crysID = 0; crysID < ECLElementNumbers::c_NCrystals; crysID++) {
564  int histbin = crysID + 1;
565  tempE.push_back(ExpEnergyperCrys[idir]->GetBinContent(histbin));
566  tempUnc.push_back(ExpEnergyperCrys[idir]->GetBinError(histbin));
567  }
568  ECLCrystalCalib* ExpectedE = new ECLCrystalCalib();
569  ExpectedE->setCalibVector(tempE, tempUnc);
570  saveCalibration(ExpectedE, DBname[idir]);
571  B2INFO("eclCosmicEAlgorithm: successfully stored expected values for " << DBname[idir]);
572  }
573 
575  } else {
576  std::vector<float> tempCalib;
577  std::vector<float> tempCalibUnc;
578  for (int crysID = 0; crysID < ECLElementNumbers::c_NCrystals; crysID++) {
579  int histbin = crysID + 1;
580  tempCalib.push_back(CalibvsCrys->GetBinContent(histbin));
581  tempCalibUnc.push_back(CalibvsCrys->GetBinError(histbin));
582  }
583  ECLCrystalCalib* CosmicECalib = new ECLCrystalCalib();
584  CosmicECalib->setCalibVector(tempCalib, tempCalibUnc);
585  saveCalibration(CosmicECalib, "ECLCrystalEnergyCosmic");
586  B2INFO("eclCosmicEAlgorithm: successfully stored calibration constants");
587  }
588  }
589 
591  for (int idir = 0; idir < 2; idir++) {
592  PeakperCrys[idir]->Write();
593  SigmaperCrys[idir]->Write();
594  EtaperCrys[idir]->Write();
595  ConstperCrys[idir]->Write();
596  StatusperCrys[idir]->Write();
597  hStatus[idir]->Write();
598  fracPeakUnc[idir]->Write();
599  hfitProb[idir]->Write();
600  }
601 
603  if (findExpValues) {
604  ExpEnergyperCrys[0]->Write();
605  ExpEnergyperCrys[1]->Write();
606  } else {
607  CalibvsCrys->Write();
608  }
609  histfile->Close();
610 
613  dummy = (TH1F*)gROOT->FindObject("PeakperCrysSame"); delete dummy;
614  dummy = (TH1F*)gROOT->FindObject("SigmaperCrysSame"); delete dummy;
615  dummy = (TH1F*)gROOT->FindObject("EtaperCrysSame"); delete dummy;
616  dummy = (TH1F*)gROOT->FindObject("ConstperCrysSame"); delete dummy;
617  dummy = (TH1F*)gROOT->FindObject("StatusperCrysSame"); delete dummy;
618  dummy = (TH1F*)gROOT->FindObject("StatusSame"); delete dummy;
619  dummy = (TH1F*)gROOT->FindObject("fracPeakUncSame"); delete dummy;
620  dummy = (TH1F*)gROOT->FindObject("fitProbSame"); delete dummy;
621  dummy = (TH1F*)gROOT->FindObject("ExpEnergyperCrysSame"); delete dummy;
622  dummy = (TH1F*)gROOT->FindObject("PeakperCrysDifferent"); delete dummy;
623  dummy = (TH1F*)gROOT->FindObject("SigmaperCrysDifferent"); delete dummy;
624  dummy = (TH1F*)gROOT->FindObject("EtaperCrysDifferent"); delete dummy;
625  dummy = (TH1F*)gROOT->FindObject("ConstperCrysDifferent"); delete dummy;
626  dummy = (TH1F*)gROOT->FindObject("StatusperCrysDifferent"); delete dummy;
627  dummy = (TH1F*)gROOT->FindObject("StatusDifferent"); delete dummy;
628  dummy = (TH1F*)gROOT->FindObject("fracPeakUncDifferent"); delete dummy;
629  dummy = (TH1F*)gROOT->FindObject("fitProbDifferent"); delete dummy;
630  dummy = (TH1F*)gROOT->FindObject("ExpEnergyperCrysDifferent"); delete dummy;
631  dummy = (TH1F*)gROOT->FindObject("CalibvsCrys"); delete dummy;
632 
635  if (storeConst == -1) {
636  B2INFO("eclCosmicEAlgorithm performed fits but was not asked to store contants");
637  return c_Failure;
638  } else if (!DBsuccess) {
639  if (findExpValues) { B2INFO("eclCosmicEAlgorithm: failed to store expected values"); }
640  else { B2INFO("eclCosmicEAlgorithm: failed to store calibration constants"); }
641  return c_Failure;
642  }
643  return c_OK;
644 }
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
@ c_OK
Finished successfuly =0 in Python.
@ c_NotEnoughData
Needs more data =2 in Python.
@ c_Failure
Failed =3 in Python.
General DB object to store one calibration number per ECL crystal.
void setCalibVector(const std::vector< float > &CalibConst, const std::vector< float > &CalibConstUnc)
Set vector of constants with uncertainties.
double tRatioMin
Fit range is adjusted so that fit at upper endpoint is between tRatioMin and tRatioMax of peak.
int poorFit
low chi square; fit not useable
int iterations
fit reached max number of iterations, but is useable
int storeConst
controls which values are written to the database.
bool performFits
if false, input histograms are copied to output, but no fits are done.
int cellIDHi
Last cellID to be fit.
int cellIDLo
Parameters to control Novosibirsk fit to signal measured in each crystal.
bool findExpValues
if true, fits are used to find expected energy deposit for each crystal instead of the calibration co...
int minEntries
All crystals to be fit must have at least minEntries events in the fit range.
int noPeak
Novosibirsk component of fit is negligible; fit not useable.
int atLimit
a parameter is at the limit; fit not useable
int maxIterations
no more than maxIteration iterations
double tRatioMax
Fit range is adjusted so that fit at upper endpoint is between tRatioMin and tRatioMax of peak.
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
const int c_NCrystals
Number of crystals.

◆ checkPyExpRun()

bool checkPyExpRun ( PyObject *  pyObj)
inherited

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.

◆ convertPyExpRun()

ExpRun convertPyExpRun ( PyObject *  pyObj)
inherited

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.

◆ execute()

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.

◆ getCollectorName()

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 algorihtm.

Definition at line 164 of file CalibrationAlgorithm.h.

◆ setInputFileNames() [1/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.

◆ setInputFileNames() [2/2]

void setInputFileNames ( 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.

Member Data Documentation

◆ cellIDLo

int cellIDLo

Parameters to control Novosibirsk fit to signal measured in each crystal.

First cellID to be fit

Definition at line 34 of file eclCosmicEAlgorithm.h.

◆ storeConst

int storeConst

controls which values are written to the database.

0 (default): store value found by successful fits, or -|input value| otherwise; -1 : do not store values 1 : store values if every fit for [cellIDLo,cellIDHi] was successful

Definition at line 42 of file eclCosmicEAlgorithm.h.


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