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

#include <TruthSmearer.h>

Inheritance diagram for WireCell::Gen::TruthSmearer:
WireCell::IDuctor WireCell::IConfigurable WireCell::IQueuedoutNode< IDepo, IFrame > WireCell::IComponent< IConfigurable > WireCell::IQueuedoutNodeBase WireCell::Interface WireCell::INode WireCell::IComponent< INode > WireCell::Interface

Public Member Functions

 TruthSmearer ()
 
virtual bool operator() (const input_pointer &depo, output_queue &frames)
 The calling signature: More...
 
virtual void configure (const WireCell::Configuration &config)
 Accept a configuration. More...
 
virtual WireCell::Configuration default_configuration () const
 Optional, override to return a hard-coded default configuration. More...
 
- Public Member Functions inherited from WireCell::IDuctor
virtual ~IDuctor ()
 
virtual std::string signature ()
 
- Public Member Functions inherited from WireCell::IQueuedoutNode< IDepo, IFrame >
virtual ~IQueuedoutNode ()
 
virtual bool operator() (const boost::any &anyin, queuedany &outanyq)
 The calling signature: More...
 
virtual std::vector< std::stringinput_types ()
 
virtual std::vector< std::stringoutput_types ()
 
- Public Member Functions inherited from WireCell::IQueuedoutNodeBase
virtual ~IQueuedoutNodeBase ()
 
virtual NodeCategory category ()
 Return the behavior category type. More...
 
virtual int concurrency ()
 By default assume all subclasses maintain state. 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 Member Functions

void process (output_queue &frames)
 
bool start_processing (const input_pointer &depo)
 

Private Attributes

std::string m_anode_tn
 
std::string m_rng_tn
 
IAnodePlane::pointer m_anode
 
IRandom::pointer m_rng
 
IDepo::vector m_depos
 
double m_start_time
 
double m_readout_time
 
double m_tick
 
double m_drift_speed
 
double m_time_smear
 
double m_wire_smear_ind
 
double m_wire_smear_col
 
std::string m_smear_response_tn
 
double m_truth_gain
 
double m_nsigma
 
bool m_fluctuate
 
bool m_continuous
 
int m_frame_count
 

Additional Inherited Members

- Public Types inherited from WireCell::IDuctor
typedef std::shared_ptr< IDuctorpointer
 
- Public Types inherited from WireCell::IQueuedoutNode< IDepo, IFrame >
typedef std::shared_ptr< IQueuedoutNodeBasepointer
 
typedef IDepo input_type
 
typedef IFrame output_type
 
typedef std::shared_ptr< const IDepoinput_pointer
 
typedef std::shared_ptr< const IFrameoutput_pointer
 
typedef std::deque< output_pointeroutput_queue
 
- Public Types inherited from WireCell::IQueuedoutNodeBase
typedef std::shared_ptr< IQueuedoutNodeBasepointer
 
typedef std::deque< boost::any > queuedany
 
- 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 16 of file TruthSmearer.h.

Constructor & Destructor Documentation

Gen::TruthSmearer::TruthSmearer ( )

based on Gen::Ductor without convolution just smearing of charge depos in time and wire dimenstions (time_smear = 0, wire_smear = 1) means "Charge Truth" otherwires, "Signal Truth" with signal processing residual

Definition at line 26 of file TruthSmearer.cxx.

27  : m_anode_tn("AnodePlane")
28  , m_rng_tn("Random")
29  , m_start_time(0.0*units::ns)
31  , m_tick(0.5*units::us)
33  , m_time_smear(1.4*units::us) // Fig.15 in arXiv:1802.08709
34  , m_wire_smear_ind(0.75) // Fig. 16 in arXiv: 1802.08709
35  , m_wire_smear_col(0.95) // Fig. 16 in arXiv: 1802.08709
36  , m_smear_response_tn("smear_response") // interface
37  , m_truth_gain(-1.0)
38  , m_nsigma(3.0)
39  , m_fluctuate(true)
40  , m_continuous(true)
41  , m_frame_count(0)
42 {
43 }
static const double ms
Definition: Units.h:104
static const double ns
Definition: Units.h:102
static const double mm
Definition: Units.h:55
static const double us
Definition: Units.h:105

Member Function Documentation

void Gen::TruthSmearer::configure ( const WireCell::Configuration config)
virtual

