16 #include "art/Framework/Core/ModuleMacros.h"
17 #include "art/Framework/Principal/Event.h"
18 #include "art/Framework/Core/EDProducer.h"
19 #include "canvas/Persistency/Common/FindOneP.h"
20 #include "art/Framework/Services/Registry/ServiceHandle.h"
21 #include "messagefacility/MessageLogger/MessageLogger.h"
32 #include "TDecompSVD.h"
64 fCalDataModuleLabel = pset.get< std::string >(
"CalDataModuleLabel");
65 fMinSigInd = pset.get<
double >(
"MinSigInd");
66 fMinSigCol = pset.get<
double >(
"MinSigCol");
67 fIndWidth = pset.get<
double >(
"IndWidth");
68 fColWidth = pset.get<
double >(
"ColWidth");
69 fIndMinWidth = pset.get<
double >(
"IndMinWidth");
70 fColMinWidth = pset.get<
double >(
"ColMinWidth");
73 fAreaNorms = pset.get< std::vector< double > >(
"AreaNorms");
94 art::Handle< std::vector<recob::Wire> > wireVecHandle;
96 art::ServiceHandle<geo::Geometry const> geom;
99 art::FindOneP<raw::RawDigit> WireToRawDigits
102 std::vector<int> startTimes;
103 std::vector<int> maxTimes;
104 std::vector<int> endTimes;
106 int minTimeHolder = 0;
108 bool maxFound =
false;
109 double threshold = 0.;
110 double fitWidth = 0.;
111 double minWidth = 0.;
112 std::string eqn =
"gaus(0)";
114 std::stringstream numConv;
118 for(
unsigned int wireIter = 0; wireIter < wireVecHandle->size(); wireIter++) {
120 art::Ptr<recob::Wire> wire(wireVecHandle, wireIter);
124 std::vector<float> signal(wire->Signal());
125 std::vector<float>::iterator timeIter;
129 channel = wire->Channel();
130 sigType = geom->SignalType(channel);
144 for(timeIter = signal.begin(); timeIter+2 < signal.end(); timeIter++){
146 if(*timeIter > *(timeIter+1) && *(timeIter+1) < *(timeIter+2)){
149 endTimes.push_back(time+1);
152 minTimeHolder = time+2;
154 else minTimeHolder = time+1;
158 else if(*timeIter < *(timeIter+1) &&
159 *(timeIter+1) > *(timeIter+2) &&
160 *(timeIter+1) > threshold){
162 maxTimes.push_back(time+1);
163 startTimes.push_back(minTimeHolder);
170 while(maxTimes.size()>endTimes.size())
171 endTimes.push_back(signal.size()-1);
172 if(startTimes.size() == 0)
continue;
183 double amplitude(0), position(0), width(0);
184 double amplitudeErr(0), positionErr(0), widthErr(0);
185 double goodnessOfFit(0), chargeErr(0);
186 double minPeakHeight(0);
190 std::vector<double> hitSig;
193 while(hitIndex < (
signed)startTimes.size()) {
197 minPeakHeight = signal[maxTimes[hitIndex]];
204 while(numHits < fMaxMultiHit &&
205 numHits+hitIndex < (
signed)endTimes.size() &&
206 signal[endTimes[hitIndex+numHits-1]] >threshold/2.0 &&
207 startTimes[hitIndex+numHits] - endTimes[hitIndex+numHits-1] < 2){
209 if(signal[maxTimes[hitIndex+numHits]] < minPeakHeight)
210 minPeakHeight = signal[maxTimes[hitIndex+numHits]];
216 startT = startTimes[hitIndex];
218 while(signal[(
int)startT] < minPeakHeight/2.0) ++startT;
221 endT = endTimes[hitIndex+numHits-1];
223 while(signal[(
int)endT] <minPeakHeight/2.0) --endT;
224 size = (int)(endT-startT);
225 TH1D hitSignal(
"hitSignal",
"",size,startT,endT);
226 for(
int i = (
int)startT; i < (int)endT; ++i)
227 hitSignal.Fill(i,signal[i]);
232 for(
int i = 3; i < numHits*3; i+=3) {
233 eqn.append(
"+gaus(");
236 eqn.append(numConv.str());
240 TF1 gSum(
"gSum",eqn.c_str(),0,
size);
243 TArrayD data(numHits*numHits);
244 TVectorD amps(numHits);
245 for(
int i = 0; i < numHits; ++i) {
246 amps[i] = signal[maxTimes[hitIndex+i]];
247 for(
int j = 0; j < numHits;j++)
248 data[i+numHits*j] = TMath::Gaus(maxTimes[hitIndex+j],
249 maxTimes[hitIndex+i],
256 TMatrixD
h(numHits,numHits);
257 h.Use(numHits,numHits,data.GetArray());
262 mf::LogInfo(
"FFTHitFinder")<<
"TDcompSVD failed";
267 for(
int i = 0; i < numHits; ++i) {
271 if(amps[i] > 0 ) amplitude = amps[i];
272 else amplitude = 0.5*(threshold+signal[maxTimes[hitIndex+i]]);
273 gSum.SetParameter(3*i,amplitude);
274 gSum.SetParameter(1+3*i, maxTimes[hitIndex+i]);
275 gSum.SetParameter(2+3*i, fitWidth);
276 gSum.SetParLimits(3*i, 0.0, 3.0*amplitude);
277 gSum.SetParLimits(1+3*i, startT , endT);
278 gSum.SetParLimits(2+3*i, 0.0, 10.0*fitWidth);
282 gSum.SetParameters(signal[maxTimes[hitIndex]],maxTimes[hitIndex],fitWidth);
283 gSum.SetParLimits(0,0.0,1.5*signal[maxTimes[hitIndex]]);
284 gSum.SetParLimits(1, startT , endT);
285 gSum.SetParLimits(2,0.0,10.0*fitWidth);
289 hitSignal.Fit(&gSum,
"QNRW",
"", startT, endT);
290 for(
int hitNumber = 0; hitNumber < numHits; ++hitNumber) {
292 if(gSum.GetParameter(3*hitNumber) > threshold/2.0 &&
293 gSum.GetParameter(3*hitNumber+2) > minWidth) {
294 amplitude = gSum.GetParameter(3*hitNumber);
295 position = gSum.GetParameter(3*hitNumber+1);
296 width = gSum.GetParameter(3*hitNumber+2);
297 amplitudeErr = gSum.GetParError(3*hitNumber);
298 positionErr = gSum.GetParError(3*hitNumber+1);
299 widthErr = gSum.GetParError(3*hitNumber+2);
300 goodnessOfFit = gSum.GetChisquare()/(double)gSum.GetNDF();
301 int DoF = gSum.GetNDF();
304 chargeErr = std::sqrt(TMath::Pi())*(amplitudeErr*width+widthErr*amplitude);
308 for(
int sigPos = 0; sigPos <
size; ++sigPos){
309 hitSig[sigPos] = amplitude*TMath::Gaus(sigPos+startT,position, width);
310 totSig += hitSig[(int)sigPos];
314 totSig = std::sqrt(2*TMath::Pi())*amplitude*width/fAreaNorms[(size_t)sigType];
317 std::vector<geo::WireID> wids = geom->ChannelToWire(channel);
336 (signal.begin() + (int) startT, signal.begin() + (int) endT, 0.),
345 art::Ptr<raw::RawDigit> rawdigits = WireToRawDigits.at(wireIter);
double fIndMinWidth
Minimum induction hit width.
FFTHitFinder(fhicl::ParameterSet const &pset)
double fMinSigInd
Induction signal height threshold.
fMaxMultiHit(pset.get< int >("MaxMultiHit"))
double fIndWidth
Initial width for induction fit.
std::size_t size(FixedBins< T, C > const &) noexcept
int fMaxMultiHit
maximum hits for multi fit
double fColWidth
Initial width for collection fit.
static void declare_products(art::ProducesCollector &collector, std::string instance_name="", bool doWireAssns=true, bool doRawDigitAssns=true)
Declares the hit products we are going to fill.
std::vector< double > fAreaNorms
factors for converting area to same units as peak height
Class managing the creation of a new recob::Hit object.
Helper functions to create a hit.
std::string fCalDataModuleLabel
constexpr ChannelID_t InvalidChannelID
ID of an invalid channel.
A class handling a collection of hits and its associations.
Signal from induction planes.
enum geo::_plane_sigtype SigType_t
double fColMinWidth
Minimum collection hit width.
void emplace_back(recob::Hit &&hit, art::Ptr< recob::Wire > const &wire=art::Ptr< recob::Wire >(), art::Ptr< raw::RawDigit > const &digits=art::Ptr< raw::RawDigit >())
Adds the specified hit to the data collection.
void produce(art::Event &evt) override
Definition of data types for geometry description.
void put_into(art::Event &)
Moves the data into an event.
double fMinSigCol
Collection signal height threshold.
Declaration of basic channel signal object.
fAreaMethod(pset.get< int >("AreaMethod"))
int fAreaMethod
Type of area calculation.
unsigned int ChannelID_t
Type representing the ID of a readout channel.
art framework interface to geometry description
Signal from collection planes.