10 #include "art/Framework/Core/EDProducer.h"
11 #include "art/Framework/Core/ModuleMacros.h"
12 #include "art/Framework/Principal/Event.h"
13 #include "art/Framework/Principal/Handle.h"
14 #include "art/Framework/Principal/Run.h"
15 #include "art/Framework/Principal/SubRun.h"
16 #include "canvas/Utilities/InputTag.h"
17 #include "fhiclcpp/ParameterSet.h"
18 #include "messagefacility/MessageLogger/MessageLogger.h"
19 #include "canvas/Utilities/Exception.h"
20 #include "canvas/Utilities/InputTag.h"
21 #include "art/Framework/Services/Registry/ServiceHandle.h"
22 #include "art_root_io/TFileService.h"
52 class opHitFinderSBND;
54 class opHitFinderSBND :
public art::EDProducer {
67 void produce(art::Event &
e)
override;
98 double& Area,
double& amplitude,
100 void denoise(std::vector<double>& waveform, std::vector<double>& outwaveform);
102 std::vector<double>& outwaveform,
105 unsigned int width,
const double lambda);
113 fInputModuleName =
p.get< std::string >(
"InputModule" );
114 fBaselineSample =
p.get<
int >(
"BaselineSample");
115 fSaturation =
p.get<
double >(
"Saturation" );
116 fArea1pePMT =
p.get<
double >(
"Area1pePMT" );
117 fArea1peSiPM =
p.get<
double >(
"Area1peSiPM" );
118 fThresholdPMT =
p.get<
double >(
"ThresholdPMT" );
119 fThresholdArapuca =
p.get<
double>(
"ThresholdArapuca");
120 fPulsePolarityPMT =
p.get<
int >(
"PulsePolarityPMT");
121 fPulsePolarityArapuca =
p.get<
int>(
"PulsePolarityArapuca");
122 fUseDenoising =
p.get<
bool >(
"UseDenoising");
124 auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
125 fSampling = clockData.OpticalClock().Frequency();
126 fSampling_Daphne =
p.get<
double>(
"DaphneFrequency");
129 produces<std::vector<recob::OpHit>>();
136 mf::LogInfo(
"opHitFinder") <<
"Event #" <<
fEvNumber;
138 std::unique_ptr< std::vector< recob::OpHit > > pulseVecPtr(std::make_unique< std::vector< recob::OpHit > > ());
142 art::ServiceHandle<art::TFileService>
tfs;
143 art::Handle< std::vector< raw::OpDetWaveform > > wvfHandle;
144 std::vector<art::Ptr<raw::OpDetWaveform>> wvfList;
146 art::fill_ptr_vector(wvfList, wvfHandle);
148 if(!wvfHandle.isValid()) {
149 mf::LogWarning(
"opHitFinder") << Form(
"Did not find any waveform");
153 double FWHM = 1, Area = 0, phelec, fasttotal = 3./4., rms = 0, amplitude = 0, time = 0;
154 unsigned short frame = 1;
156 for(
auto const& wvf_P : wvfList) {
157 auto const& wvf = *wvf_P;
158 if (wvf.size() == 0 ) {
159 mf::LogInfo(
"opHitFinder") <<
"Empty waveform, continue.";
173 mf::LogWarning(
"opHitFinder") <<
"Unexpected OpChannel: " <<
opdetType;
178 for(
unsigned int i = 0; i < wvf.size(); i++) {
191 mf::LogInfo(
"opHitFinder") <<
"Unexpected OpChannel: " <<
opdetType
192 <<
", continue." << std::endl;
200 else time = wvf.TimeStamp() + (double)timebin /
fSampling;
209 mf::LogWarning(
"opHitFinder") <<
"Unexpected OpChannel: " <<
opdetType
216 pulseVecPtr->emplace_back(opHit);
219 e.put(std::move(pulseVecPtr));
227 std::
string pdtype,
std::
string electronicsType,
double& rms)
232 double NBins=fBaselineSample;
233 if (electronicsType==
"daphne") NBins/=(fSampling/fSampling_Daphne);
237 for(
int i = 0; i < NBins; i++) {
238 baseline += waveform[i];
239 rms += std::pow(waveform[i], 2);
243 baseline = baseline / cnt;
244 rms = sqrt(rms / cnt - baseline * baseline);
245 rms = rms / sqrt(cnt - 1);
247 if(pdtype ==
"pmt_coated" || pdtype ==
"pmt_uncoated") {
248 for(
unsigned int i = 0; i < waveform.size(); i++) waveform[i] = fPulsePolarityPMT * (waveform[i] - baseline);
250 else if((opdetType ==
"xarapuca_vuv") || (opdetType ==
"xarapuca_vis")) {
251 for(
unsigned int i = 0; i < waveform.size(); i++) waveform[i] = fPulsePolarityArapuca * (waveform[i] - baseline);
254 mf::LogWarning(
"opHitFinder") <<
"Unexpected OpChannel: " << opdetType;
262 size_t& timebin,
double& Area,
263 double& amplitude,
const int& threshold,
264 const std::string& opdetType,
265 const std::string& electronicsType)
268 std::vector<double>::iterator max_element_it = std::max_element(waveform.begin(), waveform.end());
269 amplitude = *max_element_it;
270 if(amplitude < threshold)
return false;
275 auto it_e = std::find_if(max_element_it,
281 auto it_s = std::find_if(std::make_reverse_iterator(max_element_it),
282 std::make_reverse_iterator(waveform.begin()),
283 [threshold](
const double&
x)->bool
290 Area = std::accumulate(it_s, it_e, 0.0);
291 if (electronicsType ==
"daphne"){
306 int wavelength = waveform.size();
307 outwaveform = waveform;
309 const uint retries = 5; uint try_ = 0;
310 if (wavelength > 0) {
311 while (try_ <= retries) {
314 mf::LogInfo(
"opHitFinder") << try_ <<
"/" << retries
315 <<
" Coming out of TV1D_denoise() unsuccessfully, "
316 <<
"using lambda: " <<
lambda;
318 if (try_ == retries) mf::LogWarning(
"opHitFinder") <<
"Couldn't denoise!";
325 for(
int i = 0; i < wavelength; i++) {
326 if(outwaveform[i]) waveform[i] = outwaveform[i];
332 std::vector<double>& outwaveform,
335 int width = waveform.size();
338 double vmin = waveform[0] -
lambda, vmax = waveform[0] +
lambda;
340 const double twolambda = 2.0 *
lambda;
341 const double minlambda = -
lambda;
343 while (k == width - 1) {
345 do outwaveform[k0++] = vmin;
while (k0 <=
kminus);
346 umax = (vmin = waveform[
kminus = k = k0]) + (umin = lambda) - vmax;
348 else if (umax > 0.0) {
349 do outwaveform[k0++] = vmax;
while (k0 <= kplus);
350 umin = (vmax = waveform[kplus = k = k0]) + (umax = minlambda) - vmin;
353 vmin += umin / (k - k0 + 1);
354 do outwaveform[k0++] = vmin;
while(k0 <= k);
358 if ((umin += waveform[k + 1] - vmin) < minlambda) {
359 if (k0 > width)
return false;
360 do outwaveform[k0++] = vmin;
while (k0 <=
kminus);
361 vmax = (vmin = waveform[kplus =
kminus = k = k0]) + twolambda;
362 umin =
lambda; umax = minlambda;
364 else if ((umax += waveform[k + 1] - vmax) >
lambda) {
365 if (k0 > width)
return false;
366 do outwaveform[k0++] = vmax;
while (k0 <= kplus);
367 vmin = (vmax = waveform[kplus =
kminus = k = k0]) - twolambda;
368 umin =
lambda; umax = minlambda;
372 if (k > width)
return false;
373 if (umin >= lambda) {
377 if (umax <= minlambda) {
378 vmax += (umax +
lambda) / ((kplus = k) - k0 + 1);
387 unsigned int width,
const double lambda)
391 std::vector<unsigned int> indstart_low(width);
392 std::vector<unsigned int> indstart_up(width);
393 unsigned int j_low = 0, j_up = 0, jseg = 0, indjseg = 0, i = 1, indjseg2, ind;
394 double output_low_first = input[0] -
lambda;
395 double output_low_curr = output_low_first;
396 double output_up_first = input[0] +
lambda;
397 double output_up_curr = output_up_first;
398 const double twolambda = 2.0 *
lambda;
400 output[0] = input[0];
406 for (; i < width; i++) {
407 if (input[i] >= output_low_curr) {
408 if (input[i] <= output_up_curr) {
409 output_up_curr += (input[i] - output_up_curr) / (i - indstart_up[j_up] + 1);
410 output[indjseg] = output_up_first;
411 while ((j_up > jseg) && (output_up_curr <= output[ind = indstart_up[j_up - 1]]))
412 output_up_curr += (output[ind] - output_up_curr) *
413 ((
double)(indstart_up[j_up--] - ind) / (i - ind + 1));
415 while ((output_up_curr <= output_low_first) && (jseg < j_low)) {
416 indjseg2 = indstart_low[++jseg];
417 output_up_curr += (output_up_curr - output_low_first) *
418 ((
double)(indjseg2 - indjseg) / (i - indjseg2 + 1));
419 while (indjseg < indjseg2) output[indjseg++] = output_low_first;
420 output_low_first = output[indjseg];
422 output_up_first = output_up_curr;
423 indstart_up[j_up = jseg] = indjseg;
425 else output[indstart_up[j_up]] = output_up_curr;
428 output_up_curr = output[i] = input[indstart_up[++j_up] = i];
429 output_low_curr += (input[i] - output_low_curr) / (i - indstart_low[j_low] + 1);
430 output[indjseg] = output_low_first;
431 while ((j_low > jseg) && (output_low_curr >= output[ind = indstart_low[j_low - 1]]))
432 output_low_curr += (output[ind] - output_low_curr) *
433 ((
double)(indstart_low[j_low--] - ind) / (i - ind + 1));
435 while ((output_low_curr >= output_up_first) && (jseg < j_up)) {
436 indjseg2 = indstart_up[++jseg];
437 output_low_curr += (output_low_curr - output_up_first) *
438 ((
double)(indjseg2 - indjseg) / (i - indjseg2 + 1));
439 while (indjseg < indjseg2) output[indjseg++] = output_up_first;
440 output_up_first = output[indjseg];
442 if ((indstart_low[j_low = jseg] = indjseg) == i) output_low_first = output_up_first - twolambda;
443 else output_low_first = output_low_curr;
445 else output[indstart_low[j_low]] = output_low_curr;
448 output_up_curr += ((output_low_curr = output[i] = input[indstart_low[++j_low] = i]) -
449 output_up_curr) / (i - indstart_up[j_up] + 1);
450 output[indjseg] = output_up_first;
451 while ((j_up > jseg) && (output_up_curr <= output[ind = indstart_up[j_up - 1]]))
452 output_up_curr += (output[ind] - output_up_curr) *
453 ((
double)(indstart_up[j_up--] - ind) / (i - ind + 1));
455 while ((output_up_curr <= output_low_first) && (jseg < j_low)) {
456 indjseg2 = indstart_low[++jseg];
457 output_up_curr += (output_up_curr - output_low_first) *
458 ((
double)(indjseg2 - indjseg) / (i - indjseg2 + 1));
459 while (indjseg < indjseg2) output[indjseg++] = output_low_first;
460 output_low_first = output[indjseg];
462 if ((indstart_up[j_up = jseg] = indjseg) == i) output_up_first = output_low_first + twolambda;
463 else output_up_first = output_up_curr;
465 else output[indstart_up[j_up]] = output_up_curr;
469 if (input[i] + lambda <= output_low_curr) {
470 while (jseg < j_low) {
471 indjseg2 = indstart_low[++jseg];
472 while (indjseg < indjseg2) output[indjseg++] = output_low_first;
473 output_low_first = output[indjseg];
475 while (indjseg < i) output[indjseg++] = output_low_first;
476 output[indjseg] = input[i] +
lambda;
478 else if (input[i] - lambda >= output_up_curr) {
479 while (jseg < j_up) {
480 indjseg2 = indstart_up[++jseg];
481 while (indjseg < indjseg2) output[indjseg++] = output_up_first;
482 output_up_first = output[indjseg];
484 while (indjseg < i) output[indjseg++] = output_up_first;
485 output[indjseg] = input[i] -
lambda;
488 output_low_curr += (input[i] + lambda - output_low_curr) / (i - indstart_low[j_low] + 1);
489 output[indjseg] = output_low_first;
490 while ((j_low > jseg) && (output_low_curr >= output[ind = indstart_low[j_low - 1]]))
491 output_low_curr += (output[ind] - output_low_curr) *
492 ((
double)(indstart_low[j_low--] - ind) / (i - ind + 1));
494 if (output_up_first >= output_low_curr)
495 while (indjseg <= i) output[indjseg++] = output_low_curr;
497 output_up_curr += (input[i] - lambda - output_up_curr) / (i - indstart_up[j_up] + 1);
498 output[indjseg] = output_up_first;
499 while ((j_up > jseg) && (output_up_curr <= output[ind = indstart_up[j_up - 1]]))
500 output_up_curr += (output[ind] - output_up_curr) *
501 ((
double)(indstart_up[j_up--] - ind) / (i - ind + 1));
502 while (jseg < j_up) {
503 indjseg2 = indstart_up[++jseg];
504 while (indjseg < indjseg2) output[indjseg++] = output_up_first;
505 output_up_first = output[indjseg];
507 indjseg = indstart_up[j_up];
508 while (indjseg <= i) output[indjseg++] = output_up_curr;
512 while (jseg < j_low) {
513 indjseg2 = indstart_low[++jseg];
514 while (indjseg < indjseg2) output[indjseg++] = output_low_first;
515 output_low_first = output[indjseg];
517 indjseg = indstart_low[j_low];
518 while (indjseg <= i) output[indjseg++] = output_low_curr;
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
process_name opflash particleana ie x
void TV1D_denoise_v2(std::vector< double > &input, std::vector< double > &output, unsigned int width, const double lambda)
double lambda(double a, double b, double c)
process_name eventweight kplus
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
std::vector< double > outwvform
Simulation objects for optical detectors.
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
Service to provide microboone-specific signal shaping for simulation (convolution) and reconstruction...
void subtractBaseline(TH1D *hist, std::string pdtype, double &rms)
opHitFinderSBND(fhicl::ParameterSet const &p, const detinfo::DetectorClocks *timeService)
std::string fInputModuleName
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
std::vector< double > fwaveform
void TV1D_denoise(float *input, float *&output, const int width, const float lambda)
void produce(art::Event &e) override
std::string electronicsType(size_t ch) const
BEGIN_PROLOG sequence::SlidingWindowTriggerPatternsOppositeWindows END_PROLOG simSlidingORM6O6 effSlidingORW output
std::string electronicsType
opHitFinderSBND & operator=(opHitFinderSBND const &)=delete
object containing MC truth information necessary for making RawDigits and doing back tracking ...
art::ServiceHandle< art::TFileService > tfs
process_name eventweight kminus
std::string pdType(size_t ch) const override
Tools and modules for checking out the basics of the Monte Carlo.
art framework interface to geometry description
double fPulsePolarityArapuca
bool findAndSuppressPeak(std::vector< double > &waveform, size_t &timebin, double &Area, double &litude, const int &threshold, const std::string &opdetType, const std::string &electronicsType)