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

#include <EmpiricalNoiseModel.h>

Inheritance diagram for WireCell::Gen::EmpiricalNoiseModel:
WireCell::IChannelSpectrum WireCell::IConfigurable WireCell::IComponent< IChannelSpectrum > WireCell::IComponent< IConfigurable > WireCell::Interface WireCell::Interface

Classes

struct  NoiseSpectrum
 

Public Member Functions

 EmpiricalNoiseModel (const std::string &spectra_file="", const int nsamples=10000, const double period=0.5 *units::us, const double wire_length_scale=1.0 *units::cm, const std::string anode_tn="AnodePlane", const std::string chanstat_tn="StaticChannelStatus")
 
virtual ~EmpiricalNoiseModel ()
 
virtual const amplitude_toperator() (int chid) const
 IChannelSpectrum. More...
 
virtual const std::vector< float > & freq () const
 
virtual const double gain (int chid) const
 
virtual const double shaping_time (int chid) const
 
virtual void configure (const WireCell::Configuration &config)
 IConfigurable. More...
 
virtual WireCell::Configuration default_configuration () const
 Optional, override to return a hard-coded default configuration. More...
 
void resample (NoiseSpectrum &spectrum) const
 
void gen_elec_resp_default ()
 
amplitude_t interpolate (int plane, double wire_length) const
 
int get_nsamples ()
 
- Public Member Functions inherited from WireCell::IChannelSpectrum
virtual ~IChannelSpectrum ()
 
- Public Member Functions inherited from WireCell::IComponent< IChannelSpectrum >
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 Types

typedef std::unordered_map< int, amplitude_tlen_amp_cache_t
 

Private Attributes

IAnodePlane::pointer m_anode
 
IChannelStatus::pointer m_chanstat
 
std::string m_spectra_file
 
int m_nsamples
 
int m_fft_length
 
double m_period
 
double m_wlres
 
std::string m_anode_tn
 
std::string m_chanstat_tn
 
std::map< int, std::vector< NoiseSpectrum * > > m_spectral_data
 
std::unordered_map< int, int > m_chid_to_intlen
 
std::vector< len_amp_cache_tm_amp_cache
 
Waveform::realseq_t m_elec_resp_freq
 
std::unordered_map< int, Waveform::realseq_tm_elec_resp_cache
 
amplitude_t comb_amp
 
Log::logptr_t log
 

Additional Inherited Members

- Public Types inherited from WireCell::IChannelSpectrum
typedef std::vector< float > amplitude_t
 
- Public Types inherited from WireCell::IComponent< IChannelSpectrum >
typedef std::shared_ptr< IChannelSpectrumpointer
 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

Definition at line 31 of file EmpiricalNoiseModel.h.

Member Typedef Documentation

typedef std::unordered_map<int, amplitude_t> WireCell::Gen::EmpiricalNoiseModel::len_amp_cache_t
private

Definition at line 106 of file EmpiricalNoiseModel.h.

Constructor & Destructor Documentation

Gen::EmpiricalNoiseModel::EmpiricalNoiseModel ( const std::string spectra_file = "",
const int  nsamples = 10000,
const double  period = 0.5*units::us,
const double  wire_length_scale = 1.0*units::cm,
const std::string  anode_tn = "AnodePlane",
const std::string  chanstat_tn = "StaticChannelStatus" 
)

Definition at line 21 of file EmpiricalNoiseModel.cxx.

30  : m_spectra_file(spectra_file)
31  , m_nsamples(nsamples)
32  , m_period(period)
33  , m_wlres(wire_length_scale)
34  // , m_tres(time_scale)
35  // , m_gres(gain_scale)
36  // , m_fres(freq_scale)
37  , m_anode_tn(anode_tn)
38  , m_chanstat_tn(chanstat_tn)
39  , m_amp_cache(4)
40  , log(Log::logger("sim"))
41 {
43  // m_fft_length = m_nsamples;
45 }
std::vector< len_amp_cache_t > m_amp_cache
std::size_t fft_best_length(size_t nsamples, bool keep_odd_even=false)
logptr_t logger(std::string name)
Definition: Logging.cxx:71
Gen::EmpiricalNoiseModel::~EmpiricalNoiseModel ( )
virtual

