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

#include <PlaneImpactResponse.h>

Inheritance diagram for WireCell::Gen::PlaneImpactResponse:
WireCell::IPlaneImpactResponse WireCell::IConfigurable WireCell::IComponent< IPlaneImpactResponse > WireCell::IComponent< IConfigurable > WireCell::Interface WireCell::Interface

Public Types

typedef std::vector< int > region_indices_t
 
typedef std::vector< region_indices_twire_region_indicies_t
 
- Public Types inherited from WireCell::IComponent< IPlaneImpactResponse >
typedef std::shared_ptr< IPlaneImpactResponsepointer
 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...
 

Public Member Functions

 PlaneImpactResponse (int plane_ident=0, size_t nbins=10000, double tick=0.5 *units::us)
 
 ~PlaneImpactResponse ()
 
virtual void configure (const WireCell::Configuration &cfg)
 Accept a configuration. More...
 
virtual WireCell::Configuration default_configuration () const
 Optional, override to return a hard-coded default configuration. More...
 
virtual IImpactResponse::pointer closest (double relpitch) const
 
virtual TwoImpactResponses bounded (double relpitch) const
 
double pitch_range () const
 
double pitch () const
 
double impact () const
 
int nwires () const
 The number of wires that span the pitch range. More...
 
size_t nbins () const
 
int nimp_per_wire () const
 not in the interface More...
 
const wire_region_indicies_tbywire_map () const
 
std::pair< int, int > closest_wire_impact (double relpitch) const
 
- Public Member Functions inherited from WireCell::IPlaneImpactResponse
virtual ~IPlaneImpactResponse ()
 
- Public Member Functions inherited from WireCell::IComponent< IPlaneImpactResponse >
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 Member Functions

void build_responses ()
 

Private Attributes

std::string m_frname
 
std::vector< std::stringm_short
 
double m_overall_short_padding
 
std::vector< std::stringm_long
 
double m_long_padding
 
int m_plane_ident
 
size_t m_nbins
 
double m_tick
 
wire_region_indicies_t m_bywire
 
std::vector< IImpactResponse::pointerm_ir
 
double m_half_extent
 
double m_pitch
 
double m_impact
 
Log::logptr_t l
 

Detailed Description

Collection of all impact responses for a plane

Definition at line 53 of file PlaneImpactResponse.h.

Member Typedef Documentation

Definition at line 99 of file PlaneImpactResponse.h.

Definition at line 100 of file PlaneImpactResponse.h.

Constructor & Destructor Documentation

Gen::PlaneImpactResponse::PlaneImpactResponse ( int  plane_ident = 0,
size_t  nbins = 10000,
double  tick = 0.5*units::us 
)

Create a PlaneImpactResponse.

Field response is assumed to be normalized in units of current.

Pre-amplifier gain and peaking time is that of the FE electronics. The preamp gain should be in units consistent with the field response. If 0.0 then no electronics response will be convolved.

A flat post-FEE amplifier gain can also be given to provide a global scaling of the output of the electronics.

Fixme: field response should be provided by a component.

Definition at line 34 of file PlaneImpactResponse.cxx.

Gen::PlaneImpactResponse::~PlaneImpactResponse ( )

Definition at line 253 of file PlaneImpactResponse.cxx.

254 {
255 }

Member Function Documentation

TwoImpactResponses Gen::PlaneImpactResponse::bounded ( double  relpitch) const
virtual

Return the two responses which are associated with the impact positions on either side of the given pitch location (measured relative to the wire of interest).

Implements WireCell::IPlaneImpactResponse.

Definition at line 302 of file PlaneImpactResponse.cxx.

303 {
304  if (relpitch < -m_half_extent || relpitch > m_half_extent) {
305  return TwoImpactResponses(nullptr, nullptr);
306  }
307 
308  std::pair<int,int> wi = closest_wire_impact(relpitch);
309 
310  auto region = m_bywire[wi.first];
311  if (wi.second == 0) {
312  return std::make_pair(m_ir[region[0]], m_ir[region[1]]);
313  }
314  if (wi.second == (int)region.size()-1) {
315  return std::make_pair(m_ir[region[wi.second-1]], m_ir[region[wi.second]]);
316  }
317 
318  const double absimpact = m_half_extent + relpitch - wi.first*m_pitch;
319  const double sign = absimpact - wi.second*m_impact;
320 
321  if (sign > 0) {
322  return TwoImpactResponses(m_ir[region[wi.second]], m_ir[region[wi.second+1]]);
323  }
324  return TwoImpactResponses(m_ir[region[wi.second-1]], m_ir[region[wi.second]]);
325 }
std::pair< IImpactResponse::pointer, IImpactResponse::pointer > TwoImpactResponses
std::pair< int, int > closest_wire_impact(double relpitch) const
int sign(double val)
Definition: UtilFunc.cxx:104
std::vector< IImpactResponse::pointer > m_ir
void Gen::PlaneImpactResponse::build_responses ( )
private

