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

#include <Drifter.h>

Inheritance diagram for WireCell::Gen::Drifter:
WireCell::IDrifter WireCell::IConfigurable WireCell::IQueuedoutNode< IDepo, IDepo > WireCell::IComponent< IConfigurable > WireCell::IQueuedoutNodeBase WireCell::Interface WireCell::INode WireCell::IComponent< INode > WireCell::Interface

Classes

struct  DepoTimeCompare
 
struct  IsInsideBulk
 
struct  IsInsideResp
 
struct  Xregion
 

Public Member Functions

 Drifter ()
 
virtual ~Drifter ()
 
virtual void reset ()
 
virtual bool operator() (const input_pointer &depo, output_queue &outq)
 The calling signature: More...
 
virtual void configure (const WireCell::Configuration &config)
 WireCell::IConfigurable interface. More...
 
virtual WireCell::Configuration default_configuration () const
 Optional, override to return a hard-coded default configuration. More...
 
IDepo::pointer transport (IDepo::pointer depo)
 
double proper_time (IDepo::pointer depo)
 
bool insert (const input_pointer &depo)
 
void flush (output_queue &outq)
 
void flush_ripe (output_queue &outq, double now)
 
virtual void set_lifetime (double lifetime_to_set)
 
- Public Member Functions inherited from WireCell::IDrifter
virtual ~IDrifter ()
 
virtual std::string signature ()
 
- Public Member Functions inherited from WireCell::IQueuedoutNode< IDepo, IDepo >
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 ()
 
- 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 Attributes

IRandom::pointer m_rng
 
std::string m_rng_tn
 
double m_DL
 
double m_DT
 
double m_lifetime
 
bool m_fluctuate
 
double m_speed
 
double m_toffset
 
int n_dropped
 
int n_drifted
 
std::vector< Xregionm_xregions
 
Log::logptr_t l
 

Additional Inherited Members

- Public Types inherited from WireCell::IDrifter
typedef std::shared_ptr< IDrifterpointer
 
- Public Types inherited from WireCell::IQueuedoutNode< IDepo, IDepo >
typedef std::shared_ptr< IQueuedoutNodeBasepointer
 
typedef IDepo input_type
 
typedef IDepo output_type
 
typedef std::shared_ptr< const IDepoinput_pointer
 
typedef std::shared_ptr< const IDepooutput_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

This component drifts depos bounded by planes perpendicular to the X-axis. The boundary planes are specified with the "xregions" list. Each list is an object fully specified with a "cathode" an "anode" and a "response" attribute giving X locations in the same coordinate system as depos of three planes.

If "anode" is not given then its value is take to be that of "response" and vice versa and at least one must be specified. A "cathode" value must be specified.

Any depo not falling between "anode" and "cathode" will be dropped.

Any depo falling between "response" and "cathode" will be drifted to the "response" plane.

Any depo falling between "anode" and "response" will be ANTI-DRIFTED to the "response" plane. Ie, it will be "BACKED UP" in space an time as if it had be produced earlier and at the response plane.

Input depositions must be ordered in absolute time (their current time) and output depositions are produced ordered by their time after being drifted to the response plane.

Diffusion and absorption effects and also, optionally, fluctuations are applied. Fano factor and Recombination are not applied in this component (see IRecombinationModel implementations).

Typically a drifter is used just prior to a ductor and in such cases the "response" plane should be made coincident with the non-physical "response plane" which defines the starting point for the field response functions. The location of the response plane realtive to the wire planes can be found using:

$ wriecell-sigproc response-info garfield-1d-3planes-21wires-6impacts-dune-v1.json.bz2 origin:10.00 cm, period:0.10 us, tstart:0.00 us, speed:1.60 mm/us, axis:(1.00,0.00,0.00) plane:0, location:9.4200mm, pitch:4.7100mm plane:1, location:4.7100mm, pitch:4.7100mm plane:2, location:0.0000mm, pitch:4.7100mm

Here, "origin" gives the location of the response plane. The location of the wire planes according to wire geometry can be similarly dumped.

$ wirecell-util wires-info protodune-wires-larsoft-v3.json.bz2 anode:0 face:0 X=[-3584.63,-3584.63]mm Y=[6066.70,6066.70]mm Z=[7.92,7.92]mm 0: x=-3584.63mm dx=9.5250mm 1: x=-3589.39mm dx=4.7620mm 2: x=-3594.16mm dx=0.0000mm .... anode:5 face:1 X=[3584.63,3584.63]mm Y=[6066.70,6066.70]mm Z=[6940.01,6940.01]mm 0: x=3584.63mm dx=-9.5250mm 1: x=3589.39mm dx=-4.7620mm 2: x=3594.16mm dx=0.0000mm