Definition at line 48 of file EmpiricalNoiseModel.cxx.

49 {
50 }

Member Function Documentation

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

IConfigurable.

Implements WireCell::IConfigurable.

Definition at line 150 of file EmpiricalNoiseModel.cxx.

151 {
152  m_anode_tn = get(cfg, "anode", m_anode_tn);
153  m_anode = Factory::find_tn<IAnodePlane>(m_anode_tn);
154 
155  m_chanstat_tn = get(cfg, "chanstat", m_chanstat_tn);
156  if (m_chanstat_tn != "") { // allow for an empty channel status, no deviation from norm
157  m_chanstat = Factory::find_tn<IChannelStatus>(m_chanstat_tn);
158  }
159 
160  log->debug("EmpiricalNoiseModel: using anode {}, chanstat {}", m_anode_tn, m_chanstat_tn);
161 
162  m_spectra_file = get(cfg, "spectra_file", m_spectra_file);
163 
164  m_nsamples = get(cfg, "nsamples", m_nsamples);
166  //m_fft_length = m_nsamples;
167  m_period = get(cfg, "period", m_period);
168  m_wlres = get(cfg, "wire_length_scale", m_wlres);
169  // m_tres = get(cfg, "time_scale", m_tres);
170  // m_gres = get(cfg, "gain_scale", m_gres);
171  // m_fres = get(cfg, "freq_scale", m_fres);
172 
173  // Load the data file assuming. The file should be a list of
174  // dictionaries matching the
175  // wirecell.sigproc.noise.schema.NoiseSpectrum class. Fixme:
176  // should break out this code separate.
177  auto jdat = Persist::load(m_spectra_file);
178  const int nentries = jdat.size();
179  m_spectral_data.clear();
180 
182 
183  for (int ientry=0; ientry<nentries; ++ientry) {
184  auto jentry = jdat[ientry];
185  NoiseSpectrum *nsptr = new NoiseSpectrum();
186 
187  nsptr->plane = jentry["plane"].asInt();
188  nsptr->nsamples = jentry["nsamples"].asInt();
189  nsptr->period = jentry["period"].asFloat();// * m_tres;
190  nsptr->gain = jentry["gain"].asFloat();// *m_gres;
191  nsptr->shaping = jentry["shaping"].asFloat();// * m_tres;
192  nsptr->wirelen = jentry["wirelen"].asFloat();// * m_wlres;
193  nsptr->constant = jentry["const"].asFloat();
194 
195  auto jfreqs = jentry["freqs"];
196  const int nfreqs = jfreqs.size();
197  nsptr->freqs.resize(nfreqs, 0.0);
198  for (int ind=0; ind<nfreqs; ++ind) {
199  nsptr->freqs[ind] = jfreqs[ind].asFloat();// * m_fres;
200  }
201  auto jamps = jentry["amps"];
202  const int namps = jamps.size();
203  nsptr->amps.resize(namps+1, 0.0);
204  for (int ind=0; ind<namps; ++ind) {
205  nsptr->amps[ind] = jamps[ind].asFloat();
206  }
207  // put the constant term at the end of the amplitude ...
208  // nsptr->amps[namps] = nsptr->constant;
209 
210  resample(*nsptr);
211  m_spectral_data[nsptr->plane].push_back(nsptr); // assumes ordered by wire length!
212  }
213 }
void resample(NoiseSpectrum &spectrum) const
std::size_t fft_best_length(size_t nsamples, bool keep_odd_even=false)
cfg
Definition: dbjson.py:29
Json::Value load(const std::string &filename, const externalvars_t &extvar=externalvars_t(), const externalvars_t &extcode=externalvars_t())
Definition: Persist.cxx:121
std::map< int, std::vector< NoiseSpectrum * > > m_spectral_data
WireCell::Configuration Gen::EmpiricalNoiseModel::default_configuration ( ) const
virtual

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