FIXME: this assumes impact positions are on uniform grid!

FIXME: this assumes paths are ordered by pitch

FIXME: this assumes detailed ordering of paths w/in one wire

Definition at line 97 of file PlaneImpactResponse.cxx.

98 {
99  auto ifr = Factory::find_tn<IFieldResponse>(m_frname);
100 
101  const size_t n_short_length = fft_best_length(m_overall_short_padding/m_tick);
102 
103  // build "short" response spectra
104  WireCell::Waveform::compseq_t short_spec(n_short_length, Waveform::complex_t(1.0, 0.0));
105  const size_t nshort = m_short.size();
106  for (size_t ind=0; ind<nshort; ++ind) {
107  const auto& name = m_short[ind];
108  auto iw = Factory::find_tn<IWaveform>(name);
109  if (std::abs(iw->waveform_period() - m_tick) > 1*units::ns) {
110  l->critical("from {} got {} us sample period expected {} us",
111  name, iw->waveform_period()/units::us, m_tick/units::us);
112  THROW(ValueError() << errmsg{"Tick mismatch in " + name});
113  }
114  auto wave = iw->waveform_samples(); // copy
115  if (wave.size() != n_short_length) {
116  l->debug("PIR: short response {} has different number of samples ({}) than expected ({})", name, wave.size(), n_short_length);
117  wave.resize(n_short_length, 0);
118  }
119  // note: we are ignoring waveform_start which will introduce
120  // an arbitrary phase shift....
121  auto spec = Waveform::dft(wave);
122  for (size_t ibin=0; ibin < n_short_length; ++ibin) {
123  short_spec[ibin] *= spec[ibin];
124  }
125  }
126 
127 
128  // build "long" response spectrum in time domain ...
129  size_t n_long_length = fft_best_length(m_nbins);
130  WireCell::Waveform::compseq_t long_spec(n_long_length, Waveform::complex_t(1.0, 0.0));
131  const size_t nlong = m_long.size();
132  for (size_t ind=0; ind<nlong; ++ind) {
133  const auto& name = m_long[ind];
134  auto iw = Factory::find_tn<IWaveform>(name);
135  if (std::abs(iw->waveform_period() - m_tick) > 1*units::ns) {
136  l->critical("from {} got {} us sample period expected {} us",
137  name, iw->waveform_period()/units::us, m_tick/units::us);
138  THROW(ValueError() << errmsg{"Tick mismatch in " + name});
139  }
140  auto wave = iw->waveform_samples(); // copy
141  if (wave.size() != n_long_length) {
142  l->debug("PIR: long response {} has different number of samples ({}) than expected ({})", name, wave.size(), n_long_length);
143  wave.resize(n_long_length, 0);
144  }
145  // note: we are ignoring waveform_start which will introduce
146  // an arbitrary phase shift....
147  auto spec = Waveform::dft(wave);
148  for (size_t ibin=0; ibin < n_long_length; ++ibin) {
149  long_spec[ibin] *= spec[ibin];
150  }
151 
152  }
154  if (nlong >0)
155  long_wf = Waveform::idft(long_spec);
156 
157 
158  const auto& fr = ifr->field_response();
159  const auto& pr = *fr.plane(m_plane_ident);
160  const int npaths = pr.paths.size();
161 
162  // FIXME HUGE ASSUMPTIONS ABOUT ORGANIZATION OF UNDERLYING
163  // FIELD RESPONSE DATA!!!
164  //
165  // Paths must be in increasing pitch with one impact position at
166  // nearest wire and 5 more impact positions equally spaced and at
167  // smaller pitch distances than the associated wire. The final
168  // impact position should be no further from the wire than 1/2
169  // pitch.
170 
171  const int n_per = 6; // fixme: assumption
172  const int n_wires = npaths/n_per;
173  const int n_wires_half = n_wires / 2; // integer div
174  //const int center_index = n_wires_half * n_per;
175 
176  /// FIXME: this assumes impact positions are on uniform grid!
177  m_impact = std::abs(pr.paths[1].pitchpos - pr.paths[0].pitchpos);
178  /// FIXME: this assumes paths are ordered by pitch
179  m_half_extent = std::max(std::abs(pr.paths.front().pitchpos),
180  std::abs(pr.paths.back().pitchpos));
181  /// FIXME: this assumes detailed ordering of paths w/in one wire
182  m_pitch = 2.0*std::abs(pr.paths[n_per-1].pitchpos - pr.paths[0].pitchpos);
183 
184 
185  // native response time binning
186  const int rawresp_size = pr.paths[0].current.size();
187  const double rawresp_min = fr.tstart;
188  const double rawresp_tick = fr.period;
189  const double rawresp_max = rawresp_min + rawresp_size*rawresp_tick;
190  Binning rawresp_bins(rawresp_size, rawresp_min, rawresp_max);
191 
192  // collect paths and index by wire and impact position.
193  std::map<int, region_indices_t> wire_to_ind;
194  for (int ipath = 0; ipath < npaths; ++ipath) {
195  const Response::Schema::PathResponse& path = pr.paths[ipath];
196  const int wirenum = int(ceil(path.pitchpos/pr.pitch)); // signed
197  wire_to_ind[wirenum].push_back(ipath);
198 
199  // match response sampling to digi and zero-pad
200  WireCell::Waveform::realseq_t wave(n_short_length, 0.0);
201  for (int rind=0; rind<rawresp_size; ++rind) { // sample at fine bins of response function
202  const double time = rawresp_bins.center(rind);
203 
204  // fixme: assumes field response appropriately centered
205  const size_t bin = time/m_tick;
206 
207  if (bin>= n_short_length) {
208  l->warn("PIR: out of bounds field response bin={}, ntbins={}, time={} us, tick={} us", bin, n_short_length, time/units::us, m_tick/units::us);
209  }
210 
211 
212  // Here we have sampled, instantaneous induced *current*
213  // (in WCT system-of-units for current) due to a single
214  // drifting electron from the field response function.
215  const double induced_current = path.current[rind];
216 
217  // Integrate across the fine time bin to get the element
218  // of induced *charge* over this bin.
219  const double induced_charge = induced_current*rawresp_tick;
220 
221  // sum up over coarse ticks.
222  wave[bin] += induced_charge;
223  }
225 
226  // Convolve with short responses
227  if (nshort) {
228  for (size_t find=0; find < n_short_length; ++find) {
229  spec[find] *= short_spec[find];
230  }
231  }
233  wf.resize(m_nbins,0);
234 
235  IImpactResponse::pointer ir = std::make_shared<Gen::ImpactResponse>(ipath, wf, m_overall_short_padding/m_tick, long_wf, m_long_padding/m_tick);
236  m_ir.push_back(ir);
237  }
238 
239  // apply symmetry.
240  for (int irelwire=-n_wires_half; irelwire <= n_wires_half; ++irelwire) {
241  auto direct = wire_to_ind[irelwire];
242  auto other = wire_to_ind[-irelwire];
243 
244  std::vector<int> indices(direct.begin(), direct.end());
245  for (auto it = other.rbegin()+1; it != other.rend(); ++it) {
246  indices.push_back(*it);
247  }
248  m_bywire.push_back(indices);
249  }
250 
251 }
static QCString name
Definition: declinfo.cpp:673
std::shared_ptr< IImpactResponse > pointer
Access subclass facet by pointer.
Definition: IComponent.h:33
Sequence< real_t > realseq_t
Definition: Waveform.h:31
boost::error_info< struct tag_errmsg, std::string > errmsg
Definition: Exceptions.h:54
std::size_t fft_best_length(size_t nsamples, bool keep_odd_even=false)
uint size() const
Definition: qcstring.h:201
T abs(T value)
compseq_t dft(realseq_t seq)
Definition: Waveform.cxx:141
Configuration find(Configuration &lst, const std::string &dotpath, const T &val)
Return dictionary in given list if it value at dotpath matches.
double pitchpos
The position in the pitch direction to the starting point of the path.
Definition: Response.h:36
constexpr std::array< std::size_t, geo::vect::dimension< Vector >)> indices()
Returns a sequence of indices valid for a vector of the specified type.
#define THROW(e)
Definition: Exceptions.h:25
static int max(int a, int b)
static const double ns
Definition: Units.h:102
Thrown when a wrong value has been encountered.
Definition: Exceptions.h:37
std::vector< std::string > m_short
WireCell::Waveform::realseq_t current
An array holding the induced current for the path on the wire-of-interest.
Definition: Response.h:33
std::vector< std::string > m_long
std::vector< IImpactResponse::pointer > m_ir
realseq_t idft(compseq_t spec)
Definition: Waveform.cxx:149
QTextStream & bin(QTextStream &s)
static const double us
Definition: Units.h:105
std::complex< float > complex_t
The type for the spectrum in each bin.
Definition: Waveform.h:21
Sequence< complex_t > compseq_t
A complex-valued sequence, eg for discrete spectrum powers.
Definition: Waveform.h:34
const wire_region_indicies_t& WireCell::Gen::PlaneImpactResponse::bywire_map ( ) const
inline