Note, as can see, these two sources of information may not be consistent w.r.t. the inter-plane separation distance (4.71mm and 4.76mm, respectively). This mismatch will result in a relative shift in time between the planes for various waveform features (eg induction zero crossings and collection peak).

For the example above, likely candidates for "anode" X locations are:

x = -3594.16mm + 10cm

and

x = +3594.16mm - 10cm

Definition at line 102 of file Drifter.h.

Constructor & Destructor Documentation

Gen::Drifter::Drifter ( )

Definition at line 59 of file Drifter.cxx.

60  : m_rng(nullptr)
61  , m_rng_tn("Random")
62  , m_DL(7.2 * units::centimeter2/units::second) // from arXiv:1508.07059v2
63  , m_DT(12.0 * units::centimeter2/units::second) // ditto
64  , m_lifetime(8*units::ms) // read off RHS of figure 6 in MICROBOONE-NOTE-1003-PUB
65  , m_fluctuate(true)
67  , m_toffset(0.0)
68  , n_dropped(0)
69  , n_drifted(0)
70  , l(Log::logger("sim"))
71 {
72 }
IRandom::pointer m_rng
Definition: Drifter.h:131
static const double ms
Definition: Units.h:104
std::string m_rng_tn
Definition: Drifter.h:136
Log::logptr_t l
Definition: Drifter.h:183
static const double centimeter2
Definition: Units.h:27
logptr_t logger(std::string name)
Definition: Logging.cxx:71
static const double mm
Definition: Units.h:55
static const double second
Definition: Units.h:92
static const double us
Definition: Units.h:105
Gen::Drifter::~Drifter ( )
virtual

Definition at line 74 of file Drifter.cxx.

75 {
76 }

Member Function Documentation

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

WireCell::IConfigurable interface.

Implements WireCell::IConfigurable.

Definition at line 93 of file Drifter.cxx.

94 {
95  reset();
96 
97  m_rng_tn = get(cfg, "rng", m_rng_tn);
98  m_rng = Factory::find_tn<IRandom>(m_rng_tn);
99 
100  m_DL = get<double>(cfg, "DL", m_DL);
101  m_DT = get<double>(cfg, "DT", m_DT);
102  m_lifetime = get<double>(cfg, "lifetime", m_lifetime);
103  m_fluctuate = get<bool>(cfg, "fluctuate", m_fluctuate);
104  m_speed = get<double>(cfg, "drift_speed", m_speed);
105  m_toffset = get<double>(cfg, "time_offset", m_toffset);
106 
107  auto jxregions = cfg["xregions"];
108  if (jxregions.empty()) {
109  l->critical("no xregions given so I can do nothing");
110  THROW(ValueError() << errmsg{"no xregions given"});
111  }
112  for (auto jone : jxregions) {
113  m_xregions.push_back(Xregion(jone));
114  }
115  l->debug("Drifter: time offset: {} ms, drift speed: {} mm/us",
116  m_toffset/units::ms, m_speed/(units::mm/units::us));
117 }
virtual void reset()
Definition: Drifter.cxx:119
boost::error_info< struct tag_errmsg, std::string > errmsg
Definition: Exceptions.h:54
std::vector< Xregion > m_xregions
Definition: Drifter.h:170
cfg
Definition: dbjson.py:29
IRandom::pointer m_rng
Definition: Drifter.h:131
static const double ms
Definition: Units.h:104
std::string m_rng_tn
Definition: Drifter.h:136
Log::logptr_t l
Definition: Drifter.h:183
#define THROW(e)
Definition: Exceptions.h:25
Thrown when a wrong value has been encountered.
Definition: Exceptions.h:37
static const double mm
Definition: Units.h:55
static const double us
Definition: Units.h:105
WireCell::Configuration Gen::Drifter::default_configuration ( ) const
virtual

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

Reimplemented from WireCell::IConfigurable.

Definition at line 78 of file Drifter.cxx.

79 {
81  cfg["DL"] = m_DL;
82  cfg["DT"] = m_DT;
83  cfg["lifetime"] = m_lifetime;
84  cfg["fluctuate"] = m_fluctuate;
85  cfg["drift_speed"] = m_speed;
86  cfg["time_offset"] = m_toffset;
87 
88  // see comments in .h file
89  cfg["xregions"] = Json::arrayValue;
90  return cfg;
91 }
cfg
Definition: dbjson.py:29
Json::Value Configuration
Definition: Configuration.h:50
void Gen::Drifter::flush ( output_queue outq)

