Public Member Functions | Private Attributes | List of all members
WireCell::SigProc::L1SPFilter Class Reference

#include <L1SPFilter.h>

Inheritance diagram for WireCell::SigProc::L1SPFilter:
WireCell::IFrameFilter WireCell::IConfigurable WireCell::IFunctionNode< IFrame, IFrame > WireCell::IComponent< IConfigurable > WireCell::IFunctionNodeBase WireCell::Interface WireCell::INode WireCell::IComponent< INode > WireCell::Interface

Public Member Functions

 L1SPFilter (double gain=14.0 *units::mV/units::fC, double shaping=2.2 *units::microsecond, double postgain=1.2, double ADC_mV=4096/(2000.*units::mV), double fine_time_offset=0.0 *units::microsecond, double coarse_time_offset=-8.0 *units::microsecond)
 
virtual ~L1SPFilter ()
 
virtual bool operator() (const input_pointer &in, output_pointer &out)
 IFrameFilter interface. More...
 
virtual void configure (const WireCell::Configuration &config)
 IConfigurable interface. More...
 
virtual WireCell::Configuration default_configuration () const
 Optional, override to return a hard-coded default configuration. More...
 
void init_resp ()
 
int L1_fit (std::shared_ptr< WireCell::SimpleTrace > &newtrace, std::shared_ptr< const WireCell::ITrace > &adctrace, int start_tick, int end_tick, bool flag_shorted=false)
 
- Public Member Functions inherited from WireCell::IFrameFilter
virtual ~IFrameFilter ()
 
virtual std::string signature ()
 Set the signature for all subclasses. More...
 
- Public Member Functions inherited from WireCell::IFunctionNode< IFrame, IFrame >
virtual ~IFunctionNode ()
 
virtual bool operator() (const boost::any &anyin, boost::any &anyout)
 The calling signature: More...
 
virtual std::vector< std::stringinput_types ()
 
virtual std::vector< std::stringoutput_types ()
 
- Public Member Functions inherited from WireCell::IFunctionNodeBase
virtual ~IFunctionNodeBase ()
 
virtual NodeCategory category ()
 Return the behavior category type. More...
 
virtual int concurrency ()
 By default assume all subclasses are stateless. More...
 
- Public Member Functions inherited from WireCell::INode
virtual ~INode ()
 
virtual void reset ()
 
- Public Member Functions inherited from WireCell::IComponent< INode >
virtual ~IComponent ()
 
- Public Member Functions inherited from WireCell::Interface
virtual ~Interface ()
 
- Public Member Functions inherited from WireCell::IConfigurable
virtual ~IConfigurable ()
 
- Public Member Functions inherited from WireCell::IComponent< IConfigurable >
virtual ~IComponent ()
 

Private Attributes

Configuration m_cfg
 
double m_gain
 
double m_shaping
 
double m_postgain
 
double m_ADC_mV
 
double m_fine_time_offset
 
double m_coarse_time_offset
 
double m_period
 
linterp< double > * lin_V
 
linterp< double > * lin_W
 

Additional Inherited Members

- Public Types inherited from WireCell::IFrameFilter
typedef std::shared_ptr< IFrameFilterpointer
 
- Public Types inherited from WireCell::IFunctionNode< IFrame, IFrame >
typedef IFrame input_type
 
typedef IFrame output_type
 
typedef std::shared_ptr< const IFrameinput_pointer
 
typedef std::shared_ptr< const IFrameoutput_pointer
 
typedef IFunctionNode< IFrame, IFramesignature_type
 
- Public Types inherited from WireCell::IFunctionNodeBase
typedef std::shared_ptr< IFunctionNodeBasepointer
 
- Public Types inherited from WireCell::INode
enum  NodeCategory {
  unknown, sourceNode, sinkNode, functionNode,
  queuedoutNode, joinNode, splitNode, faninNode,
  fanoutNode, multioutNode, hydraNode
}
 
- Public Types inherited from WireCell::IComponent< INode >
typedef std::shared_ptr< INodepointer
 Access subclass facet by pointer. More...
 
typedef std::vector< pointervector
 Vector of shared pointers. More...
 
- Public Types inherited from WireCell::Interface
typedef std::shared_ptr< Interfacepointer
 
- Public Types inherited from WireCell::IComponent< IConfigurable >
typedef std::shared_ptr< IConfigurablepointer
 Access subclass facet by pointer. More...
 
typedef std::vector< pointervector
 Vector of shared pointers. More...
 

Detailed Description

Definition at line 18 of file L1SPFilter.h.

Constructor & Destructor Documentation

L1SPFilter::L1SPFilter ( double  gain = 14.0 * units::mV/units::fC,
double  shaping = 2.2 * units::microsecond,
double  postgain = 1.2,
double  ADC_mV = 4096/(2000.*units::mV),
double  fine_time_offset = 0.0 * units::microsecond,
double  coarse_time_offset = -8.0 * units::microsecond 
)

Definition at line 25 of file L1SPFilter.cxx.

31  : m_gain(gain)
32  , m_shaping(shaping)
33  , m_postgain(postgain)
34  , m_ADC_mV(ADC_mV)
35  , m_fine_time_offset(fine_time_offset)
36  , m_coarse_time_offset(coarse_time_offset)
37  , lin_V(0)
38  , lin_W(0)
39 {
40 }
linterp< double > * lin_W
Definition: L1SPFilter.h:53
linterp< double > * lin_V
Definition: L1SPFilter.h:52
L1SPFilter::~L1SPFilter ( )
virtual

