DepoTransform.cxx
Go to the documentation of this file.
1 /* Comentary:
2 
3  This class is one element in a 2 by 2 matrix of classes which start
4  very symmetric.
5 
6  (Depo, Impact) outer-product (Zipper, Transform)
7 
8  The "Depo" class is high level and uses the low level "Impact" class.
9 
10  The "Transform" version is newer than the "Zipper" version and
11  while it started with a symmetric interface, it must grow out of
12  it.
13 
14  The "Transform" version is faster than the "Zipper" for most
15  realistically complicated event topology. It will be made faster
16  yet but this will break the symmetry:
17 
18  1) The "Tranform" version builds a dense array so sending its
19  output through the narrow waveform() is silly.
20 
21  2) It can be optimized if the array has a channel basis instead of
22  a wire one so the "zipper" interface is not fitting.
23 
24  3) It may be further optimized by performing its transforms on two
25  planes from each face (for two-faced APAs) simultaneously. This
26  requires a different intrerface, possibly by (ab)using
27  BinnedDiffusion in a different way than "zipper".
28 
29  4) It may be optimized yet further by breaking up the FFTs to do
30  smaller ones (in time) on charge (X) FR and then doing the larger
31  ones over ER(X)RC(X)RC. This work also requires extension of PIR.
32  This improvement may also be applicable to zipper.
33 
34  All of this long winded explantion, which nobody will ever read, is
35  "justification" for the otherwise disgusting copy-paste which is
36  going on with these two pairs of classes.
37 
38  */
39 
40 
48 #include "WireCellUtil/Units.h"
49 #include "WireCellUtil/Point.h"
50 
53 
54 using namespace WireCell;
55 using namespace std;
56 
58  : m_start_time(0.0*units::ns)
59  , m_readout_time(5.0*units::ms)
60  , m_tick(0.5*units::us)
61  , m_drift_speed(1.0*units::mm/units::us)
62  , m_nsigma(3.0)
63  , m_frame_count(0)
64  , l(Log::logger("sim"))
65 {
66 }
67 
68 Gen::DepoTransform::~DepoTransform()
69 {
70 }
71 
73 {
74  auto anode_tn = get<string>(cfg, "anode", "");
75  m_anode = Factory::find_tn<IAnodePlane>(anode_tn);
76 
77  m_nsigma = get<double>(cfg, "nsigma", m_nsigma);
78  bool fluctuate = get<bool>(cfg, "fluctuate", false);
79  m_rng = nullptr;
80  if (fluctuate) {
81  auto rng_tn = get<string>(cfg, "rng", "");
82  m_rng = Factory::find_tn<IRandom>(rng_tn);
83  }
84 
85  m_readout_time = get<double>(cfg, "readout_time", m_readout_time);
86  m_tick = get<double>(cfg, "tick", m_tick);
87  m_start_time = get<double>(cfg, "start_time", m_start_time);
88  m_drift_speed = get<double>(cfg, "drift_speed", m_drift_speed);
89  m_frame_count = get<int>(cfg, "first_frame_number", m_frame_count);
90 
91  auto jpirs = cfg["pirs"];
92  if (jpirs.isNull() or jpirs.empty()) {
93  std::string msg = "must configure with some plane impact response components";
94  l->error(msg);
95  THROW(ValueError() << errmsg{"Gen::Ductor: " + msg});
96  }
97  m_pirs.clear();
98  for (auto jpir : jpirs) {
99  auto tn = jpir.asString();
100  auto pir = Factory::find_tn<IPlaneImpactResponse>(tn);
101  m_pirs.push_back(pir);
102  }
103 
104 }
105 WireCell::Configuration Gen::DepoTransform::default_configuration() const
106 {
108 
109 
110  /// How many Gaussian sigma due to diffusion to keep before truncating.
111  put(cfg, "nsigma", m_nsigma);
112 
113  /// Whether to fluctuate the final Gaussian deposition.
114  put(cfg, "fluctuate", false);
115 
116  /// The open a gate. This is actually a "readin" time measured at
117  /// the input ("reference") plane.
118  put(cfg, "start_time", m_start_time);
119 
120  /// The time span for each readout. This is actually a "readin"
121  /// time span measured at the input ("reference") plane.
122  put(cfg, "readout_time", m_readout_time);
123 
124  /// The sample period
125  put(cfg, "tick", m_tick);
126 
127  /// The nominal speed of drifting electrons
128  put(cfg, "drift_speed", m_drift_speed);
129 
130  /// Allow for a custom starting frame number
131  put(cfg, "first_frame_number", m_frame_count);
132 
133  /// Name of component providing the anode plane.
134  put(cfg, "anode", "");
135  /// Name of component providing the anode pseudo random number generator.
136  put(cfg, "rng", "");
137 
138  /// Plane impact responses
139  cfg["pirs"] = Json::arrayValue;
140 
141 
142  return cfg;
143 }
144 
145 bool Gen::DepoTransform::operator()(const input_pointer& in, output_pointer& out)
146 {
147  if (!in) {
148  out = nullptr;
149  return true;
150  }
151 
152  auto depos = in->depos();
153 
154  Binning tbins(m_readout_time/m_tick, m_start_time, m_start_time+m_readout_time);
155  ITrace::vector traces;
156  for (auto face : m_anode->faces()) {
157 
158  // Select the depos which are in this face's sensitive volume
159  IDepo::vector face_depos, dropped_depos;
160  auto bb = face->sensitive();
161  if (bb.empty()) {
162  l->debug("anode {} face {} is marked insensitive, skipping",
163  m_anode->ident(), face->ident());
164  continue;
165  }
166 
167  for (auto depo : (*depos)) {
168  if (bb.inside(depo->pos())) {
169  face_depos.push_back(depo);
170  }
171  else {
172  dropped_depos.push_back(depo);
173  }
174  }
175 
176  if (face_depos.size()) {
177  auto ray = bb.bounds();
178  l->debug("anode: {}, face: {}, processing {} depos spanning "
179  "t:[{},{}]ms, bb:[{}-->{}]cm",
180  m_anode->ident(), face->ident(), face_depos.size(),
181  face_depos.front()->time()/units::ms,
182  face_depos.back()->time()/units::ms,
183  ray.first/units::cm,ray.second/units::cm);
184  }
185  if (dropped_depos.size()) {
186  auto ray = bb.bounds();
187  l->debug("anode: {}, face: {}, dropped {} depos spanning "
188  "t:[{},{}]ms, outside bb:[{}-->{}]cm",
189  m_anode->ident(), face->ident(),
190  dropped_depos.size(),
191  dropped_depos.front()->time()/units::ms,
192  dropped_depos.back()->time()/units::ms,
193  ray.first/units::cm, ray.second/units::cm);
194 
195  }
196 
197  int iplane = -1;
198  for (auto plane : face->planes()) {
199  ++iplane;
200 
201  const Pimpos* pimpos = plane->pimpos();
202 
203  Binning tbins(m_readout_time/m_tick, m_start_time,
204  m_start_time+m_readout_time);
205 
206  Gen::BinnedDiffusion_transform bindiff(*pimpos, tbins, m_nsigma, m_rng);
207  for (auto depo : face_depos) {
208  depo = modify_depo(plane->planeid(), depo);
209  bindiff.add(depo, depo->extent_long() / m_drift_speed, depo->extent_tran());
210  }
211 
212  auto& wires = plane->wires();
213 
214  auto pir = m_pirs.at(iplane);
215  Gen::ImpactTransform transform(pir, bindiff);
216 
217  const int nwires = pimpos->region_binning().nbins();
218  for (int iwire=0; iwire<nwires; ++iwire) {
219  auto wave = transform.waveform(iwire);
220 
221  auto mm = Waveform::edge(wave);
222  if (mm.first == (int)wave.size()) { // all zero
223  continue;
224  }
225 
226  int chid = wires[iwire]->channel();
227  int tbin = mm.first;
228 
229  ITrace::ChargeSequence charge(wave.begin()+mm.first, wave.begin()+mm.second);
230  auto trace = make_shared<SimpleTrace>(chid, tbin, charge);
231  traces.push_back(trace);
232  }
233  }
234  }
235 
236  auto frame = make_shared<SimpleFrame>(m_frame_count, m_start_time, traces, m_tick);
237  ++m_frame_count;
238  out = frame;
239  return true;
240 }
241 
const int nwires
void msg(const char *fmt,...)
Definition: message.cpp:107
std::string string
Definition: nybbler.cc:12
boost::error_info< struct tag_errmsg, std::string > errmsg
Definition: Exceptions.h:54
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
WIRECELL_FACTORY(DepoTransform, WireCell::Gen::DepoTransform, WireCell::IDepoFramer, WireCell::IConfigurable) using namespace WireCell
bool add(IDepo::pointer deposition, double sigma_time, double sigma_pitch)
std::pair< int, int > edge(const realseq_t &wave)
Definition: Waveform.cxx:121
static QStrList * l
Definition: config.cpp:1044
tagset_t transform(const tagset_t &ts, const ruleset_t &rs, bool all_rules=true)
Definition: TagRules.cxx:43
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
Monte Carlo Simulation.
std::shared_ptr< const IFrame > output_pointer
Definition: IFunctionNode.h:40
logptr_t logger(std::string name)
Definition: Logging.cxx:71
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
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