TruthTraceID.cxx
Go to the documentation of this file.
3 #include "WireCellUtil/Units.h"
4 #include "WireCellUtil/Point.h"
8 
9 #include <string>
10 
13 
14 using namespace std;
15 using namespace WireCell;
16 
18  : m_anode_tn("AnodePlane")
19  , m_rng_tn("Random")
20  , m_start_time(0.0*units::ns)
21  , m_readout_time(5.0*units::ms)
22  , m_tick(0.5*units::us)
23  , m_pitch_range(20*3*units::mm) // +/- 10 wires
24  , m_drift_speed(1.0*units::mm/units::us)
25  , m_nsigma(3.0)
26  , m_truth_gain(-1.0)
27  , m_fluctuate(true)
28  , m_frame_count(0)
29  , m_eos(false)
30  , m_truth_type("Bare")
31  , m_num_ind_wire(2400.0)
32  , m_num_col_wire(3456.0)
33  , m_ind_sigma(1./std::sqrt(3.1415926)*1.4)
34  , m_col_sigma(1./std::sqrt(3.1415926)*3.0)
35  , m_time_sigma(0.14*units::megahertz)
36  , m_wire_power(2.0)
37  , m_time_power(2.0)
38  , m_max_wire_freq(1.0)
39  , m_max_time_freq(1.0*units::megahertz)
40  , m_wire_flag(false)
41  , m_time_flag(true)
42 {
43 }
44 
45 WireCell::Configuration Gen::TruthTraceID::default_configuration() const{
47  put(cfg, "nsigma", m_nsigma);
48  put(cfg, "fluctuate", m_fluctuate);
49  put(cfg, "start_time", m_start_time);
50  put(cfg, "readout_time", m_readout_time);
51  put(cfg, "tick", m_tick);
52  put(cfg, "pitch_range", m_pitch_range);
53  put(cfg, "drift_speed", m_drift_speed);
54  put(cfg, "first_frame_number", m_frame_count);
55  put(cfg, "anode", m_anode_tn);
56  put(cfg, "rng", m_rng_tn);
57  put(cfg, "truth_type", m_truth_type);
58  put(cfg, "number_induction_wire", m_num_ind_wire);
59  put(cfg, "number_collection_wire", m_num_col_wire);
60  put(cfg, "induction_sigma", m_ind_sigma);
61  put(cfg, "collection_sigma", m_col_sigma);
62  put(cfg, "time_sigma", m_time_sigma);
63  put(cfg, "wire_power", m_wire_power);
64  put(cfg, "time_power", m_time_power);
65  put(cfg, "max_wire_frequency", m_max_wire_freq);
66  put(cfg, "max_time_frequency", m_max_time_freq);
67  put(cfg, "wire_filter_flag", m_wire_flag);
68  put(cfg, "time_filter_flag", m_time_flag);
69  put(cfg, "truth_gain", m_truth_gain);
70  return cfg;
71 }
72 
74  m_anode_tn = get<string>(cfg, "anode", m_anode_tn);
75  m_anode = Factory::find_tn<IAnodePlane>(m_anode_tn);
76  if(!m_anode){
77  cerr << "Gen::Truth: failed to get anode: \"" << m_anode_tn << "\"\n";
78  return;
79  }
80 
81  m_nsigma = get<double>(cfg, "nsigma", m_nsigma);
82  m_fluctuate = get<bool>(cfg, "fluctuate", m_fluctuate);
83  m_rng = nullptr;
84  if(m_fluctuate){
85  m_rng_tn = get(cfg, "rng", m_rng_tn);
86  m_rng = Factory::find_tn<IRandom>(m_rng_tn);
87  }
88 
89  m_readout_time = get<double>(cfg, "readout_time", m_readout_time);
90  m_tick = get<double>(cfg, "tick", m_tick);
91  m_start_time = get<double>(cfg, "start_time", m_start_time);
92  m_drift_speed = get<double>(cfg, "drift_speed", m_drift_speed);
93  m_frame_count = get<int>(cfg, "first_frame_number", m_frame_count);
94  m_truth_gain = get<double>(cfg, "truth_gain", m_truth_gain);
95 
96  m_truth_type = get<string>(cfg, "truth_type", m_truth_type);
97  m_num_ind_wire = get<double>(cfg, "number_induction_wire", m_num_ind_wire);
98  m_num_col_wire = get<double>(cfg, "number_collection_wire", m_num_col_wire);
99  m_ind_sigma = get<double>(cfg, "induction_sigma", m_ind_sigma);
100  m_col_sigma = get<double>(cfg, "collection_sigma", m_col_sigma);
101  m_time_sigma = get<double>(cfg, "time_sigma", m_time_sigma);
102  m_wire_power = get<double>(cfg, "wire_power", m_wire_power);
103  m_time_power = get<double>(cfg, "time_power", m_time_power);
104  m_max_wire_freq = get<double>(cfg, "max_wire_frequency", m_max_wire_freq);
105  m_max_time_freq = get<double>(cfg, "max_time_frequency", m_max_time_freq);
106  m_wire_flag = get<bool>(cfg, "wire_filter_flag", m_wire_flag);
107  m_time_flag = get<bool>(cfg, "time_filter_flag", m_time_flag);
108 }
109 
111  ITrace::vector traces;
112  double tick = -1;
113 
114  // ### construct wire filters ###
117  auto indTruth = hf_ind.generate(indBins);
118 
121  auto colTruth = hf_col.generate(colBins);
122 
123  const int nbins = m_readout_time / m_tick;
124 
125  for(auto face : m_anode->faces()){
126  for(auto plane : face->planes()){
127  const Pimpos* pimpos = plane->pimpos();
128 
130  if(tick < 0){
131  tick = tbins.binsize();
132  }
133 
134  // ### construct time filter ###
135  Binning timeBins(tbins.nbins(),0.0,m_max_time_freq);
137  auto timeTruth = hf_time.generate(timeBins);
138 
139 
140  // ### apply diffusion at wire plane ###
141  Gen::BinnedDiffusion bindiff(*pimpos, tbins, m_nsigma, m_rng);
142  for(auto depo : m_depos){
143  bindiff.add(depo, depo->extent_long() / m_drift_speed, depo->extent_tran());
144 
145  auto& wires = plane->wires();
146  const int numwires = pimpos->region_binning().nbins();
147  for(int iwire=0; iwire<numwires; iwire++){
148  const auto rbins = pimpos->region_binning();
149  const auto ibins = pimpos->impact_binning();
150  const double wire_pos = rbins.center(iwire);
151  // fixme (?) this under-calculates the min/max impact position by 1/2 wire region (bv).
152  const int min_impact = ibins.edge_index(wire_pos - 0.5*m_pitch_range);
153  const int max_impact = ibins.edge_index(wire_pos + 0.5*m_pitch_range);
154  const int nsamples = tbins.nbins();
155  Waveform::compseq_t total_spectrum(nsamples, Waveform::complex_t(0.0,0.0));
156 
157  for(int imp = min_impact; imp<=max_impact; imp++){
158  auto id = bindiff.impact_data(imp);
159  if(!id){
160  continue;
161  }
162 
163  //debugging
164  std::cout<<"Truth: charge spectrum extracted." << imp << std::endl;
165 
166  if(m_truth_type == "Bare"){
167  const Waveform::compseq_t& charge_spectrum = id->spectrum();
168  if(charge_spectrum.empty()){
169  continue;
170  }
171  Waveform::increase(total_spectrum, charge_spectrum);
172  }
173  else{ // ### convolve with charge w/ hf filters ###
174  const Waveform::compseq_t& charge_spectrum = id->spectrum();
175  if(charge_spectrum.empty()){
176  continue;
177  }
178  Waveform::compseq_t conv_spectrum(nsamples, Waveform::complex_t(0.0,0.0));
179  std::complex<float> charge_gain = m_truth_gain;
180  for(int ind=0; ind<nsamples; ind++){
181  if(wires[iwire]->channel()<4800){
182  conv_spectrum[ind] = charge_gain*charge_spectrum[ind]*timeTruth[ind]*indTruth[iwire];
183  }
184  else{
185  conv_spectrum[ind] = charge_gain*charge_spectrum[ind]*timeTruth[ind]*colTruth[iwire];
186  }
187  }
188  Waveform::increase(total_spectrum, conv_spectrum);
189  }
190  }
191  bindiff.erase(0,min_impact);
192 
193  Waveform::realseq_t wave(nsamples,0.0);
194  wave = Waveform::idft(total_spectrum);
195  auto mm = Waveform::edge(wave);
196  if(mm.first == (int)wave.size()){
197  continue;
198  }
199 
200  // ### push to trace ###
201  int chid = wires[iwire]->channel();
202  ITrace::ChargeSequence charge(wave.begin()+mm.first,
203  wave.begin()+mm.second);
204  auto trace = make_shared<SimpleTrace>(chid, mm.first, charge);
205  traces.push_back(trace);
206  }
207  }
208  }
209  }
210 
211  // ### push to frame ###
212  auto frame = make_shared<SimpleFrame>(m_frame_count, m_start_time, traces, tick);
213  frames.push_back(frame);
214 
215  m_depos.clear();
216  m_start_time += m_readout_time;
217  ++m_frame_count;
218 }
219 
221  m_depos.clear();
222  m_eos = false;
223 }
224 
226  if(m_eos){
227  return false;
228  }
229 
230  double target_time = m_start_time + m_readout_time;
231  if(!depo || depo->time() > target_time){
232  process(frames);
233  }
234 
235  if(depo){
236  m_depos.push_back(depo);
237  }
238  else{
239  m_eos = true;
240  }
241 
242  return true;
243 }
void process(output_queue &frame)
Sequence< real_t > realseq_t
Definition: Waveform.h:31
double center(int ind) const
Definition: Binning.h:86
bool add(IDepo::pointer deposition, double sigma_time, double sigma_pitch)
const Binning & region_binning() const
Definition: Pimpos.h:109
STL namespace.
void put(Configuration &cfg, const std::string &dotpath, const T &val)
Put value in configuration at the dotted path.
cfg
Definition: dbjson.py:29
std::vector< pointer > vector
Definition: IData.h:21
virtual void configure(const WireCell::Configuration &config)
Accept a configuration.
std::pair< int, int > edge(const realseq_t &wave)
Definition: Waveform.cxx:121
const double tick
void erase(int begin_impact_index, int end_impact_index)
std::deque< output_pointer > output_queue
double binsize() const
Definition: Binning.h:73
Binning tbins(nticks, t0, t0+readout_time)
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
WireCell::Waveform::realseq_t generate(const WireCell::Waveform::Domain &domain, int nsamples)
FIXME: eradicate Domain in favor of Binning.
Definition: Response.cxx:303
megahertz_as<> megahertz
Type of frequency stored in megahertz, in double precision.
Definition: frequency.h:101
static const double mm
Definition: Units.h:73
ImpactData::pointer impact_data(int bin) const
Definition: Main.h:22
virtual bool operator()(const input_pointer &depo, output_queue &frames)
The calling signature:
static const double us
Definition: Units.h:101
realseq_t idft(compseq_t spec)
Definition: Waveform.cxx:149
Pimpos pimpos(nwires, min_wire_pitch, max_wire_pitch)
static const double ms
Definition: Units.h:100
Pitch-Impact-Position.
Definition: Pimpos.h:36
Json::Value Configuration
Definition: Configuration.h:50
std::shared_ptr< const IDepo > input_pointer
WIRECELL_FACTORY(TruthTraceID, WireCell::Gen::TruthTraceID, WireCell::IDuctor, WireCell::IConfigurable) using namespace std
std::complex< float > complex_t
The type for the spectrum in each bin.
Definition: Waveform.h:21
int nbins() const
Definition: Binning.h:42
IAnodePlane::pointer m_anode
Definition: TruthTraceID.h:29
Sequence< complex_t > compseq_t
A complex-valued sequence, eg for discrete spectrum powers.
Definition: Waveform.h:34
QAsciiDict< Entry > ns
std::vector< float > ChargeSequence
Sequential collection of charge.
Definition: ITrace.h:21
IRandom::pointer m_rng
Definition: TruthTraceID.h:30
QTextStream & endl(QTextStream &s)