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