File indexing completed on 2025-12-17 09:20:20
0001 #include "MbdSig.h"
0002 #include "MbdCalib.h"
0003
0004 #include <phool/phool.h>
0005
0006 #include <TF1.h>
0007 #include <TFile.h>
0008 #include <TGraphErrors.h>
0009 #include <TH2.h>
0010 #include <TMath.h>
0011 #include <TPad.h>
0012 #include <TSpectrum.h>
0013 #include <TSpline.h>
0014 #include <TTree.h>
0015
0016 #include <algorithm>
0017 #include <fstream>
0018 #include <iostream>
0019 #include <iomanip>
0020 #include <limits>
0021
0022 MbdSig::MbdSig(const int chnum, const int nsamp)
0023 : _ch{chnum}
0024 , _nsamples{nsamp}
0025 {
0026
0027 }
0028
0029 void MbdSig::Init()
0030 {
0031 TString name;
0032
0033 name = "hrawpulse";
0034 name += _ch;
0035 hRawPulse = new TH1F(name, name, _nsamples, -0.5, _nsamples - 0.5);
0036 name = "hsubpulse";
0037 name += _ch;
0038 hSubPulse = new TH1F(name, name, _nsamples, -0.5, _nsamples - 0.5);
0039
0040
0041 gRawPulse = new TGraphErrors();
0042 name = "grawpulse";
0043 name += _ch;
0044 gRawPulse->SetName(name);
0045
0046 gSubPulse = new TGraphErrors();
0047 name = "gsubpulse";
0048 name += _ch;
0049 gSubPulse->SetName(name);
0050 gSubPulse->GetHistogram()->SetXTitle("sample");
0051 gSubPulse->GetHistogram()->SetYTitle("ADC");
0052
0053 hpulse = hRawPulse;
0054 gpulse = gRawPulse;
0055
0056
0057 ped0stats = new MbdRunningStats(100);
0058 name = "hPed0_";
0059 name += _ch;
0060 hPed0 = new TH1F(name, name, 3000, -0.5, 2999.5);
0061
0062 name = "hPedEvt_";
0063 name += _ch;
0064 hPedEvt = new TH1F(name, name, 3000, -0.5, 2999.5);
0065
0066 SetTemplateSize(900, 1000, -10., 20.);
0067
0068
0069
0070 ped_fcn = new TF1("ped_fcn","[0]",0,2);
0071 ped_fcn->SetLineColor(3);
0072
0073
0074 ped_tail = new TF1("ped_tail","[0]+[1]*exp(-[2]*x)",0,2);
0075 ped_tail->SetLineColor(2);
0076
0077
0078
0079
0080
0081
0082 }
0083
0084 void MbdSig::SetTemplateSize(const Int_t nptsx, const Int_t nptsy, const Double_t begt, const Double_t endt)
0085 {
0086 template_npointsx = nptsx;
0087 template_npointsy = nptsy;
0088 template_begintime = begt;
0089 template_endtime = endt;
0090
0091 template_y.resize(template_npointsx);
0092 template_yrms.resize(template_npointsx);
0093
0094 Double_t xbinwid = (template_endtime - template_begintime) / (template_npointsx - 1);
0095 Double_t ybinwid = (1.1 + 0.1) / template_npointsy;
0096
0097
0098 delete h2Template;
0099
0100 delete h2Residuals;
0101
0102 TString name = "h2Template";
0103 name += _ch;
0104 h2Template = new TH2F(name, name, template_npointsx, template_begintime - (xbinwid / 2.), template_endtime + (xbinwid / 2),
0105 template_npointsy, -0.1 + (ybinwid / 2.0), 1.1 + (ybinwid / 2.0));
0106
0107 name = "h2Residuals";
0108 name += _ch;
0109 h2Residuals = new TH2F(name, name, template_npointsx, template_begintime - (xbinwid / 2.), template_endtime + (xbinwid / 2),
0110 80, -20, 20);
0111
0112
0113
0114
0115
0116
0117
0118
0119 }
0120
0121 void MbdSig::SetMinMaxFitTime(const Double_t mintime, const Double_t maxtime)
0122 {
0123 fit_min_time = mintime;
0124 fit_max_time = maxtime;
0125 }
0126
0127 MbdSig::~MbdSig()
0128 {
0129 if ( _pileupfile )
0130 {
0131 _pileupfile->close();
0132 }
0133 delete hRawPulse;
0134 delete hSubPulse;
0135 delete gRawPulse;
0136 delete gSubPulse;
0137 delete hPed0;
0138 delete ped0stats;
0139
0140 delete h2Template;
0141 delete h2Residuals;
0142 delete hAmpl;
0143 delete hTime;
0144 delete template_fcn;
0145 delete ped_fcn;
0146 delete ped_tail;
0147 }
0148
0149 void MbdSig::SetEventPed0PreSamp(const Int_t presample, const Int_t nsamps, const int max_samp)
0150 {
0151 ped_presamp = presample;
0152 ped_presamp_nsamps = nsamps;
0153 if ( ped_presamp_nsamps < 0 && max_samp > 0 )
0154 {
0155 ped_presamp_nsamps = max_samp - presample + 1;
0156 }
0157 ped_presamp_maxsamp = max_samp;
0158 }
0159
0160 void MbdSig::SetCalib(MbdCalib *m)
0161 {
0162 _mbdcal = m;
0163 _pileup_p0 = m->get_pileup(_ch,0);
0164 _pileup_p1 = m->get_pileup(_ch,1);
0165 _pileup_p2 = m->get_pileup(_ch,2);
0166 }
0167
0168
0169 void MbdSig::SetY(const Float_t* y, const int invert)
0170 {
0171 if (hRawPulse == nullptr)
0172 {
0173 Init();
0174 }
0175
0176 hpulse->Reset();
0177 f_ampl = -9999.;
0178 f_time = -9999.;
0179
0180 for (int isamp = 0; isamp < _nsamples; isamp++)
0181 {
0182 hRawPulse->SetBinContent(isamp + 1, y[isamp]);
0183 gRawPulse->SetPoint(isamp, Double_t(isamp), y[isamp]);
0184 }
0185
0186
0187 if (use_ped0 != 0 || minped0samp >= 0 || minped0x != maxped0x || ped_presamp != 0)
0188 {
0189
0190
0191 int ispileup = 0;
0192
0193
0194
0195 if (minped0samp >= 0)
0196 {
0197 CalcEventPed0(minped0samp, maxped0samp);
0198 }
0199 else if (minped0x != maxped0x)
0200 {
0201 CalcEventPed0(minped0x, maxped0x);
0202 }
0203 else if (ped_presamp != 0)
0204 {
0205 ispileup = CalcEventPed0_PreSamp(ped_presamp, ped_presamp_nsamps);
0206 }
0207
0208 for (int isamp = 0; isamp < _nsamples; isamp++)
0209 {
0210 hSubPulse->SetBinContent(isamp + 1, invert * (y[isamp] - ped0));
0211 hSubPulse->SetBinError(isamp + 1, ped0rms);
0212 gSubPulse->SetPoint(isamp, (Double_t) isamp, invert * (y[isamp] - ped0));
0213 gSubPulse->SetPointError(isamp, 0., ped0rms);
0214 }
0215
0216 if ( ispileup==1 && !std::isnan(_pileup_p0) )
0217 {
0218 Remove_Pileup();
0219 }
0220 }
0221
0222 _evt_counter++;
0223 }
0224
0225 void MbdSig::SetXY(const Float_t* x, const Float_t* y, const int invert)
0226 {
0227
0228 if (hRawPulse == nullptr)
0229 {
0230 Init();
0231 }
0232
0233 hRawPulse->Reset();
0234 hSubPulse->Reset();
0235 _status = 0;
0236
0237 f_ampl = -9999.;
0238 f_time = -9999.;
0239
0240
0241
0242
0243 for (int isamp = 0; isamp < _nsamples; isamp++)
0244 {
0245
0246 hRawPulse->SetBinContent(isamp + 1, y[isamp]);
0247 gRawPulse->SetPoint(isamp, x[isamp], y[isamp]);
0248 gRawPulse->SetPointError(isamp, 0, 4.0);
0249 }
0250 if ( _verbose && _ch==9 )
0251 {
0252 gRawPulse->Draw("ap");
0253 gRawPulse->GetHistogram()->SetTitle(gRawPulse->GetName());
0254 gPad->SetGridy(1);
0255 PadUpdate();
0256 }
0257
0258 if (use_ped0 != 0 || minped0samp >= 0 || minped0x != maxped0x || ped_presamp != 0)
0259 {
0260 int ispileup = 0;
0261
0262
0263
0264 if (minped0samp >= 0)
0265 {
0266 CalcEventPed0(minped0samp, maxped0samp);
0267 }
0268 else if (minped0x != maxped0x)
0269 {
0270 CalcEventPed0(minped0x, maxped0x);
0271 }
0272 else if (ped_presamp != 0)
0273 {
0274 ispileup = CalcEventPed0_PreSamp(ped_presamp, ped_presamp_nsamps);
0275 }
0276
0277 for (int isamp = 0; isamp < _nsamples; isamp++)
0278 {
0279 if ( _verbose && isamp==(_nsamples-1) )
0280 {
0281 std::cout << "bbb ch " << _ch << "\t" << isamp << "\t" << x[isamp] << "\t" << invert*(y[isamp]-ped0) << std::endl;
0282 }
0283 hSubPulse->SetBinContent(isamp + 1, invert * (y[isamp] - ped0));
0284 hSubPulse->SetBinError(isamp + 1, ped0rms);
0285 gSubPulse->SetPoint(isamp, x[isamp], invert * (y[isamp] - ped0));
0286 gSubPulse->SetPointError(isamp, 0., ped0rms);
0287 }
0288
0289 if ( ispileup==1 )
0290 {
0291 Remove_Pileup();
0292 }
0293
0294 if ( _verbose && _ch==9 )
0295 {
0296 std::cout << "SetXY: ch " << _ch << std::endl;
0297 gSubPulse->Print("ALL");
0298 }
0299 }
0300
0301 _evt_counter++;
0302 _verbose = 0;
0303 }
0304
0305 void MbdSig::Remove_Pileup()
0306 {
0307
0308 _verbose = 0;
0309
0310
0311
0312
0313
0314
0315
0316
0317 if ( _verbose )
0318 {
0319 std::cout << PHWHERE << " evt ch " << _evt_counter << "\t" << _ch << std::endl;
0320 }
0321
0322 if ( (_ch/8)%2 == 0 )
0323 {
0324 float offset = _pileup_p0*gSubPulse->GetPointY(0);
0325
0326 for (int isamp = 0; isamp < _nsamples; isamp++)
0327 {
0328 double x = gSubPulse->GetPointX(isamp);
0329 double y = gSubPulse->GetPointY(isamp);
0330
0331 hSubPulse->SetBinContent( isamp + 1, y - offset );
0332 gSubPulse->SetPoint( isamp, x, y - offset );
0333 }
0334 }
0335 else
0336 {
0337 if ( fit_pileup == nullptr )
0338 {
0339 TString name = "fit_pileup"; name += _ch;
0340 fit_pileup = new TF1(name,"gaus",-0.1,4.1);
0341 fit_pileup->SetLineColor(2);
0342 }
0343
0344 fit_pileup->SetRange(-0.1,4.1);
0345 fit_pileup->SetParameters( _pileup_p0*gSubPulse->GetPointY(0), _pileup_p1, _pileup_p2 );
0346
0347
0348 double plow{0.};
0349 double phigh{0.};
0350 fit_pileup->GetParLimits(2,plow,phigh);
0351 if ( phigh < _pileup_p2 )
0352 {
0353 phigh = 2*_pileup_p2;
0354 fit_pileup->SetParLimits(2,plow,phigh);
0355 }
0356
0357 if ( _verbose )
0358 {
0359 gSubPulse->Fit( fit_pileup, "R" );
0360 gSubPulse->Draw("ap");
0361 PadUpdate();
0362 }
0363 else
0364 {
0365 gSubPulse->Fit( fit_pileup, "RNQ" );
0366 }
0367
0368 for (int isamp = 0; isamp < _nsamples; isamp++)
0369 {
0370
0371 double bkg = fit_pileup->Eval(isamp);
0372
0373 double x = gSubPulse->GetPointX(isamp);
0374 double y = gSubPulse->GetPointY(isamp);
0375
0376 float newval = static_cast<float>( y - bkg );
0377
0378 hSubPulse->SetBinContent( isamp + 1, newval );
0379 gSubPulse->SetPoint( isamp, x, newval );
0380 }
0381 }
0382
0383 if ( _verbose )
0384 {
0385 gSubPulse->Draw("ap");
0386 PadUpdate();
0387 }
0388
0389 _verbose = 0;
0390 }
0391
0392 Double_t MbdSig::GetSplineAmpl()
0393 {
0394 if (gSubPulse == nullptr)
0395 {
0396 std::cout << "gsub bad " << (uint64_t) gSubPulse << std::endl;
0397 return 0.;
0398 }
0399
0400 TSpline3 s3("s3", gSubPulse);
0401
0402
0403 f_ampl = -999999.;
0404 double step_size = 0.01;
0405
0406 for (double ix = 0; ix < _nsamples; ix += step_size)
0407 {
0408 Double_t val = s3.Eval(ix);
0409 f_ampl = std::max(val, f_ampl);
0410 }
0411
0412 return f_ampl;
0413 }
0414
0415 void MbdSig::WritePedHist()
0416 {
0417 hPed0->Write();
0418 }
0419
0420 void MbdSig::FillPed0(const Int_t sampmin, const Int_t sampmax)
0421 {
0422 Double_t x;
0423 Double_t y;
0424 for (int isamp = sampmin; isamp <= sampmax; isamp++)
0425 {
0426 gRawPulse->GetPoint(isamp, x, y);
0427
0428 hPed0->Fill(y);
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439 }
0440 }
0441
0442 void MbdSig::FillPed0(const Double_t begin, const Double_t end)
0443 {
0444 Double_t x;
0445 Double_t y;
0446 Int_t n = gRawPulse->GetN();
0447 for (int isamp = 0; isamp < n; isamp++)
0448 {
0449 gRawPulse->GetPoint(isamp, x, y);
0450 if (x >= begin && x <= end)
0451 {
0452 hPed0->Fill(y);
0453
0454
0455
0456
0457
0458
0459
0460
0461 }
0462
0463
0464 if (x > end)
0465 {
0466 break;
0467 }
0468 }
0469 }
0470
0471 void MbdSig::SetPed0(const Double_t mean, const Double_t rms)
0472 {
0473 ped0 = mean;
0474 ped0rms = rms;
0475 use_ped0 = 1;
0476 hpulse = hSubPulse;
0477 gpulse = gSubPulse;
0478
0479 }
0480
0481
0482 void MbdSig::CalcEventPed0(const Int_t minpedsamp, const Int_t maxpedsamp)
0483 {
0484
0485 hPedEvt->Reset();
0486
0487 Double_t x;
0488 Double_t y;
0489 for (int isamp = minpedsamp; isamp <= maxpedsamp; isamp++)
0490 {
0491 gRawPulse->GetPoint(isamp, x, y);
0492
0493 hPed0->Fill(y);
0494 hPedEvt->Fill(y);
0495
0496
0497 }
0498
0499
0500
0501 float mean = hPedEvt->GetMean();
0502 float rms = hPedEvt->GetRMS();
0503
0504 SetPed0(mean, rms);
0505
0506 }
0507
0508
0509 void MbdSig::CalcEventPed0(const Double_t minpedx, const Double_t maxpedx)
0510 {
0511 hPedEvt->Reset();
0512
0513 Double_t x;
0514 Double_t y;
0515 Int_t n = gRawPulse->GetN();
0516
0517 for (int isamp = 0; isamp < n; isamp++)
0518 {
0519 gRawPulse->GetPoint(isamp, x, y);
0520
0521 if (x >= minpedx && x <= maxpedx)
0522 {
0523 hPed0->Fill(y);
0524 hPedEvt->Fill(y);
0525
0526 }
0527 }
0528
0529
0530
0531 SetPed0(hPedEvt->GetMean(), hPedEvt->GetRMS());
0532 }
0533
0534
0535
0536
0537
0538 int MbdSig::CalcEventPed0_PreSamp(const int presample, const int nsamps)
0539 {
0540
0541
0542
0543
0544 int status = 0;
0545
0546
0547
0548 Long64_t max = ped_presamp_maxsamp;
0549
0550
0551 Long64_t actual_max = TMath::LocMax(gRawPulse->GetN(), gRawPulse->GetY());
0552
0553 if ( ped_presamp_maxsamp == -1 )
0554 {
0555 max = actual_max;
0556 }
0557
0558 Int_t minsamp = max - presample - nsamps + 1;
0559 Int_t maxsamp = max - presample;
0560
0561
0562 if (minsamp < 0)
0563 {
0564 static int counter = 0;
0565 if ( counter<1 )
0566 {
0567 std::cout << PHWHERE << " ped minsamp " << minsamp << "\t" << max << "\t" << presample << "\t" << nsamps << std::endl;
0568 counter++;
0569 }
0570 minsamp = 0;
0571 }
0572 if (maxsamp < 0)
0573 {
0574 static int counter = 0;
0575 if ( counter<1 )
0576 {
0577 std::cout << PHWHERE << " ped maxsamp " << maxsamp << "\t" << max << "\t" << presample << std::endl;
0578 counter++;
0579 }
0580 maxsamp = minsamp;
0581 }
0582
0583 if ( _verbose )
0584 {
0585 std::cout << "CalcEventPed0_Presamp(), ch " << _ch << std::endl;
0586 }
0587
0588 double mean = ped0stats->Mean();
0589
0590 double rms = _mbdcal->get_pedrms(_ch);
0591 if ( std::isnan(rms) )
0592 {
0593
0594 rms = 5.0;
0595 }
0596
0597 ped_fcn->SetRange(minsamp-0.1,maxsamp+0.1);
0598 ped_fcn->SetParameter(0,1500.);
0599
0600 if ( gRawPulse->GetN()==0 )
0601 {
0602 std::cout << PHWHERE << " gRawPulse 0" << std::endl;
0603 }
0604
0605 if ( _verbose )
0606 {
0607 gRawPulse->Fit( ped_fcn, "RQ" );
0608
0609 double chi2ndf = ped_fcn->GetChisquare()/ped_fcn->GetNDF();
0610 if ( chi2ndf > 4.0 )
0611 {
0612 gRawPulse->Draw("ap");
0613 ped_fcn->Draw("same");
0614 PadUpdate();
0615 }
0616 }
0617 else
0618 {
0619
0620 gRawPulse->Fit( ped_fcn, "RNQ" );
0621
0622 double chi2ndf = ped_fcn->GetChisquare()/ped_fcn->GetNDF();
0623 if ( _pileupfile != nullptr && chi2ndf > 4.0 )
0624 {
0625 *_pileupfile << "ped " << _ch << " mean " << mean << "\t";
0626 for ( int i=0; i<gRawPulse->GetN(); i++)
0627 {
0628 *_pileupfile << std::setw(6) << gRawPulse->GetPointY(i);
0629 }
0630 *_pileupfile << std::endl;
0631 }
0632 }
0633
0634 double chi2 = ped_fcn->GetChisquare();
0635 double ndf = ped_fcn->GetNDF();
0636
0637 if ( chi2/ndf < 4.0 )
0638 {
0639 mean = ped_fcn->GetParameter(0);
0640
0641 Double_t x;
0642 Double_t y;
0643
0644 for (int isamp = minsamp; isamp <= maxsamp; isamp++)
0645 {
0646 gRawPulse->GetPoint(isamp, x, y);
0647
0648
0649 if ( fabs(y-mean) < 4.0*rms )
0650 {
0651 ped0stats->Push( y );
0652 }
0653
0654 if ( _verbose )
0655 {
0656 std::cout << "CalcEventPed0_PreSamp: ped0stats " << _ch << "\t" << _evt_counter << "\t"
0657 << "isamp " << isamp << "\t" << x << "\t" << y << std::endl;
0658 }
0659 }
0660 }
0661 else
0662 {
0663
0664
0665 status = 1;
0666
0667 if ( ped0stats->Size() < ped0stats->MaxNum() && !std::isnan(_mbdcal->get_ped(_ch)) )
0668 {
0669 mean = _mbdcal->get_ped(_ch);
0670 }
0671 else
0672 {
0673 mean = ped0stats->Mean();
0674
0675 if ( _verbose )
0676 {
0677 gRawPulse->Draw("ap");
0678 PadUpdate();
0679
0680 if ( _evt_counter<100 )
0681 {
0682 double ped0statsrms = ped0stats->RMS();
0683 std::cout << "aaa ch " << _ch << "\t" << _evt_counter << "\t" << mean << "\t" << ped0statsrms << std::endl;
0684 }
0685 std::string junk;
0686 std::cin >> junk;
0687 }
0688 }
0689
0690
0691
0692
0693
0694
0695 }
0696
0697 SetPed0(mean, rms);
0698
0699 if (_verbose > 0 && _evt_counter < 10)
0700 {
0701 std::cout << "CalcEventPed0_PreSamp: ped0stats " << _ch << "\t" << _evt_counter << "\t" << mean << "\t" << rms << std::endl;
0702 std::cout << "CalcEventPed0_PreSamp: ped0stats " << ped0stats->RMS() << std::endl;
0703 }
0704
0705 _verbose = 0;
0706
0707 return status;
0708 }
0709
0710 Double_t MbdSig::LeadingEdge(const Double_t threshold)
0711 {
0712
0713
0714
0715 int n = gSubPulse->GetN();
0716 Double_t* x = gSubPulse->GetX();
0717 Double_t* y = gSubPulse->GetY();
0718
0719 int sample = -1;
0720 for (int isamp = 0; isamp < n; isamp++)
0721 {
0722 if (y[isamp] > threshold)
0723 {
0724 if (isamp == (n - 1) || y[isamp + 1] > threshold)
0725 {
0726 sample = isamp;
0727 break;
0728 }
0729 }
0730 }
0731 if (sample < 1)
0732 {
0733 return -9999.;
0734 }
0735
0736
0737 Double_t dx = x[sample] - x[sample - 1];
0738 Double_t dy = y[sample] - y[sample - 1];
0739 Double_t dt1 = y[sample] - threshold;
0740
0741 Double_t t0 = x[sample] - (dt1 * (dx / dy));
0742
0743 return t0;
0744 }
0745
0746 Double_t MbdSig::dCFD(const Double_t fraction_threshold)
0747 {
0748
0749
0750
0751 int n = gSubPulse->GetN();
0752 Double_t* x = gSubPulse->GetX();
0753 Double_t* y = gSubPulse->GetY();
0754
0755
0756 Double_t ymax = TMath::MaxElement(n, y);
0757 if (f_ampl == -9999.)
0758 {
0759 f_ampl = ymax;
0760 }
0761
0762 Double_t threshold = fraction_threshold * ymax;
0763
0764
0765 int sample = -1;
0766 for (int isamp = 0; isamp < n; isamp++)
0767 {
0768 if (y[isamp] > threshold)
0769 {
0770 if (isamp == (n - 1) || y[isamp + 1] > threshold)
0771 {
0772 sample = isamp;
0773 break;
0774 }
0775 }
0776 }
0777 if (sample < 1)
0778 {
0779 return -9999.;
0780 }
0781
0782
0783 Double_t dx = x[sample] - x[sample - 1];
0784 Double_t dy = y[sample] - y[sample - 1];
0785 Double_t dt1 = y[sample] - threshold;
0786
0787 Double_t t0 = x[sample] - (dt1 * (dx / dy));
0788
0789 return t0;
0790 }
0791
0792 Double_t MbdSig::MBDTDC(const Int_t max_samp)
0793 {
0794
0795
0796 Double_t* y = gSubPulse->GetY();
0797
0798 if (y == nullptr)
0799 {
0800 std::cout << "ERROR y == 0" << std::endl;
0801 return std::numeric_limits<Double_t>::quiet_NaN();
0802 }
0803
0804 f_time = y[max_samp];
0805
0806 if ( y[2]>100. )
0807 {
0808 f_time = 0.;
0809 }
0810
0811
0812
0813
0814
0815
0816
0817
0818
0819 return f_time;
0820 }
0821
0822 Double_t MbdSig::Integral(const Double_t xmin, const Double_t xmax)
0823 {
0824 Int_t n = gSubPulse->GetN();
0825 Double_t* x = gSubPulse->GetX();
0826 Double_t* y = gSubPulse->GetY();
0827
0828 f_integral = 0.;
0829 for (int ix = 0; ix < n; ix++)
0830 {
0831 if (x[ix] >= xmin && x[ix] <= xmax)
0832 {
0833
0834 Double_t dx = (x[ix + 1] - x[ix - 1]) / 2.0;
0835 f_integral += (y[ix] * dx);
0836 }
0837 }
0838
0839 return f_integral;
0840 }
0841
0842 void MbdSig::LocMax(Double_t& x_at_max, Double_t& ymax, Double_t xminrange, Double_t xmaxrange)
0843 {
0844 _verbose = 0;
0845 if ( _verbose && _ch==250 )
0846 {
0847 gSubPulse->Draw("ap");
0848 gPad->Modified();
0849 gPad->Update();
0850 }
0851
0852
0853 Int_t n = gSubPulse->GetN();
0854 Double_t* x = gSubPulse->GetX();
0855 Double_t* y = gSubPulse->GetY();
0856
0857
0858 if (xmaxrange <= xminrange)
0859 {
0860 xminrange = -DBL_MAX;
0861 xmaxrange = DBL_MAX;
0862 }
0863
0864 x_at_max = -DBL_MAX;
0865 ymax = -DBL_MAX;
0866
0867 for (int i = 0; i < n; i++)
0868 {
0869
0870 if (x[i] < xminrange)
0871 {
0872 continue;
0873 }
0874 if (x[i] > xmaxrange)
0875 {
0876 break;
0877 }
0878
0879 if (y[i] > ymax)
0880 {
0881 ymax = y[i];
0882 x_at_max = x[i];
0883 }
0884 }
0885
0886 if ( _verbose )
0887 {
0888 std::string junk;
0889 std::cin >> junk;
0890 std::cout << "MbdSig::LocMax, " << x_at_max << "\t" << ymax << std::endl;
0891 _verbose = 0;
0892 }
0893 }
0894
0895 void MbdSig::LocMin(Double_t& x_at_min, Double_t& ymin, Double_t xminrange, Double_t xmaxrange)
0896 {
0897
0898 Int_t n = gSubPulse->GetN();
0899 Double_t* x = gSubPulse->GetX();
0900 Double_t* y = gSubPulse->GetY();
0901
0902
0903 if (xmaxrange <= xminrange)
0904 {
0905 xminrange = -DBL_MAX;
0906 xmaxrange = DBL_MAX;
0907 }
0908
0909 ymin = DBL_MAX;
0910
0911 for (int i = 0; i < n; i++)
0912 {
0913
0914 if (x[i] < xminrange)
0915 {
0916 continue;
0917 }
0918 if (x[i] > xmaxrange)
0919 {
0920 break;
0921 }
0922
0923 if (y[i] < ymin)
0924 {
0925 ymin = y[i];
0926 x_at_min = x[i];
0927 }
0928 }
0929
0930
0931
0932 }
0933
0934 void MbdSig::Print()
0935 {
0936 Double_t x;
0937 Double_t y;
0938 std::cout << "CH " << _ch << std::endl;
0939 for (int isamp = 0; isamp < _nsamples; isamp++)
0940 {
0941 gpulse->GetPoint(isamp, x, y);
0942 std::cout << isamp << "\t" << x << "\t" << y << std::endl;
0943 }
0944 }
0945
0946 void MbdSig::DrawWaveform()
0947 {
0948 int orig_verbose = _verbose;
0949 if ( _verbose <= 5 )
0950 {
0951 _verbose = 6;
0952 }
0953
0954 gSubPulse->Draw("ap");
0955 gSubPulse->GetHistogram()->SetTitle(gSubPulse->GetName());
0956 gPad->SetGridy(1);
0957 if ( template_fcn!=nullptr )
0958 {
0959 template_fcn->Draw("same");
0960 }
0961 PadUpdate();
0962
0963 _verbose = orig_verbose;
0964 }
0965
0966 void MbdSig::PadUpdate() const
0967 {
0968
0969 std::cout << PHWHERE << " PadUpdate\t_verbose = " << _verbose << std::endl;
0970 if ( _verbose>5 )
0971 {
0972 gPad->Modified();
0973 gPad->Update();
0974 std::cout << _ch << " ? ";
0975 if ( _verbose>10 )
0976 {
0977 std::string junk;
0978 std::cin >> junk;
0979
0980 if (junk[0] == 'w' || junk[0] == 's')
0981 {
0982 TString name = "ch";
0983 name += _ch;
0984 name += ".png";
0985 gPad->SaveAs(name);
0986 }
0987 }
0988 }
0989 }
0990
0991 Double_t MbdSig::TemplateFcn(const Double_t* x, const Double_t* par)
0992 {
0993
0994
0995
0996 Double_t xx = x[0] - par[1];
0997 Double_t f = 0.;
0998
0999 int verbose = 0;
1000 if ( verbose )
1001 {
1002 std::cout << PHWHERE << " " << _ch << " x par0 par1 " << x[0] << "\t" << par[0] << "\t" << par[1] << std::endl;
1003 }
1004
1005
1006
1007 if (xx < template_begintime || xx > template_endtime || std::isnan(xx) )
1008 {
1009 TF1::RejectPoint();
1010
1011 if ( std::isnan(xx) )
1012 {
1013 if (verbose > 0)
1014 {
1015 std::cout << PHWHERE << " " << _evt_counter << ", " << _ch
1016 << " ERROR x par0 par1 " << x[0] << "\t" << par[0] << "\t" << par[1] << std::endl;
1017 if ( x[0] == 0. )
1018 {
1019 gSubPulse->Print("ALL");
1020 }
1021 }
1022 return 0.;
1023 }
1024
1025 if (xx < template_begintime)
1026 {
1027
1028 Double_t y0 = template_y[0];
1029 return par[0] * y0;
1030 }
1031 if (xx > template_endtime)
1032 {
1033
1034 Double_t y0 = template_y[template_npointsx - 1];
1035 return par[0] * y0;
1036 }
1037 }
1038
1039
1040 Double_t x0 = 0.;
1041 Double_t y0 = 0.;
1042 Double_t x1 = 0.;
1043 Double_t y1 = 0.;
1044
1045
1046 Double_t step = (template_endtime - template_begintime) / (template_npointsx - 1);
1047 Double_t index = (xx - template_begintime) / step;
1048
1049
1050 int ilow = TMath::FloorNint(index);
1051 int ihigh = TMath::CeilNint(index);
1052 if (ilow < 0 || ihigh >= template_npointsx)
1053 {
1054 if (verbose > 0)
1055 {
1056 std::cout << "ERROR, ilow ihigh " << ilow << "\t" << ihigh << std::endl;
1057 std::cout << " " << xx << " " << x[0] << " " << par[1] << std::endl;
1058 }
1059
1060 if (ilow < 0)
1061 {
1062 ilow = 0;
1063 }
1064 else if (ihigh >= template_npointsx)
1065 {
1066 ihigh = template_npointsx - 1;
1067 }
1068 }
1069
1070 if (ilow == ihigh)
1071 {
1072 f = par[0] * template_y[ilow];
1073 }
1074 else
1075 {
1076 x0 = template_begintime + ilow * step;
1077 y0 = template_y[ilow];
1078 x1 = template_begintime + ihigh * step;
1079 y1 = template_y[ihigh];
1080 f = par[0] * (y0 + ((y1 - y0) / (x1 - x0)) * (xx - x0));
1081 }
1082
1083
1084 if (template_yrms[ilow] >= 1.0 || template_yrms[ihigh] >= 1.0)
1085 {
1086 TF1::RejectPoint();
1087
1088 }
1089
1090
1091 int samp_point = static_cast<int>(x[0]);
1092 Double_t temp_x;
1093 Double_t temp_y;
1094 gRawPulse->GetPoint(samp_point, temp_x, temp_y);
1095 if (temp_y > 16370)
1096 {
1097
1098 TF1::RejectPoint();
1099 }
1100
1101
1102 return f;
1103 }
1104
1105
1106 int MbdSig::FitTemplate( const Int_t sampmax )
1107 {
1108
1109
1110
1111
1112
1113 if (gSubPulse->GetN() == 0)
1114 {
1115 f_ampl = 0.;
1116 f_time = std::numeric_limits<Float_t>::quiet_NaN();
1117 std::cout << "ERROR, gSubPulse empty" << std::endl;
1118 return 1;
1119 }
1120
1121
1122 Double_t *rawsamps = gRawPulse->GetY();
1123 Int_t nrawsamps = gRawPulse->GetN();
1124 int nsaturated = 0;
1125 for (int ipt=0; ipt<nrawsamps; ipt++)
1126 {
1127 if ( rawsamps[ipt] > 16370. )
1128 {
1129 nsaturated++;
1130 }
1131 }
1132
1133
1134
1135
1136
1137
1138
1139
1140 if (_verbose > 0)
1141 {
1142 std::cout << "Fitting ch " << _ch << std::endl;
1143 }
1144
1145
1146 Double_t x_at_max{-1.};
1147 Double_t ymax{0.};
1148 if ( sampmax>=0 )
1149 {
1150 gSubPulse->GetPoint(sampmax, x_at_max, ymax);
1151 if ( nsaturated<=3 )
1152 {
1153 x_at_max -= 2.0;
1154 }
1155 else
1156 {
1157 x_at_max -= 1.5;
1158 ymax = 16370.+nsaturated*2000.;
1159 }
1160 }
1161 else
1162 {
1163 ymax = TMath::MaxElement( gSubPulse->GetN(), gSubPulse->GetY() );
1164 x_at_max = TMath::LocMax( gSubPulse->GetN(), gSubPulse->GetY() );
1165 }
1166
1167
1168 if ( ymax < 20. )
1169 {
1170 f_ampl = 0.;
1171 f_time = std::numeric_limits<Float_t>::quiet_NaN();
1172 if ( _verbose>20 )
1173 {
1174
1175 std::cout << "skipping, ymax < 20" << std::endl;
1176 gSubPulse->Draw("ap");
1177 gSubPulse->GetHistogram()->SetTitle(gSubPulse->GetName());
1178 gPad->SetGridy(1);
1179 PadUpdate();
1180 }
1181
1182 _verbose = 0;
1183 return 1;
1184 }
1185
1186 template_fcn->SetParameters(ymax, x_at_max);
1187
1188
1189
1190 if ( nsaturated<=3 )
1191 {
1192 template_fcn->SetRange(0, _nsamples);
1193 }
1194 else
1195 {
1196 template_fcn->SetRange(0, sampmax + nsaturated - 0.5);
1197 }
1198
1199 if ( gSubPulse->GetN()==0 )
1200 {
1201 std::cout << PHWHERE << " gSubPulse 0" << std::endl;
1202 }
1203
1204 if (_verbose == 0)
1205 {
1206
1207 gSubPulse->Fit(template_fcn, "RNQ");
1208 }
1209 else
1210 {
1211 std::cout << "doing fit1 " << x_at_max << "\t" << ymax << std::endl;
1212 gSubPulse->Fit(template_fcn, "R");
1213 gSubPulse->Draw("ap");
1214 gSubPulse->GetHistogram()->SetTitle(gSubPulse->GetName());
1215 gPad->SetGridy(1);
1216 PadUpdate();
1217
1218
1219
1220 }
1221
1222
1223 f_ampl = template_fcn->GetParameter(0);
1224 f_time = template_fcn->GetParameter(1);
1225 if ( f_time<0. || f_time>_nsamples )
1226 {
1227 f_time = _nsamples*0.5;
1228 }
1229
1230
1231 template_fcn->SetParameters( f_ampl, f_time );
1232 if ( nsaturated<=3 )
1233 {
1234 template_fcn->SetRange( 0., f_time+4.0 );
1235 }
1236 else
1237 {
1238 template_fcn->SetRange( 0., f_time+nsaturated+0.8 );
1239 }
1240
1241 if (_verbose == 0)
1242 {
1243
1244 int fit_status = gSubPulse->Fit(template_fcn, "RNQ");
1245 if ( fit_status<0 )
1246 {
1247 std::cout << PHWHERE << "\t" << fit_status << std::endl;
1248 gSubPulse->Print("ALL");
1249 gSubPulse->Draw("ap");
1250 gSubPulse->Fit(template_fcn, "R");
1251 std::cout << "ampl time before refit " << f_ampl << "\t" << f_time << std::endl;
1252 f_ampl = template_fcn->GetParameter(0);
1253 f_time = template_fcn->GetParameter(1);
1254 std::cout << "ampl time after refit " << f_ampl << "\t" << f_time << std::endl;
1255 PadUpdate();
1256 std::string junk;
1257 std::cin >> junk;
1258 }
1259 }
1260 else
1261 {
1262 gSubPulse->Fit(template_fcn, "R");
1263
1264 std::cout << "ampl time before refit " << f_ampl << "\t" << f_time << std::endl;
1265 f_ampl = template_fcn->GetParameter(0);
1266 f_time = template_fcn->GetParameter(1);
1267 std::cout << "ampl time after refit " << f_ampl << "\t" << f_time << std::endl;
1268 }
1269
1270 f_ampl = template_fcn->GetParameter(0);
1271 f_time = template_fcn->GetParameter(1);
1272
1273
1274
1275
1276
1277
1278 if (_verbose > 0 && fabs(f_ampl) > 0.)
1279 {
1280 _verbose = 12;
1281 std::cout << "FitTemplate " << _ch << "\t" << f_ampl << "\t" << f_time << std::endl;
1282 std::cout << " " << template_fcn->GetChisquare()/template_fcn->GetNDF() << std::endl;
1283 gSubPulse->Draw("ap");
1284 gSubPulse->GetHistogram()->SetTitle(gSubPulse->GetName());
1285 gPad->SetGridy(1);
1286 template_fcn->SetLineColor(4);
1287 template_fcn->Draw("same");
1288 PadUpdate();
1289 }
1290
1291 _verbose = 0;
1292 return 1;
1293 }
1294
1295 int MbdSig::SetTemplate(const std::vector<float>& shape, const std::vector<float>& sherr)
1296 {
1297 template_y = shape;
1298 template_yrms = sherr;
1299
1300 if (_verbose)
1301 {
1302 std::cout << "SHAPE " << _ch << "\t" << template_y.size() << std::endl;
1303 for (size_t i = 0; i < template_y.size(); i++)
1304 {
1305 if (i % 10 == 0)
1306 {
1307 std::cout << i << ":\t" << std::endl;
1308 }
1309 std::cout << " " << template_y[i];
1310 }
1311 std::cout << std::endl;
1312 }
1313
1314 if (template_fcn == nullptr)
1315 {
1316 TString name = "template_fcn";
1317 name += _ch;
1318
1319
1320 template_fcn = new TF1(name, this, &MbdSig::TemplateFcn, 0, _nsamples, 2, "MbdSig", "TemplateFcn");
1321 template_fcn->SetParameters(1, 10);
1322 template_fcn->SetParName(0, "ampl");
1323 template_fcn->SetParName(1, "time");
1324 SetTemplateSize(900, 1000, -10., 20.);
1325
1326 if (_verbose)
1327 {
1328 std::cout << "SHAPE " << _ch << std::endl;
1329 template_fcn->Draw("acp");
1330 gPad->Modified();
1331 gPad->Update();
1332 }
1333 }
1334
1335 return 1;
1336 }