Definition at line 101 of file PlaneImpactResponse.h.

101 { return m_bywire; }
IImpactResponse::pointer Gen::PlaneImpactResponse::closest ( double  relpitch) const
virtual

Return the response at the impact position closest to the given relative pitch location (measured relative to the wire of interest).

Implements WireCell::IPlaneImpactResponse.

Definition at line 275 of file PlaneImpactResponse.cxx.

276 {
277  if (relpitch < -m_half_extent || relpitch > m_half_extent) {
278  return nullptr;
279  }
280  std::pair<int,int> wi = closest_wire_impact(relpitch);
281  if (wi.first < 0 || wi.first >= (int)m_bywire.size()) {
282  l->debug("PIR: closest relative pitch:{} outside of wire range: {}",
283  relpitch, wi.first);
284  return nullptr;
285  }
286  const std::vector<int>& region = m_bywire[wi.first];
287  if (wi.second < 0 || wi.second >= (int)region.size()) {
288  l->debug("PIR: relative pitch:{} outside of impact range: {}",
289  relpitch, wi.second);
290  return nullptr;
291  }
292  int irind = region[wi.second];
293  if (irind < 0 || irind > (int)m_ir.size()) {
294  l->debug("PIR: relative pitch:{} no impact response for region: {}",
295  relpitch, irind);
296  return nullptr;
297  }
298 
299  return m_ir[irind];
300 }
std::pair< int, int > closest_wire_impact(double relpitch) const
std::vector< IImpactResponse::pointer > m_ir
std::pair< int, int > Gen::PlaneImpactResponse::closest_wire_impact ( double  relpitch) const

