Public Member Functions | Private Attributes | List of all members
WireCell::Gen::ImpactZipper Class Reference

#include <ImpactZipper.h>

Public Member Functions

 ImpactZipper (IPlaneImpactResponse::pointer pir, BinnedDiffusion &bd)
 
virtual ~ImpactZipper ()
 
Waveform::realseq_t waveform (int wire) const
 

Private Attributes

IPlaneImpactResponse::pointer m_pir
 
BinnedDiffusionm_bd
 

Detailed Description

An ImpactZipper "zips" up through all the impact positions along a wire plane convolving the response functions and the local drifted charge distribution producing a waveform on each central wire.

Definition at line 16 of file ImpactZipper.h.

Constructor & Destructor Documentation

Gen::ImpactZipper::ImpactZipper ( IPlaneImpactResponse::pointer  pir,
BinnedDiffusion bd 
)

Definition at line 8 of file ImpactZipper.cxx.

9  :m_pir(pir), m_bd(bd)
10 {
11 
12 }
IPlaneImpactResponse::pointer m_pir
Definition: ImpactZipper.h:18
BinnedDiffusion & m_bd
Definition: ImpactZipper.h:19
Gen::ImpactZipper::~ImpactZipper ( )
virtual

Definition at line 16 of file ImpactZipper.cxx.

17 {
18 }

Member Function Documentation

Waveform::realseq_t Gen::ImpactZipper::waveform ( int  wire) const

Return the wire's waveform. If the response functions are just field response (ie, instantaneous current) then the waveforms are expressed as current integrated over each sample bin and thus in units of charge. If the response functions include electronics response then the waveforms are in units of voltage representing the sampling of the output of the FEE amplifiers.

Definition at line 21 of file ImpactZipper.cxx.