The file holding the spectral data

Reimplemented from WireCell::IConfigurable.

Definition at line 80 of file EmpiricalNoiseModel.cxx.

81 {
83 
84  /// The file holding the spectral data
85  cfg["spectra_file"] = m_spectra_file;
86  cfg["nsamples"] = m_nsamples; // number of samples up to Nyquist frequency
87  cfg["period"] = m_period;
88  cfg["wire_length_scale"] = m_wlres; //
89  // cfg["time_scale"] = m_tres;
90  // cfg["gain_scale"] = m_gres;
91  // cfg["freq_scale"] = m_fres;
92  cfg["anode"] = m_anode_tn; // name of IAnodePlane component
93 
94  return cfg;
95 }
cfg
Definition: dbjson.py:29
Json::Value Configuration
Definition: Configuration.h:50
const std::vector< float > & Gen::EmpiricalNoiseModel::freq ( ) const
virtual

Definition at line 266 of file EmpiricalNoiseModel.cxx.

267 {
268  // assume frequency is universal ...
269  const int iplane = 0;
270  auto it = m_spectral_data.find(iplane);
271  const auto& spectra = it->second;
272  return spectra.front()->freqs;
273 }
std::map< int, std::vector< NoiseSpectrum * > > m_spectral_data
const double Gen::EmpiricalNoiseModel::gain ( int  chid) const
virtual

Definition at line 284 of file EmpiricalNoiseModel.cxx.

285 {
286  auto wpid = m_anode->resolve(chid);
287  const int iplane = wpid.index();
288  auto it = m_spectral_data.find(iplane);
289  const auto& spectra = it->second;
290  return spectra.front()->gain;
291 }
std::map< int, std::vector< NoiseSpectrum * > > m_spectral_data
void Gen::EmpiricalNoiseModel::gen_elec_resp_default ( )

Definition at line 52 of file EmpiricalNoiseModel.cxx.

52  {
53  // double shaping[5]={1,1.1,2,2.2,3}; // us
54 
55  // calculate the frequencies ...
57  for (unsigned int i=0;i!=m_elec_resp_freq.size();i++){
58  if (i<=m_elec_resp_freq.size()/2.){
59  m_elec_resp_freq.at(i) = i / (m_elec_resp_freq.size() *1.0) * 1./m_period ; // the second half is useless ...
60  }else{
61  m_elec_resp_freq.at(i) = (m_elec_resp_freq.size()-i) / (m_elec_resp_freq.size() *1.0) * 1./m_period ; // the second half is useless ...
62  }
63 
64  // if (m_elec_resp_freq.at(i) > 1./m_period / 2.){
65  // m_elec_resp_freq.resize(i);
66  // break;
67  // }
68  }
69 
70  // for (int i=0;i!=5;i++){
71  // Response::ColdElec elec_resp(1, shaping[i]); // default at 1 mV/fC
72  // auto sig = elec_resp.generate(WireCell::Waveform::Domain(0, m_fft_length*m_period), m_fft_length);
73  // auto filt = Waveform::dft(sig);
74  // int nconfig = shaping[i]/ 0.1;
75  // auto ele_resp_amp = Waveform::magnitude(filt);
76  // m_elec_resp_cache[nconfig] = ele_resp_amp;
77  // }
78 }
int WireCell::Gen::EmpiricalNoiseModel::get_nsamples ( )
inline

Definition at line 87 of file EmpiricalNoiseModel.h.

IChannelSpectrum::amplitude_t Gen::EmpiricalNoiseModel::interpolate ( int  plane,
double  wire_length 
) const

Definition at line 216 of file EmpiricalNoiseModel.cxx.