Definition at line 262 of file PlaneImpactResponse.cxx.

263 {
264  const int center_wire = nwires()/2;
265 
266  const int relwire = int(round(relpitch/m_pitch));
267  const int wire_index = center_wire + relwire;
268 
269  const double remainder_pitch = relpitch - relwire*m_pitch;
270  const int impact_index = int(round(remainder_pitch / m_impact)) + nimp_per_wire()/2;
271 
272  return std::make_pair(wire_index, impact_index);
273 }
int nwires() const
The number of wires that span the pitch range.
int nimp_per_wire() const
not in the interface
void Gen::PlaneImpactResponse::configure ( const WireCell::Configuration config)
virtual

Accept a configuration.

Implements WireCell::IConfigurable.

Definition at line 64 of file PlaneImpactResponse.cxx.

65 {
66  m_frname = get(cfg, "field_response", m_frname);
67  m_plane_ident = get(cfg, "plane", m_plane_ident);
68 
69  m_short.clear();
70  auto jfilts = cfg["short_responses"];
71  if (!jfilts.isNull() and !jfilts.empty()) {
72  for (auto jfn: jfilts) {
73  auto tn = jfn.asString();
74  m_short.push_back(tn);
75  }
76  }
77 
78  m_long.clear();
79  auto jfilts1 = cfg["long_responses"];
80  if (!jfilts1.isNull() and !jfilts1.empty()) {
81  for (auto jfn: jfilts1) {
82  auto tn = jfn.asString();
83  m_long.push_back(tn);
84  }
85  }
86 
87  m_overall_short_padding = get(cfg, "overall_short_padding", m_overall_short_padding);
88  m_long_padding = get(cfg, "long_padding", m_long_padding);
89 
90  m_nbins = (size_t) get(cfg, "nticks", (int)m_nbins);
91  m_tick = get(cfg, "tick", m_tick);
92 
94 }
cfg
Definition: dbjson.py:29
std::vector< std::string > m_short
std::vector< std::string > m_long
WireCell::Configuration Gen::PlaneImpactResponse::default_configuration ( ) const
virtual

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

