SignalShapingServiceDUNE_service.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file SignalShapingServiceDUNE_service.cc
3 /// \author H. Greenlee
4 ////////////////////////////////////////////////////////////////////////
5 
10 #include "cetlib_except/exception.h"
17 #include "TFile.h"
18 
19 using std::string;
20 
21 //----------------------------------------------------------------------
22 // Constructor.
24  art::ActivityRegistry& /* reg */)
25  : fInit(false)
26 {
27  reconfigure(pset);
28 }
29 
30 
31 //----------------------------------------------------------------------
32 // Destructor.
34 {}
35 
36 
37 //----------------------------------------------------------------------
38 // Reconfigure method.
40 {
41  // Reset initialization flag.
42 
43  fInit = false;
44 
45  // Reset kernels.
46 
50 
51  // Fetch fcl parameters.
52 
53  fNFieldBins = pset.get<int>("FieldBins");
54  fCol3DCorrection = pset.get<double>("Col3DCorrection");
55  fInd3DCorrection = pset.get<double>("Ind3DCorrection");
56  fColFieldRespAmp = pset.get<double>("ColFieldRespAmp");
57  fIndUFieldRespAmp = pset.get<double>("IndUFieldRespAmp");
58  fIndVFieldRespAmp = pset.get<double>("IndVFieldRespAmp");
59 
60  fDeconNorm = pset.get<double>("DeconNorm");
61  fADCPerPCAtLowestASICGain = pset.get<double>("ADCPerPCAtLowestASICGain");
62  fASICGainInMVPerFC = pset.get<std::vector<double> >("ASICGainInMVPerFC");
63  fShapeTimeConst = pset.get<std::vector<double> >("ShapeTimeConst");
64  fNoiseFactVec = pset.get<std::vector<DoubleVec> >("NoiseFactVec");
65 
66  fInputFieldRespSamplingPeriod = pset.get<double>("InputFieldRespSamplingPeriod");
67 
68  fFieldResponseTOffset = pset.get<std::vector<double> >("FieldResponseTOffset");
69  fCalibResponseTOffset = pset.get<std::vector<double> >("CalibResponseTOffset");
70 
71  fUseFunctionFieldShape= pset.get<bool>("UseFunctionFieldShape");
72  fUseHistogramFieldShape = pset.get<bool>("UseHistogramFieldShape");
73 
74  fGetFilterFromHisto= pset.get<bool>("GetFilterFromHisto");
75 
76  // Construct parameterized collection filter function.
77  if(!fGetFilterFromHisto)
78  {
79  mf::LogInfo("SignalShapingServiceDUNE") << "Getting Filter from .fcl file";
80  std::string colFilt = pset.get<std::string>("ColFilter");
81  std::vector<double> colFiltParams =
82  pset.get<std::vector<double> >("ColFilterParams");
83  fColFilterFunc = new TF1("colFilter", colFilt.c_str());
84  for(unsigned int i=0; i<colFiltParams.size(); ++i)
85  fColFilterFunc->SetParameter(i, colFiltParams[i]);
86 
87  // Construct parameterized induction filter function.
88 
89  std::string indUFilt = pset.get<std::string>("IndUFilter");
90  std::vector<double> indUFiltParams = pset.get<std::vector<double> >("IndUFilterParams");
91  fIndUFilterFunc = new TF1("indUFilter", indUFilt.c_str());
92  for(unsigned int i=0; i<indUFiltParams.size(); ++i)
93  fIndUFilterFunc->SetParameter(i, indUFiltParams[i]);
94 
95  std::string indVFilt = pset.get<std::string>("IndVFilter");
96  std::vector<double> indVFiltParams = pset.get<std::vector<double> >("IndVFilterParams");
97  fIndVFilterFunc = new TF1("indVFilter", indVFilt.c_str());
98  for(unsigned int i=0; i<indVFiltParams.size(); ++i)
99  fIndVFilterFunc->SetParameter(i, indVFiltParams[i]);
100 
101  }
102  else
103  {
104 
105  std::string histoname = pset.get<std::string>("FilterHistoName");
106  mf::LogInfo("SignalShapingServiceDUNE") << " using filter from .root file ";
107  int fNPlanes=3;
108 
109  // constructor decides if initialized value is a path or an environment variable
111  cet::search_path sp("FW_SEARCH_PATH");
112  sp.find_file(pset.get<std::string>("FilterFunctionFname"), fname);
113 
114  TFile * in=new TFile(fname.c_str(),"READ");
115  for(int i=0;i<fNPlanes;i++){
116  TH1D * temp=(TH1D *)in->Get(Form(histoname.c_str(),i));
117  fFilterHist[i]=new TH1D(Form(histoname.c_str(),i),Form(histoname.c_str(),i),temp->GetNbinsX(),0,temp->GetNbinsX());
118  temp->Copy(*fFilterHist[i]);
119  }
120 
121  in->Close();
122 
123  }
124 
125  /////////////////////////////////////
126  if(fUseFunctionFieldShape)
127  {
128  std::string colField = pset.get<std::string>("ColFieldShape");
129  std::vector<double> colFieldParams =
130  pset.get<std::vector<double> >("ColFieldParams");
131  fColFieldFunc = new TF1("colField", colField.c_str());
132  for(unsigned int i=0; i<colFieldParams.size(); ++i)
133  fColFieldFunc->SetParameter(i, colFieldParams[i]);
134 
135  // Construct parameterized induction filter function.
136 
137  std::string indUField = pset.get<std::string>("IndUFieldShape");
138  std::vector<double> indUFieldParams = pset.get<std::vector<double> >("IndUFieldParams");
139  fIndUFieldFunc = new TF1("indUField", indUField.c_str());
140  for(unsigned int i=0; i<indUFieldParams.size(); ++i)
141  fIndUFieldFunc->SetParameter(i, indUFieldParams[i]);
142  // Warning, last parameter needs to be multiplied by the FFTSize, in current version of the code,
143 
144  std::string indVField = pset.get<std::string>("IndVFieldShape");
145  std::vector<double> indVFieldParams = pset.get<std::vector<double> >("IndVFieldParams");
146  fIndVFieldFunc = new TF1("indVField", indVField.c_str());
147  for(unsigned int i=0; i<indVFieldParams.size(); ++i)
148  fIndVFieldFunc->SetParameter(i, indVFieldParams[i]);
149  // Warning, last parameter needs to be multiplied by the FFTSize, in current version of the code,
150 
151  } else if ( fUseHistogramFieldShape ) {
152  mf::LogInfo("SignalShapingServiceDUNE") << " using the field response provided from a .root file " ;
153  int fNPlanes = 3;
154 
155  // constructor decides if initialized value is a path or an environment variable
157  cet::search_path sp("FW_SEARCH_PATH");
158  sp.find_file( pset.get<std::string>("FieldResponseFname"), fname );
159  std::string histoname = pset.get<std::string>("FieldResponseHistoName");
160 
161  std::unique_ptr<TFile> fin(new TFile(fname.c_str(), "READ"));
162  if ( !fin->IsOpen() ) throw art::Exception( art::errors::NotFound ) << "Could not find the field response file " << fname << "!" << std::endl;
163 
164  std::string iPlane[3] = { "U", "V", "Y" };
165 
166  for ( int i = 0; i < fNPlanes; i++ ) {
167  TString iHistoName = Form( "%s_%s", histoname.c_str(), iPlane[i].c_str());
168  TH1F *temp = (TH1F*) fin->Get( iHistoName );
169  if ( !temp ) throw art::Exception( art::errors::NotFound ) << "Could not find the field response histogram " << iHistoName << std::endl;
170  if ( temp->GetNbinsX() > fNFieldBins ) throw art::Exception( art::errors::InvalidNumber ) << "FieldBins should always be larger than or equal to the number of the bins in the input histogram!" << std::endl;
171 
172  fFieldResponseHist[i] = new TH1F( iHistoName, iHistoName, temp->GetNbinsX(), temp->GetBinLowEdge(1), temp->GetBinLowEdge( temp->GetNbinsX() + 1) );
173  temp->Copy(*fFieldResponseHist[i]);
174  fFieldResponseHist[i]->SetDirectory(0);
175  }
176 
177  fin->Close();
178  }
179 }
180 
181 
182 //----------------------------------------------------------------------
183 // Accessor for single-plane signal shaper.
184 const util::SignalShaping&
186  const string myname = "SignalShapingServiceDUNE::ctor: ";
187  if(!fInit)
188  init();
189 
190  // Figure out plane type.
191 
193  //geo::SigType_t sigtype = geom->SignalType(channel);
194 
195  // we need to distinguis between the U and V planes
196  geo::View_t view = geom->View(channel);
197 
198  // Return appropriate shaper.
199 
200  if(view == geo::kU)
201  return fIndUSignalShaping;
202  else if (view == geo::kV)
203  return fIndVSignalShaping;
204  else if(view == geo::kZ)
205  return fColSignalShaping;
206  else
207  throw cet::exception("SignalShapingServiceDUNEt") << myname
208  << "can't determine view for channel " << channel << " with geometry " << geom->DetectorName() << "\n";
209 
210 return fColSignalShaping;
211 }
212 const util::SignalShaping&
214  const string myname = "SignalShapingServiceDUNE::ElectronicShaping: ";
215  if(!fInit)
216  init();
217 
218  // Figure out plane type.
219 
221  //geo::SigType_t sigtype = geom->SignalType(channel);
222 
223  // we need to distinguis between the U and V planes
224  geo::View_t view = geom->View(channel);
225 
226  // Return appropriate shaper.
227 
228  if(view == geo::kU)
230  else if (view == geo::kV)
232  else if(view == geo::kZ)
234  else
235  throw cet::exception("SignalShapingServiceDUNE") << myname
236  << "can't determine view for channel " << channel << " with geometry " << geom->DetectorName() << "\n";
237 
239 }
240 
241 
242 std::vector<DoubleVec> util::SignalShapingServiceDUNE::GetNoiseFactVec() const {
243  return fNoiseFactVec;
244 }
245 
246 //-----Give Gain Settings to SimWire-----//jyoti
247 double util::SignalShapingServiceDUNE::GetASICGain(unsigned int const channel) const {
248  const string myname = "SignalShapingServiceDUNE::GetASICGain: ";
250  //geo::SigType_t sigtype = geom->SignalType(channel);
251 
252  // we need to distinguis between the U and V planes
253  geo::View_t view = geom->View(channel);
254 
255  double gain = 0;
256  if(view == geo::kU)
257  gain = fASICGainInMVPerFC.at(0);
258  else if(view == geo::kV)
259  gain = fASICGainInMVPerFC.at(1);
260  else if(view == geo::kZ)
261  gain = fASICGainInMVPerFC.at(2);
262  else
263  throw cet::exception("SignalShapingServiceDUNEt") << myname
264  << "can't determine view for channel " << channel << " with geometry " << geom->DetectorName() << "\n";
265  return gain;
266 }
267 
268 
269 //-----Give Shaping time to SimWire-----//jyoti
270 double util::SignalShapingServiceDUNE::GetShapingTime(unsigned int const channel) const {
271  const string myname = "SignalShapingServiceDUNE::GetShapingTime: ";
273  //geo::SigType_t sigtype = geom->SignalType(channel);
274 
275  // we need to distinguis between the U and V planes
276  geo::View_t view = geom->View(channel);
277 
278  double shaping_time = 0;
279 
280  if(view == geo::kU)
281  shaping_time = fShapeTimeConst.at(0);
282  else if(view == geo::kV)
283  shaping_time = fShapeTimeConst.at(1);
284  else if(view == geo::kZ)
285  shaping_time = fShapeTimeConst.at(2);
286  else
287  throw cet::exception("SignalShapingServiceDUNEt") << myname
288  << "can't determine view for channel " << channel << " with geometry " << geom->DetectorName() << "\n";
289  return shaping_time;
290 }
291 
292 double util::SignalShapingServiceDUNE::GetRawNoise(unsigned int const channel) const {
293  const string myname = "SignalShapingServiceDUNE::GetRawNoise: ";
294  unsigned int plane;
296  //geo::SigType_t sigtype = geom->SignalType(channel);
297 
298  // we need to distinguis between the U and V planes
299  geo::View_t view = geom->View(channel);
300 
301  if(view == geo::kU)
302  plane = 0;
303  else if(view == geo::kV)
304  plane = 1;
305  else if(view == geo::kZ)
306  plane = 2;
307  else
308  throw cet::exception("SignalShapingServiceDUNEt") << myname
309  << "can't determine view for channel " << channel << " with geometry " << geom->DetectorName() << "\n";
310 
311  double shapingtime = fShapeTimeConst.at(plane);
312  double gain = fASICGainInMVPerFC.at(plane);
313  int temp;
314  if (shapingtime == 0.5){
315  temp = 0;
316  }else if (shapingtime == 1.0){
317  temp = 1;
318  }else if (shapingtime == 2.0){
319  temp = 2;
320  }else{
321  temp = 3;
322  }
323  double rawNoise;
324 
325  auto tempNoise = fNoiseFactVec.at(plane);
326  rawNoise = tempNoise.at(temp);
327 
328  rawNoise *= gain/4.7;
329  return rawNoise;
330 }
331 
332 double util::SignalShapingServiceDUNE::GetDeconNoise(unsigned int const channel) const {
333  const string myname = "SignalShapingServiceDUNE::GetDeconNoise: ";
334  unsigned int plane;
336  //geo::SigType_t sigtype = geom->SignalType(channel);
337 
338  // we need to distinguis between the U and V planes
339  geo::View_t view = geom->View(channel);
340 
341  if(view == geo::kU)
342  plane = 0;
343  else if(view == geo::kV)
344  plane = 1;
345  else if(view == geo::kZ)
346  plane = 2;
347  else
348  throw cet::exception("SignalShapingServiceDUNEt") << myname
349  << "can't determine view for channel " << channel << " with geometry " << geom->DetectorName() << "\n";
350 
351  double shapingtime = fShapeTimeConst.at(plane);
352  int temp;
353  if (shapingtime == 0.5){
354  temp = 0;
355  }else if (shapingtime == 1.0){
356  temp = 1;
357  }else if (shapingtime == 2.0){
358  temp = 2;
359  }else{
360  temp = 3;
361  }
362  auto tempNoise = fNoiseFactVec.at(plane);
363  double deconNoise = tempNoise.at(temp);
364 
365  deconNoise = deconNoise /4096.*2000./4.7 *6.241*1000/fDeconNorm;
366  return deconNoise;
367 }
368 
370  return fDeconNorm;
371 }
372 
374  return SignalShaping(0).Response().size();
375 }
376 
377 //----------------------------------------------------------------------
378 // Initialization method.
379 // Here we do initialization that can't be done in the constructor.
380 // All public methods should ensure that this method is called as necessary.
382 {
383  if(!fInit) {
384  fInit = true;
385 
386  // Do microboone-specific configuration of SignalShaping by providing
387  // microboone response and filter functions.
388 
389  // Calculate field and electronics response functions.
390 
391  // Lazy evaluation in a multi-threaded environment is problematic.
392  // The best we can do here is to use the global data available
393  // through detector-properties service.
394  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
395  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataForJob(clockData);
396  SetFieldResponse(clockData, detProp);
398 
399  // Configure convolution kernels.
400 
405  //fColSignalShaping.SetPeakResponseTime(0.);
409 
411 
416  //fIndUSignalShaping.SetPeakResponseTime(0.);
420 
422 
427  //fIndVSignalShaping.SetPeakResponseTime(0.);
431 
432 
433  SetResponseSampling(clockData);
434  SetResponseSampling(clockData, true);
435 
436  // Calculate filter functions.
437 
438  SetFilters(clockData);
439 
440  // Configure deconvolution kernels.
441 
444 
447 
450  }
451 }
452 
453 
454 //----------------------------------------------------------------------
455 // Calculate microboone field response.
457  detinfo::DetectorPropertiesData const& detProp)
458 {
459  // Get services.
460 
462 
463  // Get plane pitch.
464 
465  double xyz1[3] = {0.};
466  double xyz2[3] = {0.};
467  double xyzl[3] = {0.};
468  // should always have at least 2 planes
469  geo->Plane(0).LocalToWorld(xyzl, xyz1);
470  geo->Plane(1).LocalToWorld(xyzl, xyz2);
471 
472  // this assumes all planes are equidistant from each other,
473  // probably not a bad assumption
474  double pitch = xyz2[0] - xyz1[0]; ///in cm
475 
476  fColFieldResponse.resize(fNFieldBins, 0.);
477  fIndUFieldResponse.resize(fNFieldBins, 0.);
478  fIndVFieldResponse.resize(fNFieldBins, 0.);
479 
480  // set the response for the collection plane first
481  // the first entry is 0
482 
483  double driftvelocity=detProp.DriftVelocity()/1000.;
484  int nbinc = TMath::Nint(fCol3DCorrection*(std::abs(pitch))/(driftvelocity*sampling_rate(clockData))); ///number of bins //KP
485  double integral = 0;
486  ////////////////////////////////////////////////////
488  {
490  int signalSize = fft->FFTSize();
491  std::vector<double> ramp(signalSize);
492  // TComplex kernBin;
493  // int size = signalSize/2;
494  // int bin=0;
495  //std::vector<TComplex> freqSig(size+1);
496  std::vector<double> bipolar(signalSize);
497 
498 
499  fColFieldResponse.resize(signalSize, 0.);
500  fIndUFieldResponse.resize(signalSize, 0.);
501  fIndVFieldResponse.resize(signalSize, 0.);
502 
503  // Hardcoding. Bad. Temporary hopefully.
504  fIndUFieldFunc->SetParameter(4,fIndUFieldFunc->GetParameter(4)*signalSize);
505  fIndVFieldFunc->SetParameter(4,fIndVFieldFunc->GetParameter(4)*signalSize);
506 
507  //double integral = 0.;
508  for(int i = 0; i < signalSize; i++) {
509  ramp[i]=fColFieldFunc->Eval(i);
510  fColFieldResponse[i]=ramp[i];
511  integral += fColFieldResponse[i];
512  // rampc->Fill(i,ramp[i]);
513  bipolar[i]=fIndUFieldFunc->Eval(i);
514  fIndUFieldResponse[i]=bipolar[i];
515  bipolar[i]=fIndVFieldFunc->Eval(i);
516  fIndVFieldResponse[i]=bipolar[i];
517  // bipol->Fill(i,bipolar[i]);
518  }
519 
520  for(int i = 0; i < signalSize; ++i){
522  }
523 
524  //this might be not necessary if the function definition is not defined in the middle of the signal range
525  fft->ShiftData(fIndUFieldResponse,signalSize/2.0);
526  } else if ( fUseHistogramFieldShape ) {
527 
528  // Ticks in nanosecond
529  // Calculate the normalization of the collection plane
530  for ( int ibin = 1; ibin <= fFieldResponseHist[2]->GetNbinsX(); ibin++ )
531  integral += fFieldResponseHist[2]->GetBinContent( ibin );
532 
533  // Induction plane
534  for ( int ibin = 1; ibin <= fFieldResponseHist[0]->GetNbinsX(); ibin++ )
535  fIndUFieldResponse[ibin-1] = fIndUFieldRespAmp*fFieldResponseHist[0]->GetBinContent( ibin )/integral;
536 
537  for ( int ibin = 1; ibin <= fFieldResponseHist[1]->GetNbinsX(); ibin++ )
538  fIndVFieldResponse[ibin-1] = fIndVFieldRespAmp*fFieldResponseHist[1]->GetBinContent( ibin )/integral;
539 
540  for ( int ibin = 1; ibin <= fFieldResponseHist[2]->GetNbinsX(); ibin++ )
541  fColFieldResponse[ibin-1] = fColFieldRespAmp*fFieldResponseHist[2]->GetBinContent( ibin )/integral;
542  }else
543  {
544  //////////////////////////////////////////////////
545  mf::LogInfo("SignalShapingServiceDUNE") << " using the old field shape ";
546  double integral = 0.;
547  for(int i = 1; i < nbinc; ++i){
548  fColFieldResponse[i] = fColFieldResponse[i-1] + 1.0;
549  integral += fColFieldResponse[i];
550  }
551 
552  for(int i = 0; i < nbinc; ++i){
554  }
555 
556  // now the induction plane
557 
558 
559  int nbini = TMath::Nint(fInd3DCorrection*(fabs(pitch))/(driftvelocity*sampling_rate(clockData)));//KP
560  for(int i = 0; i < nbini; ++i){
561  fIndUFieldResponse[i] = fIndUFieldRespAmp/(1.*nbini);
562  fIndUFieldResponse[nbini+i] = -fIndUFieldRespAmp/(1.*nbini);
563  }
564 
565  for(int i = 0; i < nbini; ++i){
566  fIndVFieldResponse[i] = fIndVFieldRespAmp/(1.*nbini);
567  fIndVFieldResponse[nbini+i] = -fIndVFieldRespAmp/(1.*nbini);
568  }
569 
570  }
571 
572  return;
573 }
574 
575 void util::SignalShapingServiceDUNE::SetElectResponse(double shapingtime, double gain)
576 {
577  // Get services.
578 
581 
582  MF_LOG_DEBUG("SignalShapingDUNE") << "Setting DUNE electronics response function...";
583 
584  int nticks = fft->FFTSize();
585  fElectResponse.resize(nticks, 0.);
586  std::vector<double> time(nticks,0.);
587 
588  //Gain and shaping time variables from fcl file:
589  double Ao = 1.0;
590  double To = shapingtime; //peaking time
591 
592  // this is actually sampling time, in ns
593  // mf::LogInfo("SignalShapingDUNE") << "Check sampling intervals: "
594  // << fSampleRate << " ns"
595  // << "Check number of samples: " << fNTicks;
596 
597  // The following sets the microboone electronics response function in
598  // time-space. Function comes from BNL SPICE simulation of DUNE35t
599  // electronics. SPICE gives the electronics transfer function in
600  // frequency-space. The inverse laplace transform of that function
601  // (in time-space) was calculated in Mathematica and is what is being
602  // used below. Parameters Ao and To are cumulative gain/timing parameters
603  // from the full (ASIC->Intermediate amp->Receiver->ADC) electronics chain.
604  // They have been adjusted to make the SPICE simulation to match the
605  // actual electronics response. Default params are Ao=1.4, To=0.5us.
606  double max = 0;
607 
608  for(size_t i = 0; i < fElectResponse.size(); ++i){
609 
610  //convert time to microseconds, to match fElectResponse[i] definition
611  time[i] = (1.*i)*fInputFieldRespSamplingPeriod *1e-3;
612  fElectResponse[i] =
613  4.31054*exp(-2.94809*time[i]/To)*Ao - 2.6202*exp(-2.82833*time[i]/To)*cos(1.19361*time[i]/To)*Ao
614  -2.6202*exp(-2.82833*time[i]/To)*cos(1.19361*time[i]/To)*cos(2.38722*time[i]/To)*Ao
615  +0.464924*exp(-2.40318*time[i]/To)*cos(2.5928*time[i]/To)*Ao
616  +0.464924*exp(-2.40318*time[i]/To)*cos(2.5928*time[i]/To)*cos(5.18561*time[i]/To)*Ao
617  +0.762456*exp(-2.82833*time[i]/To)*sin(1.19361*time[i]/To)*Ao
618  -0.762456*exp(-2.82833*time[i]/To)*cos(2.38722*time[i]/To)*sin(1.19361*time[i]/To)*Ao
619  +0.762456*exp(-2.82833*time[i]/To)*cos(1.19361*time[i]/To)*sin(2.38722*time[i]/To)*Ao
620  -2.6202*exp(-2.82833*time[i]/To)*sin(1.19361*time[i]/To)*sin(2.38722*time[i]/To)*Ao
621  -0.327684*exp(-2.40318*time[i]/To)*sin(2.5928*time[i]/To)*Ao +
622  +0.327684*exp(-2.40318*time[i]/To)*cos(5.18561*time[i]/To)*sin(2.5928*time[i]/To)*Ao
623  -0.327684*exp(-2.40318*time[i]/To)*cos(2.5928*time[i]/To)*sin(5.18561*time[i]/To)*Ao
624  +0.464924*exp(-2.40318*time[i]/To)*sin(2.5928*time[i]/To)*sin(5.18561*time[i]/To)*Ao;
625 
626  if(fElectResponse[i] > max) max = fElectResponse[i];
627 
628  }// end loop over time buckets
629 
630 
631  MF_LOG_DEBUG("SignalShapingDUNE") << " Done.";
632 
633  //normalize fElectResponse[i], before the convolution
634 
635  for(auto& element : fElectResponse){
636  element /= max;
637  element *= fADCPerPCAtLowestASICGain * 1.60217657e-7;
638  element *= gain / 4.7;
639  }
640 
641  return;
642 
643 }
644 
645 
646 
647 
648 //----------------------------------------------------------------------
649 // Calculate microboone filter functions.
651 {
652  // Get services.
653 
655 
656  double ts = sampling_rate(clockData);
657  int n = fft->FFTSize() / 2;
658 
659  // Calculate collection filter.
660 
661  fColFilter.resize(n+1);
662  fIndUFilter.resize(n+1);
663  fIndVFilter.resize(n+1);
664 
666  {
667  fColFilterFunc->SetRange(0, double(n));
668 
669  for(int i=0; i<=n; ++i) {
670  double freq = 500. * i / (ts * n); // Cycles / microsecond.
671  double f = fColFilterFunc->Eval(freq);
672  fColFilter[i] = TComplex(f, 0.);
673  }
674 
675 
676  // Calculate induction filter.
677 
678  fIndUFilterFunc->SetRange(0, double(n));
679 
680  for(int i=0; i<=n; ++i) {
681  double freq = 500. * i / (ts * n); // Cycles / microsecond.
682  double f = fIndUFilterFunc->Eval(freq);
683  fIndUFilter[i] = TComplex(f, 0.);
684  }
685 
686  fIndVFilterFunc->SetRange(0, double(n));
687 
688  for(int i=0; i<=n; ++i) {
689  double freq = 500. * i / (ts * n); // Cycles / microsecond.
690  double f = fIndVFilterFunc->Eval(freq);
691  fIndVFilter[i] = TComplex(f, 0.);
692  }
693 
694  }
695  else
696  {
697 
698  for(int i=0; i<=n; ++i) {
699  double f = fFilterHist[2]->GetBinContent(i); // hardcoded plane numbers. Bad. To change later.
700  fColFilter[i] = TComplex(f, 0.);
701  double g = fFilterHist[1]->GetBinContent(i);
702  fIndVFilter[i] = TComplex(g, 0.);
703  double h = fFilterHist[0]->GetBinContent(i);
704  fIndUFilter[i] = TComplex(h, 0.);
705  }
706  }
707 
708  //fIndUSignalShaping.AddFilterFunction(fIndFilter);
709  //fIndVSignalShaping.AddFilterFunction(fIndVFilter);
710  //fColSignalShaping.AddFilterFunction(fColFilter);
711 
712 }
713 
714 //----------------------------------------------------------------------
715 // Sample microboone response (the convoluted field and electronic
716 // response), will probably add the filter later
718 {
719  // Get services
722 
723  // Operation permitted only if output of rebinning has a larger bin size
725  throw cet::exception(__FUNCTION__) << "\033[93m"
726  << "Invalid operation: cannot rebin to a more finely binned vector!"
727  << "\033[00m" << std::endl;
728 
729  int nticks = fft->FFTSize();
730  std::vector<double> SamplingTime( nticks, 0. );
731  for ( int itime = 0; itime < nticks; itime++ ) {
732  SamplingTime[itime] = (1.*itime) * sampling_rate(clockData);
733  /// VELOCITY-OUT ... comment out kDVel usage here
734  //SamplingTime[itime] = (1.*itime) * sampling_rate(clockData) / kDVel;
735  }
736 
737  // Sampling
738  for ( int iplane = 0; iplane < 3; iplane++ ) {
739  const std::vector<double>* pResp;
740  if (not elect_only) {
741  switch ( iplane ) {
742  case 0: pResp = &(fIndUSignalShaping.Response_save()); break;
743  case 1: pResp = &(fIndVSignalShaping.Response_save()); break;
744  default: pResp = &(fColSignalShaping.Response_save()); break;
745  }
746  } else {
747  switch ( iplane ) {
748  case 0: pResp = &(fIndUElectResponseSignalShaping.Response_save()); break;
749  case 1: pResp = &(fIndVElectResponseSignalShaping.Response_save()); break;
750  default: pResp = &(fColElectResponseSignalShaping.Response_save()); break;
751  }
752  }
753 
754  std::vector<double> SamplingResp(nticks , 0. );
755 
756 
757  int nticks_input = pResp->size();
758  std::vector<double> InputTime(nticks_input, 0. );
759  for ( int itime = 0; itime < nticks_input; itime++ ) {
760  InputTime[itime] = (1.*itime) * fInputFieldRespSamplingPeriod;
761  }
762 
763 
764  /*
765  Much more sophisticated approach using a linear (trapezoidal) interpolation
766  Current default!
767  */
768  int SamplingCount = 0;
769  for ( int itime = 0; itime < nticks; itime++ ) {
770  int low = -1, up = -1;
771  for ( int jtime = 0; jtime < nticks_input; jtime++ ) {
772  if ( InputTime[jtime] == SamplingTime[itime] ) {
773  SamplingResp[itime] = (*pResp)[jtime];
774  /// VELOCITY-OUT ... comment out kDVel usage here
775  //SamplingResp[itime] = kDVel * (*pResp)[jtime];
776  SamplingCount++;
777  break;
778  } else if ( InputTime[jtime] > SamplingTime[itime] ) {
779  low = jtime - 1;
780  up = jtime;
781  SamplingResp[itime] = (*pResp)[low] + ( SamplingTime[itime] - InputTime[low] ) * ( (*pResp)[up] - (*pResp)[low] ) / ( InputTime[up] - InputTime[low] );
782  /// VELOCITY-OUT ... comment out kDVel usage here
783  //SamplingResp[itime] *= kDVel;
784  SamplingCount++;
785  break;
786  } else {
787  SamplingResp[itime] = 0.;
788  }
789  } // for ( int jtime = 0; jtime < nticks; jtime++ )
790  } // for ( int itime = 0; itime < nticks; itime++ )
791  SamplingResp.resize( SamplingCount, 0.);
792 
793 
794  if (not elect_only) {
795  switch ( iplane ) {
796  case 0: fIndUSignalShaping.AddResponseFunction( SamplingResp, true ); break;
797  case 1: fIndVSignalShaping.AddResponseFunction( SamplingResp, true ); break;
798  default: fColSignalShaping.AddResponseFunction( SamplingResp, true ); break;
799  }
800  } else {
801  switch ( iplane ) {
802  case 0: fIndUElectResponseSignalShaping.AddResponseFunction( SamplingResp, true ); break;
803  case 1: fIndVElectResponseSignalShaping.AddResponseFunction( SamplingResp, true ); break;
804  default: fColElectResponseSignalShaping.AddResponseFunction( SamplingResp, true ); break;
805  }
806 
807  }
808 
809 
810 
811  } // for ( int iplane = 0; iplane < fNPlanes; iplane++ )
812 
813  return;
814 }
815 
816 
817 
819  unsigned int const channel) const {
820  const string myname = "SignalShapingServiceDUNE::FieldResponseTOffset: ";
822  //geo::SigType_t sigtype = geom->SignalType(channel);
823 
824  // we need to distinguis between the U and V planes
825  geo::View_t view = geom->View(channel);
826 
827  double time_offset = 0;
828 
829  if(view == geo::kU)
830  time_offset = fFieldResponseTOffset.at(0) + fCalibResponseTOffset.at(0);
831  else if(view == geo::kV)
832  time_offset = fFieldResponseTOffset.at(1) + fCalibResponseTOffset.at(1);
833  else if(view == geo::kZ)
834  time_offset = fFieldResponseTOffset.at(2) + fCalibResponseTOffset.at(2);
835  else
836  throw cet::exception("SignalShapingServiceDUNEt") << myname
837  << "can't determine view for channel " << channel << " with geometry " << geom->DetectorName() << "\n";
838 
839  return clockData.TPCClock().Ticks(time_offset/1.e3);
840 
841 }
842 
845  unsigned int channel, FloatVector& func) const {
846  return Convolute<float>(clockData, channel, func);
847 }
848 
851  unsigned int channel, DoubleVector& func) const {
852  return Convolute<double>(clockData, channel, func);
853 }
856  unsigned int channel, FloatVector& func) const {
857  return ConvoluteElectronicResponse<float>(clockData, channel, func);
858 }
859 
862  unsigned int channel, DoubleVector& func) const {
863  return ConvoluteElectronicResponse<double>(clockData, channel, func);
864 }
865 
868  unsigned int channel, FloatVector& func) const {
869  return Deconvolute<float>(clockData, channel, func);
870 }
871 
874  unsigned int channel, DoubleVector& func) const {
875  return Deconvolute<double>(clockData, channel, func);
876 }
877 
878 
879 namespace util {
880 
882 
883 }
void set_normflag(bool flag)
const std::vector< double > & Response_save() const
Definition: SignalShaping.h:78
double fColFieldRespAmp
amplitude of response to field
TF1 * fColFilterFunc
Parameterized collection filter function.
void Deconvolute(detinfo::DetectorClocksData const &clockData, Channel channel, std::vector< T > &func) const
bool fUseFunctionFieldShape
Flag that allows to use a parameterized field response instead of the hardcoded version.
Namespace for general, non-LArSoft-specific utilities.
util::SignalShaping fColElectResponseSignalShaping
double GetShapingTime(Channel channel) const override
PlaneGeo const & Plane(unsigned int const p, unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified wire.
bool fGetFilterFromHisto
Flag that allows to use a filter function from a histogram instead of the functional dependency...
static constexpr double g
Definition: Units.h:144
std::vector< double > fShapeTimeConst
time constants for exponential shaping
void ShiftData(std::vector< TComplex > &input, double shift)
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
std::string string
Definition: nybbler.cc:12
void SetFilters(detinfo::DetectorClocksData const &clockData)
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
Planes which measure V.
Definition: geo_types.h:130
std::vector< DoubleVec > GetNoiseFactVec() const override
const std::vector< double > & Response() const
Definition: SignalShaping.h:77
std::vector< float > FloatVector
double fCol3DCorrection
correction factor to account for 3D path of
int fNFieldBins
number of bins for field response
void AddResponseFunction(const std::vector< double > &resp, bool ResetResponse=false)
Planes which measure Z direction.
Definition: geo_types.h:132
uint8_t channel
Definition: CRTFragment.hh:201
TF1 * fIndUFieldFunc
Parameterized induction field shape function.
double GetDeconNoise(Channel channel) const override
std::vector< double > fFieldResponseTOffset
Time offset for field response in ns.
Service to provide microboone-specific signal shaping for simulation (convolution) and reconstruction...
std::vector< DoubleVec > fNoiseFactVec
double fIndVFieldRespAmp
amplitude of response to field
constexpr int Ticks() const noexcept
Current clock tick (that is, the number of tick Time() falls in).
Definition: ElecClock.h:205
art framework interface to geometry description
double fADCPerPCAtLowestASICGain
Pulse amplitude gain for a 1 pc charge impulse after convoluting it the with field and electronics re...
T abs(T value)
Planes which measure U.
Definition: geo_types.h:129
int FFTSize() const
Definition: LArFFT.h:69
const double e
void SetResponseSampling(detinfo::DetectorClocksData const &clockData, bool elect_only=false)
void CalculateDeconvKernel() const
void reconfigure(const fhicl::ParameterSet &pset)
std::string DetectorName() const
Returns a string with the name of the detector, as configured.
double fInd3DCorrection
correction factor to account for 3D path of
util::SignalShaping fIndUElectResponseSignalShaping
std::void_t< T > n
double fIndUFieldRespAmp
amplitude of response to field
T get(std::string const &key) const
Definition: ParameterSet.h:271
TF1 * fIndUFilterFunc
Parameterized induction filter function.
bool fUseHistogramFieldShape
Flag that turns on field response shapes from histograms.
SignalShapingServiceDUNE(const fhicl::ParameterSet &pset, art::ActivityRegistry &reg)
const util::SignalShaping & ElectronicShaping(unsigned int channel) const
ElecClock const & TPCClock() const noexcept
Borrow a const TPC clock with time set to Trigger time [us].
static int max(int a, int b)
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
View_t View(geo::PlaneID const &pid) const
Returns the view (wire orientation) on the channels of specified TPC plane.
const util::SignalShaping & SignalShaping(Channel channel) const override
util::SignalShaping fIndVElectResponseSignalShaping
void ConvoluteElectronicResponse(detinfo::DetectorClocksData const &clockData, Channel channel, std::vector< T > &func) const
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
#define DEFINE_ART_SERVICE(svc)
TF1 * fIndVFieldFunc
Parameterized induction field shape function.
int FieldResponseTOffset(detinfo::DetectorClocksData const &clockData, Channel const channel) const override
void Convolute(detinfo::DetectorClocksData const &clockData, Channel channel, std::vector< T > &func) const
Encapsulate the construction of a single detector plane.
std::vector< double > DoubleVector
Contains all timing reference information for the detector.
TF1 * fColFieldFunc
Parameterized collection field shape function.
TF1 * fIndVFilterFunc
Parameterized induction filter function.
#define MF_LOG_DEBUG(id)
def func()
Definition: docstring.py:7
TH1D * fFilterHist[3]
Histogram used to hold the collection filter, hardcoded for the time being.
std::string find_file(std::string const &filename) const
Definition: search_path.cc:96
void SetFieldResponse(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp)
double fInputFieldRespSamplingPeriod
Sampling period in the input field response.
void SetElectResponse(double shapingtime, double gain)
double GetASICGain(Channel channel) const override
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
LArSoft geometry interface.
Definition: ChannelGeo.h:16
double GetRawNoise(Channel channel) const override
void AddFilterFunction(const std::vector< TComplex > &filt)
void LocalToWorld(const double *plane, double *world) const
Transform point from local plane frame to world frame.
Definition: PlaneGeo.h:1343
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
QTextStream & endl(QTextStream &s)
Encapsulate the construction of a single detector plane.
TH1F * fFieldResponseHist[3]
Histogram used to hold the field response, hardcoded for the time being.