27 #include "messagefacility/MessageLogger/MessageLogger.h"
51 (
"GausFitCache_CCHitFinderAlg")
59 if(pset.has_key(
"MinSigInd"))
throw art::Exception(art::errors::Configuration)
60 <<
"CCHitFinderAlg: Using no-longer-valid fcl input: MinSigInd, MinSigCol, etc";
62 fMinPeak = pset.get<std::vector<float>>(
"MinPeak");
63 fMinRMS = pset.get<std::vector<float>>(
"MinRMS");
64 fMaxBumps = pset.get<
unsigned short>(
"MaxBumps");
67 fChiNorms = pset.get<std::vector< float > >(
"ChiNorms");
70 fStudyHits = pset.get<
bool>(
"StudyHits",
false);
72 fUWireRange = pset.get< std::vector< short >>(
"UWireRange");
73 fUTickRange = pset.get< std::vector< short >>(
"UTickRange");
74 fVWireRange = pset.get< std::vector< short >>(
"VWireRange");
75 fVTickRange = pset.get< std::vector< short >>(
"VTickRange");
76 fWWireRange = pset.get< std::vector< short >>(
"WWireRange");
77 fWTickRange = pset.get< std::vector< short >>(
"WTickRange");
79 if(
fMinPeak.size() != fMinRMS.size()) {
80 mf::LogError(
"CCTF")<<
"MinPeak size != MinRMS size";
89 <<
"CCHitFinder algorithm is currently hard-coded to support at most "
90 <<
MaxGaussians <<
" bumps per region of interest, but " << fMaxBumps
91 <<
" have been requested.\n"
93 <<
". If this is not acceptable, increase CCHitFinderAlg::MaxGaussians"
94 <<
" value and recompile.";
103 if(fUWireRange.size() != 2 || fUTickRange.size() != 2 ||
104 fVWireRange.size() != 2 || fVTickRange.size() != 2 ||
105 fWWireRange.size() != 2 || fWTickRange.size() != 2) {
106 mf::LogError(
"CCHF")<<
"Invalid vector size for StudyHits. Must be 2";
126 unsigned short maxticks = 1000;
127 float *
ticks =
new float[maxticks];
129 for(
unsigned short ii = 0; ii < maxticks; ++ii) {
132 float *signl =
new float[maxticks];
140 = art::ServiceHandle<lariov::ChannelStatusService const>()->GetProvider();
142 for(
size_t wireIter = 0; wireIter < Wires.size(); wireIter++){
165 mf::LogError(
"CCHF")<<
"MinPeak vector too small for plane "<<
thePlane;
179 std::vector<float> signal(theWire.
Signal());
181 unsigned short nabove = 0;
182 unsigned short tstart = 0;
183 unsigned short maxtime = signal.size() - 2;
185 unsigned short mintime = 3;
186 for(
unsigned short time = 3; time < maxtime; ++time) {
192 for(
unsigned short time = mintime; time < maxtime; ++time) {
194 if(nabove == 0) tstart = time;
198 if(nabove > minSamples) {
200 if(nabove > maxticks) mf::LogError(
"CCHitFinder")
201 <<
"Long RAT "<<nabove<<
" "<<maxticks
202 <<
" No signal on wire "<<
theWireNum<<
" after time "<<time;
203 if(nabove > maxticks)
break;
204 unsigned short npt = 0;
208 for(
unsigned short ii = tstart; ii < time; ++ii) {
209 signl[npt] = signal[ii];
210 adcsum += signl[npt];
211 if(signal[ii ] > signal[ii - 1] &&
212 signal[ii - 1] > signal[ii - 2] &&
213 signal[ii ] > signal[ii + 1] &&
214 signal[ii + 1] > signal[ii + 2])
bumps.push_back(npt);
223 StoreHits(tstart, npt, WireInfo, adcsum);
228 unsigned short nHitsFit =
bumps.size();
229 unsigned short nfit = 0;
232 bool HitStored =
false;
236 while(nHitsFit <= nMaxFit) {
238 FitNG(nHitsFit, npt, ticks, signl);
245 StoreHits(tstart, npt, WireInfo, adcsum);
254 if( !HitStored && npt < maxticks) {
257 StoreHits(tstart, npt, WireInfo, adcsum);
277 unsigned short npt,
float const*
ticks,
float const*signl,
278 std::array<double, 3>& params,
279 std::array<double, 3>& paramerrors,
287 const float time_shift = (ticks[npt - 1] + ticks[0]) / 2.
F;
290 for (
size_t i = 0; i < npt; ++i) {
292 MF_LOG_DEBUG(
"CCHitFinderAlg")
293 <<
"Non-positive charge encountered. Backing up to ROOT fit.";
297 fitter.
add(ticks[i] - time_shift, signl[i]);
303 MF_LOG_DEBUG(
"CCHitFinderAlg") <<
"Fast Gaussian fit failed.";
310 chidof = chi2 / fitter.
NDF();
313 params[1] += time_shift;
318 for (
double&
par: paramerrors)
par *= std::sqrt(chidof);
326 float *
ticks,
float *signl)
330 dof = npt - 3 * nGaus;
335 if(
bumps.size() == 0)
return;
338 std::vector<double> partmp;
339 std::vector<double> partmperr;
349 std::array<double, 3> params, paramerrors;
356 std::copy(params.begin(), params.end(), partmp.begin());
358 std::copy(paramerrors.begin(), paramerrors.end(), partmperr.begin());
360 else bNeedROOTfit =
true;
373 std::stringstream numConv;
374 std::string eqn =
"gaus";
375 if(nGaus > 1) eqn =
"gaus(0)";
376 for(
unsigned short ii = 3; ii < nGaus*3; ii+=3){
377 eqn.append(
" + gaus(");
380 eqn.append(numConv.str());
384 auto Gn = std::make_unique<TF1>(
"gn",eqn.c_str());
388 TGraph *fitn =
new TGraph(npt, ticks, signl);
394 for(
unsigned short ii = 0; ii <
bumps.size(); ++ii) {
395 unsigned short index = ii * 3;
396 unsigned short bumptime =
bumps[ii];
397 double amp = signl[bumptime];
398 Gn->SetParameter(index , amp);
399 Gn->SetParLimits(index, 0., 9999.);
400 Gn->SetParameter(index + 1, (
double)bumptime);
401 Gn->SetParLimits(index + 1, 0, (
double)npt);
403 Gn->SetParLimits(index + 2, 1., 3*(
double)
fMinRMS[thePlane]);
411 for(
unsigned short ii =
bumps.size(); ii < nGaus; ++ii) {
414 unsigned short imbig = 0;
415 for(
unsigned short jj = 0; jj < npt; ++jj) {
416 float diff = signl[jj] - Gn->Eval((Double_t)jj, 0, 0, 0);
428 unsigned short index = ii * 3;
429 Gn->SetParameter(index , (
double)big);
430 Gn->SetParLimits(index, 0., 9999.);
431 Gn->SetParameter(index + 1, (
double)imbig);
432 Gn->SetParLimits(index + 1, 0, (
double)npt);
434 Gn->SetParLimits(index + 2, 1., 5*(
double)
fMinRMS[thePlane]);
440 fitn->Fit(&*Gn,
"WNQB");
442 for(
unsigned short ipar = 0; ipar < 3 * nGaus; ++ipar) {
443 partmp.push_back(Gn->GetParameter(ipar));
444 partmperr.push_back(Gn->GetParError(ipar));
455 std::vector< std::pair<unsigned short, unsigned short> > times;
457 for(
unsigned short ii = 0; ii < nGaus; ++ii) {
458 unsigned short index = ii * 3;
459 times.push_back(std::make_pair(partmp[index + 1],ii));
461 std::sort(times.begin(), times.end());
464 for(
unsigned short ii = 0; ii < nGaus; ++ii) {
465 if(times[ii].
second != ii) {
472 std::vector<double> partmpt;
473 std::vector<double> partmperrt;
474 for(
unsigned short ii = 0; ii < nGaus; ++ii) {
475 unsigned short index = times[ii].second * 3;
476 partmpt.push_back(partmp[index]);
477 partmpt.push_back(partmp[index+1]);
478 partmpt.push_back(partmp[index+2]);
479 partmperrt.push_back(partmperr[index]);
480 partmperrt.push_back(partmperr[index+1]);
481 partmperrt.push_back(partmperr[index+2]);
484 partmperr = partmperrt;
500 for(
unsigned short ii = 0; ii < nGaus; ++ii) {
501 unsigned short index = ii * 3;
503 short fittime = partmp[index + 1];
504 if(fittime < 0 || fittime > npt - 1) {
514 float rms = partmp[index + 2];
515 if(rms < 0.5 *
fMinRMS[thePlane] || rms > 5 *
fMinRMS[thePlane]) {
520 for(
unsigned short jj = 0; jj < nGaus; ++jj) {
521 if(jj == ii)
continue;
522 unsigned short jndex = jj * 3;
523 float timediff =
std::abs(partmp[jndex + 1] - partmp[index + 1]);
546 float *
ticks,
float *signl)
551 for(
unsigned short ii = 0; ii < npt; ++ii) {
553 sumST += signl[ii] * ticks[ii];
555 float mean = sumST / sumS;
557 for(
unsigned short ii = 0; ii < npt; ++ii) {
558 float arg = ticks[ii] -
mean;
559 rms += signl[ii] * arg * arg;
561 rms = std::sqrt(rms / sumS);
562 float amp = sumS / (
Sqrt2Pi * rms);
574 float meanerr = std::sqrt(1/sumS);
575 float rmserr = 0.2 * rms;
577 parerr.push_back(meanerr);
593 size_t nhits =
par.size() / 3;
596 mf::LogError(
"CCHitFinder")
597 <<
"Too many hits: existing " <<
allhits.size() <<
" plus new " << nhits
598 <<
" beyond the maximum " <<
allhits.max_size();
602 if(nhits == 0)
return;
607 const float loTime = TStart;
608 const float hiTime = TStart + npt;
612 for(
size_t hit = 0;
hit < nhits; ++
hit) {
613 const unsigned short index = 3 *
hit;
616 for(
size_t hit = 0;
hit < nhits; ++
hit) {
617 const size_t index = 3 *
hit;
619 const float charge_err =
SqrtPi
620 * (
parerr[index] * par[index + 2] + par[index] *
parerr[index + 2]);
626 par[index + 1] + TStart,
631 adcsum * charge / gsum,
661 float *
ticks,
float *signl,
unsigned short tstart) {
677 for(
unsigned short ipl = 0; ipl < 3; ++ipl) {
733 for(
unsigned short ii = 0; ii < npt; ++ii) {
734 if(signl[ii] > big) {
758 for(
unsigned short ii = 0; ii < npt; ++ii) {
760 sumt += signl[ii] * ii;
762 float aveb = sumt / sum;
765 for(
unsigned short ii = 0; ii < npt; ++ii) {
766 float dbin = (float)ii - aveb;
767 sumt += signl[ii] * dbin * dbin;
777 if(
par.size() == 3) {
790 std::cout<<
"Check lo and hi W/T for each plane"<<std::endl;
791 for(
unsigned short ipl = 0; ipl < 3; ++ipl) {
795 std::cout<<
" ipl nRAT bCnt bChi bRMS hCnt hRMS dT/dW New_ChiNorm"<<std::endl;
796 for(
unsigned short ipl = 0; ipl < 3; ++ipl) {
805 <<std::setw(7)<<std::fixed<<std::setprecision(2)<<
bumpChi[ipl]
807 <<std::setw(7)<<
hitCnt[ipl]
808 <<std::setw(7)<<std::setprecision(1)<<
hitRMS[ipl]
810 <<std::setw(7)<<std::setprecision(2)
815 std::cout<<
"nRAT is the number of Regions Above Threshold (RAT) used in the study.\n";
816 std::cout<<
"bCnt is the number of single bumps that were successfully fitted \n";
817 std::cout<<
"bChi is the average chisq/DOF of the first fit\n";
818 std::cout<<
"bRMS is the average calculated RMS of the bumps\n";
819 std::cout<<
"hCnt is the number of RATs that have a single hit\n";
820 std::cout<<
"hRMS is the average RMS from the Gaussian fit -> use this value for fMinRMS[plane] in the fcl file\n";
821 std::cout<<
"dTdW is the slope of the track\n";
822 std::cout<<
"New_ChiNorm is the recommended values of ChiNorm that should be used in the fcl file\n";
839 if (nGaus == 0)
return;
847 ++MultiGausFits[std::min(nGaus, (
unsigned int) MultiGausFits.size()) - 1];
void RunCCHitFinder(std::vector< recob::Wire > const &Wires)
bool add(Data_t x, Data_t y, Data_t sy=Data_t(1.0))
void AddMultiGaus(unsigned int nGaus)
float fChiSplit
Estimated noise error on the Signal.
static constexpr float SqrtPi
void FitNG(unsigned short nGaus, unsigned short npt, float *ticks, float *signl)
virtual bool IsBad(raw::ChannelID_t channel) const =0
Returns whether the specified channel is bad in the current run.
exchange data about the originating wire
std::vector< short > fWTickRange
std::vector< short > fWWireRange
virtual void reconfigure(fhicl::ParameterSet const &pset)
raw::ChannelID_t theChannel
then echo unknown compiler flag
std::vector< float > loWire
void StoreHits(unsigned short TStart, unsigned short npt, HitChannelInfo_t info, float adcsum)
void StudyHits(unsigned short flag, unsigned short npt=0, float *ticks=0, float *signl=0, unsigned short tstart=0)
std::vector< float > hiWire
std::vector< unsigned short > bumps
std::vector< float > fChiNorms
std::vector< float > bumpRMS
std::vector< short > fUWireRange
bool fUseFastFit
whether to attempt using a fast fit on single gauss.
std::vector< short > fVWireRange
CCHitFinderAlg(fhicl::ParameterSet const &pset)
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
virtual Data_t ChiSquare() const override
Returns the of the original fit.
std::vector< short > fVTickRange
FitStats_t TriedFitStats
counts of the tried fits
SigType_t SignalType(geo::PlaneID const &pid) const
Returns the type of signal on the channels of specified TPC plane.
unsigned int FastFits
count of single-Gaussian fast fits
tick ticks
Alias for common language habits.
virtual bool FillResults(FitParameters_t ¶ms, FitMatrix_t &Xmat, Data_t &det, FitMatrix_t &Smat) const override
Fills the specified parameters.
Classes performing simple fits.
geo::View_t View() const
Returns the view the channel belongs to.
A set of TF1 linear sum of base functions (Gaussians)
std::vector< recob::Hit > allhits
raw::ChannelID_t Channel() const
Returns the ID of the channel (or InvalidChannelID)
MF_LOG_WARNING("SimWire")<< "SimWire is an example module that works for the "<< "MicroBooNE detector. Each experiment should implement "<< "its own version of this module to simulate electronics "<< "response."
void Reset(unsigned int nGaus)
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
"Fast" Gaussian fit
Class providing information about the quality of channels.
std::vector< float > hiTime
The geometry of one entire detector, as served by art.
std::vector< int > bumpCnt
std::vector< float > Signal() const
Return a zero-padded full length vector filled with RoI signal.
std::vector< float > loTime
static bool FastGaussianFit(unsigned short npt, float const *ticks, float const *signl, std::array< double, 3 > ¶ms, std::array< double, 3 > ¶merrors, float &chidof)
Performs a "fast" fit.
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
virtual int NDF() const override
Returns the degrees of freedom in the determination of the fit.
unsigned short theWireNum
std::vector< unsigned int > MultiGausFits
multi-Gaussian stats
std::vector< float > fMinPeak
Interface for experiment-specific channel quality info provider.
Class holding the regions of interest of signal from a channel.
std::vector< int > hitCnt
static constexpr unsigned int MaxGaussians
static constexpr float Sqrt2Pi
unsigned short fMaxXtraHits
std::vector< short > fUTickRange
void MakeCrudeHit(unsigned short npt, float *ticks, float *signl)
std::vector< float > hitRMS
Interface for experiment-specific service for channel quality info.
std::vector< int > RATCnt
FitStats_t FinalFitStats
counts of the good fits
std::vector< double > parerr
HitChannelInfo_t(recob::Wire const *w, geo::WireID wid, geo::Geometry const &geom)
std::vector< float > fMinRMS
std::vector< float > bumpChi
std::vector< double > par
art framework interface to geometry description
BEGIN_PROLOG could also be cout