9#include <pxd/calibration/PXDChargeCalibrationAlgorithm.h>
10#include <pxd/dbobjects/PXDClusterChargeMapPar.h>
19#include <boost/format.hpp>
39 void getNumberOfBins(
const std::shared_ptr<TH1I>& histo_ptr,
unsigned short& nBinsU,
unsigned short& nBinsV)
41 set<unsigned short> uBinSet;
42 set<unsigned short> vBinSet;
45 for (
auto histoBin = 1; histoBin <= histo_ptr->GetXaxis()->GetNbins(); histoBin++) {
47 string label = histo_ptr->GetXaxis()->GetBinLabel(histoBin);
50 istringstream stream(label);
52 getline(stream, token,
'_');
53 getline(stream, token,
'_');
54 unsigned short uBin = std::stoi(token);
56 getline(stream, token,
'_');
57 unsigned short vBin = std::stoi(token);
63 if (uBinSet.empty() || vBinSet.empty()) {
64 B2FATAL(
"Not able to determine the grid size. Something is wrong with collected data.");
66 nBinsU = *uBinSet.rbegin() + 1;
67 nBinsV = *vBinSet.rbegin() + 1;
74 set<unsigned short> sensorSet;
77 for (
auto histoBin = 1; histoBin <= histo_ptr->GetXaxis()->GetNbins(); histoBin++) {
79 string label = histo_ptr->GetXaxis()->GetBinLabel(histoBin);
82 istringstream stream(label);
84 getline(stream, token,
'_');
85 VxdID sensorID(token);
86 sensorSet.insert(sensorID.getID());
89 return sensorSet.size();
97 minClusters(5000), noiseSigma(0.6), safetyFactor(2.0), forceContinue(false), strategy(0)
100 " ------------------------------ PXDChargeCalibrationAlgorithm -----------------------------------\n"
102 " Algorithm for estimating pxd median/MPV cluster charges for different position on sensor in ADU \n"
103 " ------------------------------------------------------------------------------------------------\n"
114 auto cluster_counter = getObjectPtr<TH1I>(
"PXDClusterCounter");
117 auto nSensors = getNumberOfSensors(cluster_counter);
120 unsigned short nBinsU = 0;
121 unsigned short nBinsV = 0;
122 getNumberOfBins(cluster_counter, nBinsU, nBinsV);
127 B2INFO(
"Not enough Data: Only " << cluster_counter->GetEntries() <<
" hits were collected but " <<
int(
safetyFactor *
minClusters*
128 nSensors * nBinsU * nBinsV) <<
" needed!");
131 B2INFO(
"Continue despite low statistics: Only " << cluster_counter->GetEntries() <<
" hits were collected but" <<
int(
133 nSensors * nBinsU * nBinsV) <<
" would be desirable!");
137 B2INFO(
"Start calibration using a " << nBinsU <<
"x" << nBinsV <<
" grid per sensor.");
143 for (
auto histoBin = 1; histoBin <= cluster_counter->GetXaxis()->GetNbins(); histoBin++) {
145 string label = cluster_counter->GetXaxis()->GetBinLabel(histoBin);
148 istringstream stream(label);
150 getline(stream, token,
'_');
151 VxdID sensorID(token);
153 getline(stream, token,
'_');
154 unsigned short uBin = std::stoi(token);
156 getline(stream, token,
'_');
157 unsigned short vBin = std::stoi(token);
160 int numberOfDataHits = cluster_counter->GetBinContent(histoBin);
171 B2WARNING(label <<
": Number of data hits too small for fitting (" << numberOfDataHits <<
" < " <<
minClusters <<
172 "). Use default value of 0.");
181 B2INFO(
"PXD Cluster Charge Calibration Successful");
193 const string treename = str(format(
"tree_%1%_%2%_%3%_%4%_%5%") % layerNumber % ladderNumber % sensorNumber % uBin % vBin);
195 vector<double> signals;
198 auto tree = getObjectPtr<TTree>(treename);
199 tree->SetBranchAddress(
"signal", &m_signal);
202 const auto nEntries = tree->GetEntries();
203 for (
int i = 0; i < nEntries; ++i) {
206 double noise = gRandom->Gaus(0.0,
noiseSigma);
207 signals.push_back(m_signal + noise);
212 B2FATAL(
"strategy unavailable, use 0 for medians or 1 for landau fit!");
219 auto size = signals.size();
224 sort(signals.begin(), signals.end());
226 return (signals[size / 2 - 1] + signals[size / 2]) / 2;
228 return signals[size / 2];
235 auto size = signals.size();
236 if (size == 0)
return 0.0;
239 int max = *max_element(signals.begin(), signals.end());
240 int min = *min_element(signals.begin(), signals.end());
244 TH1D* hist_signals =
new TH1D(
"",
"", max - min, min, max);
245 for (
auto it = signals.begin(); it != signals.end(); ++it) {
246 hist_signals->Fill(*it);
250 TF1* landau =
new TF1(
"landau",
"TMath::Landau(x,[0],[1])*[2]", min, max);
251 landau->SetParNames(
"MPV",
"sigma",
"scale");
252 landau->SetParameters(100, 1, 1000);
255 Int_t status = hist_signals->Fit(
"landau",
"Lq",
"", 30, 350);
256 double MPV = landau->GetParameter(
"MPV");
263 if (status == 0)
return MPV;
265 B2WARNING(
"Fit failed! using default value 0.0!");
Base class for calibration algorithms.
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
void setDescription(const std::string &description)
Set algorithm description (in constructor)
EResult
The result of calibration.
@ c_OK
Finished successfully =0 in Python.
@ c_NotEnoughData
Needs more data =2 in Python.
double EstimateCharge(VxdID sensorID, unsigned short uBin, unsigned short vBin)
Estimate median charge form collected clusters on part of PXD.
double FitLandau(std::vector< double > &signals)
calculate MPV of unsorted signal vector using a Landau fit
PXDChargeCalibrationAlgorithm()
Constructor set the prefix to PXDChargeCalibrationAlgorithm.
int minClusters
Minimum number of collected clusters for estimating median charge.
float noiseSigma
Artificial noise sigma for smearing cluster charge.
virtual EResult calibrate() override
Run algo on data.
int strategy
strategy to used for gain calibration, 0 for medians, 1 for landau fit
float safetyFactor
Safety factor for determining whether the collected number of clusters is enough.
double CalculateMedian(std::vector< double > &signals)
Calculate a median from unsorted signal vector. The input vector gets sorted.
bool forceContinue
Force continue in low statistics runs instead of returning c_NotEnoughData.
The payload class for PXD cluster charge calibrations.
void setContent(unsigned short sensorID, unsigned short globalID, float value)
Set map content.
Class to uniquely identify a any structure of the PXD and SVD.
baseType getID() const
Get the unique id.
baseType getSensorNumber() const
Get the sensor id.
baseType getLadderNumber() const
Get the ladder id.
baseType getLayerNumber() const
Get the layer id.
unsigned short getNumberOfSensors(const std::shared_ptr< TH1I > &histo_ptr)
Helper function to extract number of sensors from counter histogram labels.
void getNumberOfBins(const std::shared_ptr< TH1I > &histo_ptr, unsigned short &nBinsU, unsigned short &nBinsV)
Helper function to extract number of bins along u side and v side from counter histogram labels.
Abstract base class for different kinds of events.