9#include <pxd/calibration/PXDAnalyticGainCalibrationAlgorithm.h>
10#include <pxd/calibration/PXDCalibrationUtilities.h>
11#include <pxd/dbobjects/PXDGainMapPar.h>
13#include <boost/format.hpp>
40 minClusters(1000), safetyFactor(2.0), forceContinue(false), strategy(0), useChargeRatioHistogram(true), correctForward(false)
43 " -------------------------- PXDAnalyticGainCalibrationAlgorithm ---------------------------------\n"
45 " Algorithm for estimating pxd gains (conversion factor from charge to ADU) \n"
46 " ----------------------------------------------------------------------------------------\n"
55 auto cluster_counter = getObjectPtr<TH1I>(
"PXDClusterCounter");
58 if (cluster_counter ==
nullptr) {
59 B2WARNING(
"No PXD cluster reconstructed!");
63 B2WARNING(
"Skip processing.");
72 unsigned short nBinsU = 0;
73 unsigned short nBinsV = 0;
79 B2WARNING(
"Not enough Data: Only " << cluster_counter->GetEntries() <<
" hits were collected but " <<
int(
81 nSensors * nBinsU * nBinsV) <<
" needed!");
84 B2WARNING(
"Continue despite low statistics: Only " << cluster_counter->GetEntries() <<
" hits were collected but" <<
int(
86 nSensors * nBinsU * nBinsV) <<
" would be desirable!");
90 B2INFO(
"Start calibration using a " << nBinsU <<
"x" << nBinsV <<
" grid per sensor.");
91 B2INFO(
"Number of collected clusters is " << cluster_counter->GetEntries());
95 set<VxdID> pxdSensors;
98 for (
auto histoBin = 1; histoBin <= cluster_counter->GetXaxis()->GetNbins(); histoBin++) {
100 string label = cluster_counter->GetXaxis()->GetBinLabel(histoBin);
103 istringstream stream(label);
105 getline(stream, token,
'_');
106 VxdID sensorID(token);
108 getline(stream, token,
'_');
109 unsigned short uBin = std::stoi(token);
111 getline(stream, token,
'_');
112 unsigned short vBin = std::stoi(token);
115 int numberOfHits = cluster_counter->GetBinContent(histoBin);
123 auto hClusterChargeRatio = getObjectPtr<TH2F>(
"PXDClusterChargeRatio");
124 TH1D* hRatios = hClusterChargeRatio->ProjectionY(
"proj", histoBin, histoBin);
132 B2WARNING(label <<
": Number of hits is too small (" << numberOfHits <<
" < " <<
minClusters <<
133 "). Use default gain.");
136 pxdSensors.insert(sensorID);
143 for (
const auto& sensorID : pxdSensors) {
148 for (
unsigned short uBin = 0; uBin < nBinsU; ++uBin) {
150 double gainForwardRegion = 1.0;
151 unsigned short vBinToCheck = nBinsV - 1;
152 for (
unsigned short vBinGood = nBinsV - 2; vBinGood >= 1; --vBinGood) {
153 auto temp = gainMapPar->
getContent(sensorID.getID(), uBin, vBinGood);
155 gainForwardRegion = temp;
156 vBinToCheck = vBinGood + 1;
161 if (gainForwardRegion != 1.0)
162 for (
unsigned short vBin = nBinsV - 1; vBin >= vBinToCheck; --vBin) {
163 auto gain = gainMapPar->
getContent(sensorID.getID(), uBin, vBin);
165 gainMapPar->
setContent(sensorID.getID(), uBin, vBin, gainForwardRegion);
166 B2RESULT(
"Gain calibration on sensor=" << sensorID <<
", vBin=" << vBin <<
" uBin " << uBin <<
167 ": Replace default gain with that from the closest vBin with non default value "
168 << gainForwardRegion);
174 for (
unsigned short vBin = 0; vBin < nBinsV; ++vBin) {
177 unsigned short nGood = 0;
178 unsigned short nBad = 0;
179 for (
unsigned short uBin = 0; uBin < nBinsU; ++uBin) {
180 auto gain = gainMapPar->
getContent(sensorID.getID(), uBin, vBin);
189 B2RESULT(
"Gain calibration on sensor=" << sensorID <<
" and vBin=" << vBin <<
" was successful on " << nGood <<
"/" << nBinsU <<
193 if (nGood > 0 && nBad > 0) {
195 for (
unsigned short uBin = 0; uBin < nBinsU; ++uBin) {
196 auto gain = gainMapPar->
getContent(sensorID.getID(), uBin, vBin);
198 gainMapPar->
setContent(sensorID.getID(), uBin, vBin, meanGain);
199 B2RESULT(
"Gain calibration on sensor=" << sensorID <<
", vBin=" << vBin <<
" uBin " << uBin <<
200 ": Replace default gain with average "
201 << meanGain <<
" of uBins with non-default gains.");
213 B2INFO(
"PXD Gain Calibration Successful");
224 double (*estimateGainFromVec)(std::vector<double>&) = &
CalculateMedian;
232 B2FATAL(
"strategy unavailable, use 0 for medians or 1 for landau fit!");
237 gain = estimateGainFromHist(hist);
243 const string treename = str(format(
"tree_%1%_%2%_%3%_%4%_%5%") % layerNumber % ladderNumber % sensorNumber % uBin % vBin);
245 vector<double> ratios;
247 auto tree = getObjectPtr<TTree>(treename);
248 tree->SetBranchAddress(
"signal", &m_signal);
249 tree->SetBranchAddress(
"estimated", &m_estimated);
252 const auto nEntries_MC = tree->GetEntries();
253 for (
int i = 0; i < nEntries_MC; ++i) {
255 ratios.push_back(
double(m_signal) / m_estimated);
257 gain = estimateGainFromVec(ratios);
262 B2WARNING(
"Retrieved negative median/MPV for sensor=" << sensorID <<
" uBin=" << uBin <<
" vBin=" << vBin <<
263 ". Set gain to default value (=1.0) as well.");
269 B2DEBUG(10,
"Gain from db used in PXDDigitizer is " << gainFromDB);
270 B2DEBUG(10,
"New gain correction derived is " << gain);
271 B2DEBUG(10,
"The total gain we should return is " << gain * gainFromDB);
273 return gain * gainFromDB;
281 auto dbtree = getObjectPtr<TTree>(
"dbtree");
282 dbtree->SetBranchAddress(
"run", &m_run);
283 dbtree->SetBranchAddress(
"exp", &m_exp);
284 dbtree->SetBranchAddress(
"gainMap", &gainMapPtr);
291 const auto nEntries = dbtree->GetEntries();
292 for (
int i = 0; i < nEntries; ++i) {
298 gainMapPtr =
nullptr;
300 return sum / counter;
308 B2INFO(
"This is the first run encountered, let's say it is a boundary.");
Base class for calibration algorithms.
void saveCalibration(TClonesArray *data, const std::string &name)
Store DBArray payload with given name with default IOV.
std::vector< Calibration::ExpRun > m_boundaries
When using the boundaries functionality from isBoundaryRequired, this is used to store the boundaries...
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.
PXDAnalyticGainCalibrationAlgorithm()
Constructor set the prefix to PXDAnalyticGainCalibrationAlgorithm.
double GetCurrentGainFromDB(VxdID sensorID, unsigned short uBin, unsigned short vBin)
Retrive current gain value from pulled in data base payload.
bool correctForward
Flag to update default gains in forward region due to low statistics.
int minClusters
Minimum number of collected clusters for estimating gains.
double EstimateGain(VxdID sensorID, unsigned short uBin, unsigned short vBin, TH1 *hist=nullptr)
Estimate gain as ratio of medians from MC and data for a part of PXD.
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.
bool useChargeRatioHistogram
Flag to use histogram of charge ratio (relative to expected MPV)
bool forceContinue
Force continue in low statistics runs instead of returning c_NotEnoughData.
virtual bool isBoundaryRequired(const Calibration::ExpRun &) override
Decide if a run should be a payload boundary. Only used in certain Python Algorithm Starategies.
The payload class for PXD gain corrections.
float getContent(unsigned short sensorID, unsigned short globalID) const
Get content.
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.
Namespace to encapsulate code needed for simulation and reconstrucion of the PXD.
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.
double CalculateMedian(std::vector< double > &signals)
Helper function to calculate a median from unsorted signal vector.
double FitLandau(TH1 *hist)
Helper function to estimate MPV from 1D histogram.
Abstract base class for different kinds of events.