31 #include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h" 32 #include "larevt/CalibrationDBI/Interface/ChannelStatusService.h" 49 (
"GausFitCache_CCHitFinderAlg"))
58 <<
"CCHitFinderAlg: Using no-longer-valid fcl input: MinSigInd, MinSigCol, etc";
61 fMinRMS = pset.
get<std::vector<float>>(
"MinRMS");
77 if (
fMinPeak.size() != fMinRMS.size()) {
87 <<
"CCHitFinder algorithm is currently hard-coded to support at most " <<
MaxGaussians 88 <<
" bumps per region of interest, but " << fMaxBumps <<
" have been requested.\n" 90 <<
". If this is not acceptable, increase CCHitFinderAlg::MaxGaussians" 91 <<
" value and recompile.";
100 if (fUWireRange.size() != 2 || fUTickRange.size() != 2 || fVWireRange.size() != 2 ||
101 fVTickRange.size() != 2 || fWWireRange.size() != 2 || fWTickRange.size() != 2) {
102 mf::LogError(
"CCHF") <<
"Invalid vector size for StudyHits. Must be 2";
112 : wire(w), wireID(wid), sigType(geom.SignalType(w->Channel()))
121 unsigned short maxticks = 1000;
122 float*
ticks =
new float[maxticks];
124 for (
unsigned short ii = 0; ii < maxticks; ++ii) {
127 float* signl =
new float[maxticks];
134 lariov::ChannelStatusProvider
const& channelStatus =
137 for (
size_t wireIter = 0; wireIter < Wires.size(); wireIter++) {
142 if (channelStatus.IsBad(
theChannel))
continue;
174 std::vector<float> signal(theWire.
Signal());
176 unsigned short nabove = 0;
177 unsigned short tstart = 0;
178 unsigned short maxtime = signal.size() - 2;
180 unsigned short mintime = 3;
181 for (
unsigned short time = 3; time < maxtime; ++time) {
187 for (
unsigned short time = mintime; time < maxtime; ++time) {
189 if (nabove == 0) tstart = time;
194 if (nabove > minSamples) {
196 if (nabove > maxticks)
198 <<
"Long RAT " << nabove <<
" " << maxticks <<
" No signal on wire " <<
theWireNum 199 <<
" after time " << time;
200 if (nabove > maxticks)
break;
201 unsigned short npt = 0;
205 for (
unsigned short ii = tstart; ii < time; ++ii) {
206 signl[npt] = signal[ii];
207 adcsum += signl[npt];
208 if (signal[ii] > signal[ii - 1] && signal[ii - 1] > signal[ii - 2] &&
209 signal[ii] > signal[ii + 1] && signal[ii + 1] > signal[ii + 2])
210 bumps.push_back(npt);
219 StoreHits(tstart, npt, WireInfo, adcsum);
224 unsigned short nHitsFit =
bumps.size();
225 unsigned short nfit = 0;
228 bool HitStored =
false;
232 while (nHitsFit <= nMaxFit) {
234 FitNG(nHitsFit, npt, ticks, signl);
241 StoreHits(tstart, npt, WireInfo, adcsum);
250 if (!HitStored && npt < maxticks) {
253 StoreHits(tstart, npt, WireInfo, adcsum);
255 else if (nHitsFit > 0)
275 std::array<double, 3>& params,
276 std::array<double, 3>& paramerrors,
284 const float time_shift = (ticks[npt - 1] + ticks[0]) / 2.F;
287 for (
size_t i = 0; i < npt; ++i) {
290 <<
"Non-positive charge encountered. Backing up to ROOT fit.";
294 fitter.
add(ticks[i] - time_shift, signl[i]);
300 MF_LOG_DEBUG(
"CCHitFinderAlg") <<
"Fast Gaussian fit failed.";
307 chidof = chi2 / fitter.
NDF();
310 params[1] += time_shift;
315 for (
double&
par : paramerrors)
316 par *= std::sqrt(chidof);
326 dof = npt - 3 * nGaus;
331 if (
bumps.size() == 0)
return;
334 std::vector<double> partmp;
335 std::vector<double> partmperr;
345 std::array<double, 3> params, paramerrors;
352 std::copy(params.begin(), params.end(), partmp.begin());
354 std::copy(paramerrors.begin(), paramerrors.end(), partmperr.begin());
370 std::stringstream numConv;
371 std::string eqn =
"gaus";
372 if (nGaus > 1) eqn =
"gaus(0)";
373 for (
unsigned short ii = 3; ii < nGaus * 3; ii += 3) {
374 eqn.append(
" + gaus(");
377 eqn.append(numConv.str());
381 auto Gn = std::make_unique<TF1>(
"gn", eqn.c_str());
385 TGraph* fitn =
new TGraph(npt, ticks, signl);
391 for (
unsigned short ii = 0; ii <
bumps.size(); ++ii) {
392 unsigned short index = ii * 3;
393 unsigned short bumptime =
bumps[ii];
394 double amp = signl[bumptime];
395 Gn->SetParameter(index, amp);
396 Gn->SetParLimits(index, 0., 9999.);
397 Gn->SetParameter(index + 1, (
double)bumptime);
398 Gn->SetParLimits(index + 1, 0, (
double)npt);
400 Gn->SetParLimits(index + 2, 1., 3 * (
double)
fMinRMS[thePlane]);
408 for (
unsigned short ii =
bumps.size(); ii < nGaus; ++ii) {
411 unsigned short imbig = 0;
412 for (
unsigned short jj = 0; jj < npt; ++jj) {
413 float diff = signl[jj] - Gn->Eval((Double_t)jj, 0, 0, 0);
425 unsigned short index = ii * 3;
426 Gn->SetParameter(index, (
double)big);
427 Gn->SetParLimits(index, 0., 9999.);
428 Gn->SetParameter(index + 1, (
double)imbig);
429 Gn->SetParLimits(index + 1, 0, (
double)npt);
431 Gn->SetParLimits(index + 2, 1., 5 * (
double)
fMinRMS[thePlane]);
437 fitn->Fit(&*Gn,
"WNQB");
439 for (
unsigned short ipar = 0; ipar < 3 * nGaus; ++ipar) {
440 partmp.push_back(Gn->GetParameter(ipar));
441 partmperr.push_back(Gn->GetParError(ipar));
452 std::vector<std::pair<unsigned short, unsigned short>> times;
454 for (
unsigned short ii = 0; ii < nGaus; ++ii) {
455 unsigned short index = ii * 3;
456 times.push_back(std::make_pair(partmp[index + 1], ii));
458 std::sort(times.begin(), times.end());
461 for (
unsigned short ii = 0; ii < nGaus; ++ii) {
462 if (times[ii].
second != ii) {
469 std::vector<double> partmpt;
470 std::vector<double> partmperrt;
471 for (
unsigned short ii = 0; ii < nGaus; ++ii) {
472 unsigned short index = times[ii].second * 3;
473 partmpt.push_back(partmp[index]);
474 partmpt.push_back(partmp[index + 1]);
475 partmpt.push_back(partmp[index + 2]);
476 partmperrt.push_back(partmperr[index]);
477 partmperrt.push_back(partmperr[index + 1]);
478 partmperrt.push_back(partmperr[index + 2]);
481 partmperr = partmperrt;
497 for (
unsigned short ii = 0; ii < nGaus; ++ii) {
498 unsigned short index = ii * 3;
500 short fittime = partmp[index + 1];
501 if (fittime < 0 || fittime > npt - 1) {
511 float rms = partmp[index + 2];
512 if (rms < 0.5 *
fMinRMS[thePlane] || rms > 5 *
fMinRMS[thePlane]) {
517 for (
unsigned short jj = 0; jj < nGaus; ++jj) {
518 if (jj == ii)
continue;
519 unsigned short jndex = jj * 3;
520 float timediff =
std::abs(partmp[jndex + 1] - partmp[index + 1]);
548 for (
unsigned short ii = 0; ii < npt; ++ii) {
550 sumST += signl[ii] * ticks[ii];
552 float mean = sumST / sumS;
554 for (
unsigned short ii = 0; ii < npt; ++ii) {
555 float arg = ticks[ii] -
mean;
556 rms += signl[ii] * arg * arg;
558 rms = std::sqrt(rms / sumS);
559 float amp = sumS / (
Sqrt2Pi * rms);
571 float meanerr = std::sqrt(1 / sumS);
572 float rmserr = 0.2 * rms;
574 parerr.push_back(meanerr);
591 size_t nhits =
par.size() / 3;
594 mf::LogError(
"CCHitFinder") <<
"Too many hits: existing " <<
allhits.size() <<
" plus new " 595 << nhits <<
" beyond the maximum " <<
allhits.max_size();
599 if (nhits == 0)
return;
604 const float loTime = TStart;
605 const float hiTime = TStart + npt;
609 for (
size_t hit = 0;
hit < nhits; ++
hit) {
610 const unsigned short index = 3 *
hit;
613 for (
size_t hit = 0;
hit < nhits; ++
hit) {
614 const size_t index = 3 *
hit;
616 const float charge_err =
622 par[index + 1] + TStart,
627 adcsum * charge / gsum,
658 unsigned short tstart)
675 for (
unsigned short ipl = 0; ipl < 3; ++ipl) {
731 for (
unsigned short ii = 0; ii < npt; ++ii) {
732 if (signl[ii] > big) {
756 for (
unsigned short ii = 0; ii < npt; ++ii) {
758 sumt += signl[ii] * ii;
760 float aveb = sumt /
sum;
763 for (
unsigned short ii = 0; ii < npt; ++ii) {
764 float dbin = (float)ii - aveb;
765 sumt += signl[ii] * dbin * dbin;
775 if (
par.size() == 3) {
787 std::cout <<
"Check lo and hi W/T for each plane" << std::endl;
788 for (
unsigned short ipl = 0; ipl < 3; ++ipl) {
789 std::cout << ipl <<
" lo " <<
loWire[ipl] <<
" " <<
loTime[ipl] <<
" hi " <<
hiWire[ipl]
790 <<
" " <<
hiTime[ipl] << std::endl;
792 std::cout <<
" ipl nRAT bCnt bChi bRMS hCnt hRMS dT/dW New_ChiNorm" << std::endl;
793 for (
unsigned short ipl = 0; ipl < 3; ++ipl) {
800 std::cout << ipl <<
std::right << std::setw(5) <<
RATCnt[ipl] << std::setw(5)
801 <<
bumpCnt[ipl] << std::setw(7) << std::fixed << std::setprecision(2)
803 << std::setw(7) << std::setprecision(1) <<
hitRMS[ipl] << std::setw(7) << dTdW
808 std::cout <<
"nRAT is the number of Regions Above Threshold (RAT) used in the study.\n";
809 std::cout <<
"bCnt is the number of single bumps that were successfully fitted \n";
810 std::cout <<
"bChi is the average chisq/DOF of the first fit\n";
811 std::cout <<
"bRMS is the average calculated RMS of the bumps\n";
812 std::cout <<
"hCnt is the number of RATs that have a single hit\n";
813 std::cout <<
"hRMS is the average RMS from the Gaussian fit -> use this value for " 814 "fMinRMS[plane] in the fcl file\n";
815 std::cout <<
"dTdW is the slope of the track\n";
817 <<
"New_ChiNorm is the recommended values of ChiNorm that should be used in the fcl file\n";
834 if (nGaus == 0)
return;
835 MultiGausFits.resize(nGaus);
836 std::fill(MultiGausFits.begin(), MultiGausFits.end(), 0);
842 ++MultiGausFits[std::min(nGaus, (
unsigned int)MultiGausFits.size()) - 1];
void RunCCHitFinder(std::vector< recob::Wire > const &Wires)
std::vector< short > fWTickRange
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
bool add(Data_t x, Data_t y, Data_t sy=Data_t(1.0))
Clears all the input statistics.
void AddMultiGaus(unsigned int nGaus)
float fChiSplit
Estimated noise error on the Signal.
static constexpr float SqrtPi
art::ServiceHandle< geo::Geometry const > geom
std::vector< WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
void FitNG(unsigned short nGaus, unsigned short npt, float *ticks, float *signl)
exchange data about the originating wire
virtual void reconfigure(fhicl::ParameterSet const &pset)
raw::ChannelID_t theChannel
std::vector< float > loWire
void StoreHits(unsigned short TStart, unsigned short npt, HitChannelInfo_t info, float adcsum)
std::vector< float > hiWire
std::vector< unsigned short > bumps
std::vector< float > fChiNorms
std::vector< float > bumpRMS
bool fUseFastFit
whether to attempt using a fast fit on single gauss.
constexpr auto abs(T v)
Returns the absolute value of the argument.
CCHitFinderAlg(fhicl::ParameterSet const &pset)
FitStats_t TriedFitStats
counts of the tried fits
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
tick ticks
Alias for common language habits.
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)
virtual bool FillResults(FitParameters_t ¶ms, FitMatrix_t &Xmat, Data_t &det, FitMatrix_t &Smat) const override
Fills the specified parameters.
std::vector< short > fUTickRange
std::vector< recob::Hit > allhits
raw::ChannelID_t Channel() const
Returns the ID of the channel (or InvalidChannelID)
T get(std::string const &key) const
void Reset(unsigned int nGaus)
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
std::vector< float > hiTime
std::vector< short > fUWireRange
virtual int NDF() const override
Returns the degrees of freedom in the determination of the fit.
bool has_key(std::string const &key) const
The geometry of one entire detector, as served by art.
std::vector< int > bumpCnt
Detector simulation of raw signals on wires.
std::vector< float > Signal() const
Return a zero-padded full length vector filled with RoI signal.
std::vector< float > loTime
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
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)
void StudyHits(unsigned short flag, unsigned short npt=0, float *signl=nullptr, unsigned short tstart=0)
std::vector< short > fWWireRange
unsigned short theWireNum
std::vector< float > fMinPeak
Class holding the regions of interest of signal from a channel.
std::vector< int > hitCnt
static constexpr unsigned int MaxGaussians
static constexpr float Sqrt2Pi
std::vector< short > fVWireRange
std::vector< short > fVTickRange
virtual Data_t ChiSquare() const override
Returns the of the original fit.
unsigned short fMaxXtraHits
void MakeCrudeHit(unsigned short npt, float *ticks, float *signl)
std::vector< float > hitRMS
#define MF_LOG_WARNING(category)
std::vector< int > RATCnt
second_as<> second
Type of time stored in seconds, in double precision.
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