Accept a configuration.

An interface, not used. Exact "Truth" after signal processing.

Implements WireCell::IConfigurable.

Definition at line 105 of file TruthSmearer.cxx.

106 {
107  m_anode_tn = get<string>(cfg, "anode", m_anode_tn);
108  m_anode = Factory::find_tn<IAnodePlane>(m_anode_tn);
109  if (!m_anode) {
110  cerr << "TruthSmearer["<<(void*)this <<"]: failed to get anode: \"" << m_anode_tn << "\"\n";
111  return; // fixme: should throw something!
112  }
113 
114  m_nsigma = get<double>(cfg, "nsigma", m_nsigma);
115  m_continuous = get<bool>(cfg, "continuous", m_continuous);
116  m_fluctuate = get<bool>(cfg, "fluctuate", m_fluctuate);
117  m_rng = nullptr;
118  if (m_fluctuate) {
119  m_rng_tn = get(cfg, "rng", m_rng_tn);
120  m_rng = Factory::find_tn<IRandom>(m_rng_tn);
121  }
122 
123  m_readout_time = get<double>(cfg, "readout_time", m_readout_time);
124  m_tick = get<double>(cfg, "tick", m_tick);
125  m_start_time = get<double>(cfg, "start_time", m_start_time);
126  m_drift_speed = get<double>(cfg, "drift_speed", m_drift_speed);
127  m_time_smear = get<double>(cfg, "time_smear", m_time_smear);
128  m_wire_smear_ind = get<double>(cfg, "wire_smear_ind", m_wire_smear_ind);
129  m_wire_smear_col = get<double>(cfg, "wire_smear_col", m_wire_smear_col);
130 
131  /// An interface, not used. Exact "Truth" after signal processing.
132  m_smear_response_tn = get<string>(cfg, "smear_response", m_smear_response_tn);
133 
134  m_truth_gain = get<double>(cfg, "truth_gain", m_truth_gain);
135 
136  m_frame_count = get<int>(cfg, "first_frame_number", m_frame_count);
137 
138 }
cfg
Definition: dbjson.py:29
IRandom::pointer m_rng
Definition: TruthSmearer.h:34
IAnodePlane::pointer m_anode
Definition: TruthSmearer.h:33
WireCell::Configuration Gen::TruthSmearer::default_configuration ( ) const
virtual

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

How many Gaussian sigma due to diffusion to keep before truncating.

Whether to fluctuate the final Gaussian deposition.

The initial time for this ductor

The time span for each readout.

The sample period

If false then determine start time of each readout based on the input depos. This option is useful when running WCT sim on a source of depos which have already been "chunked" in time. If true then this Ductor will continuously simulate all time in "readout_time" frames leading to empty frames in the case of some readout time with no depos.

The nominal speed of drifting electrons

Gaussian longitudinal (time) smearing – time filter in SP

Discrete wire smear – wire filter in Fig.16 arXiv: 1802.08709 the charge within one wire pitch is equally weighted, i.e. no impact position dependency

Transverse (wire) smearing – re-distribute the charge onto nearby wires. A function of impact position, like field response. Attention: this is the residual field response (true / average). Normalization issue – true, see percentage level charge bias for point source of charge at various locations within a wire. An interface, not used are present.

gain for truth – sign of charge in the output

Allow for a custom starting frame number

Name of component providing the anode plane.

Reimplemented from WireCell::IConfigurable.

Definition at line 45 of file TruthSmearer.cxx.