22 {
23  const double pitch_range = m_pir->pitch_range();
24 
25  const auto pimpos = m_bd.pimpos();
26  const auto rb = pimpos.region_binning();
27  const auto ib = pimpos.impact_binning();
28  const double wire_pos = rb.center(iwire);
29 
30  const int min_impact = ib.edge_index(wire_pos - 0.5*pitch_range);
31  const int max_impact = ib.edge_index(wire_pos + 0.5*pitch_range);
32  const int nsamples = m_bd.tbins().nbins();
33  Waveform::compseq_t total_spectrum(nsamples, Waveform::complex_t(0.0,0.0));
34 
35 
36  int nfound=0;
37  const bool share=true;
38  const Waveform::complex_t complex_one_half(0.5,0.0);
39 
40  // The BinnedDiffusion is indexed by absolute impact and the
41  // PlaneImpactResponse relative impact.
42  for (int imp = min_impact; imp <= max_impact; ++imp) {
43 
44  // ImpactData
45  auto id = m_bd.impact_data(imp);
46  if (!id) {
47  // common as we are scanning all impacts covering a wire
48  // fixme: is there a way to predict this to avoid the query?
49  //std::cerr << "ImpactZipper: no data for absolute impact number: " << imp << std::endl;
50  continue;
51  }
52 
53  const Waveform::compseq_t& charge_spectrum = id->spectrum();
54  // for interpolation
55  const Waveform::compseq_t& weightcharge_spectrum = id->weight_spectrum();
56 
57  if (charge_spectrum.empty()) {
58  // should not happen
59  std::cerr << "ImpactZipper: no charge for absolute impact number: " << imp << std::endl;
60  continue;
61  }
62  if (weightcharge_spectrum.empty()) {
63  // weight == 0, should not happen
64  std::cerr << "ImpactZipper: no weight charge for absolute impact number: " << imp << std::endl;
65  continue;
66  }
67 
68  const double imp_pos = ib.center(imp);
69  const double rel_imp_pos = imp_pos - wire_pos;
70  //std::cerr << "IZ: " << " imp=" << imp << " imp_pos=" << imp_pos << " rel_imp_pos=" << rel_imp_pos << std::endl;
71 
72  Waveform::compseq_t conv_spectrum(nsamples, Waveform::complex_t(0.0,0.0));
73  if (share) { // fixme: make a configurable option
74  TwoImpactResponses two_ir = m_pir->bounded(rel_imp_pos);
75  if (!two_ir.first || !two_ir.second) {
76  //std::cerr << "ImpactZipper: no impact response for absolute impact number: " << imp << std::endl;
77  continue;
78  }
79  // fixme: this is average, not interpolation.
80  Waveform::compseq_t rs1 = two_ir.first->spectrum();
81  Waveform::compseq_t rs2 = two_ir.second->spectrum();
82 
83  for (int ind=0; ind < nsamples; ++ind) {
84  //conv_spectrum[ind] = complex_one_half*(rs1[ind]+rs2[ind])*charge_spectrum[ind];
85 
86  // linear interpolation: wQ*rs1 + (Q-wQ)*rs2
87  conv_spectrum[ind] = weightcharge_spectrum[ind]*rs1[ind]+(charge_spectrum[ind]-weightcharge_spectrum[ind])*rs2[ind];
88  /* debugging */
89  /* if(iwire == 1000 && ind>1000 && ind<2000) { */
90  /* std::cerr<<"rs1 spectrum: "<<imp<<"|"<<ind<<": "<<std::abs(rs1[ind])<<std::endl; */
91  /* std::cerr<<"rs2 spectrum: "<<imp<<"|"<<ind<<": "<<std::abs(rs2[ind])<<std::endl; */
92  /* std::cerr<<"rs1 charge spectrum "<<ind<<": "<<weightcharge_spectrum[ind]<<std::endl; */
93  /* std::cerr<<"rs2 charge spectrum "<<ind<<": "<<charge_spectrum[ind]-weightcharge_spectrum[ind]<<std::endl; */
94  /* //std::cerr<<"rs1 charge spectrum "<<ind<<": "<<complex_one_half*charge_spectrum[ind]<<std::endl; */
95  /* //std::cerr<<"rs2 charge spectrum "<<ind<<": "<<complex_one_half*charge_spectrum[ind]<<std::endl; */
96  /* } */
97  }
98  }
99  else {
100  auto ir = m_pir->closest(rel_imp_pos);
101  if (! ir) {
102  // std::cerr << "ImpactZipper: no impact response for absolute impact number: " << imp << std::endl;
103  continue;
104  }
105  Waveform::compseq_t response_spectrum = ir->spectrum();
106  for (int ind=0; ind < nsamples; ++ind) {
107  conv_spectrum[ind] = response_spectrum[ind]*charge_spectrum[ind];
108  }
109  }
110 
111  ++nfound;
112  // std::cerr << "ImpactZipper: found:"<<nfound<<" for absolute impact number " << imp
113  // << " csize=" << csize << " rsize=" << rsize << " rebin=" << rebinfactor
114  // << std::endl;
115 
116  Waveform::increase(total_spectrum, conv_spectrum);
117  }
118  //std::cerr << "ImpactZipper: found " << nfound << " in abs impact: [" << min_impact << ","<< max_impact << "]\n";
119 
120  // Clear memory assuming next call is iwire+1.
121  // fixme: this is a dumb way to go. Better to make an iterator.
122  m_bd.erase(0, min_impact);
123 
124  if (!nfound) {
125  return Waveform::realseq_t(nsamples, 0.0);
126  }
127 
128  auto waveform = Waveform::idft(total_spectrum);
129 
130  return waveform;
131 }
Sequence< real_t > realseq_t
Definition: Waveform.h:31
double center(int ind) const
Definition: Binning.h:86
const Binning & region_binning() const
Definition: Pimpos.h:109
void erase(int begin_impact_index, int end_impact_index)
IPlaneImpactResponse::pointer m_pir
Definition: ImpactZipper.h:18
const Binning & impact_binning() const
Definition: Pimpos.h:113
void increase(Sequence< Val > &seq, Val scalar)
Increase (shift) sequence values by scalar.
Definition: Waveform.h:129
std::pair< IImpactResponse::pointer, IImpactResponse::pointer > TwoImpactResponses
const Pimpos & pimpos() const
ImpactData::pointer impact_data(int bin) const
realseq_t idft(compseq_t spec)
Definition: Waveform.cxx:149
Pimpos pimpos(nwires, min_wire_pitch, max_wire_pitch)
const Binning & tbins() const
Waveform::realseq_t waveform(int wire) const
BinnedDiffusion & m_bd
Definition: ImpactZipper.h:19
std::complex< float > complex_t
The type for the spectrum in each bin.
Definition: Waveform.h:21
int nbins() const
Definition: Binning.h:42
Sequence< complex_t > compseq_t
A complex-valued sequence, eg for discrete spectrum powers.
Definition: Waveform.h:34
QTextStream & endl(QTextStream &s)

Member Data Documentation

BinnedDiffusion& WireCell::Gen::ImpactZipper::m_bd
private

Definition at line 19 of file ImpactZipper.h.

IPlaneImpactResponse::pointer WireCell::Gen::ImpactZipper::m_pir
private

Definition at line 18 of file ImpactZipper.h.


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