Definition at line 206 of file Drifter.cxx.

207 {
208  for (auto& xr : m_xregions) {
209  l->debug("xregion: anode: {} mm, response: {} mm, cathode: {} mm, flushing {}",
210  xr.anode/units::mm, xr.response/units::mm,
211  xr.cathode/units::mm, xr.depos.size());
212  outq.insert(outq.end(), xr.depos.begin(), xr.depos.end());
213  xr.depos.clear();
214  }
215  std::sort(outq.begin(), outq.end(), by_time);
216  outq.push_back(nullptr);
217 }
bool by_time(const IDepo::pointer &lhs, const IDepo::pointer &rhs)
Definition: Drifter.cxx:201
std::vector< Xregion > m_xregions
Definition: Drifter.h:170
Log::logptr_t l
Definition: Drifter.h:183
static const double mm
Definition: Units.h:55
void Gen::Drifter::flush_ripe ( output_queue outq,
double  now 
)

Definition at line 219 of file Drifter.cxx.

220 {
221  // It might be faster to use a sorted set which would avoid an
222  // exhaustive iteration of each depos stash. Or not.
223  for (auto& xr : m_xregions) {
224  if (xr.depos.empty()) {
225  continue;
226  }
227 
228  Xregion::ordered_depos_t::const_iterator depo_beg=xr.depos.begin(), depo_end=xr.depos.end();
229  Xregion::ordered_depos_t::iterator depoit = depo_beg;
230  while (depoit != depo_end) {
231  if ((*depoit)->time() < now) {
232  ++depoit;
233  continue;
234  }
235  break;
236  }
237  if (depoit == depo_beg) {
238  continue;
239  }
240 
241  outq.insert(outq.end(), depo_beg, depoit);
242  xr.depos.erase(depo_beg, depoit);
243  }
244  if (outq.empty()) {
245  return;
246  }
247  std::sort(outq.begin(), outq.end(), by_time);
248 }
intermediate_table::iterator iterator
bool by_time(const IDepo::pointer &lhs, const IDepo::pointer &rhs)
Definition: Drifter.cxx:201
std::vector< Xregion > m_xregions
Definition: Drifter.h:170
intermediate_table::const_iterator const_iterator
bool Gen::Drifter::insert ( const input_pointer depo)

Definition at line 125 of file Drifter.cxx.