46 {
48 
49  /// How many Gaussian sigma due to diffusion to keep before truncating.
50  put(cfg, "nsigma", m_nsigma);
51 
52  /// Whether to fluctuate the final Gaussian deposition.
53  put(cfg, "fluctuate", m_fluctuate);
54 
55  /// The initial time for this ductor
56  put(cfg, "start_time", m_start_time);
57 
58  /// The time span for each readout.
59  put(cfg, "readout_time", m_readout_time);
60 
61  /// The sample period
62  put(cfg, "tick", m_tick);
63 
64  /// If false then determine start time of each readout based on the
65  /// input depos. This option is useful when running WCT sim on a
66  /// source of depos which have already been "chunked" in time. If
67  /// true then this Ductor will continuously simulate all time in
68  /// "readout_time" frames leading to empty frames in the case of
69  /// some readout time with no depos.
70  put(cfg, "continuous", true);
71 
72  /// The nominal speed of drifting electrons
73  put(cfg, "drift_speed", m_drift_speed);
74 
75  /// Gaussian longitudinal (time) smearing -- time filter in SP
76  put(cfg, "time_smear", m_time_smear);
77 
78  /// Discrete wire smear -- wire filter in Fig.16 arXiv: 1802.08709
79  /// the charge within one wire pitch is equally weighted, i.e.
80  /// no impact position dependency
81  put(cfg, "wire_smear_ind", m_wire_smear_ind);
82  put(cfg, "wire_smear_col", m_wire_smear_col);
83 
84  /// Transverse (wire) smearing -- re-distribute the charge onto
85  /// nearby wires. A function of impact position, like field response.
86  /// Attention: this is the residual field response (true / average).
87  /// Normalization issue -- true, see percentage level charge bias
88  /// for point source of charge at various locations within a wire.
89  /// An interface, not used are present.
90  put(cfg, "smear_response", m_smear_response_tn);
91 
92  /// gain for truth -- sign of charge in the output
93  put(cfg, "truth_gain", m_truth_gain);
94 
95  /// Allow for a custom starting frame number
96  put(cfg, "first_frame_number", m_frame_count);
97 
98  /// Name of component providing the anode plane.
99  put(cfg, "anode", m_anode_tn);
100  put(cfg, "rng", m_rng_tn);
101 
102  return cfg;
103 }
void put(Configuration &cfg, const std::string &dotpath, const T &val)
Put value in configuration at the dotted path.
cfg
Definition: dbjson.py:29
Json::Value Configuration
Definition: Configuration.h:50
bool Gen::TruthSmearer::operator() ( const input_pointer in,
output_queue outq 
)
virtual

The calling signature:

Implements WireCell::IQueuedoutNode< IDepo, IFrame >.

Definition at line 318 of file TruthSmearer.cxx.

319 {
320  if (start_processing(depo)) {
321  process(frames);
322  }
323 
324  if (depo) {
325  m_depos.push_back(depo);
326  }
327  else {
328  frames.push_back(nullptr);
329  }
330 
331  return true;
332 }
void process(output_queue &frames)
bool start_processing(const input_pointer &depo)
void Gen::TruthSmearer::process ( output_queue frames)
private

Similar to ImpactZipper::waveform No convolution m_waveform from BinnedDiffusion::impact_data()

it is doable to read in a JsonArray of the wire smear and use relative bin to target wire as array index fo each wire (or impact position) smear

end: charge wire smearing per wire filter

Definition at line 140 of file TruthSmearer.cxx.

