DepoZipper.cxx
Go to the documentation of this file.
9 #include "WireCellUtil/Units.h"
10 #include "WireCellUtil/Point.h"
11 
14 
15 using namespace WireCell;
16 using namespace std;
17 
19  : m_start_time(0.0*units::ns)
20  , m_readout_time(5.0*units::ms)
21  , m_tick(0.5*units::us)
22  , m_drift_speed(1.0*units::mm/units::us)
23  , m_nsigma(3.0)
24  , m_frame_count(0)
25 {
26 }
27 
28 Gen::DepoZipper::~DepoZipper()
29 {
30 }
31 
33 {
34  auto anode_tn = get<string>(cfg, "anode", "");
35  m_anode = Factory::find_tn<IAnodePlane>(anode_tn);
36 
37  m_nsigma = get<double>(cfg, "nsigma", m_nsigma);
38  bool fluctuate = get<bool>(cfg, "fluctuate", false);
39  m_rng = nullptr;
40  if (fluctuate) {
41  auto rng_tn = get<string>(cfg, "rng", "");
42  m_rng = Factory::find_tn<IRandom>(rng_tn);
43  }
44 
45  m_readout_time = get<double>(cfg, "readout_time", m_readout_time);
46  m_tick = get<double>(cfg, "tick", m_tick);
47  m_start_time = get<double>(cfg, "start_time", m_start_time);
48  m_drift_speed = get<double>(cfg, "drift_speed", m_drift_speed);
49  m_frame_count = get<int>(cfg, "first_frame_number", m_frame_count);
50 
51  auto jpirs = cfg["pirs"];
52  if (jpirs.isNull() or jpirs.empty()) {
53  THROW(ValueError() << errmsg{"Gen::Ductor: must configure with some plane impact response components"});
54  }
55  m_pirs.clear();
56  for (auto jpir : jpirs) {
57  auto tn = jpir.asString();
58  auto pir = Factory::find_tn<IPlaneImpactResponse>(tn);
59  m_pirs.push_back(pir);
60  }
61 
62 }
63 WireCell::Configuration Gen::DepoZipper::default_configuration() const
64 {
66 
67 
68  /// How many Gaussian sigma due to diffusion to keep before truncating.
69  put(cfg, "nsigma", m_nsigma);
70 
71  /// Whether to fluctuate the final Gaussian deposition.
72  put(cfg, "fluctuate", false);
73 
74  /// The open a gate. This is actually a "readin" time measured at
75  /// the input ("reference") plane.
76  put(cfg, "start_time", m_start_time);
77 
78  /// The time span for each readout. This is actually a "readin"
79  /// time span measured at the input ("reference") plane.
80  put(cfg, "readout_time", m_readout_time);
81 
82  /// The sample period
83  put(cfg, "tick", m_tick);
84 
85  /// The nominal speed of drifting electrons
86  put(cfg, "drift_speed", m_drift_speed);
87 
88  /// Allow for a custom starting frame number
89  put(cfg, "first_frame_number", m_frame_count);
90 
91  /// Name of component providing the anode plane.
92  put(cfg, "anode", "");
93  /// Name of component providing the anode pseudo random number generator.
94  put(cfg, "rng", "");
95 
96  /// Plane impact responses
97  cfg["pirs"] = Json::arrayValue;
98 
99 
100  return cfg;
101 }
102 
103 bool Gen::DepoZipper::operator()(const input_pointer& in, output_pointer& out)
104 {
105  if (!in) {
106  out = nullptr;
107  cerr << "Gen::DepoZipper: EOS\n";
108  return true;
109  }
110 
111  auto depos = in->depos();
112 
113  Binning tbins(m_readout_time/m_tick, m_start_time, m_start_time+m_readout_time);
114  ITrace::vector traces;
115  for (auto face : m_anode->faces()) {
116 
117  // Select the depos which are in this face's sensitive volume
118  IDepo::vector face_depos, dropped_depos;
119  auto bb = face->sensitive();
120  if (bb.empty()) {
121  cerr << "Gen::DepoZipper anode:" << m_anode->ident() << " face:" << face->ident()
122  << " is marked insensitive, skipping\n";
123  continue;
124  }
125 
126  for (auto depo : (*depos)) {
127  if (bb.inside(depo->pos())) {
128  face_depos.push_back(depo);
129  }
130  else {
131  dropped_depos.push_back(depo);
132  }
133  }
134 
135  if (face_depos.size()) {
136  auto ray = bb.bounds();
137  cerr << "Gen::Ductor: anode:" << m_anode->ident() << " face:" << face->ident()
138  << ": processing " << face_depos.size() << " depos spanning: t:["
139  << face_depos.front()->time()/units::ms << ", "
140  << face_depos.back()->time()/units::ms << "]ms, bb: "
141  << ray.first/units::cm << " --> " << ray.second/units::cm <<"cm\n";
142  }
143  if (dropped_depos.size()) {
144  auto ray = bb.bounds();
145  cerr << "Gen::Ductor: anode:" << m_anode->ident() << " face:" << face->ident()
146  << ": dropped " << dropped_depos.size()<<" depos spanning: t:["
147  << dropped_depos.front()->time()/units::ms << ", "
148  << dropped_depos.back()->time()/units::ms << "]ms, outside bb: "
149  << ray.first/units::cm << " --> " << ray.second/units::cm <<"cm\n";
150 
151  }
152 
153  int iplane = -1;
154  for (auto plane : face->planes()) {
155  ++iplane;
156 
157  const Pimpos* pimpos = plane->pimpos();
158 
159  Binning tbins(m_readout_time/m_tick, m_start_time,
160  m_start_time+m_readout_time);
161 
162  Gen::BinnedDiffusion bindiff(*pimpos, tbins, m_nsigma, m_rng);
163  for (auto depo : face_depos) {
164  bindiff.add(depo, depo->extent_long() / m_drift_speed, depo->extent_tran());
165  }
166 
167  auto& wires = plane->wires();
168 
169  auto pir = m_pirs.at(iplane);
170  Gen::ImpactZipper zipper(pir, bindiff);
171 
172  const int nwires = pimpos->region_binning().nbins();
173  for (int iwire=0; iwire<nwires; ++iwire) {
174  auto wave = zipper.waveform(iwire);
175 
176  auto mm = Waveform::edge(wave);
177  if (mm.first == (int)wave.size()) { // all zero
178  continue;
179  }
180 
181  int chid = wires[iwire]->channel();
182  int tbin = mm.first;
183 
184  //std::cout << mm.first << " "<< mm.second << std::endl;
185 
186  ITrace::ChargeSequence charge(wave.begin()+mm.first, wave.begin()+mm.second);
187  auto trace = make_shared<SimpleTrace>(chid, tbin, charge);
188  traces.push_back(trace);
189  }
190  }
191  }
192 
193  auto frame = make_shared<SimpleFrame>(m_frame_count, m_start_time, traces, m_tick);
194  cerr << "Gen::DepoZipper: make frame " << m_frame_count << "\n";
195  ++m_frame_count;
196  out = frame;
197  return true;
198 }
199 
const int nwires
boost::error_info< struct tag_errmsg, std::string > errmsg
Definition: Exceptions.h:54
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
std::pair< int, int > edge(const realseq_t &wave)
Definition: Waveform.cxx:121
Binning tbins(nticks, t0, t0+readout_time)
std::shared_ptr< const IDepoSet > input_pointer
Definition: IFunctionNode.h:39
def configure(cfg)
Definition: cuda.py:34
#define THROW(e)
Definition: Exceptions.h:25
std::shared_ptr< const IFrame > output_pointer
Definition: IFunctionNode.h:40
Thrown when a wrong value has been encountered.
Definition: Exceptions.h:37
static const double mm
Definition: Units.h:73
Definition: Main.h:22
static const double us
Definition: Units.h:101
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
WIRECELL_FACTORY(DepoZipper, WireCell::Gen::DepoZipper, WireCell::IDepoFramer, WireCell::IConfigurable) using namespace WireCell
static const double cm
Definition: Units.h:76
Waveform::realseq_t waveform(int wire) const
int nbins() const
Definition: Binning.h:42
QAsciiDict< Entry > ns
std::vector< float > ChargeSequence
Sequential collection of charge.
Definition: ITrace.h:21