217 {
218  auto it = m_spectral_data.find(iplane);
219  if (it == m_spectral_data.end()) {
220  return amplitude_t();
221  }
222 
223  const auto& spectra = it->second;
224 
225 
226 
227  // Linearly interpolate spectral data to wire length.
228 
229  // Any wire lengths
230  // which are out of bounds causes the nearest result to be
231  // returned (flat extrapolation)
232  const NoiseSpectrum* front = spectra.front();
233  if (wire_length <= front->wirelen) {
234  return front->amps;
235  }
236  const NoiseSpectrum* back = spectra.back();
237  if (wire_length >= back->wirelen) {
238  return back->amps;
239  }
240 
241  const int nspectra = spectra.size();
242  for (int ind=1; ind<nspectra; ++ind) {
243  const NoiseSpectrum* hi = spectra[ind];
244  if (hi->wirelen < wire_length) {
245  continue;
246  }
247  const NoiseSpectrum* lo = spectra[ind-1];
248 
249  const double delta = hi->wirelen - lo->wirelen;
250  const double dist = wire_length - lo->wirelen;
251  const double mu = dist/delta;
252 
253  const int nsamp = lo->amps.size();
254  amplitude_t amp(nsamp);
255  for (int isamp=0; isamp<nsamp; ++isamp) { // regular amplitude ...
256  amp[isamp] = lo->amps[isamp]*(1-mu) + hi->amps[isamp]*mu;
257  }
258  // amp[nsamp] = lo->constant*(1-mu) + hi->constant*mu; // do the constant term ...
259  return amp;
260  }
261  // should not get here
262  return amplitude_t();
263 
264 }
std::vector< float > amplitude_t
std::map< int, std::vector< NoiseSpectrum * > > m_spectral_data
const IChannelSpectrum::amplitude_t & Gen::EmpiricalNoiseModel::operator() ( int  chid) const
virtual

IChannelSpectrum.

Implements WireCell::IChannelSpectrum.

Definition at line 295 of file EmpiricalNoiseModel.cxx.