Definition at line 42 of file L1SPFilter.cxx.

43 {
44  delete lin_V;
45  delete lin_W;
46 }
linterp< double > * lin_W
Definition: L1SPFilter.h:53
linterp< double > * lin_V
Definition: L1SPFilter.h:52

Member Function Documentation

void L1SPFilter::configure ( const WireCell::Configuration config)
virtual

IConfigurable interface.

Implements WireCell::IConfigurable.

Definition at line 165 of file L1SPFilter.cxx.

166 {
167  m_cfg = cfg;
168 
169  m_gain = get(cfg,"gain",m_gain);
170  m_shaping = get(cfg,"shaping",m_shaping);
171  m_postgain = get(cfg,"postgain", m_postgain);
172  m_ADC_mV = get(cfg,"ADC_mV", m_ADC_mV);
173 
174  m_fine_time_offset = get(cfg,"fine_time_offset", m_fine_time_offset);
175  m_coarse_time_offset = get(cfg,"coarse_time_offset", m_coarse_time_offset);
176 }
cfg
Definition: dbjson.py:29
WireCell::Configuration L1SPFilter::default_configuration ( ) const
virtual

Optional, override to return a hard-coded default configuration.

Name of component providing field responses

An array holding a waveform to use as the "smearing" filter.

The tag identifying traces which represent "raw" (not deconvolved) ADC values.

The tag identifying traces which represent "signal" processed (deconvolved) waveforms.

The tag to place on the output waveforms

Reimplemented from WireCell::IConfigurable.

Definition at line 97 of file L1SPFilter.cxx.

98 {
100 
101  /// Name of component providing field responses
102  cfg["fields"] = "FieldResponse";
103 
104  /// An array holding a waveform to use as the "smearing" filter.
105  cfg["filter"] = Json::arrayValue;
106 
107  /// The tag identifying traces which represent "raw" (not
108  /// deconvolved) ADC values.
109  cfg["adctag"] = "raw";
110 
111  /// The tag identifying traces which represent "signal" processed
112  /// (deconvolved) waveforms.
113  cfg["sigtag"] = "gauss";
114 
115  /// The tag to place on the output waveforms
116  cfg["outtag"] = "l1sp";
117 
118  // 4 sigma for raw waveform ROI identification
119  cfg["raw_ROI_th_nsigma"] = 4;
120  // 10 ADC for upper limit on ADC ...
121  cfg["raw_ROI_th_adclimit"] = 10;
122  // global offset
123  cfg["overall_time_offset"] = 0;
124  // need 3 us offset for collection plane relative to the induction plane ...
125  cfg["collect_time_offset"] = 3.0;
126 
127  // ROI padding ticks ...
128  cfg["roi_pad"] = 3;
129  cfg["raw_pad"] = 15;
130 
131  // L1 fit parameters ...
132  cfg["adc_l1_threshold"] = 6;
133  cfg["adc_sum_threshold"] = 160;
134  cfg["adc_sum_rescaling"] = 90.;
135  cfg["adc_sum_rescaling_limit"] = 50.;
136  cfg["adc_ratio_threshold"] = 0.2;
137 
138  cfg["l1_seg_length"] = 120;
139  cfg["l1_scaling_factor"] = 500;
140  cfg["l1_lambda"] = 5;
141  cfg["l1_epsilon"] = 0.05;
142  cfg["l1_niteration"] = 100000;
143  cfg["l1_decon_limit"] = 100; // 100 electrons
144 
145  cfg["l1_resp_scale"] = 0.5;
146  cfg["l1_col_scale"] = 1.15;
147  cfg["l1_ind_scale"] = 0.5;
148 
149  cfg["peak_threshold"] = 1000;
150  cfg["mean_threshold"] = 500;
151 
152 
153  cfg["gain"] = m_gain;
154  cfg["shaping"] = m_shaping;
155  cfg["postgain"] = m_postgain;
156  cfg["ADC_mV"] = m_ADC_mV;
157 
158  cfg["fine_time_offset"] = m_fine_time_offset;
159  cfg["coarse_time_offset"] = m_coarse_time_offset;
160 
161 
162  return cfg;
163 }
cfg
Definition: dbjson.py:29
Json::Value Configuration
Definition: Configuration.h:50
void L1SPFilter::init_resp ( )

Definition at line 48 of file L1SPFilter.cxx.