Reimplemented from WireCell::IConfigurable.

Definition at line 44 of file PlaneImpactResponse.cxx.

45 {
47  // IFieldResponse component
48  cfg["field_response"] = m_frname;
49  // plane id to use to index into field response .plane()
50  cfg["plane"] = 0;
51  // names of IWaveforms interpreted as subsequent response
52  // functions.
53  cfg["short_responses"] = Json::arrayValue;
54  cfg["overall_short_padding"] = 100*units::us;
55  cfg["long_responses"] = Json::arrayValue;
56  cfg["long_padding"] = 1.5*units::ms;
57  // number of bins in impact response spectra
58  cfg["nticks"] = 10000;
59  // sample period of response waveforms
60  cfg["tick"] = 0.5*units::us;
61  return cfg;
62 }
cfg
Definition: dbjson.py:29
static const double ms
Definition: Units.h:104
Json::Value Configuration
Definition: Configuration.h:50
static const double us
Definition: Units.h:105
double WireCell::Gen::PlaneImpactResponse::impact ( ) const
inlinevirtual

Implements WireCell::IPlaneImpactResponse.

Definition at line 91 of file PlaneImpactResponse.h.

size_t WireCell::Gen::PlaneImpactResponse::nbins ( ) const
inlinevirtual

Implements WireCell::IPlaneImpactResponse.

Definition at line 95 of file PlaneImpactResponse.h.

int WireCell::Gen::PlaneImpactResponse::nimp_per_wire ( ) const
inline

not in the interface

Definition at line 98 of file PlaneImpactResponse.h.

98 { return m_bywire[0].size(); }
int WireCell::Gen::PlaneImpactResponse::nwires ( ) const
inlinevirtual

The number of wires that span the pitch range.

Implements WireCell::IPlaneImpactResponse.

Definition at line 93 of file PlaneImpactResponse.h.

93 { return m_bywire.size(); }
double WireCell::Gen::PlaneImpactResponse::pitch ( ) const
inlinevirtual

Implements WireCell::IPlaneImpactResponse.

Definition at line 90 of file PlaneImpactResponse.h.

double WireCell::Gen::PlaneImpactResponse::pitch_range ( ) const
inlinevirtual

The extent in pitch covered by the impact positions. This extent is relative to and centered on the "wire of interest" for which the PIR is associated.

Implements WireCell::IPlaneImpactResponse.

Definition at line 89 of file PlaneImpactResponse.h.

Member Data Documentation

Log::logptr_t WireCell::Gen::PlaneImpactResponse::l
private

Definition at line 121 of file PlaneImpactResponse.h.

wire_region_indicies_t WireCell::Gen::PlaneImpactResponse::m_bywire
private

Definition at line 116 of file PlaneImpactResponse.h.

std::string WireCell::Gen::PlaneImpactResponse::m_frname
private

Definition at line 106 of file PlaneImpactResponse.h.

double WireCell::Gen::PlaneImpactResponse::m_half_extent
private

Definition at line 119 of file PlaneImpactResponse.h.

double WireCell::Gen::PlaneImpactResponse::m_impact
private

Definition at line 119 of file PlaneImpactResponse.h.

std::vector<IImpactResponse::pointer> WireCell::Gen::PlaneImpactResponse::m_ir
private

Definition at line 118 of file PlaneImpactResponse.h.

std::vector<std::string> WireCell::Gen::PlaneImpactResponse::m_long
private

Definition at line 109 of file PlaneImpactResponse.h.

double WireCell::Gen::PlaneImpactResponse::m_long_padding
private

Definition at line 110 of file PlaneImpactResponse.h.

size_t WireCell::Gen::PlaneImpactResponse::m_nbins
private

Definition at line 113 of file PlaneImpactResponse.h.

double WireCell::Gen::PlaneImpactResponse::m_overall_short_padding
private

Definition at line 108 of file PlaneImpactResponse.h.

double WireCell::Gen::PlaneImpactResponse::m_pitch
private

Definition at line 119 of file PlaneImpactResponse.h.

int WireCell::Gen::PlaneImpactResponse::m_plane_ident
private

Definition at line 112 of file PlaneImpactResponse.h.

std::vector<std::string> WireCell::Gen::PlaneImpactResponse::m_short
private

Definition at line 107 of file PlaneImpactResponse.h.

double WireCell::Gen::PlaneImpactResponse::m_tick
private

Definition at line 114 of file PlaneImpactResponse.h.


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