296 {
297  // get truncated wire length for cache
298  int ilen=0;
299  auto chlen = m_chid_to_intlen.find(chid);
300  if (chlen == m_chid_to_intlen.end()) { // new channel
301  auto wires = m_anode->wires(chid); // sum up wire length
302  double len = 0.0;
303  for (auto wire : wires) {
304  len += ray_length(wire->ray());
305  }
306  // cache every cm ...
307  ilen = int(len/m_wlres);
308  // there might be aproblem with the wire length's unit
309  //ilen = int(len);
310  m_chid_to_intlen[chid] = ilen;
311  }
312  else {
313  ilen = chlen->second;
314  }
315 
316 
317  // saved content
318  auto wpid = m_anode->resolve(chid);
319  const int iplane = wpid.index();
320 
321  auto& amp_cache = m_amp_cache.at(iplane);
322  auto lenamp = amp_cache.find(ilen);
323  if (lenamp == amp_cache.end()) {
324  auto amp = interpolate(iplane, ilen*m_wlres); // interpolate ...
325  amp_cache[ilen] = amp;
326  }
327  lenamp = amp_cache.find(ilen);
328 
329  // prepare to scale ...
330  double db_gain = gain(chid);
331  double db_shaping = shaping_time(chid);
332 
333  // get channel gain
334  //float ch_gain = 14 * units::mV/units::fC, ch_shaping = 2.0 * units::us;
335 
336  double ch_gain = db_gain, ch_shaping = db_shaping;
337  if (m_chanstat) { // allow for deviation from nominal
338  ch_gain = m_chanstat->preamp_gain(chid);
339  ch_shaping = m_chanstat->preamp_shaping(chid);
340  }
341  double constant = lenamp->second.back();
342  int nbin = lenamp->second.size()-1;
343 
344  // amplitude_t comb_amp;
345  comb_amp = lenamp->second;
346  comb_amp.pop_back();
347 
348  if (fabs(ch_gain - db_gain ) > 0.01 * ch_gain){
349  // scale the amplitude, not the constant term ...
350  for (int i=0;i!=nbin;i++){
351  comb_amp.at(i) *= ch_gain/db_gain;
352  }
353  }
354 
355  if (fabs(ch_shaping-db_shaping) > 0.01*ch_shaping){
356  // scale the amplitude by different shaping time ...
357  int nconfig = ch_shaping/units::us/0.1;
358  auto resp1 = m_elec_resp_cache.find(nconfig);
359  if (resp1 == m_elec_resp_cache.end()){
360 
361  Response::ColdElec elec_resp(10, ch_shaping); // default at 1 mV/fC
362  auto sig = elec_resp.generate(WireCell::Waveform::Domain(0, m_fft_length*m_period), m_fft_length);
363  auto filt = Waveform::dft(sig);
364  auto ele_resp_amp = Waveform::magnitude(filt);
365 
366  ele_resp_amp.resize(m_elec_resp_freq.size());
367  m_elec_resp_cache[nconfig] = ele_resp_amp;
368 
369  }
370  resp1 = m_elec_resp_cache.find(nconfig);
371 
372  nconfig = db_shaping/units::us/0.1;
373  auto resp2 = m_elec_resp_cache.find(nconfig);
374  if (resp2 == m_elec_resp_cache.end()){
375  Response::ColdElec elec_resp(10, db_shaping); // default at 1 mV/fC
376  auto sig = elec_resp.generate(WireCell::Waveform::Domain(0, m_fft_length*m_period), m_fft_length);
377  auto filt = Waveform::dft(sig);
378  auto ele_resp_amp = Waveform::magnitude(filt);
379 
380  ele_resp_amp.resize(m_elec_resp_freq.size());
381  m_elec_resp_cache[nconfig] = ele_resp_amp;
382  }
383  resp2 = m_elec_resp_cache.find(nconfig);
384 
385  for (int i=0;i!=nbin;i++){
386  comb_amp.at(i) *= resp1->second.at(i)/resp2->second.at(i);
387  }
388 
389  }
390 
391 
392  // add the constant terms ...
393  for (int i=0;i!=nbin;i++){
394  comb_amp.at(i) = sqrt(pow(comb_amp.at(i),2) + pow(constant,2)); // units still in mV
395  }
396 
397  return comb_amp;
398 }
virtual const double gain(int chid) const
std::vector< len_amp_cache_t > m_amp_cache
constexpr T pow(T x)
Definition: pow.h:72
virtual const double shaping_time(int chid) const
compseq_t dft(realseq_t seq)
Definition: Waveform.cxx:141
std::pair< double, double > Domain
Definition: Waveform.h:75
double ray_length(const Ray &ray)
Definition: Point.cxx:62
realseq_t magnitude(const compseq_t &seq)
Return the magnitude or absolute value of the sequence.
Definition: Waveform.cxx:65
amplitude_t interpolate(int plane, double wire_length) const
static const double us
Definition: Units.h:105
std::unordered_map< int, Waveform::realseq_t > m_elec_resp_cache
std::unordered_map< int, int > m_chid_to_intlen
void Gen::EmpiricalNoiseModel::resample ( NoiseSpectrum spectrum) const

Definition at line 97 of file EmpiricalNoiseModel.cxx.

98 {
99 
100  if (spectrum.nsamples == m_fft_length && spectrum.period == m_period) {
101  return;
102  }
103 
104  // scale the amplitude ...
105  double scale = sqrt(m_fft_length/(spectrum.nsamples*1.0) * spectrum.period / (m_period*1.0));
106  spectrum.constant *= scale;
107  for (unsigned int ind = 0; ind!=spectrum.amps.size(); ind++){
108  spectrum.amps[ind] *= scale;
109  }
110 
111  // interpolate ...
112 
113  amplitude_t temp_amplitudes(m_fft_length,0);
114  int count_low = 0;
115  int count_high = 1;
116  double mu=0;
117  for (int i=0;i!=m_fft_length;i++){
118  double frequency = m_elec_resp_freq.at(i);
119  if (frequency <= spectrum.freqs[0]){
120  count_low = 0;
121  count_high = 1;
122  mu = 0;
123  }else if (frequency >= spectrum.freqs.back()){
124  count_low = spectrum.freqs.size()-2;
125  count_high = spectrum.freqs.size()-1;
126  mu = 1;
127  }else{
128  for (unsigned int j=0;j!=spectrum.freqs.size();j++){
129  if (frequency>spectrum.freqs.at(j)){
130  count_low = j;
131  count_high = j+1;
132  }else{
133  break;
134  }
135  }
136  mu = (frequency - spectrum.freqs.at(count_low)) / (spectrum.freqs.at(count_high)-spectrum.freqs.at(count_low));
137  }
138 
139 
140  temp_amplitudes.at(i) = (1-mu) * spectrum.amps[count_low] + mu * spectrum.amps[count_high];
141 
142  }
143 
144  spectrum.amps = temp_amplitudes;
145  spectrum.amps.push_back(spectrum.constant);
146 
147  return;
148 }
std::vector< float > amplitude_t
void scale(Sequence< Val > &seq, Val scalar)
Scale (multiply) sequence values by scalar.
Definition: Waveform.h:146
const double Gen::EmpiricalNoiseModel::shaping_time ( int  chid) const
virtual