48  {
49  if (lin_V==0 && lin_W==0){
50  // get field response ...
51  auto ifr = Factory::find_tn<IFieldResponse>(get<std::string>(m_cfg, "fields", "FieldResponse"));
52  Response::Schema::FieldResponse fr = ifr->field_response();
53  // Make a new data set which is the average FR, make an average for V and Y planes ...
55 
56  //get electronics response
58  WireCell::Binning tbins(Response::as_array(fravg.planes[0]).cols(), 0, Response::as_array(fravg.planes[0]).cols() * fravg.period);
60  auto ewave = ce.generate(tbins);
61  Waveform::scale(ewave, m_postgain * m_ADC_mV * (-1)); // ADC to electron ...
62  elec = Waveform::dft(ewave);
63 
64  std::complex<float> fine_period(fravg.period,0);
65 
66  // do a convolution here ...
67  WireCell::Waveform::realseq_t resp_V = fravg.planes[1].paths[0].current ;
68  WireCell::Waveform::realseq_t resp_W = fravg.planes[2].paths[0].current ;
69 
70  auto spectrum_V = WireCell::Waveform::dft(resp_V);
71  auto spectrum_W = WireCell::Waveform::dft(resp_W);
72 
73  WireCell::Waveform::scale(spectrum_V,elec);
74  WireCell::Waveform::scale(spectrum_W,elec);
75 
76  WireCell::Waveform::scale(spectrum_V,fine_period);
77  WireCell::Waveform::scale(spectrum_W,fine_period);
78 
79  // Now this response is ADC for 1 electron .
80  resp_V = WireCell::Waveform::idft(spectrum_V);
81  resp_W = WireCell::Waveform::idft(spectrum_W);
82 
83  // convolute with V and Y average responses ...
84  double intrinsic_time_offset = fravg.origin/fravg.speed;
85  //std::cout << intrinsic_time_offset << " " << m_fine_time_offset << " " << m_coarse_time_offset << " " << m_gain << " " << 14.0 * units::mV/units::fC << " " << m_shaping << " " << fravg.period << std::endl;
86 
87  double x0 = (- intrinsic_time_offset - m_coarse_time_offset + m_fine_time_offset);
88  double xstep = fravg.period;
89 
90  // boost::math::cubic_b_spline<double> spline_v(resp_V.begin(), resp_V.end(), x0, xstep);
91  // boost::math::cubic_b_spline<double> spline_w(resp_W.begin(), resp_W.end(), x0, xstep);
92  lin_V = new linterp<double>(resp_V.begin(), resp_V.end(), x0, xstep);
93  lin_W = new linterp<double>(resp_W.begin(), resp_W.end(), x0, xstep);
94  }
95 }
linterp< double > * lin_W
Definition: L1SPFilter.h:53
linterp< double > * lin_V
Definition: L1SPFilter.h:52
Sequence< real_t > realseq_t
Definition: Waveform.h:31
double period
The sampling period of the response function.
Definition: Response.h:92
A functional object caching gain and shape.
Definition: Response.h:165
Binning tbins(nticks, t0, t0+readout_time)
Array::array_xxf as_array(const Schema::PlaneResponse &pr)
Definition: Response.cxx:279
compseq_t dft(realseq_t seq)
Definition: Waveform.cxx:141
Schema::FieldResponse average_1D(const Schema::FieldResponse &fr)
Definition: Response.cxx:224
std::vector< PlaneResponse > planes
List of PlaneResponse objects.
Definition: Response.h:78
void scale(Sequence< Val > &seq, Val scalar)
Scale (multiply) sequence values by scalar.
Definition: Waveform.h:146
realseq_t idft(compseq_t spec)
Definition: Waveform.cxx:149
Sequence< complex_t > compseq_t
A complex-valued sequence, eg for discrete spectrum powers.
Definition: Waveform.h:34
Hold info about multiple plane responses in the detector.
Definition: Response.h:75
double speed
The nominal drift speed.
Definition: Response.h:95
int L1SPFilter::L1_fit ( std::shared_ptr< WireCell::SimpleTrace > &  newtrace,
std::shared_ptr< const WireCell::ITrace > &  adctrace,
int  start_tick,
int  end_tick,
bool  flag_shorted = false 
)

Definition at line 494 of file L1SPFilter.cxx.

