Diffuser.cxx
Go to the documentation of this file.
1 #include "WireCellGen/Diffuser.h"
4 #include "WireCellUtil/Units.h"
5 #include "WireCellUtil/Point.h"
6 #include "WireCellUtil/Persist.h"
7 #include <boost/format.hpp>
8 #include <cmath>
9 
10 #include <sstream>
11 #include <iostream>
12 
15 
16 using namespace std; // debugging
17 using namespace WireCell;
18 using boost::format;
19 
21  double binsize_l,
22  double time_offset,
23  double origin_l,
24  double DL,
25  double DT,
26  double drift_velocity,
27  double max_sigma_l,
28  double nsigma)
29  : m_pitch_origin(pitch.first)
30  , m_pitch_direction(ray_unit(pitch))
31  , m_time_offset(time_offset)
32  , m_origin_l(origin_l)
33  , m_origin_t(0.0) // measure pitch direction from pitch_origin
34  , m_binsize_l(binsize_l)
35  , m_binsize_t(ray_length(pitch))
36  , m_DL(DL)
37  , m_DT(DT)
38  , m_drift_velocity(drift_velocity)
39  , m_max_sigma_l(max_sigma_l)
40  , m_nsigma(nsigma)
41  , m_eos(false)
42 {
43  //dump("Diffuser created");
44 }
45 
46 Diffuser::~Diffuser()
47 {
48 }
49 
51 {
52  stringstream ss;
53  ss << "{\n"
54  << "\"pitch_origin\":{\"x\":0.0,\"y\":0.0,\"z\":0.0},\n"
55  << "\"pitch_direction\":{\"x\":0.0,\"y\":0.0,\"z\":1.0},\n"
56  << "\"pitch_distance\":" << 5.0*units::mm << ",\n"
57  << "\"timeslice\":" << 2.0 * units::us << ",\n"
58  << "\"timeoffset\":0.0,\n"
59  << "\"starttime\":0.0,\n"
60  << "\"origin\":0.0,\n"
61  << "\"DL\":" << 5.3*units::centimeter2/units::second << ",\n"
62  << "\"DT\":"<<12.8*units::centimeter2/units::second <<",\n"
63  << "\"drift_velocity\":" << 1.6 * units::mm/units::us << ",\n"
64  << "\"max_sigma_l\":" << 5.0 * units::us << ",\n"
65  << "\"nsigma\":3.0\n"
66  << "}\n";
67  return Persist::loads(ss.str());
68 }
69 
71 {
72  m_pitch_origin = get<Point>(cfg, "pitch_origin", m_pitch_origin);
73  m_pitch_direction = get<Point>(cfg, "pitch_direction", m_pitch_direction).norm();
74  m_time_offset = get<double>(cfg, "timeoffset", m_time_offset);
75 
76  m_origin_l = get<double>(cfg, "starttime", m_origin_l);
77  m_origin_t = get<double>(cfg, "origin", m_origin_t);
78 
79  m_binsize_l = get<double>(cfg, "timeslice", m_binsize_l);
80  m_binsize_t = get<double>(cfg, "pitch_distance", m_binsize_t);
81 
82  m_DL = get<double>(cfg, "DL", m_DL);
83  m_DT = get<double>(cfg, "DT", m_DT);
84 
85  m_drift_velocity = get<double>(cfg, "drift_velocity", m_drift_velocity);
86 
87  m_max_sigma_l = get<double>(cfg, "max_sigma_l", m_max_sigma_l);
88  m_nsigma = get<double>(cfg, "nsigma", m_nsigma);
89 
90  //dump("Diffuser configured");
91 }
92 
94 {
95  m_input.clear();
96 }
97 
99 {
100  stringstream ss;
101  ss << msg << endl
102  << "\tpitch origin " << m_pitch_origin << endl
103  << "\tpitch direction " << m_pitch_direction << endl
104  << "\ttime offset " << m_time_offset << endl
105  << "\torigin l " << m_origin_l << endl
106  << "\torigin t " << m_origin_t << endl
107  << "\tbinsize l " << m_binsize_l << endl
108  << "\tbinsize t " << m_binsize_t << endl
109  << "\tDL = " << m_DL << " DT = " << m_DT << endl
110  << "\tdrift velocity = " << m_drift_velocity << endl
111  << "\tmax sigma l = " << m_max_sigma_l << endl
112  << "\tnsigma = " << m_nsigma;
113  cerr << ss.str() << endl;;
114 }
115 
116 
118 {
119  if (m_eos) {
120  return false;
121  }
122  if (!depo) { // EOS flush
123  for (auto diff : m_input) {
124  outq.push_back(diff);
125  }
126  outq.push_back(nullptr);
127  m_eos = true;
128  return true;
129  }
130 
131  auto first = *depo_chain(depo).rbegin();
132  const double drift_distance = first->pos().x() - depo->pos().x();
133  const double drift_time = drift_distance / m_drift_velocity;
134 
135  const double tmpcm2 = 2*m_DL*drift_time/units::centimeter2;
136  const double sigmaL = sqrt(tmpcm2)*units::centimeter / m_drift_velocity;
137  const double sigmaT = sqrt(2*m_DT*drift_time/units::centimeter2)*units::centimeter2;
138 
139  const Vector to_depo = depo->pos() - m_pitch_origin;
140  const double pitch_distance = m_pitch_direction.dot(to_depo);
141 
142  cerr << "Diffuser: "
143  << " drift distance=" << drift_distance
144  << " drift time=" << drift_time
145  << " pitch distance = " << pitch_distance
146  << endl;
147 
148  IDiffusion::pointer diff = this->diffuse(m_time_offset + depo->time(), pitch_distance,
149  sigmaL, sigmaT, depo->charge(), depo);
150  m_input.insert(diff);
151 
152  while (m_input.size() > 2) {
153  auto first = *m_input.begin();
154  auto last = *m_input.rbegin();
155  const double last_center = 0.5*(last->lend() + last->lbegin());
156  if (last_center - first->lbegin() < m_max_sigma_l*m_nsigma) {
157  break; // new input with long diffusion may still take lead
158  }
159 
160  // now we are guaranteed no newly added diffusion can have a
161  // leading edge long enough to surpass that of the current
162  // leader.
163  outq.push_back(first);
164  m_input.erase(first);
165  }
166 
167  return true;
168 }
169 
170 
171 
172 
173 std::vector<double> Diffuser::oned(double mean, double sigma, double binsize,
175 {
176  int nbins = round((bounds.second - bounds.first)/binsize);
177 
178  /// fragment between bin_edge_{low,high}
179  std::vector<double> integral(nbins+1, 0.0);
180  for (int ibin=0; ibin <= nbins; ++ibin) {
181  double absx = bounds.first + ibin*binsize;
182  double t = 0.5*(absx-mean)/sigma;
183  double e = 0.5*std::erf(t);
184  integral[ibin] = e;
185  }
186 
187  std::vector<double> bins;
188  for (int ibin=0; ibin<nbins; ++ibin) {
189  bins.push_back(integral[ibin+1] - integral[ibin]);
190  }
191  return bins;
192 }
193 
194 
195 Diffuser::bounds_type Diffuser::bounds(double mean, double sigma, double binsize, double origin)
196 {
197  double low = floor( (mean - m_nsigma*sigma - origin) / binsize ) * binsize + origin;
198  double high = ceil( (mean + m_nsigma*sigma - origin) / binsize ) * binsize + origin;
199 
200  return std::make_pair(low, high);
201 }
202 
203 
204 IDiffusion::pointer Diffuser::diffuse(double mean_l, double mean_t,
205  double sigma_l, double sigma_t,
206  double weight, IDepo::pointer depo)
207 {
208  bounds_type bounds_l = bounds(mean_l, sigma_l, m_binsize_l, m_origin_l);
209  bounds_type bounds_t = bounds(mean_t, sigma_t, m_binsize_t, m_origin_t);
210 
211  std::vector<double> l_bins = oned(mean_l, sigma_l, m_binsize_l, bounds_l);
212  std::vector<double> t_bins = oned(mean_t, sigma_t, m_binsize_t, bounds_t);
213 
214  if (l_bins.empty() || t_bins.empty()) {
215  return nullptr;
216  }
217 
218  // get normalization
219  double power = 0;
220  for (auto l : l_bins) {
221  for (auto t : t_bins) {
222  power += l*t;
223  }
224  }
225  if (power == 0.0) {
226  return nullptr;
227  }
228 
229  Diffusion* smear = new Diffusion(depo,
230  l_bins.size(), t_bins.size(),
231  bounds_l.first, bounds_t.first,
232  bounds_l.second, bounds_t.second);
233 
234  for (size_t ind_l = 0; ind_l < l_bins.size(); ++ind_l) {
235  for (size_t ind_t = 0; ind_t < t_bins.size(); ++ind_t) {
236  double value = l_bins[ind_l]*t_bins[ind_t]/power*weight;
237  smear->set(ind_l, ind_t, value);
238  }
239  }
240 
241  IDiffusion::pointer ret(smear);
242  return ret;
243 }
244 
245 
virtual bool operator()(const input_pointer &depo, output_queue &outq)
The calling signature:
Definition: Diffuser.cxx:117
std::pair< Point, Point > Ray
A line segment running from a first (tail) to a second (head) point.
Definition: Point.h:21
std::shared_ptr< const IDiffusion > pointer
Definition: IData.h:19
IDepo::vector depo_chain(IDepo::pointer recent)
Definition: IDepo.cxx:4
virtual double set(int lind, int tind, double value)
Definition: Diffusion.cxx:56
void msg(const char *fmt,...)
Definition: message.cpp:107
void dump(const std::string &msg)
Definition: Diffuser.cxx:98
virtual void configure(const WireCell::Configuration &config)
Accept a configuration.
Definition: Diffuser.cxx:70
std::string string
Definition: nybbler.cc:12
IDiffusion::pointer diffuse(double mean_l, double mean_t, double sigma_l, double sigma_t, double weight=1.0, IDepo::pointer depo=nullptr)
Definition: Diffuser.cxx:204
STL namespace.
Point m_pitch_origin
Definition: Diffuser.h:104
IDiffusionSet m_input
Definition: Diffuser.h:116
virtual WireCell::Configuration default_configuration() const
Optional, override to return a hard-coded default configuration.
Definition: Diffuser.cxx:50
cfg
Definition: dbjson.py:29
Vector m_pitch_direction
Definition: Diffuser.h:105
static const double centimeter
Definition: Units.h:26
static QStrList * l
Definition: config.cpp:1044
std::deque< output_pointer > output_queue
std::vector< double > oned(double mean, double sigma, double binsize, const Diffuser::bounds_type &bounds)
Definition: Diffuser.cxx:173
const double e
double m_time_offset
Definition: Diffuser.h:106
double m_binsize_t
Definition: Diffuser.h:110
double ray_length(const Ray &ray)
Definition: Point.cxx:62
static const double centimeter2
Definition: Units.h:27
Vector ray_unit(const Ray &ray)
Definition: Point.cxx:71
double m_max_sigma_l
Definition: Diffuser.h:113
static const double mm
Definition: Units.h:55
double m_drift_velocity
Definition: Diffuser.h:112
auto norm(Vector const &v)
Return norm of the specified vector.
WIRECELL_FACTORY(Diffuser, WireCell::Diffuser, WireCell::IDiffuser, WireCell::IConfigurable) using namespace std
std::pair< double, double > bounds_type
Definition: Diffuser.h:34
Definition: Main.h:22
static const double second
Definition: Units.h:92
Json::Value loads(const std::string &text, const externalvars_t &extvar=externalvars_t(), const externalvars_t &extcode=externalvars_t())
Definition: Persist.cxx:152
T dot(const D3Vector &rhs) const
Return the dot product of this vector and the other.
Definition: D3Vector.h:80
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1225
bounds_type bounds(double mean, double sigma, double binsize, double origin=0.0)
Definition: Diffuser.cxx:195
Json::Value Configuration
Definition: Configuration.h:50
static const double us
Definition: Units.h:105
std::shared_ptr< const IDepo > input_pointer
weight
Definition: test.py:257
double m_binsize_l
Definition: Diffuser.h:109
virtual void reset()
Definition: Diffuser.cxx:93
double mean(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:15
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:227
QTextStream & endl(QTextStream &s)