126 {
127  // electrical charge to drift. Electrons should be negative
128  const double Qi = depo->charge();
129  if (Qi == 0.0) {
130  // Yes, some silly depo sources ask us to drift nothing....
131  return false;
132  }
133 
134  // Find which X region to add, or reject. Maybe there is a faster
135  // way to do this than a loop. For example, the regions could be
136  // examined in order to find some regular binning of the X axis
137  // and then at worse only explicitly check extent partial bins
138  // near to their edges.
139 
140 
141 
142  double respx = 0, direction = 0.0;
143 
144  auto xrit = std::find_if(m_xregions.begin(), m_xregions.end(),
146  if (xrit != m_xregions.end()) {
147  // Back up in space and time. This is a best effort fudge. See:
148  // https://github.com/WireCell/wire-cell-gen/issues/22
149 
150  respx = xrit->response;
151  direction = -1.0;
152  }
153  else {
154  xrit = std::find_if(m_xregions.begin(), m_xregions.end(),
156  if (xrit != m_xregions.end()) { // in bulk
157  respx = xrit->response;
158  direction = 1.0;
159  }
160  }
161  if (xrit == m_xregions.end()) {
162  return false; // outside both regions
163  }
164 
165  Point pos = depo->pos();
166  const double dt = std::abs((respx - pos.x())/m_speed);
167  pos.x(respx);
168 
169 
170  double dL = depo->extent_long();
171  double dT = depo->extent_tran();
172 
173  double Qf = Qi;
174  if (direction > 0) {
175  // final number of electrons after drift if no fluctuation.
176  const double absorbprob = 1 - exp(-dt/m_lifetime);
177 
178  double dQ = Qi * absorbprob;
179 
180  // How many electrons remain, with fluctuation.
181  // Note: fano/recomb fluctuation should be done before the depo was first made.
182  if (m_fluctuate) {
183  double sign = 1.0;
184  if (Qi < 0) {
185  sign = -1.0;
186  }
187  dQ = sign*m_rng->binomial((int)std::abs(Qi), absorbprob);
188  }
189  Qf = Qi - dQ;
190 
191  dL = sqrt(2.0*m_DL*dt + dL*dL);
192  dT = sqrt(2.0*m_DT*dt + dT*dT);
193  }
194 
195  auto newdepo = make_shared<SimpleDepo>(depo->time() + direction*dt + m_toffset, pos, Qf, depo, dL, dT);
196  xrit->depos.insert(newdepo);
197  return true;
198 }
D3Vector< double > Point
A 3D Cartesian point in double precision.
Definition: Point.h:15
std::vector< Xregion > m_xregions
Definition: Drifter.h:170
IRandom::pointer m_rng
Definition: Drifter.h:131
T abs(T value)
int sign(double val)
Definition: UtilFunc.cxx:104
bool Gen::Drifter::operator() ( const input_pointer in,
output_queue outq 
)
virtual

The calling signature:

Implements WireCell::IQueuedoutNode< IDepo, IDepo >.

Definition at line 252 of file Drifter.cxx.

253 {
254  if (m_speed <= 0.0) {
255  l->error("illegal drift speed: {}", m_speed);
256  return false;
257  }
258 
259  if (!depo) { // no more inputs expected, EOS flush
260 
261  flush(outq);
262 
263  if (n_dropped) {
264  l->debug("at EOS, dropped {} / {} depos from stream, outside of all {} drift regions", n_dropped, n_dropped+n_drifted, m_xregions.size());
265  }
266  n_drifted = n_dropped = 0;
267  return true;
268  }
269 
270  bool ok = insert(depo);
271  if (!ok) {
272  ++n_dropped; // depo is outside our regions but
273  return true; // nothing changed, so just bail
274  }
275  ++n_drifted;
276 
277  // At this point, time has advanced and maybe some drifted repos
278  // are ripe for removal.
279 
280  flush_ripe(outq, depo->time());
281 
282  return true;
283 }
std::vector< Xregion > m_xregions
Definition: Drifter.h:170
void flush_ripe(output_queue &outq, double now)
Definition: Drifter.cxx:219
bool insert(const input_pointer &depo)
Definition: Drifter.cxx:125
Log::logptr_t l
Definition: Drifter.h:183
void flush(output_queue &outq)
Definition: Drifter.cxx:206
double WireCell::Gen::Drifter::proper_time ( IDepo::pointer  depo)
void Gen::Drifter::reset ( void  )
virtual

Optional hook to be implemented in order to reset after an end of stream is encountered. Fixme: this should be removed.

Reimplemented from WireCell::INode.

Definition at line 119 of file Drifter.cxx.

120 {
121  m_xregions.clear();
122 }
std::vector< Xregion > m_xregions
Definition: Drifter.h:170
virtual void WireCell::Gen::Drifter::set_lifetime ( double  lifetime_to_set)
inlinevirtual

Definition at line 129 of file Drifter.h.

129  {
130  m_lifetime = lifetime_to_set;
131  };
IDepo::pointer WireCell::Gen::Drifter::transport ( IDepo::pointer  depo)

Member Data Documentation

Log::logptr_t WireCell::Gen::Drifter::l
private

Definition at line 183 of file Drifter.h.

double WireCell::Gen::Drifter::m_DL
private

Definition at line 140 of file Drifter.h.

double WireCell::Gen::Drifter::m_DT
private

Definition at line 140 of file Drifter.h.

bool WireCell::Gen::Drifter::m_fluctuate
private

Definition at line 146 of file Drifter.h.

double WireCell::Gen::Drifter::m_lifetime
private

Definition at line 143 of file Drifter.h.

IRandom::pointer WireCell::Gen::Drifter::m_rng
private

Definition at line 131 of file Drifter.h.

std::string WireCell::Gen::Drifter::m_rng_tn
private

Definition at line 136 of file Drifter.h.

double WireCell::Gen::Drifter::m_speed
private

Definition at line 148 of file Drifter.h.

double WireCell::Gen::Drifter::m_toffset
private

Definition at line 149 of file Drifter.h.

std::vector<Xregion> WireCell::Gen::Drifter::m_xregions
private

Definition at line 170 of file Drifter.h.

int WireCell::Gen::Drifter::n_drifted
private

Definition at line 151 of file Drifter.h.

int WireCell::Gen::Drifter::n_dropped
private

Definition at line 151 of file Drifter.h.


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