24 const double wire_length_scale,
30 : m_spectra_file(spectra_file)
31 , m_nsamples(nsamples)
33 , m_wlres(wire_length_scale)
37 , m_anode_tn(anode_tn)
38 , m_chanstat_tn(chanstat_tn)
44 gen_elec_resp_default();
48 Gen::EmpiricalNoiseModel::~EmpiricalNoiseModel()
52 void Gen::EmpiricalNoiseModel::gen_elec_resp_default(){
56 m_elec_resp_freq.resize(m_fft_length,0);
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 ;
61 m_elec_resp_freq.at(i) = (m_elec_resp_freq.size()-i) / (m_elec_resp_freq.size() *1.0) * 1./m_period ;
85 cfg[
"spectra_file"] = m_spectra_file;
86 cfg[
"nsamples"] = m_nsamples;
87 cfg[
"period"] = m_period;
88 cfg[
"wire_length_scale"] = m_wlres;
92 cfg[
"anode"] = m_anode_tn;
100 if (spectrum.
nsamples == m_fft_length && spectrum.
period == m_period) {
105 double scale = sqrt(m_fft_length/(spectrum.
nsamples*1.0) * spectrum.
period / (m_period*1.0));
107 for (
unsigned int ind = 0; ind!=spectrum.
amps.size(); ind++){
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]){
123 }
else if (frequency >= spectrum.
freqs.back()){
124 count_low = spectrum.
freqs.size()-2;
125 count_high = spectrum.
freqs.size()-1;
128 for (
unsigned int j=0;j!=spectrum.
freqs.size();j++){
129 if (frequency>spectrum.
freqs.at(j)){
136 mu = (frequency - spectrum.
freqs.at(count_low)) / (spectrum.
freqs.at(count_high)-spectrum.
freqs.at(count_low));
140 temp_amplitudes.at(i) = (1-mu) * spectrum.
amps[count_low] + mu * spectrum.
amps[count_high];
144 spectrum.
amps = temp_amplitudes;
152 m_anode_tn =
get(
cfg,
"anode", m_anode_tn);
153 m_anode = Factory::find_tn<IAnodePlane>(m_anode_tn);
155 m_chanstat_tn =
get(
cfg,
"chanstat", m_chanstat_tn);
156 if (m_chanstat_tn !=
"") {
157 m_chanstat = Factory::find_tn<IChannelStatus>(m_chanstat_tn);
160 log->debug(
"EmpiricalNoiseModel: using anode {}, chanstat {}", m_anode_tn, m_chanstat_tn);
162 m_spectra_file =
get(
cfg,
"spectra_file", m_spectra_file);
164 m_nsamples =
get(
cfg,
"nsamples", m_nsamples);
167 m_period =
get(
cfg,
"period", m_period);
168 m_wlres =
get(
cfg,
"wire_length_scale", m_wlres);
178 const int nentries = jdat.size();
179 m_spectral_data.clear();
181 gen_elec_resp_default();
183 for (
int ientry=0; ientry<nentries; ++ientry) {
184 auto jentry = jdat[ientry];
187 nsptr->
plane = jentry[
"plane"].asInt();
188 nsptr->
nsamples = jentry[
"nsamples"].asInt();
189 nsptr->
period = jentry[
"period"].asFloat();
190 nsptr->
gain = jentry[
"gain"].asFloat();
191 nsptr->
shaping = jentry[
"shaping"].asFloat();
192 nsptr->
wirelen = jentry[
"wirelen"].asFloat();
193 nsptr->
constant = jentry[
"const"].asFloat();
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();
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();
211 m_spectral_data[nsptr->
plane].push_back(nsptr);
218 auto it = m_spectral_data.find(iplane);
219 if (it == m_spectral_data.end()) {
223 const auto& spectra = it->second;
233 if (wire_length <= front->wirelen) {
237 if (wire_length >= back->
wirelen) {
241 const int nspectra = spectra.size();
242 for (
int ind=1; ind<nspectra; ++ind) {
244 if (hi->
wirelen < wire_length) {
250 const double dist = wire_length - lo->
wirelen;
251 const double mu = dist/delta;
253 const int nsamp = lo->
amps.size();
255 for (
int isamp=0; isamp<nsamp; ++isamp) {
256 amp[isamp] = lo->
amps[isamp]*(1-mu) + hi->
amps[isamp]*mu;
266 const std::vector<float>& Gen::EmpiricalNoiseModel::freq()
const 269 const int iplane = 0;
270 auto it = m_spectral_data.find(iplane);
271 const auto& spectra = it->second;
272 return spectra.front()->freqs;
275 const double Gen::EmpiricalNoiseModel::shaping_time(
int chid)
const 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;
284 const double Gen::EmpiricalNoiseModel::gain(
int chid)
const 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;
299 auto chlen = m_chid_to_intlen.find(chid);
300 if (chlen == m_chid_to_intlen.end()) {
301 auto wires = m_anode->wires(chid);
303 for (
auto wire : wires) {
307 ilen =
int(len/m_wlres);
310 m_chid_to_intlen[chid] = ilen;
313 ilen = chlen->second;
318 auto wpid = m_anode->resolve(chid);
319 const int iplane = wpid.index();
321 auto& amp_cache = m_amp_cache.at(iplane);
322 auto lenamp = amp_cache.find(ilen);
323 if (lenamp == amp_cache.end()) {
325 amp_cache[ilen] = amp;
327 lenamp = amp_cache.find(ilen);
330 double db_gain = gain(chid);
331 double db_shaping = shaping_time(chid);
336 double ch_gain = db_gain, ch_shaping = db_shaping;
338 ch_gain = m_chanstat->preamp_gain(chid);
339 ch_shaping = m_chanstat->preamp_shaping(chid);
341 double constant = lenamp->second.back();
342 int nbin = lenamp->second.size()-1;
345 comb_amp = lenamp->second;
348 if (fabs(ch_gain - db_gain ) > 0.01 * ch_gain){
350 for (
int i=0;i!=nbin;i++){
351 comb_amp.at(i) *= ch_gain/db_gain;
355 if (fabs(ch_shaping-db_shaping) > 0.01*ch_shaping){
358 auto resp1 = m_elec_resp_cache.find(nconfig);
359 if (resp1 == m_elec_resp_cache.end()){
366 ele_resp_amp.resize(m_elec_resp_freq.size());
367 m_elec_resp_cache[nconfig] = ele_resp_amp;
370 resp1 = m_elec_resp_cache.find(nconfig);
373 auto resp2 = m_elec_resp_cache.find(nconfig);
374 if (resp2 == m_elec_resp_cache.end()){
380 ele_resp_amp.resize(m_elec_resp_freq.size());
381 m_elec_resp_cache[nconfig] = ele_resp_amp;
383 resp2 = m_elec_resp_cache.find(nconfig);
385 for (
int i=0;i!=nbin;i++){
386 comb_amp.at(i) *= resp1->second.at(i)/resp2->second.at(i);
393 for (
int i=0;i!=nbin;i++){
394 comb_amp.at(i) = sqrt(
pow(comb_amp.at(i),2) +
pow(constant,2));
std::vector< float > amplitude_t
std::size_t fft_best_length(size_t nsamples, bool keep_odd_even=false)
A functional object caching gain and shape.
double ray_length(const Ray &ray)
WireCell::Waveform::realseq_t generate(const WireCell::Waveform::Domain &domain, int nsamples)
FIXME: eradicate Domain in favor of Binning.
double interpolate(std::vector< double > &xData, std::vector< double > &yData, double x, bool extrapolate)
WIRECELL_FACTORY(EmpiricalNoiseModel, WireCell::Gen::EmpiricalNoiseModel, WireCell::IChannelSpectrum, WireCell::IConfigurable) using namespace WireCell
logptr_t logger(std::string name)
void log(source_loc source, level::level_enum lvl, const char *fmt, const Args &...args)
std::vector< float > amps
std::vector< float > freqs
Json::Value Configuration
array_xxc dft(const array_xxf &arr)
def load(filename, jpath="depos")