141 {
142  ITrace::vector traces;
143  double tick = -1;
144 
145  for (auto face : m_anode->faces()) {
146 
147  // Select the depos which are in this face's sensitive volume
148  IDepo::vector face_depos;
149  auto bb = face->sensitive();
150  for (auto depo : m_depos) {
151  if (bb.inside(depo->pos())) {
152  face_depos.push_back(depo);
153  }
154  }
155 
156  { // debugging
157  auto ray = bb.bounds();
158  cerr << "TruthSmearer: anode:"<<m_anode->ident()<<" face:" << face->ident() << ": processing " << face_depos.size() << " depos "
159  << "with bb: "<< ray.first << " --> " << ray.second <<"\n";
160  }
161 
162  for (auto plane : face->planes()) {
163 
164  const Pimpos* pimpos = plane->pimpos();
165 
168 
169  if (tick < 0) { // fixme: assume same tick for all.
170  tick = tbins.binsize();
171  }
172 
173  Gen::BinnedDiffusion bindiff(*pimpos, tbins, m_nsigma, m_rng);
174  for (auto depo : face_depos) {
175  // time filter smearing
176  double extent_time = depo->extent_long()/m_drift_speed;
177  bindiff.add(depo, sqrt(extent_time*extent_time+m_time_smear*m_time_smear), depo->extent_tran());
178  }
179 
180  auto& wires = plane->wires();
181  int planeid = plane->ident();
182 
183  double wire_smear = 1.0;
184  if(planeid == 2){
185  wire_smear = m_wire_smear_col;
186  }
187  else if(planeid == 0 || planeid == 1){
188  wire_smear = m_wire_smear_ind;
189  }
190  else{
191  std::cerr<<"Truthsmearer: planeid "<< planeid << " cannot be identified!"<<std::endl;
192  }
193 
194  auto ib = pimpos->impact_binning();
195  auto rb = pimpos->region_binning();
196 
197  const double pitch = rb.binsize();
198  const double impact = ib.binsize();
199  const int nwires = rb.nbins();
200  for (int iwire=0; iwire<nwires; ++iwire) {
201 
202  /// Similar to ImpactZipper::waveform
203  /// No convolution
204  /// m_waveform from BinnedDiffusion::impact_data()
205 
206  const double wire_pos = rb.center(iwire);
207 
208  // impact positions within +/-1 wires
209  const int min_impact = ib.edge_index(wire_pos - 1.5*pitch + 0.1*impact);
210  const int max_impact = ib.edge_index(wire_pos + 1.5*pitch - 0.1*impact);
211  const int nsamples = bindiff.tbins().nbins();
212 
213  // total waveform for iwire
214  Waveform::realseq_t total_spectrum(nsamples, 0.0);
215 
216  // ATTENTION: the bin center of max_imapct is in +2 wire pitch
217  for(int imp = min_impact; imp < max_impact; imp++) {
218 
219  // charge weight
220  double wire_weight = 1.0;
221 
222  /// it is doable to read in a JsonArray of the wire smear
223  /// and use relative bin to target wire as array index
224  /// fo each wire (or impact position) smear
225  const double rel_imp_pos = ib.center(imp) - wire_pos;
226  const double dist_to_wire = abs(rel_imp_pos/rb.binsize());
227  if( dist_to_wire <0.5){
228  wire_weight = wire_smear*1.0;
229  }
230  else if( dist_to_wire >0.5 && dist_to_wire <1.5 ){
231  wire_weight = 0.5*(1.0-wire_smear);
232  }
233  else{
234  // should not happen
235  wire_weight = 0.0;
236  std::cerr<<"TruthSmearer: impact "<< imp << " position: "
237  << ib.center(imp) <<" out of +/-1 wire region or at wire boundary, wire pitch: "
238  << rb.binsize() <<", "<< pitch <<", target wire position: "<< wire_pos
239  << std::endl;
240  }
241 
242  // ImpactData
243  auto id = bindiff.impact_data(imp);
244  if(!id) {
245  continue;
246  }
247 
248  Waveform::realseq_t charge_spectrum = id->waveform();
249  if (charge_spectrum.empty()) {
250  std::cerr<<"impactZipper: no charge spectrum for absolute impact number: "<< imp <<endl;
251  continue;
252  }
253 
254  //debugging
255  /* std::cout<<"TruthSmearer: planeid: " << planeid << " relative impact position: "<< rel_imp_pos */
256  /* << " charge weight: "<<wire_weight*m_truth_gain<<endl; */
257  /* auto xx = Waveform::edge(charge_spectrum); */
258  /* //debugging */
259  /* std::cout<<"TruthSmearer: wire: "<< iwire << " impact: " << imp << " charge spectrum edges: "<< xx.first << ", " << xx.second << std::endl; */
260  Waveform::scale(charge_spectrum, wire_weight*m_truth_gain);
261  Waveform::increase(total_spectrum, charge_spectrum);
262  }
263 
264  bindiff.erase(0, min_impact);
265 
266  /// end: charge wire smearing per wire filter
267 
268  auto mm = Waveform::edge(total_spectrum);
269  if (mm.first == (int)total_spectrum.size()) { // all zero
270  //std::cout<<"TruthSmearer: all zero wave spectrum at wire: "<< iwire << std::endl;
271  continue;
272  }
273 
274  int chid = wires[iwire]->channel();
275  int tbin = mm.first;
276  ITrace::ChargeSequence charge(total_spectrum.begin()+mm.first, total_spectrum.begin()+mm.second);
277  auto trace = make_shared<SimpleTrace>(chid, tbin, charge);
278  traces.push_back(trace);
279  }
280  }
281  }
282 
283  auto frame = make_shared<SimpleFrame>(m_frame_count, m_start_time, traces, tick);
284  frames.push_back(frame);
285 
286  // fixme: what about frame overflow here? If the depos extend
287  // beyond the readout where does their info go? 2nd order,
288  // diffusion and finite field response can cause depos near the
289  // end of the readout to have some portion of their waveforms
290  // lost?
291  m_depos.clear();
292 
293  m_start_time += m_readout_time;
294  ++m_frame_count;
295 }
const int nwires
Sequence< real_t > realseq_t
Definition: Waveform.h:31
const Binning & region_binning() const
Definition: Pimpos.h:109
std::vector< pointer > vector
Definition: IData.h:21
IRandom::pointer m_rng
Definition: TruthSmearer.h:34
std::pair< int, int > edge(const realseq_t &wave)
Definition: Waveform.cxx:121
const double tick
double binsize() const
Definition: Binning.h:73
Binning tbins(nticks, t0, t0+readout_time)
const Binning & impact_binning() const
Definition: Pimpos.h:113
T abs(T value)
void increase(Sequence< Val > &seq, Val scalar)
Increase (shift) sequence values by scalar.
Definition: Waveform.h:129
IAnodePlane::pointer m_anode
Definition: TruthSmearer.h:33
static const double mm
Definition: Units.h:73
void scale(Sequence< Val > &seq, Val scalar)
Scale (multiply) sequence values by scalar.
Definition: Waveform.h:146
Pimpos pimpos(nwires, min_wire_pitch, max_wire_pitch)
Pitch-Impact-Position.
Definition: Pimpos.h:36
std::vector< float > ChargeSequence
Sequential collection of charge.
Definition: ITrace.h:21
QTextStream & endl(QTextStream &s)
bool Gen::TruthSmearer::start_processing ( const input_pointer depo)
private