494  {
495 
496  double overall_time_offset = get(m_cfg,"overall_time_offset",overall_time_offset) * units::us;
497  double collect_time_offset = get(m_cfg,"collect_time_offset",collect_time_offset) * units::us;
498  double adc_l1_threshold = get(m_cfg,"adc_l1_threshold",adc_l1_threshold);
499  double adc_sum_threshold= get(m_cfg,"adc_sum_threshold",adc_sum_threshold);
500  double adc_sum_rescaling= get(m_cfg,"adc_sum_rescaling",adc_sum_rescaling);
501  double adc_sum_rescaling_limit= get(m_cfg,"adc_sum_rescaling_limit",adc_sum_rescaling_limit);
502  double adc_ratio_threshold = get(m_cfg,"adc_ratio_threshold",adc_ratio_threshold);
503 
504  double l1_seg_length= get(m_cfg,"l1_seg_length",l1_seg_length);
505  double l1_scaling_factor= get(m_cfg,"l1_scaling_factor",l1_scaling_factor);
506  double l1_lambda= get(m_cfg,"l1_lambda",l1_lambda);
507  double l1_epsilon= get(m_cfg,"l1_epsilon",l1_epsilon);
508  double l1_niteration= get(m_cfg,"l1_niteration",l1_niteration);
509  double l1_decon_limit= get(m_cfg,"l1_decon_limit",l1_decon_limit);
510 
511  double l1_resp_scale = get(m_cfg,"l1_resp_scale",l1_resp_scale);
512  double l1_col_scale = get(m_cfg,"l1_col_scale",l1_col_scale);
513  double l1_ind_scale = get(m_cfg,"l1_ind_scale",l1_ind_scale);
514 
515  double mean_threshold = get(m_cfg,"mean_threshold",mean_threshold);
516  double peak_threshold = get(m_cfg,"peak_threshold",peak_threshold);
517 
518 
519  std::vector<double> smearing_vec = get< std::vector<double> >(m_cfg, "filter");
520 
521  // algorithm
522  const int nbin_fit = end_tick-start_tick;
523 
524  // fill the data ...
525  VectorXd init_W = VectorXd::Zero(nbin_fit);
526  VectorXd init_beta = VectorXd::Zero(nbin_fit);
527  VectorXd final_beta = VectorXd::Zero(nbin_fit*2);
528 
529  double temp_sum = 0;
530  double temp1_sum = 0;
531  double temp2_sum = 0;
532  double max_val = -1;
533  double min_val = 1;
534  for (int i=0; i!= nbin_fit; i++){
535  init_W(i) = adctrace->charge().at(i+start_tick-newtrace->tbin()) ;
536  init_beta(i) = newtrace->charge().at(i+start_tick-newtrace->tbin()) ;
537 
538  if (max_val < init_W(i)) max_val = init_W(i);
539  if (min_val > init_W(i)) min_val = init_W(i);
540 
541  if (fabs(init_W(i))>adc_l1_threshold) {
542  temp_sum += init_W(i);
543  temp1_sum += fabs(init_W(i));
544  temp2_sum += fabs(init_beta(i));
545  }
546  }
547 
548 
549 
550  int flag_l1 = 0; // do nothing
551  // 1 do L1
552  if (temp_sum/(temp1_sum*adc_sum_rescaling*1.0/nbin_fit)>adc_ratio_threshold && temp1_sum>adc_sum_threshold){
553  flag_l1 = 1; // do L1 ...
554  }else if (temp1_sum*adc_sum_rescaling*1.0/nbin_fit < adc_sum_rescaling_limit){
555  flag_l1 = 2; //remove signal ...
556  }else if (temp2_sum > 30 * nbin_fit && temp1_sum < 2.0*nbin_fit && max_val - min_val < 22){
557  flag_l1 = 2;
558  }
559 
560 
561 
562  // if (adctrace->channel() == 4079){
563  // std::cout << adctrace->channel() << " " << nbin_fit << " " << start_tick << " " << end_tick << " " << temp_sum << " " << temp1_sum << " " << temp2_sum << " " << max_val << " " << min_val << " " << flag_l1 << std::endl;
564  // }
565 
566  // std::cout << temp_sum << " " << temp1_sum << " " << temp_sum/(temp1_sum*adc_sum_rescaling*1.0/nbin_fit) << " " << adc_ratio_threshold << " " << temp1_sum*adc_sum_rescaling*1.0/nbin_fit << " " << flag_l1 << std::endl;
567 
568  if (flag_l1==1){
569  // do L1 fit ...
570  int n_section = std::round(nbin_fit/l1_seg_length*1.0);
571  if (n_section ==0) n_section =1;
572  std::vector<int> boundaries;
573  for (int i=0;i!=n_section;i++){
574  boundaries.push_back(int(i * nbin_fit /n_section));
575  }
576  boundaries.push_back(nbin_fit);
577 
578  for (int i=0;i!=n_section;i++){
579  int temp_nbin_fit = boundaries.at(i+1)-boundaries.at(i);
580  VectorXd W = VectorXd::Zero(temp_nbin_fit);
581  for (int j=0;j!=temp_nbin_fit;j++){
582  W(j) = init_W(boundaries.at(i)+j);
583  }
584 
585  //for matrix G
586  MatrixXd G = MatrixXd::Zero(temp_nbin_fit, temp_nbin_fit*2);
587 
588  for (int i=0;i!=temp_nbin_fit;i++){
589  // X
590  double t1 = i/2.*units::us; // us, measured time
591  for (int j=0;j!=temp_nbin_fit;j++){
592  // Y ...
593  double t2 = j/2.*units::us; // us, real signal time
594  double delta_t = t1 - t2;
595  if (delta_t >-15*units::us - overall_time_offset && delta_t < 10*units::us - overall_time_offset){
596  G(i,j) = (*lin_W)(delta_t+overall_time_offset+collect_time_offset) * l1_scaling_factor * l1_resp_scale;
597  G(i,temp_nbin_fit+j) = (*lin_V)(delta_t+overall_time_offset) * l1_scaling_factor * l1_resp_scale;
598  }
599  }
600  }
601 
602  double lambda = l1_lambda;//1/2.;
603  WireCell::LassoModel m2(lambda, l1_niteration, l1_epsilon);
604  m2.SetData(G, W);
605  m2.Fit();
606  VectorXd beta = m2.Getbeta();
607  for (int j=0;j!=temp_nbin_fit;j++){
608  final_beta(boundaries.at(i)+j) = beta(j);
609  final_beta(nbin_fit + boundaries.at(i)+j) = beta(temp_nbin_fit+j);
610  }
611  }
612 
613  double sum1 = 0;
614  double sum2 = 0;
615  for (int i=0;i!=nbin_fit;i++){
616  sum1 += final_beta(i);
617  sum2 += final_beta(nbin_fit+i);
618  }
619 
620  if (sum1 > adc_l1_threshold){
621  Waveform::realseq_t l1_signal(nbin_fit,0);
622  Waveform::realseq_t l2_signal(nbin_fit,0);
623  for (int j=0;j!=nbin_fit;j++){
624  l1_signal.at(j) = final_beta(j) * l1_col_scale + final_beta(nbin_fit+j) * l1_ind_scale;
625  }
626  int mid_bin = (smearing_vec.size()-1)/2;
627  //std::cout << smearing_vec.size() << " " << mid_bin << std::endl;
628  for (int j=0;j!=nbin_fit;j++){
629  double content = l1_signal.at(j);
630  if (content>0){
631  for (size_t k=0;k!=smearing_vec.size();k++){
632  int bin = j+k-mid_bin;
633  if (bin>=0&&bin<nbin_fit)
634  l2_signal.at(bin) += content * smearing_vec.at(k);
635  }
636  }
637  }
638 
639  for (int j=0;j!=nbin_fit;j++){
640  if (l2_signal.at(j)<l1_decon_limit/l1_scaling_factor){ // 50 electrons
641  l1_signal.at(j) = 0;
642  }else{
643  l1_signal.at(j) = l2_signal.at(j) * l1_scaling_factor;
644  }
645  }
646 
647  {
648  // go through the new data and clean the small peaks ...
649  std::vector<int> nonzero_bins;
650  std::vector<std::pair<int,int>> ROIs;
651  for (int j=0;j!=nbin_fit;j++){
652  if (l1_signal.at(j)>0)
653  nonzero_bins.push_back(j);
654  }
655 
656  bool flag_start = false;
657  int start_bin=-1,end_bin=-1;
658  for (size_t j=0;j!=nonzero_bins.size();j++){
659  if (!flag_start){
660  start_bin = nonzero_bins.at(j);
661  end_bin = nonzero_bins.at(j);
662  flag_start = true;
663  }else{
664  if (nonzero_bins.at(j) - end_bin == 1){
665  end_bin = nonzero_bins.at(j);
666  }else{
667  ROIs.push_back(std::make_pair(start_bin,end_bin));
668  start_bin = nonzero_bins.at(j);
669  end_bin = nonzero_bins.at(j);
670  }
671  }
672  }
673  if (start_bin >=0)
674  ROIs.push_back(std::make_pair(start_bin,end_bin));
675 
676  for (size_t j=0;j!=ROIs.size();j++){
677  double max_val = -1;
678  double mean_val1 = 0;
679  double mean_val2 = 0;
680  for (int k=ROIs.at(j).first; k<=ROIs.at(j).second; k++){
681  if (l1_signal.at(k) > max_val) max_val = l1_signal.at(k);
682  mean_val1 += l1_signal.at(k);
683  mean_val2 ++;
684  }
685  if (mean_val2!=0)
686  mean_val1 /= mean_val2;
687  if (max_val < peak_threshold && mean_val1 < mean_threshold){
688  for (int k=ROIs.at(j).first; k<=ROIs.at(j).second; k++){
689  l1_signal.at(k) = 0;
690  }
691  }
692  //std::cout << max_val << " " << mean_val1 << std::endl;
693 
694  }
695 
696  // std::cout << nonzero_bins.front() << " X " << nonzero_bins.back() << std::endl;
697  // std::cout << ROIs.size() << std::endl;
698  // for (size_t i=0;i!=ROIs.size();i++){
699  // std::cout << ROIs.at(i).first << " " << ROIs.at(i).second << std::endl;
700  // }
701 
702  // finish cleaning ...
703  }
704 
705 
706  for (int time_tick = start_tick; time_tick!= end_tick; time_tick++){
707  newtrace->charge().at(time_tick-newtrace->tbin())=l1_signal.at(time_tick-start_tick);
708  }
709  }
710  }else if (flag_l1==2){
711  if (flag_shorted){
712  for (int time_tick = start_tick; time_tick!= end_tick; time_tick++){
713  // temporary hack to reset the data ...
714  newtrace->charge().at(time_tick-newtrace->tbin())=0;
715  }
716  }
717  }
718 
719  return flag_l1;
720 
721 }
Sequence< real_t > realseq_t
Definition: Waveform.h:31
Val sum2(const Sequence< Val > &seq)
Return sum of square of all entries in sequence.
Definition: Waveform.h:184
static const double m2
Definition: Units.h:80
QTextStream & bin(QTextStream &s)
static const double us
Definition: Units.h:105
bool L1SPFilter::operator() ( const input_pointer in,
output_pointer out 
)
virtual

