Waveform.h
Go to the documentation of this file.
1 #ifndef WIRECELL_WAVEFORM
2 #define WIRECELL_WAVEFORM
3 
4 #include <map>
5 #include <cstdint>
6 #include <vector>
7 #include <complex>
8 #include <numeric>
9 #include <algorithm>
10 #include <string>
11 
12 namespace WireCell {
13 
14 
15  namespace Waveform {
16 
17  /// The type for the signal in each bin.
18  typedef float real_t;
19 
20  /// The type for the spectrum in each bin.
21  typedef std::complex<float> complex_t;
22 
23 
24  /// A sequence is an ordered array of values (real or
25  /// complex). By itself it is not associated with a domain.
26  template<typename Val>
27  using Sequence = std::vector<Val>;
28 
29 
30  // A real-valued sequence, eg for discrete signal values.
32 
33  /// A complex-valued sequence, eg for discrete spectrum powers.
35 
36 
37  /// A half-open range of bins (from first bin to one past last bin)
38  typedef std::pair<int,int> BinRange;
39 
40  /// A list of bin ranges.
41  typedef std::vector<BinRange> BinRangeList;
42 
43  /// Return a new list with any overlaps formed into unions.
44  BinRangeList merge(const BinRangeList& br);
45 
46  /// Merge two bin range lists, forming a union from any overlapping ranges
47  BinRangeList merge(const BinRangeList& br1, const BinRangeList& br2);
48 
49  /// Map channel number to a vector of BinRanges
50  typedef std::map<int, BinRangeList > ChannelMasks;
51 
52  /// Return a new mapping which is the union of all same channel masks.
53  ChannelMasks merge(const ChannelMasks& one, const ChannelMasks& two);
54 
55 
56 
57 
58  /// Collect channel masks by some label.
59  typedef std::map<std::string, ChannelMasks> ChannelMaskMap;
60 
61  // merge second maskmap into the first maskmap
62  void merge(ChannelMaskMap &one, ChannelMaskMap &two, std::map<std::string,std::string>& name_map);
63 
64 
65  /// A range of time
66  typedef std::pair<double,double> Period;
67 
68  /// A range of frequency
69  typedef std::pair<double,double> Band;
70 
71 
72  /// A domain of a sequence is bounded by the time or frequency
73  /// at the start of its first element and that at the end of
74  /// its last.
75  typedef std::pair<double,double> Domain;
76  /// Return the number of samples needed to cover the domain with sample size width.
77  inline int sample_count(const Domain& domain, double width) {
78  return (domain.second-domain.first)/width;
79  }
80  /// Return the sample size if domain is equally sampled with given number of samples
81  inline double sample_width(const Domain& domain, int count) {
82  return (domain.second-domain.first)/count;
83  }
84 
85  /// Return the begin/end sample numbers inside the a subdomain of a domain with nsamples total.
86  std::pair<int,int> sub_sample(const Domain& domain, int nsamples, const Domain& subdomain);
87 
88  /// Return a new sequence resampled and interpolated from the
89  /// original wave defined over the domain to a new domain of
90  /// nsamples.
91  template<typename Val>
92  Sequence<Val> resample(const Sequence<Val>& wave, const Domain& domain, int nsamples, const Domain& newdomain) {
93  const int oldnsamples = wave.size();
94  const double oldstep = sample_width(domain, oldnsamples);
95  const double step = sample_width(newdomain, nsamples);
96  Sequence<Val> ret;
97  for (int ind=0; ind<nsamples; ++ind) {
98  double cursor = newdomain.first + ind*step;
99  double oldfracsteps = (cursor-domain.first)/oldstep;
100  int oldind = int(oldfracsteps);
101  if (cursor <= domain.first || oldind <= 0) {
102  ret.push_back(wave[0]);
103  continue;
104  }
105  if (cursor >= domain.second or oldind+1 >= oldnsamples) {
106  ret.push_back(wave[oldnsamples-1]);
107  continue;
108  }
109  double d1 = oldfracsteps - oldstep*oldind;
110  double d2 = oldstep - d1;
111  Val newval = (wave[oldind] * d1 + wave[oldind+1]*d2) / oldstep;
112  ret.push_back(newval);
113  }
114  return ret;
115  }
116 
117  /// Return the real part of the sequence
118  realseq_t real(const compseq_t& seq);
119  /// Return the imaginary part of the sequence
120  realseq_t imag(const compseq_t& seq);
121  /// Return the magnitude or absolute value of the sequence
122  realseq_t magnitude(const compseq_t& seq);
123  /// Return the phase or arg part of the sequence
124  realseq_t phase(const compseq_t& seq);
125 
126 
127  /// Increase (shift) sequence values by scalar
128  template<typename Val>
129  void increase(Sequence<Val>& seq, Val scalar) {
130  std::transform(seq.begin(), seq.end(), seq.begin(),
131  [scalar](Val x) { return x+scalar; });
132  }
133  inline void increase(Sequence<float>& seq, double scalar) {
134  increase(seq, (float)scalar);
135  }
136 
137  /// Increase (shift) sequence values by values in another sequence
138  template<typename Val>
140  std::transform(seq.begin(), seq.end(), other.begin(), seq.begin(),
141  std::plus<Val>());
142  }
143 
144  /// Scale (multiply) sequence values by scalar
145  template<typename Val>
146  void scale(Sequence<Val>& seq, Val scalar) {
147  std::transform(seq.begin(), seq.end(), seq.begin(),
148  [scalar](Val x) { return x*scalar; });
149  }
150  inline void scale(Sequence<float>& seq, double scalar) {
151  scale(seq, (float)scalar);
152  }
153 
154  /// Scale (multiply) seq values by values from the other sequence.
155  template<typename Val>
156  void scale(Sequence<Val>& seq, const Sequence<Val>& other) {
157  std::transform(seq.begin(), seq.end(), other.begin(), seq.begin(),
158  std::multiplies<Val>());
159  }
160  /// Shrink (divide) seq values by values from the other sequence.
161  template<typename Val>
163  std::transform(seq.begin(), seq.end(), other.begin(), seq.begin(),
164  std::divides<Val>());
165  }
166 
167 
168  /// Return a pair of indices into wave which bound non-zero
169  /// region. First index is of first non-zero sample, second
170  /// index is one past last non-zero sample. If entire wave is
171  /// empty then both are set to size().
172  std::pair<int, int> edge(const realseq_t& wave);
173 
174 
175 
176  /// Return sum of all entries in sequence.
177  template<typename Val>
178  Val sum(const Sequence<Val>& seq) {
179  return std::accumulate(seq.begin(), seq.end(), Val());
180  }
181 
182  /// Return sum of square of all entries in sequence.
183  template<typename Val>
184  Val sum2(const Sequence<Val>& seq) {
185  return std::accumulate(seq.begin(), seq.end(), Val(),
186  [](const Val& bucket, Val x) {
187  return bucket + x*x;
188  });
189  }
190 
191  // Return the mean and (population) RMS over a waveform signal.
192  std::pair<double,double> mean_rms(const realseq_t& wave);
193 
194 
195  // Return the median value. This is rather slow as it
196  // involves a sort.
197  real_t median(realseq_t& wave);
198 
199  // Return the median value. This is faster but introduces
200  // inaccuracies due to binning.
201  real_t median_binned(realseq_t& wave);
202 
203  real_t percentile(realseq_t& wave, real_t percentage);
204  real_t percentile_binned(realseq_t& wave, real_t percentage);
205 
206  /// Discrete Fourier transform of real sequence. Returns full
207  /// spectrum. No normalization scaling applied
208  compseq_t dft(realseq_t seq);
209 
210  // Linear convolution, returns in1.size()+in2.size()-1. If
211  // truncate is false then the returned sequence will be
212  // truncated to length that of the first input. Otherwise the
213  // function is symmetric between the two inputs.
214  realseq_t linear_convolve(Waveform::realseq_t in1,
216  bool truncate = true);
217 
218  // Replace old response in wave with new response. If
219  // truncate is false then the returned sequence will be the
220  // length required for linear convolution. This is the sum of
221  // the sizes of all input less one and less the smallest.
222  realseq_t replace_convolve(Waveform::realseq_t wave,
223  Waveform::realseq_t newres,
224  Waveform::realseq_t oldres,
225  bool truncate = true);
226 
227  /// Inverse, discrete Fourier transform. Expects full
228  /// spectrum (twice Nyquist frequency). Applies the
229  /// 1/Nsamples normalization.
230  realseq_t idft(compseq_t spec);
231 
232  /// Return the smallest, most frequent value to appear in vector.
233  short most_frequent(const std::vector<short>& vals);
234 
235  }
236 }
237 
238 #endif
std::vector< Val > Sequence
Definition: Waveform.h:27
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
std::vector< T > Waveform
Definition: IWaveformTool.h:21
Val sum2(const Sequence< Val > &seq)
Return sum of square of all entries in sequence.
Definition: Waveform.h:184
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
const double width
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
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
void shrink(Sequence< Val > &seq, const Sequence< Val > &other)
Shrink (divide) seq values by values from the other sequence.
Definition: Waveform.h:162
std::map< std::string, ChannelMasks > ChannelMaskMap
Collect channel masks by some label.
Definition: Waveform.h:59
void increase(Sequence< Val > &seq, Val scalar)
Increase (shift) sequence values by scalar.
Definition: Waveform.h:129
std::vector< BinRange > BinRangeList
A list of bin ranges.
Definition: Waveform.h:41
std::pair< double, double > Period
A range of time.
Definition: Waveform.h:66
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
Definition: Main.h:22
void scale(Sequence< Val > &seq, Val scalar)
Scale (multiply) sequence values by scalar.
Definition: Waveform.h:146
realseq_t idft(compseq_t spec)
Definition: Waveform.cxx:149
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
std::pair< double, double > Band
A range of frequency.
Definition: Waveform.h:69
realseq_t imag(const compseq_t &seq)
Return the imaginary part of the sequence.
Definition: Waveform.cxx:60
list x
Definition: train.py:276
std::complex< float > complex_t
The type for the spectrum in each bin.
Definition: Waveform.h:21
int sample_count(const Domain &domain, double width)
Return the number of samples needed to cover the domain with sample size width.
Definition: Waveform.h:77
Sequence< complex_t > compseq_t
A complex-valued sequence, eg for discrete spectrum powers.
Definition: Waveform.h:34
real_t percentile_binned(realseq_t &wave, real_t percentage)
Definition: Waveform.cxx:93
Sequence< Val > resample(const Sequence< Val > &wave, const Domain &domain, int nsamples, const Domain &newdomain)
Definition: Waveform.h:92
realseq_t linear_convolve(Waveform::realseq_t in1, Waveform::realseq_t in2, bool truncate=true)
Definition: Waveform.cxx:159