Waveform.cxx
Go to the documentation of this file.
2 
3 #include <algorithm>
4 
5 // for FFT
6 #include <Eigen/Core>
7 #include <unsupported/Eigen/FFT>
8 
9 #include <complex>
10 
11 using namespace WireCell;
12 
13 
14 std::pair<int,int>
15 WireCell::Waveform::sub_sample(const Waveform::Domain& domain, int nsamples, const Waveform::Domain& subdomain)
16 {
17  const double bin = sample_width(domain, nsamples);
18  int beg = ceil((subdomain.first - domain.first) / bin);
19  int end = nsamples- ceil((domain.second - subdomain.second) / bin);
20  return std::make_pair(std::max(0,beg), std::min(nsamples, end));
21 }
22 
23 std::pair<double,double>
25 {
26  const int n = wf.size();
27  if (n==0) {
28  return std::make_pair<double,double>(0,0);
29  }
30  if (n==1) {
31  return std::make_pair<double,double>(wf[0],0);
32  }
33 
34  // if left as float, numerical precision will lead to many NaN for
35  // the RMS due to sometimes subtracting similar sized numbers.
36  std::vector<double> wfd(wf.begin(), wf.end());
37 
38  const double wsum = Waveform::sum(wfd);
39  const double w2sum = Waveform::sum2(wfd);
40  const double mean = wsum/n;
41  const double rms = sqrt( (w2sum - wsum*wsum/n) / n );
42  // const double rms = sqrt( (w2sum - wsum*wsum/n) / (n-1) );
43  return std::make_pair(mean,rms);
44 }
45 
46 
47 template<class Func>
49 {
50  Waveform::realseq_t ret(seq.size());
51  std::transform(seq.begin(), seq.end(), ret.begin(), func);
52  return ret;
53 }
54 
56 {
57  return c2r(seq, [](Waveform::complex_t c) { return std::real(c); });
58 }
59 
61 {
62  return c2r(seq, [](Waveform::complex_t c) { return std::imag(c); });
63 }
64 
66 {
67  return c2r(seq, [](Waveform::complex_t c) { return std::abs(c); });
68 }
69 
71 {
72  return c2r(seq, [](Waveform::complex_t c) { return std::arg(c); });
73 }
74 
75 
77 {
78  return percentile(wave,0.5);
79 }
80 
82 {
83  return percentile_binned(wave,0.5);
84 }
85 
86 
88 {
89  std::nth_element(wave.begin(), wave.begin()+wave.size()*percentage, wave.end());
90  return wave.at(wave.size()*percentage);
91 }
92 
94  const auto mm = std::minmax_element(wave.begin(), wave.end());
95  const auto vmin = *mm.first;
96  const auto vmax = *mm.second;
97  const int nbins = wave.size();
98  const auto binsize = (vmax-vmin)/nbins;
100  for (auto val : wave) {
101  int bin = int(round((val - vmin)/binsize));
102  bin = std::max(0, bin);
103  bin = std::min(nbins-1, bin);
104  hist[bin] += 1.0;
105  }
106 
107  const int imed = wave.size() * percentage;
108  int count = 0;
109  for (int ind=0; ind<nbins; ++ind) {
110  count += hist[ind];
111  if (count > imed) {
112  float ret = vmin + ind*binsize;
113  return ret;
114  }
115  }
116  // can't reach here, return bogus value.
117  return vmin + (vmax-vmin)*percentage;
118 }
119 
120 
121 std::pair<int, int> WireCell::Waveform::edge(const realseq_t& wave)
122 {
123  const int size = wave.size();
124  int imin=size, imax=size;
125 
126  for (int ind=0; ind < size; ++ind) {
127  const real_t val = wave[ind];
128  if (val != 0.0) {
129  if (imin == size) { // found start edge
130  imin = ind;
131  }
132  if (imin < size) {
133  imax = ind+1;
134  }
135  }
136  }
137  return std::make_pair(imin, imax);
138 }
139 
140 
142 {
143  auto v = Eigen::Map<Eigen::VectorXf>(wave.data(), wave.size());
144  Eigen::FFT<Waveform::real_t> trans;
145  Eigen::VectorXcf ret = trans.fwd(v);
146  return compseq_t(ret.data(), ret.data()+ret.size());
147 }
148 
150 {
151  Eigen::FFT<Waveform::real_t> trans;
152  auto v = Eigen::Map<Eigen::VectorXcf>(spec.data(), spec.size());
153  Eigen::VectorXf ret;
154  trans.inv(ret, v);
155  return realseq_t(ret.data(), ret.data()+ret.size());
156 }
157 
158 // Linear convolution, returns in1.size()+in2.size()-1.
161  bool truncate)
162 {
163  size_t n1_orig = in1.size(), n2_orig = in2.size();
164  size_t n_out = n1_orig + n2_orig - 1;
165 
166  in1.resize(n_out, 0);
167  in2.resize(n_out, 0);
168 
169  auto v1 = Eigen::Map<Eigen::VectorXf>(in1.data(), in1.size());
170  auto v2 = Eigen::Map<Eigen::VectorXf>(in2.data(), in2.size());
171 
172  Eigen::FFT<Waveform::real_t> trans;
173 
174  Eigen::VectorXcf s1 = trans.fwd(v1);
175  Eigen::VectorXcf s2 = trans.fwd(v2);
176  Eigen::VectorXcf s12 = (s1.array() * s2.array()).matrix();
177  Eigen::VectorXf vret;
178  trans.inv(vret, s12);
179  realseq_t ret(vret.data(), vret.data()+vret.size());
180  if (truncate) {
181  ret.resize(n1_orig);
182  }
183  return ret;
184 }
185 
186 // Replace old response in wave with new response.
188  Waveform::realseq_t newres,
189  Waveform::realseq_t oldres,
190  bool truncate)
191 {
192  size_t sizes[3] = {wave.size(), newres.size(), oldres.size()};
193  size_t n_out = sizes[0]+sizes[1]+sizes[2] - *std::min_element(sizes, sizes+3) - 1;
194 
195  wave.resize(n_out, 0);
196  newres.resize(n_out, 0);
197  oldres.resize(n_out, 0);
198 
199  auto v1 = Eigen::Map<Eigen::VectorXf>(wave.data(), wave.size());
200  auto v2 = Eigen::Map<Eigen::VectorXf>(newres.data(), newres.size());
201  auto v3 = Eigen::Map<Eigen::VectorXf>(oldres.data(), oldres.size());
202 
203  Eigen::FFT<Waveform::real_t> trans;
204 
205  Eigen::VectorXcf s1 = trans.fwd(v1);
206  Eigen::VectorXcf s2 = trans.fwd(v2);
207  Eigen::VectorXcf s3 = trans.fwd(v3);
208 
209  Eigen::VectorXcf s123 = (s1.array() * s2.array() / s3.array()).matrix();
210 
211  Eigen::VectorXf vret;
212  trans.inv(vret, s123);
213  realseq_t ret(vret.data(), vret.data()+vret.size());
214  if (truncate) {
215  ret.resize(sizes[0]);
216  }
217  return ret;
218 }
219 
220 
223 {
224  WireCell::Waveform::BinRangeList tmp(brl.begin(), brl.end());
226  sort(tmp.begin(), tmp.end());
227  Waveform::BinRange last_br = tmp[0];
228  out.push_back(last_br);
229 
230  for (size_t ind=1; ind<tmp.size(); ++ind) {
231  Waveform::BinRange this_br = tmp[ind];
232  if (out.back().second >= this_br.first) {
233  out.back().second = this_br.second;
234  continue;
235  }
236  out.push_back(this_br);
237  }
238  return out;
239 }
240 
241 /// Merge two bin range lists, forming a union from any overlapping ranges
245 {
247  out.reserve(br1.size() + br2.size());
248  out.insert(out.end(), br1.begin(), br1.end());
249  out.insert(out.end(), br2.begin(), br2.end());
250  return merge(out);
251 }
252 
253 
254 
255 
256 /// Return a new mapping which is the union of all same channel masks.
260 {
262  for (auto const &it : two) {
263  int ch = it.first;
264  out[ch] = merge(out[ch], it.second);
265  }
266  return out;
267 }
268 
269 
270 void WireCell::Waveform::merge(ChannelMaskMap &one, ChannelMaskMap &two, std::map<std::string,std::string>& name_map){
271 
272  // loop over second map
273  for (auto const& it: two){
274  std::string name = it.first;
275  std::string mapped_name;
276  if (name_map.find(name)!=name_map.end()){
277  mapped_name = name_map[name];
278  }else{
279  mapped_name = name;
280  }
281  if (one.find(mapped_name) != one.end()){
282  one[mapped_name] = merge(one[mapped_name],it.second);
283  }else{
284  one[mapped_name] = it.second;
285  }
286  }
287 }
288 
289 short WireCell::Waveform::most_frequent(const std::vector<short>& vals)
290 {
291  const size_t nbins = 1<<16;
292  std::vector<unsigned int> hist(nbins, 0);
293  for (unsigned short val : vals) {
294  hist[val] += 1;
295  }
296  auto it = std::max_element(hist.begin(), hist.end());
297  return it - hist.begin(); // casts back to signed short
298 }
299 
300 
301 // Local Variables:
302 // mode: c++
303 // c-basic-offset: 4
304 // End:
static QCString name
Definition: declinfo.cpp:673
std::pair< int, int > BinRange
A half-open range of bins (from first bin to one past last bin)
Definition: Waveform.h:38
realseq_t real(const compseq_t &seq)
Return the real part of the sequence.
Definition: Waveform.cxx:55
Sequence< real_t > realseq_t
Definition: Waveform.h:31
double rms(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:39
std::string string
Definition: nybbler.cc:12
Val sum2(const Sequence< Val > &seq)
Return sum of square of all entries in sequence.
Definition: Waveform.h:184
internal::named_arg< T, char > arg(string_view name, const T &arg)
Definition: core.h:1391
std::map< int, BinRangeList > ChannelMasks
Map channel number to a vector of BinRanges.
Definition: Waveform.h:50
std::pair< int, int > edge(const realseq_t &wave)
Definition: Waveform.cxx:121
short most_frequent(const std::vector< short > &vals)
Return the smallest, most frequent value to appear in vector.
Definition: Waveform.cxx:289
float real_t
The type for the signal in each bin.
Definition: Waveform.h:18
tagset_t transform(const tagset_t &ts, const ruleset_t &rs, bool all_rules=true)
Definition: TagRules.cxx:43
BinRangeList merge(const BinRangeList &br)
Return a new list with any overlaps formed into unions.
Definition: Waveform.cxx:222
std::pair< int, int > sub_sample(const Domain &domain, int nsamples, const Domain &subdomain)
Return the begin/end sample numbers inside the a subdomain of a domain with nsamples total...
Definition: Waveform.cxx:15
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:72
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:87
realseq_t replace_convolve(Waveform::realseq_t wave, Waveform::realseq_t newres, Waveform::realseq_t oldres, bool truncate=true)
Definition: Waveform.cxx:187
real_t median(realseq_t &wave)
Definition: Waveform.cxx:76
T abs(T value)
compseq_t dft(realseq_t seq)
Definition: Waveform.cxx:141
double sample_width(const Domain &domain, int count)
Return the sample size if domain is equally sampled with given number of samples. ...
Definition: Waveform.h:81
std::pair< double, double > Domain
Definition: Waveform.h:75
std::map< std::string, ChannelMasks > ChannelMaskMap
Collect channel masks by some label.
Definition: Waveform.h:59
std::vector< BinRange > BinRangeList
A list of bin ranges.
Definition: Waveform.h:41
string tmp
Definition: languages.py:63
static int max(int a, int b)
realseq_t phase(const compseq_t &seq)
Return the phase or arg part of the sequence.
Definition: Waveform.cxx:70
real_t median_binned(realseq_t &wave)
Definition: Waveform.cxx:81
real_t percentile(realseq_t &wave, real_t percentage)
Definition: Waveform.cxx:87
static const double mm
Definition: Units.h:73
Definition: Main.h:22
realseq_t idft(compseq_t spec)
Definition: Waveform.cxx:149
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
Val sum(const Sequence< Val > &seq)
Return sum of all entries in sequence.
Definition: Waveform.h:178
realseq_t magnitude(const compseq_t &seq)
Return the magnitude or absolute value of the sequence.
Definition: Waveform.cxx:65
std::pair< double, double > mean_rms(const realseq_t &wave)
Definition: Waveform.cxx:24
def func()
Definition: docstring.py:7
QTextStream & bin(QTextStream &s)
realseq_t imag(const compseq_t &seq)
Return the imaginary part of the sequence.
Definition: Waveform.cxx:60
std::complex< float > complex_t
The type for the spectrum in each bin.
Definition: Waveform.h:21
std::size_t n
Definition: format.h:3399
Sequence< complex_t > compseq_t
A complex-valued sequence, eg for discrete spectrum powers.
Definition: Waveform.h:34
double mean(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:15
real_t percentile_binned(realseq_t &wave, real_t percentage)
Definition: Waveform.cxx:93
Waveform::realseq_t c2r(const Waveform::compseq_t &seq, Func func)
Definition: Waveform.cxx:48
realseq_t linear_convolve(Waveform::realseq_t in1, Waveform::realseq_t in2, bool truncate=true)
Definition: Waveform.cxx:159