Definition at line 299 of file TruthSmearer.cxx.

300 {
301  if (!depo) {
302  return true;
303  }
304 
305  if (!m_continuous) {
306  if (m_depos.empty()) {
307  m_start_time = depo->time();
308  return false;
309  }
310  }
311 
312  // Note: we use this depo time even if it may not actually be
313  // inside our sensitive volume.
314  bool ok = depo->time() > m_start_time + m_readout_time;
315  return ok;
316 }

Member Data Documentation

IAnodePlane::pointer WireCell::Gen::TruthSmearer::m_anode
private

Definition at line 33 of file TruthSmearer.h.

std::string WireCell::Gen::TruthSmearer::m_anode_tn
private

Definition at line 30 of file TruthSmearer.h.

bool WireCell::Gen::TruthSmearer::m_continuous
private

Definition at line 50 of file TruthSmearer.h.

IDepo::vector WireCell::Gen::TruthSmearer::m_depos
private

Definition at line 35 of file TruthSmearer.h.

double WireCell::Gen::TruthSmearer::m_drift_speed
private

Definition at line 40 of file TruthSmearer.h.

bool WireCell::Gen::TruthSmearer::m_fluctuate
private

Definition at line 49 of file TruthSmearer.h.

int WireCell::Gen::TruthSmearer::m_frame_count
private

Definition at line 52 of file TruthSmearer.h.

double WireCell::Gen::TruthSmearer::m_nsigma
private

Definition at line 48 of file TruthSmearer.h.

double WireCell::Gen::TruthSmearer::m_readout_time
private

Definition at line 38 of file TruthSmearer.h.

IRandom::pointer WireCell::Gen::TruthSmearer::m_rng
private

Definition at line 34 of file TruthSmearer.h.

std::string WireCell::Gen::TruthSmearer::m_rng_tn
private

Definition at line 31 of file TruthSmearer.h.

std::string WireCell::Gen::TruthSmearer::m_smear_response_tn
private

Definition at line 45 of file TruthSmearer.h.

double WireCell::Gen::TruthSmearer::m_start_time
private

Definition at line 37 of file TruthSmearer.h.

double WireCell::Gen::TruthSmearer::m_tick
private

Definition at line 39 of file TruthSmearer.h.

double WireCell::Gen::TruthSmearer::m_time_smear
private

Definition at line 42 of file TruthSmearer.h.

double WireCell::Gen::TruthSmearer::m_truth_gain
private

Definition at line 46 of file TruthSmearer.h.

double WireCell::Gen::TruthSmearer::m_wire_smear_col
private

Definition at line 44 of file TruthSmearer.h.

double WireCell::Gen::TruthSmearer::m_wire_smear_ind
private

Definition at line 43 of file TruthSmearer.h.


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