Definition at line 275 of file EmpiricalNoiseModel.cxx.

276 {
277  auto wpid = m_anode->resolve(chid);
278  const int iplane = wpid.index();
279  auto it = m_spectral_data.find(iplane);
280  const auto& spectra = it->second;
281  return spectra.front()->shaping;
282 }
std::map< int, std::vector< NoiseSpectrum * > > m_spectral_data

Member Data Documentation

amplitude_t WireCell::Gen::EmpiricalNoiseModel::comb_amp
mutableprivate

Definition at line 112 of file EmpiricalNoiseModel.h.

Log::logptr_t WireCell::Gen::EmpiricalNoiseModel::log
private

Definition at line 114 of file EmpiricalNoiseModel.h.

std::vector<len_amp_cache_t> WireCell::Gen::EmpiricalNoiseModel::m_amp_cache
mutableprivate

Definition at line 107 of file EmpiricalNoiseModel.h.

IAnodePlane::pointer WireCell::Gen::EmpiricalNoiseModel::m_anode
private

Definition at line 87 of file EmpiricalNoiseModel.h.

std::string WireCell::Gen::EmpiricalNoiseModel::m_anode_tn
private

Definition at line 98 of file EmpiricalNoiseModel.h.

IChannelStatus::pointer WireCell::Gen::EmpiricalNoiseModel::m_chanstat
private

Definition at line 91 of file EmpiricalNoiseModel.h.

std::string WireCell::Gen::EmpiricalNoiseModel::m_chanstat_tn
private

Definition at line 98 of file EmpiricalNoiseModel.h.

std::unordered_map<int, int> WireCell::Gen::EmpiricalNoiseModel::m_chid_to_intlen
mutableprivate

Definition at line 104 of file EmpiricalNoiseModel.h.

std::unordered_map<int, Waveform::realseq_t> WireCell::Gen::EmpiricalNoiseModel::m_elec_resp_cache
mutableprivate

Definition at line 111 of file EmpiricalNoiseModel.h.

Waveform::realseq_t WireCell::Gen::EmpiricalNoiseModel::m_elec_resp_freq
private

Definition at line 110 of file EmpiricalNoiseModel.h.

int WireCell::Gen::EmpiricalNoiseModel::m_fft_length
private

Definition at line 95 of file EmpiricalNoiseModel.h.

int WireCell::Gen::EmpiricalNoiseModel::m_nsamples
private

Definition at line 94 of file EmpiricalNoiseModel.h.

double WireCell::Gen::EmpiricalNoiseModel::m_period
private

Definition at line 96 of file EmpiricalNoiseModel.h.

std::string WireCell::Gen::EmpiricalNoiseModel::m_spectra_file
private

Definition at line 93 of file EmpiricalNoiseModel.h.

std::map<int, std::vector<NoiseSpectrum*> > WireCell::Gen::EmpiricalNoiseModel::m_spectral_data
private

Definition at line 101 of file EmpiricalNoiseModel.h.

double WireCell::Gen::EmpiricalNoiseModel::m_wlres
private

Definition at line 96 of file EmpiricalNoiseModel.h.


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