IFrameFilter interface.

here, use the ADC and signal traces to do L1SP put result in out_traces

Implements WireCell::IFunctionNode< IFrame, IFrame >.

Definition at line 178 of file L1SPFilter.cxx.

179 {
180  out = nullptr;
181  if (!in) {
182  return true; // eos
183  }
184 
185  std::string adctag = get<std::string>(m_cfg, "adctag");
186  std::string sigtag = get<std::string>(m_cfg, "sigtag");
187  std::string outtag = get<std::string>(m_cfg, "outtag");
188 
189 
190  // std::cout << smearing_vec.size() << std::endl;
191 
192  int roi_pad = 0;
193  roi_pad = get(m_cfg,"roi_pad",roi_pad);
194  int raw_pad = 0;
195  raw_pad = get(m_cfg,"raw_pad",raw_pad);
196 
197  double raw_ROI_th_nsigma = get(m_cfg,"raw_ROI_th_nsigma",raw_ROI_th_nsigma);
198  double raw_ROI_th_adclimit = get(m_cfg,"raw_ROI_th_adclimit",raw_ROI_th_adclimit);
199 
200 
201  // std::cout << "Xin: " << raw_ROI_th_nsigma << " " << raw_ROI_th_adclimit << " " << overall_time_offset << " " << collect_time_offset << " " << roi_pad << " " << adc_l1_threshold << " " << adc_sum_threshold << " " << adc_sum_rescaling << " " << adc_sum_rescaling_limit << " " << l1_seg_length << " " << l1_scaling_factor << " " << l1_lambda << " " << l1_epsilon << " " << l1_niteration << " " << l1_decon_limit << " " << l1_resp_scale << " " << l1_col_scale << " " << l1_ind_scale << std::endl;
202  init_resp();
203 
204 
205 
206 
207  // std::cout << (*lin_V)(0*units::us) << " " << (*lin_W)(0*units::us) << std::endl;
208  // std::cout << (*lin_V)(1*units::us) << " " << (*lin_W)(1*units::us) << std::endl;
209  // for (size_t i=0; i!=resp_V.size(); i++){
210  // std::cout << (i*fravg.period - intrinsic_time_offset - m_coarse_time_offset + m_fine_time_offset)/units::us << " " << resp_V.at(i) << " " << resp_W.at(i) << " " << ewave.at(i) << std::endl;
211  //}
212  // std::complex<float> fine_period(fravg.period,0);
213  // int fine_nticks = Response::as_array(fravg.planes[0]).cols();
214  // Waveform::realseq_t ftbins(fine_nticks);
215  // for (int i=0;i!=fine_nticks;i++){
216  // ftbins.at(i) = i * fravg.period;
217  //}
218 
219 
220 
221  auto adctraces = FrameTools::tagged_traces(in, adctag);
222  auto sigtraces = FrameTools::tagged_traces(in, sigtag);
223 
224  if (adctraces.empty() or sigtraces.empty() or adctraces.size() != sigtraces.size()) {
225  std::cerr << "L1SPFilter got unexpected input: "
226  << adctraces.size() << " ADC traces and "
227  << sigtraces.size() << " signal traces\n";
228  THROW(RuntimeError() << errmsg{"L1SPFilter: unexpected input"});
229  }
230 
231  m_period = in->tick();
232 
233  //std::cout << m_period/units::us << std::endl;
234 
235  /// here, use the ADC and signal traces to do L1SP
236  /// put result in out_traces
237  ITrace::vector out_traces;
238 
239  std::map<int,std::set<int>> init_map;
240  // do ROI from the decon signal
241  for (auto trace : sigtraces) {
242  int ch = trace->channel();
243  int tbin = trace->tbin();
244  auto const& charges = trace->charge();
245  const int ntbins = charges.size();
246  std::set<int> time_ticks;
247 
248  for (int qi = 0; qi < ntbins; qi++){
249  if (charges[qi]>0){
250  time_ticks.insert(tbin+qi);
251  }
252  }
253 
254  init_map[ch] = time_ticks;
255  // if (time_ticks.size()>0){
256  // std::cout << ch << " " << time_ticks.size() << std::endl;
257  // }
258  }
259 
260  // do ROI from the raw signal
261  int ntot_ticks=0;
262 
263  std::map<int,std::shared_ptr<const WireCell::ITrace>> adctrace_ch_map;
264 
265  for (auto trace : adctraces) {
266  int ch = trace->channel();
267 
268  adctrace_ch_map[ch] = trace;
269 
270  int tbin = trace->tbin();
271  auto const& charges = trace->charge();
272  const int ntbins = charges.size();
273  std::set<int>& time_ticks = init_map[ch];
274 
275  if (ntot_ticks < ntbins)
276  ntot_ticks = ntbins;
277 
278  Waveform::realseq_t tmp_charge = charges;
279  double mean = Waveform::percentile(tmp_charge,0.5);
280  double mean_p1sig = Waveform::percentile(tmp_charge,0.5+0.34);
281  double mean_n1sig = Waveform::percentile(tmp_charge,0.5-0.34);
282  double cut = raw_ROI_th_nsigma * sqrt((pow(mean_p1sig-mean,2)+pow(mean_n1sig-mean,2))/2.);
283  if (cut < raw_ROI_th_adclimit) cut = raw_ROI_th_adclimit;
284 
285  // if (ch==4090)
286  // std::cout << cut << " " << raw_pad << std::endl;
287 
288  for (int qi = 0; qi < ntbins; qi++){
289  if (fabs(charges[qi])>cut){
290  for (int qii = -raw_pad; qii!=raw_pad+1;qii++){
291  if (tbin+qi+qii >=0 && tbin+qi+qii<ntot_ticks)
292  time_ticks.insert(tbin+qi+qii);
293  }
294  }
295  }
296  // if (time_ticks.size()>0){
297  // std::cout << ch << " " << time_ticks.size() << std::endl;
298  // }
299  }
300 
301 
302  // create ROIs ...
303  std::map<int, std::vector<std::pair<int,int>>> map_ch_rois;
304 
305  for (auto it = init_map.begin(); it!=init_map.end(); it++){
306  int wire_index = it->first;
307  std::set<int>& time_slices_set = it->second;
308  if (time_slices_set.size()==0) continue;
309  std::vector<int> time_slices;
310  std::copy(time_slices_set.begin(), time_slices_set.end(), std::back_inserter(time_slices));
311 
312  std::vector<std::pair<int,int>> rois;
313  std::vector<std::pair<int,int>> rois_save;
314 
315  rois.push_back(std::make_pair(time_slices.front(),time_slices.front()));
316  for (size_t i=1; i<time_slices.size();i++){
317  if (time_slices.at(i) - rois.back().second <= roi_pad*2){
318  rois.back().second = time_slices.at(i);
319  }else{
320  rois.push_back(std::make_pair(time_slices.at(i),time_slices.at(i)));
321  }
322  }
323 
324  // extend the rois to both side according to the bin content
325  for (auto it = rois.begin(); it!= rois.end(); it++){
326  int start_bin = it->first;
327  int end_bin = it->second;
328  start_bin = start_bin - roi_pad;
329  end_bin = end_bin + roi_pad;
330  if (start_bin <0) start_bin = 0;
331  if (end_bin>ntot_ticks-1) end_bin = ntot_ticks-1;
332  it->first = start_bin;
333  it->second = end_bin;
334  }
335 
336  for (auto it = rois.begin(); it!= rois.end(); it++){
337  if (rois_save.size()==0){
338  rois_save.push_back(*it);
339  }else if (it->first <= rois_save.back().second){
340  rois_save.back().second = it->second;
341  }else{
342  rois_save.push_back(*it);
343  }
344  }
345 
346  if (rois_save.size()>0)
347  map_ch_rois[wire_index] = rois_save;
348  // for (auto it = rois_save.begin(); it!=rois_save.end(); it++){
349  // std::cout << wire_index << " " << it->first << " " << it->second +1 << std::endl;
350  // }
351  }
352 
353 
354  std::map<int, std::vector<int> > map_ch_flag_rois;
355  // prepare for the output signal ...
356  for (auto trace : sigtraces) {
357  auto newtrace = std::make_shared<SimpleTrace>(trace->channel(), trace->tbin(), trace->charge());
358  // How to access the sigtraces together ???
359  if (map_ch_rois.find(trace->channel()) != map_ch_rois.end()){
360  std::vector<std::pair<int,int>>& rois_save = map_ch_rois[trace->channel()];
361  std::vector<int> flag_rois;
362  map_ch_flag_rois[trace->channel()] = flag_rois;
363 
364  bool flag_shorted = false;
365  for (size_t i1 = 0; i1!=rois_save.size(); i1++){
366  //
367 
368  int temp_flag = L1_fit(newtrace, adctrace_ch_map[trace->channel()], rois_save.at(i1).first, rois_save.at(i1).second+1, flag_shorted);
369  map_ch_flag_rois[trace->channel()].push_back(temp_flag);
370 
371  for (int time_tick = rois_save.at(i1).first; time_tick!=rois_save.at(i1).second+1; time_tick++){
372  // temporary hack to reset the data ...
373  if (newtrace->charge().at(time_tick-trace->tbin())<0)
374  newtrace->charge().at(time_tick-trace->tbin())=0;
375  }
376  }
377 
378 
379  flag_shorted = false;
380  int prev_time_tick = -2000;
381  for (size_t i1 = 0; i1!=rois_save.size(); i1++){
382  if (rois_save.at(i1).first - prev_time_tick > 20) flag_shorted = false;
383 
384  if (map_ch_flag_rois[trace->channel()].at(i1)==1){
385  flag_shorted = true;
386  }else if (map_ch_flag_rois[trace->channel()].at(i1)==2){
387  if (flag_shorted){
388  L1_fit(newtrace, adctrace_ch_map[trace->channel()], rois_save.at(i1).first, rois_save.at(i1).second+1, flag_shorted);
389  map_ch_flag_rois[trace->channel()].at(i1) = 0;
390  }
391  }else if (map_ch_flag_rois[trace->channel()].at(i1)==0){
392  flag_shorted = false;
393  }
394  prev_time_tick = rois_save.at(i1).second;
395  }
396 
397  if (rois_save.size()>0){
398  prev_time_tick = rois_save.back().second + 2000;
399 
400  for (size_t i1 = 0; i1!=rois_save.size(); i1++){
401  if (prev_time_tick - rois_save.at(rois_save.size()-1-i1).second > 20) flag_shorted = false;
402 
403  if (map_ch_flag_rois[trace->channel()].at(i1)==1){
404  flag_shorted = true;
405  }else if (map_ch_flag_rois[trace->channel()].at(i1)==2){
406  if (flag_shorted){
407  L1_fit(newtrace, adctrace_ch_map[trace->channel()], rois_save.at(i1).first, rois_save.at(i1).second+1, flag_shorted);
408  map_ch_flag_rois[trace->channel()].at(i1) = 0;
409  }
410  }else if (map_ch_flag_rois[trace->channel()].at(i1)==0){
411  flag_shorted = false;
412  }
413  prev_time_tick = rois_save.at(i1).first;
414  }
415  }
416 
417 
418 
419  }
420 
421 
422  // std::cout << trace->channel() << std::endl;
423  out_traces.push_back(newtrace);
424  }
425 
426  for (size_t i2 = 0; i2!=out_traces.size(); i2++){
427  auto new_trace = std::make_shared<SimpleTrace>(out_traces.at(i2)->channel(), out_traces.at(i2)->tbin(), out_traces.at(i2)->charge());
428  int ch = out_traces.at(i2)->channel();
429  if (map_ch_rois.find(ch) != map_ch_rois.end()){
430  std::vector<std::pair<int,int>>& rois_save = map_ch_rois[ch];
431  std::vector<std::pair<int,int> > next_rois_save;
432  if (map_ch_rois.find(ch+1)!=map_ch_rois.end())
433  next_rois_save = map_ch_rois[ch+1];
434  std::vector<std::pair<int,int> > prev_rois_save;
435  if (map_ch_rois.find(ch-1)!=map_ch_rois.end())
436  prev_rois_save = map_ch_rois[ch-1];
437 
438  for (size_t i1 = 0; i1!=rois_save.size(); i1++){
439  if ( map_ch_flag_rois[ch].at(i1) == 2 ){
440  bool flag_shorted = false;
441  // need to check now ...
442  for (size_t i3 = 0; i3 != next_rois_save.size(); i3++){
443  if (map_ch_flag_rois[ch+1].at(i3)==1){
444  if (rois_save.at(i1).first - 3 <= next_rois_save.at(i3).second + 3 &&
445  rois_save.at(i1).second + 3 >= next_rois_save.at(i3).first - 3){
446  flag_shorted = true;
447  break;
448  }
449  }
450  }
451  if (!flag_shorted)
452  for (size_t i3 = 0; i3 != prev_rois_save.size(); i3++){
453  if (map_ch_flag_rois[ch-1].at(i3)==1){
454  if (rois_save.at(i1).first - 3 <= prev_rois_save.at(i3).second + 3 &&
455  rois_save.at(i1).second + 3 >= prev_rois_save.at(i3).first - 3){
456  flag_shorted = true;
457  break;
458  }
459  }
460  }
461  if(flag_shorted){
462  for (int time_tick = rois_save.at(i1).first; time_tick!=rois_save.at(i1).second+1; time_tick++){
463  new_trace->charge().at(time_tick-out_traces.at(i2)->tbin())=0;
464  }
465  }
466  }
467  }
468  }
469  out_traces.at(i2) = new_trace;
470  }
471 
472 
473 
474  std::cerr << "L1SPFilter: frame: " << in->ident() << " "
475  << adctag << "[" << adctraces.size() << "] + "
476  << sigtag << "[" << sigtraces.size() << "] --> "
477  << outtag << "[" << out_traces.size() << "]\n";
478 
479 
480 
481  // Finally, we save the traces to an output frame with tags.
482 
483  IFrame::trace_list_t tl(out_traces.size());
484  std::iota(tl.begin(), tl.end(), 0);
485 
486  auto sf = new SimpleFrame(in->ident(), in->time(), out_traces, in->tick());
487  sf->tag_traces(outtag, tl);
488  out = IFrame::pointer(sf);
489 
490  return true;
491 }
ITrace::vector tagged_traces(IFrame::pointer frame, IFrame::tag_t tag)
Definition: FrameTools.cxx:111
std::shared_ptr< const IFrame > pointer
Definition: IData.h:19
Sequence< real_t > realseq_t
Definition: Waveform.h:31
void tag_traces(const tag_t &tag, const IFrame::trace_list_t &indices, const IFrame::trace_summary_t &summary=IFrame::trace_summary_t(0))
Definition: SimpleFrame.cxx:76
std::string string
Definition: nybbler.cc:12
boost::error_info< struct tag_errmsg, std::string > errmsg
Definition: Exceptions.h:54
constexpr T pow(T x)
Definition: pow.h:72
std::vector< pointer > vector
Definition: IData.h:21
#define THROW(e)
Definition: Exceptions.h:25
real_t percentile(realseq_t &wave, real_t percentage)
Definition: Waveform.cxx:87
int L1_fit(std::shared_ptr< WireCell::SimpleTrace > &newtrace, std::shared_ptr< const WireCell::ITrace > &adctrace, int start_tick, int end_tick, bool flag_shorted=false)
Definition: L1SPFilter.cxx:494
T copy(T const &v)
Thrown when an error occurs during the data processing.
Definition: Exceptions.h:49
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:80
std::vector< size_t > trace_list_t
Definition: IFrame.h:36
double mean(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:15

Member Data Documentation

linterp<double>* WireCell::SigProc::L1SPFilter::lin_V
private

Definition at line 52 of file L1SPFilter.h.

linterp<double>* WireCell::SigProc::L1SPFilter::lin_W
private

Definition at line 53 of file L1SPFilter.h.

double WireCell::SigProc::L1SPFilter::m_ADC_mV
private

Definition at line 47 of file L1SPFilter.h.

Configuration WireCell::SigProc::L1SPFilter::m_cfg
private

Definition at line 42 of file L1SPFilter.h.

double WireCell::SigProc::L1SPFilter::m_coarse_time_offset
private

Definition at line 49 of file L1SPFilter.h.

double WireCell::SigProc::L1SPFilter::m_fine_time_offset
private

Definition at line 48 of file L1SPFilter.h.

double WireCell::SigProc::L1SPFilter::m_gain
private

Definition at line 44 of file L1SPFilter.h.

double WireCell::SigProc::L1SPFilter::m_period
private

Definition at line 50 of file L1SPFilter.h.

double WireCell::SigProc::L1SPFilter::m_postgain
private

Definition at line 46 of file L1SPFilter.h.

double WireCell::SigProc::L1SPFilter::m_shaping
private

Definition at line 45 of file L1SPFilter.h.


The documentation for this class was generated from the following files: