26 return par[0] + (par[1] * (1 + par[2] * std::exp(-(
x - par[4]) / par[3]))) /
27 ((1 + std::exp((-
x + par[4]) / par[6])) * (1 + std::exp((
x - par[5]) / par[7])));
33 std::array<double, 8> params{};
42 m_settings =
new T0ClassicSettings(0., 300., 100, -100., 900., 1000, 1, 1000, 1, 8, params, 10., 4);
46 if (log.level() <= MSG::INFO) log << MSG::INFO <<
"T0CalibrationClassic::T0CalibrationClassic" <<
m_name <<
" " <<
name <<
endmsg;
49 std::string HistoFileName =
"T0Classic_" +
m_name +
".root";
50 if (log.level() <= MSG::INFO)
51 log << MSG::INFO <<
"T0CalibrationClassic::T0CalibrationClassic" <<
m_name <<
" " <<
name <<
" " << HistoFileName <<
endmsg;
52 m_file = std::make_unique<TFile>(HistoFileName.c_str(),
"recreate");
64 float distanceToRO =
hit->distanceToReadout();
66 bool ROside = distanceToRO < 130000.;
71 int nML =
id.mdtMultilayer();
72 int nL =
id.mdtTubeLayer();
73 int nT =
id.mdtTube();
79 log << MSG::WARNING <<
"no Single Tube Calib info found for ML=" << nML <<
" L=" << nL <<
" T=" << nT <<
endmsg;
80 log << MSG::WARNING <<
"container size " <<
m_result->size() <<
endmsg;
81 log << MSG::WARNING <<
"container nML " <<
m_result->numMultilayers() <<
endmsg;
82 log << MSG::WARNING <<
"container nL " <<
m_result->numLayers() <<
endmsg;
83 log << MSG::WARNING <<
"container nT " <<
m_result->numTubes() <<
endmsg;
91 float ttime =
hit->driftTime();
93 histos->time->Fill(ttime);
94 histos->adc->Fill(
hit->adcCount());
97 histosAll->
time->Fill(ttime);
98 histosAll->
adc->Fill(
hit->adcCount());
102 histosML->
time->Fill(ttime);
103 histosML->
adc->Fill(
hit->adcCount());
106 histosMezz->
time->Fill(ttime);
107 histosMezz->
adc->Fill(
hit->adcCount());
110 int serialGas = nML * 10 + (nT - 1) % 3 + 1;
112 histosSerialGas->time->Fill(ttime);
113 histosSerialGas->adc->Fill(
hit->adcCount());
121 if (log.level() <= MSG::INFO) log << MSG::INFO <<
"T0CalibrationClassic::analyse iteration " <<
m_currentItnum <<
endmsg;
125 for (std::unique_ptr<T0ClassicHistos> &hist :
m_histos) {
129 int idtube = hist->id;
130 if (idtube != 0 && (
int)(idtube / 100000000) != 9) {
140 bool setInfo =
m_result->setCalib(st, tubeId, log);
141 if (!setInfo) log << MSG::WARNING <<
"T0CalibrationClassic::PROBLEM! could not set SingleTubeCalib info " <<
endmsg;
142 setInfo =
m_result->setFit(std::move(full), tubeId, log);
143 if (!setInfo) log << MSG::WARNING <<
"T0CalibrationClassic::PROBLEM! could not set SingleTubeFullInfo info " <<
endmsg;
161 std::unique_ptr<TMinuit> gMinuit = std::make_unique<TMinuit>();
165 std::vector<double> pfit(np, 0), errfit(np, 0);
166 Double_t **matrix =
new Double_t *[np];
168 for (
int i = 0; i < np; i++) {
169 matrix[i] =
new Double_t[np];
170 for (
int j = 0; j < np; j++) matrix[i][j] = 0.;
172 const std::array<double, 8> &pdefault =
m_settings->params();
179 if (T0h.
id == 1 || T0h.
id == 2 || (T0h.
id > 10 && T0h.
id <= 23)) isMultilayer = 1;
183 if (log.level() <= MSG::INFO) log << MSG::INFO <<
" STARTING doTimeFit " <<
endmsg;
187 if (log.level() <= MSG::DEBUG) log << MSG::DEBUG << T0h.
id <<
endmsg;
191 if (fitMezz == 1 && !isMultilayer) {
194 std::string HistoId = std::format(
"time_mezz_{:}", (hIdMezz) % (900000000));
195 if (log.level() <= MSG::DEBUG) {
196 log << MSG::DEBUG <<
" doTimeFit HistogramId : " << T0h.
id <<
endmsg;
197 log << MSG::DEBUG <<
" doTimeFit Histogram : " << HistoId <<
endmsg;
199 TH1F *timeHis = (TH1F *)
m_regiondir->Get(HistoId.c_str());
201 for (
int i = 0; i < np; i++)
delete[] matrix[i];
207 h = histosMezz->
time.get();
213 if (log.level() <= MSG::VERBOSE)
214 log << MSG::VERBOSE <<
" histogram " <<
h->GetName() <<
" " <<
h->GetTitle() <<
" entries=" <<
h->GetEntries()
215 <<
" min entries=" <<
m_settings->entries() << std::endl;
220 std::unique_ptr<TF1> FitFunction{
h->GetFunction(
"TimeSpectrum")};
222 for (
int i = 0; i < np; i++) {
223 pfit[i] = FitFunction->GetParameter(i);
224 errfit[i] = FitFunction->GetParError(i);
226 chi2 = FitFunction->GetChisquare();
227 ndof = FitFunction->GetNDF();
229 std::unique_ptr<TF1> TimeSpectrum = std::make_unique<TF1>(
230 "TimeSpectrum",
"[0]+([1]*(1+[2]*exp(-(x-[4])/[3])))/((1+exp((-x+[4])/[6]))*(1+exp((x-[5])/[7]))) ",
232 for (
int i = 0; i < np; i++) {
233 pfit[i] = pdefault[i];
234 if (log.level() <= MSG::DEBUG)
235 log << MSG::DEBUG <<
"T0CalibrationClassic::doTimeFit initial parameters" << i <<
"=" << pfit[i] <<
endmsg;
238 if (log.level() <= MSG::DEBUG) {
239 log << MSG::DEBUG <<
"T0CalibrationClassic::doTimeFit parameters after searchParams " <<
endmsg;
240 for (
int i = 0; i < np; ++i) { log << MSG::DEBUG <<
"i,pfit(i) " << i <<
" " << pfit[i] <<
endmsg; }
242 TimeSpectrum->SetParameters(pfit.data());
243 TimeSpectrum->SetParLimits(0, 0., 5.);
244 TimeSpectrum->SetParLimits(1, 0., 1000.);
245 TimeSpectrum->SetParLimits(2, 0., 40.);
246 TimeSpectrum->SetParLimits(3, 50., 400.);
247 TimeSpectrum->SetParLimits(4, 0., 1000.);
249 TimeSpectrum->SetParLimits(5, pfit[5], pfit[5]);
250 TimeSpectrum->SetParLimits(6, pfit[6], pfit[6]);
251 TimeSpectrum->SetParLimits(7, pfit[7], pfit[7]);
252 h->Fit(
"TimeSpectrum",
"QLB");
254 TimeSpectrum->SetParLimits(5, 500., 2000.);
255 TimeSpectrum->SetParLimits(6, pfit[6], pfit[6]);
256 TimeSpectrum->SetParLimits(7, pfit[7], pfit[7]);
257 h->Fit(
"TimeSpectrum",
"QLB");
259 TimeSpectrum->SetParLimits(6, 4., 30.);
260 h->Fit(
"TimeSpectrum",
"QLB");
262 TimeSpectrum->SetParLimits(6, 4., 30.);
263 TimeSpectrum->SetParLimits(7, 4., 30.);
264 double xmin =
h->GetBinLowEdge(1);
265 double xmax = pfit[5] + 250.;
266 h->Fit(
"TimeSpectrum",
"QLB",
"",
xmin,
xmax);
268 gMinuit->mnemat(&matrix[0][0], np);
269 for (
int i = 0; i < np; i++) {
270 pfit[i] = TimeSpectrum->GetParameter(i);
271 errfit[i] = TimeSpectrum->GetParError(i);
273 chi2 = TimeSpectrum->GetChisquare();
274 ndof = TimeSpectrum->GetNDF();
277 if (ndof == 0.) ndof = -1;
279 if (log.level() <= MSG::VERBOSE)
280 log << MSG::VERBOSE <<
" fit results chi2/ndof=" <<
chi2 / ndof <<
" T0=" << pfit[4] <<
" err=" << errfit[4] <<
endmsg;
281 if (
chi2 / ndof < m_settings->chi2max()) {
288 for (
int i = 0; i < np; i++) fi.
par[i] = pfit[i];
295 for (
int i = 0; i < np; i++) fi.
cov[i] = errfit[i];
321 for (
int i = 0; i < np; i++)
delete[] matrix[i];
324 if (log.level() <= MSG::DEBUG) log << MSG::DEBUG <<
" ENDING doTimeFit " <<
endmsg;
336 std::array<double, 4> par{0}, errpar{0};
341 if (log.level() <= MSG::DEBUG) log << MSG::DEBUG <<
" doAdcFit : checking Single tube entries" <<
endmsg;
342 double adcThreshold = 50.;
343 TH1 *hcheck = T0h.
adc.get();
344 int nhits =
static_cast<int>(hcheck->GetEntries());
346 int adcBinThreshold = (int)((adcThreshold - hcheck->GetBinLowEdge(1)) / (hcheck->GetBinWidth(1)) + 1);
347 int nhitsAboveAdcCut = (int)hcheck->Integral(adcBinThreshold, hcheck->GetNbinsX());
348 if (log.level() <= MSG::DEBUG)
349 log << MSG::DEBUG <<
" doAdcFit : TotHits, nhitsAboveAdcCut " << nhits <<
" " << nhitsAboveAdcCut <<
endmsg;
352 fi.
cov[21] = nhitsAboveAdcCut;
354 if (log.level() <= MSG::DEBUG) log << MSG::DEBUG <<
" STARTING doAdcFit " <<
endmsg;
360 std::string HistoId = std::format(
"charge_mezz_{:}", (hIdMezz) % (900000000));
361 if (log.level() <= MSG::DEBUG) {
362 log << MSG::DEBUG <<
" doAdcFit HistogramId : " << T0h.
id <<
endmsg;
363 log << MSG::DEBUG <<
" doAdcFit Histogram : " << HistoId <<
endmsg;
365 TH1F *adcHis = (TH1F *)
m_regiondir->Get(HistoId.c_str());
369 h = histosMezz->
adc.get();
372 if (log.level() <= MSG::VERBOSE)
373 log << MSG::VERBOSE <<
" histogram " <<
h->GetName() <<
" " <<
h->GetTitle() <<
" entries=" <<
h->GetEntries() <<
endmsg;
379 TF1 *FitFunction =
h->GetFunction(
"AdcSpectrum");
381 chi2 = FitFunction->GetChisquare();
382 ndof = FitFunction->GetNDF();
383 for (
int i = 0; i < 4; i++) {
384 par[i] = FitFunction->GetParameter(i);
385 errpar[i] = FitFunction->GetParError(i);
389 double m =
h->GetMean();
390 double r =
h->GetRMS();
391 double maxval =
h->GetMaximum();
392 std::array<double, 4> adcpar{};
393 adcpar[0] = maxval * 2.;
398 std::unique_ptr<TF1> AdcSpectrum = std::make_unique<TF1>(
399 "AdcSpectrum",
" ([0]*exp((x-[1])/[2]))/ (1.+exp((x-[1])/[3])) ",
m_settings->minAdc(),
m_settings->maxAdc());
400 AdcSpectrum->SetParameters(adcpar.data());
401 double fitMin = m - (3 *
r);
402 double fitMax = m + (3 *
r);
403 if (fitMin < adcThreshold) fitMin = adcThreshold;
404 if (fitMax > 300) fitMax = 300.;
405 h->Fit(
"AdcSpectrum",
"Q",
" ", fitMin, fitMax);
406 chi2 = AdcSpectrum->GetChisquare();
407 ndof = AdcSpectrum->GetNDF();
408 for (
int i = 0; i < 4; i++) {
409 par[i] = AdcSpectrum->GetParameter(i);
410 errpar[i] = AdcSpectrum->GetParError(i);
412 if (log.level() <= MSG::VERBOSE)
413 log << MSG::VERBOSE <<
"chi2/ndof=" <<
chi2 / ndof <<
" "
414 <<
"Mean=" << m <<
" "
415 <<
"RMS=" <<
r <<
" par 0 1 2 3 " << par[0] <<
" " << par[1] <<
" " << par[2] <<
" " << par[3] <<
endmsg;
425 if (std::abs(ndof) == 0) {
434 int nbinsX =
h->GetNbinsX();
435 double sizeX =
h->GetBinWidth(1);
436 double oldSizeX = sizeX;
437 int RebinFactor =
static_cast<int>(10. / sizeX);
439 std::unique_ptr<TH1> hnew{
h->Rebin(RebinFactor,
"hnew")};
442 if (log.level() <= MSG::DEBUG)
443 log << MSG::DEBUG <<
"nbinsx,sizex,rebinfactor=" << nbinsX <<
" " << sizeX <<
" " << RebinFactor <<
endmsg;
444 float minDeriv(9999.);
446 sizeX = hnew->GetBinWidth(1);
447 int newbins = hnew->GetNbinsX();
448 for (
int i = 0; i < np; ++i) {
449 if (log.level() <= MSG::DEBUG) log << MSG::DEBUG <<
"i,p(i) " << i <<
" " << p[i] <<
endmsg;
451 for (
int i = 0; i < newbins - 1; ++i) {
452 if (hnew->GetBinContent(i) - hnew->GetBinContent(i + 1) < minDeriv) {
453 minDeriv = hnew->GetBinContent(i) - hnew->GetBinContent(i + 1);
457 float t0guess = hnew->GetBinCenter(minDerivBin);
458 if (minDerivBin < newbins - 1) { t0guess += (hnew->GetBinCenter(minDerivBin + 1) - hnew->GetBinCenter(minDerivBin)) / 2.; }
459 if (log.level() <= MSG::DEBUG) log << MSG::DEBUG <<
" t0guess is " << t0guess <<
endmsg;
464 int numOfBins(10), numOfBinsOffset(3);
466 if (minDerivBin > numOfBins + numOfBinsOffset) {
467 imin = minDerivBin - numOfBins - numOfBinsOffset;
468 imax = minDerivBin - numOfBinsOffset;
471 if (minDerivBin > numOfBinsOffset) {
472 imax = minDerivBin - numOfBinsOffset;
478 for (
int i = imin; i <=
imax; ++i) {
479 noise += hnew->GetBinContent(i);
483 noise = noise / (float)(icount);
484 if (log.level() <= MSG::DEBUG) log << MSG::DEBUG <<
" noise is " << noise <<
endmsg;
488 int t0bin = minDerivBin;
489 int ix1 = t0bin + (int)(50 / sizeX);
490 int ix2 = t0bin + (int)(500 / sizeX);
491 if (log.level() <= MSG::DEBUG) log << MSG::DEBUG <<
"t0bin,ix1,ix2 " << t0bin <<
" " << ix1 <<
" " << ix2 <<
endmsg;
495 if (log.level() <= MSG::DEBUG) log << MSG::DEBUG <<
"P1,P2,P3 start are " << P1 <<
" " << P2 <<
" " << P3 <<
endmsg;
501 if (0 < ix1 && ix1 < newbins && 0 < ix2 && ix2 < newbins) {
502 float a1 = hnew->GetBinCenter(ix1);
503 float a2 = hnew->GetBinCenter(ix2);
504 float cont1 = hnew->GetBinContent(ix1);
505 float cont2 = hnew->GetBinContent(ix2);
506 if (cont1 > 0. && cont2 > 0.) {
507 float A1 = std::exp(-(a1 - t0guess) / P3);
508 float A2 = std::exp(-(a2 - t0guess) / P3);
510 P2 = (cont1 / cont2 - 1.) / (A1 - cont1 / cont2 * A2);
511 P1 = cont1 / (1 + P2 * A1);
512 P1 = P1 * oldSizeX / sizeX;
513 P2 = P2 * oldSizeX / sizeX;
514 if (log.level() <= MSG::DEBUG) {
515 log << MSG::DEBUG <<
"a1,a2 " << a1 <<
" " << a2 <<
" cont1,cont2 " << cont1 <<
" " << cont2 <<
" A1,A2 " << A1 <<
" "
517 log << MSG::DEBUG <<
" t0Guess .... P1, P2 " << P1 <<
" " << P2 <<
endmsg;
527 return std::make_shared<T0CalibrationOutput>(
m_result.get());
532 if ((
int)(idtube / 100000000) == 9) {
533 int mezz = (idtube) % (900000000);
534 HistoId = std::format(
"time_mezz_{:}", mezz);
535 }
else if (idtube == 0) {
537 }
else if (idtube == 1) {
538 HistoId =
"time_ML1";
539 }
else if (idtube == 2) {
540 HistoId =
"time_ML2";
541 }
else if (idtube == 11) {
542 HistoId =
"time_ML1_series1";
543 }
else if (idtube == 12) {
544 HistoId =
"time_ML1_series2";
545 }
else if (idtube == 13) {
546 HistoId =
"time_ML1_series3";
547 }
else if (idtube == 21) {
548 HistoId =
"time_ML2_series1";
549 }
else if (idtube == 22) {
550 HistoId =
"time_ML2_series2";
551 }
else if (idtube == 23) {
552 HistoId =
"time_ML2_series3";
558 int tubeid = (nML * 1000) + (nL * 100) + nT;
563 HistoId = std::format(
"time_{:}_{:}_{:}_{:}", stationName,
eta,
phi, tubeid);
566 TH1F *timeHis = (TH1F *)
m_regiondir->Get(HistoId.c_str());
571 for (
const std::unique_ptr<T0ClassicHistos> &hist :
m_histos) {
572 if (hist->time.get() == timeHis) {
582 std::unique_ptr<T0ClassicHistos> histos = std::make_unique<T0ClassicHistos>();
583 std::string histonametdc{}, histonameadc{};
587 if ((
int)(idtube / 100000000) == 9) {
588 int mezz = (idtube) % (900000000);
589 histonametdc = std::format(
"time_mezz_{:}", mezz);
590 histonameadc = std::format(
"charge_mezz_{:}", mezz);
591 }
else if (idtube == 0) {
592 histonametdc =
"time";
593 histonameadc =
"charge";
594 }
else if (idtube == 1) {
595 histonametdc =
"time_ML1";
596 histonameadc =
"charge_ML1";
597 }
else if (idtube == 2) {
598 histonametdc =
"time_ML2";
599 histonameadc =
"charge_ML2";
600 }
else if (idtube == 11) {
601 histonametdc =
"time_ML1_series1";
602 histonameadc =
"charge_ML1_series1";
603 }
else if (idtube == 12) {
604 histonametdc =
"time_ML1_series2";
605 histonameadc =
"charge_ML1_series2";
606 }
else if (idtube == 13) {
607 histonametdc =
"time_ML1_series3";
608 histonameadc =
"charge_ML1_series3";
609 }
else if (idtube == 21) {
610 histonametdc =
"time_ML2_series1";
611 histonameadc =
"charge_ML2_series1";
612 }
else if (idtube == 22) {
613 histonametdc =
"time_ML2_series2";
614 histonameadc =
"charge_ML2_series2";
615 }
else if (idtube == 23) {
616 histonametdc =
"time_ML2_series3";
617 histonameadc =
"charge_ML2_series3";
624 int tubeid = (nML * 1000) + (nL * 100) + nT;
628 histonametdc = std::format(
"time_{:}_{:}_{:}_{:}", stationName,
eta,
phi, tubeid);
629 histonameadc = std::format(
"charge_{:}_{:}_{:}_{:}", stationName,
eta,
phi, tubeid);
636 m_histos.emplace_back(std::move(histos));
649 m_result = std::make_unique<MdtTubeFitContainer>(*t0Input->
t0s());
650 m_result->setImplementation(
"T0CalibrationClassic");
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
Header file for AthHistogramAlgorithm.
Identifier channelID(int stationName, int stationEta, int stationPhi, int multilayer, int tubeLayer, int tube) const
Interface to pass calibration output during calibration.
IMdtCalibration(const std::string &name)
constructor, string used to identify the instance
virtual std::string name() const
returns name (region) of instance
std::shared_ptr< IMdtCalibrationOutput > MdtCalibOutputPtr
std::vector< std::shared_ptr< MuonCalibSegment > > MuonSegVec
A MuonCalibSegment is a reconstructed three dimensional track segment in the MuonSpectrometer.
std::shared_ptr< MdtCalibHitBase > MdtHitPtr
typedef for a collection of MdtCalibHitBase s
const MdtHitVec & mdtHOT() const
retrieve the full set of MdtCalibHitBase s assigned to this segment
Implements fixed identifiers not dependent upon Athena Identifier for internal use in the calibration...
int mdtMezzanine() const
Mdt specific: compute the mezzanine number.
static std::string stationNumberToFixedStationString(const int station)
int mdtTubeLayer() const
Mdt specific:
int mdtTube() const
Mdt specific:
bool isValid() const
check validity of the identifier.
std::string stationNameString() const
int mdtMultilayer() const
Mdt specific:
std::string m_name
calibration region name
int m_currentItnum
current iteration (always 1?)
std::unique_ptr< TFile > m_file
pointer to the histogram file
virtual MdtCalibOutputPtr analyseSegments(const MuonSegVec &segs) override
new interface function
bool handleSegment(MuonCalibSegment &seg)
fill tube spectra
virtual MdtCalibOutputPtr getResults() const override
void setInput(const IMdtCalibrationOutput *input) override
unused
void searchParams(TH1 *h, double *p, int np)
estimate initial parameters for time spectrum fit from the spectrum itself
const T0ClassicSettings * m_settings
pointer to the settings
std::unique_ptr< MdtTubeFitContainer > m_result
tube constants
bool converged() const
return m_converged (always false?)
TDirectory * m_regiondir
pointer to the ROOT directory
~T0CalibrationClassic()
destructor
std::vector< std::unique_ptr< T0ClassicHistos > > m_histos
vector of pointers to tube histograms
void doAdcFit(T0ClassicHistos &, MdtTubeFitContainer::SingleTubeFit &, MdtTubeFitContainer::SingleTubeCalib &)
fit adc spectrum
void doTimeFit(T0ClassicHistos &, MdtTubeFitContainer::SingleTubeFit &, MdtTubeFitContainer::SingleTubeCalib &)
fit time spectrum
T0ClassicHistos * getHistos(unsigned int idtube)
retrieve pointer for tube idtube histograms
bool m_converged
convergence status
T0CalibrationClassic(const std::string &name, const T0ClassicSettings *settings)
constructor
T0ClassicHistos * bookHistos(unsigned int idtube)
booking of histograms
bool analyse()
extract parameters from spectra
class for the communication of the results of T0 calibration algorithms
const MdtTubeFitContainer * t0s() const
Tube histograms used in T0 calibration.
std::unique_ptr< TH1 > adc
adc spectrum
std::unique_ptr< TH1 > time
time spectrum
Settings for the T0 calibration (histogram booking and fitting parameters).
double chi2(TH1 *h0, TH1 *h1)
IMessageSvc * getMessageSvc(bool quiet=false)
CscCalcPed - algorithm that finds the Cathode Strip Chamber pedestals from an RDO.
Double_t TimeSpectrum_func(Double_t *xx, Double_t *par)
float adcCal
quality flag for the SingleTubeCalib constants: 0 all ok, 1 no hits found, 2 too few hits,...
float t0
< relative t0 in chamber (ns)
std::array< float, 8 > par
std::array< float, 4 > adc_par
std::array< float, 36 > cov
int statistics
< number of hits used for the fit
std::array< float, 4 > adc_err