1 #include "SystemResponse.h" 5 #include "AnalysisWaveform.h" 12 void AnitaResponse::DeconvolutionMethod::deconvolve(
int Nf,
double df,
FFTWComplex *
Y,
const FFTWComplex * response)
const 23 size_t N = wf->
Nfreq();
31 for (
unsigned i = 0; i < N; i++)
35 double H2 = response[i].getAbsSq();
36 double SNR = snr(f,H2,N);
37 printf(
"SNR(%f) = %f\n", f, SNR);
39 if (SNR <=0)
Y[i] = zero;
42 Y[i] =
Y[i] / response[i] * ( H2 / (H2 + 1./SNR));
52 max = g->GetX()[g->GetN()-1];
77 double AnitaResponse::WienerDeconvolution::snr(
double f,
double R2,
int N )
const 83 if (f < min || f > max )
return 0;
84 double sc = scale ? *scale : 1;
85 return sc*snr_graph->Eval(f);
87 else if (snr_function)
90 if (f < min || f > max )
return 0;
91 return snr_function->Eval(f);
96 return R2/noise_level/N ;
99 fprintf(stderr,
"Something's wrong...\n");
107 size_t N = wf->
Nfreq();
111 for (
unsigned i = 0; i < N; i++)
122 size_t N = wf->
Nfreq();
125 double total_mag = 0;
126 for (
unsigned i = 0; i < N; i++)
128 total_mag += response[i].getAbsSq();
130 total_mag = sqrt(total_mag);
132 for (
unsigned i = 0; i < N; i++)
139 AnitaResponse::CLEAN::CLEAN(
int max_loops,
double loop_gain,
double thresh_factor, TString restoring_beam,
bool add_residuals,
bool only_return_residuals)
141 fMaxLoops = max_loops;
142 fLoopGain = loop_gain;
143 fThreshFactor = thresh_factor;
144 fRestoringBeam = restoring_beam;
145 fAddResiduals = add_residuals;
146 fOnlyReturnResiduals = only_return_residuals;
153 for(
int i = 0; i < clean.even()->GetN(); i++)
155 clean.updateEven()->GetY()[i] = 0;
166 for(
int i = 0; i < y.Neven(); i++)
168 if(y.even()->GetX()[i] < 25 || y.even()->GetX()[i] > 70)
170 noise_est += y.
even()->GetY()[i] * y.even()->GetY()[i];
171 noise_mean += y.even()->GetY()[i];
175 noise_mean /= n_noise;
176 noise_est = sqrt(noise_est/n_noise - (noise_mean * noise_mean));
178 double snr_est = (1./fThreshFactor) * (y.even()->pk2pk())/(2*noise_est);
181 double thresh = 1./snr_est;
182 double loop_gain = fLoopGain;
183 int max_loops = fMaxLoops;
184 double noise_level = snr_est/3.;
186 double max_clean = 0;
189 double max_y = y.even()->peakVal(0, 0, -1,
true);
190 double max_r = r.even()->peakVal(0, 0, -1,
true);
192 double scale_to_wf = (TMath::Abs(max_y))/(TMath::Abs(max_r));
194 for(
int i = 0; i < r.Neven(); i++)
196 r.updateEven()->GetY()[i] *= scale_to_wf;
200 double normalize = 1./sqrt(y.even()->getSumV2() + r.even()->getSumV2());
201 for(
int i = 0; i < y.Neven(); i++)
203 y.updateEven()->GetY()[i] *= normalize;
205 for(
int i = 0; i < r.Neven(); i++)
207 r.updateEven()->GetY()[i] *= normalize;
209 if(fRestoringBeam.Length() > 0)
211 TF1 restore(
"restoring_beam", fRestoringBeam.Data(), y.even()->GetX()[0], y.even()->GetX()[y.Neven()-1]);
212 for(
int i = 0; i < rbeam.Neven(); i++)
214 rbeam.updateEven()->GetY()[i] = restore.Eval(rbeam.updateEven()->GetX()[i]);
218 double restore_norm = rbeam.even()->getSumV2();
219 for(
int i = 0; i < rbeam.Neven(); i++)
221 rbeam.updateEven()->GetY()[i] /= restore_norm;
226 int loc = TMath::LocMax(r.Neven(), r.even()->GetY());
227 r.updateEven()->shift(r.Neven()/2 - loc,
false);
228 double E_i = y.even()->getSumV2();
232 while(((E_curr/E_i) > thresh) && (max_loops != 0))
235 double rms1 = y.even()->GetRMS(2);
236 double rms2 = r.even()->GetRMS(2);
238 max_corr = xc->
even()->peakVal(&loc, 0, -1,
true);
239 clean.updateEven()->GetY()[loc] += xc->
even()->GetY()[loc] * loop_gain;
241 r.updateEven()->shift(xc->
Neven()/2 - loc,
false);
243 for(
int i = 0; i < y.even()->GetN(); i++)
245 y.updateEven()->GetY()[i] -= loop_gain * r.even()->GetY()[i] * xc->
even()->GetY()[loc];
247 r.updateEven()->shift(-1*(xc->
Neven()/2 - loc),
false);
248 E_curr = y.even()->getSumV2();
251 max_clean = clean.
even()->peakVal(0, 0, -1,
true);
253 for(
int i = 0; i < y.Neven(); i++)
255 y.updateEven()->GetY()[i] *= 1./normalize;
256 clean.updateEven()->GetY()[i] *= (fabs(clean.updateEven()->GetY()[i]) > max_clean/noise_level) ? 1./normalize : 0;
258 if(fOnlyReturnResiduals)
260 for(
int i = 0; i <
Y->Nfreq(); i++)
262 Y->updateFreq()[i] = y.freq()[i];
265 else if(fRestoringBeam.Length() > 0)
271 xc =
new AnalysisWaveform(clean.Neven(), clean.freq(), clean.deltaF(), clean.even()->GetX()[0]);
272 for(
int i = 0; i < xc->
Nfreq(); i++)
276 double scale_clean = fabs(clean.even()->peakVal(0, 0, -1, 1)/xc->
even()->peakVal(0,0,-1,1));
277 for(
int i = 0; i < xc->
Neven(); i++)
284 for(
int i = 0; i < xc->
Neven(); i++)
286 xc->
updateEven()->GetY()[i] += y.even()->GetY()[i];
290 for(
int i = 0; i <
Y->Nfreq(); i++)
292 Y->updateFreq()[i] = xc->
freq()[i];
300 for(
int i = 0; i < clean.Neven(); i++)
302 clean.
updateEven()->GetY()[i] += y.even()->GetY()[i];
306 for(
int i = 0; i <
Y->Nfreq(); i++)
308 Y->updateFreq()[i] = clean.freq()[i];
316 size_t N = wf->
Nfreq();
320 for (
unsigned i = 0; i < N; i++)
329 size_t N = wf->
Nfreq();
334 size_t min_i =(size_t) TMath::Max(0,
int(min_freq / df));
335 size_t max_i =(size_t) TMath::Min((
int) N-1, int(max_freq / df));
338 for (
size_t i = 0; i < min_i; i++)
343 for (
size_t i = min_i; i < max_i; i++)
347 for (
size_t i = max_i; i < N; i++)
356 AnitaResponse::Response::Response(
int Nfreq,
double df,
int nangles,
const double * the_angles,
const FFTWComplex ** the_responses)
357 : Nfreq(Nfreq), df(df)
359 for (
int i = 0; i < nangles; i++)
361 addResponseAtAngle(the_angles[i], the_responses[i]);
366 void AnitaResponse::Response::addResponseAtAngle(
double angle,
const FFTWComplex * response)
369 memcpy(copy, response, Nfreq *
sizeof(
FFTWComplex));
370 responses[angle] = copy;
375 AnitaResponse::Response::Response(
int Nfreq,
double df)
376 : Nfreq(Nfreq), df(df)
381 AnitaResponse::Response::Response(
const TGraph * timedomain,
int npad)
383 AnalysisWaveform aw(timedomain->GetN(), timedomain->GetX(), timedomain->GetY(), timedomain->GetX()[1] - timedomain->GetX()[0]);
388 addResponseAtAngle(0,aw.freq());
393 AnitaResponse::Response::Response(
int Nfreq,
double df,
const FFTWComplex * response)
394 : Nfreq(Nfreq),df(df)
396 addResponseAtAngle(0, response);
400 FFTWComplex * AnitaResponse::AbstractResponse::getResponseArray(
int N,
const double * f,
double angle,
FFTWComplex *answer)
const 403 for (
int i = 0; i < N; i++) answer[i] = getResponse(f[i], angle);
408 FFTWComplex * AnitaResponse::AbstractResponse::getResponseArray(
int N,
double df,
double angle,
FFTWComplex *answer)
const 411 for (
int i = 0; i < N; i++) answer[i] = getResponse(i*df, angle);
417 void AnitaResponse::Response::recompute()
const 420 int nangles = responses.size();
421 real.SetBins( Nfreq, 0, df * Nfreq,nangles, -90, 90);
422 imag.SetBins( Nfreq, 0, df * Nfreq, nangles, -90, 90);
428 double bin_boundaries[nangles+1];
429 double center_angles[nangles];
433 for (std::map<double, FFTWComplex *>::const_iterator it = responses.begin(); it!=responses.end(); it++)
435 center_angles[i++] = it->first;
439 bin_boundaries[0] = center_angles[0] - (center_angles[1]-center_angles[0])/2;
440 bin_boundaries[nangles] = center_angles[nangles-1] + (center_angles[nangles-1]-center_angles[nangles-2])/2;
442 for (
int i = 1; i < nangles; i++)
444 bin_boundaries[i] = (center_angles[i-1] + center_angles[i])/2;
447 imag.GetYaxis()->Set(nangles, bin_boundaries);
448 real.GetYaxis()->Set(nangles, bin_boundaries);
453 for (std::map<double, FFTWComplex *>::const_iterator it = responses.begin(); it!=responses.end(); it++)
455 for (
int i = 0; i < Nfreq; i++)
457 imag.SetBinContent(i+1,j, it->second[i].im);
458 real.SetBinContent(i+1,j, it->second[i].re);
468 FFTWComplex AnitaResponse::CompositeResponse::getResponse(
double f,
double angle )
const 472 for (
size_t i = 0; i < responses.size(); i++) answer*= responses[i]->getResponse(f,angle);
481 FFTWComplex AnitaResponse::Response::getResponse(
double f,
double angle )
const 491 if ( f > real.GetXaxis()->GetXmax() || f > imag.GetXaxis()->GetXmax())
return FFTWComplex(0,0);
492 double re = real.Interpolate(f,angle);
493 double im = imag.Interpolate(f,angle);
499 double AnitaResponse::AbstractResponse::getMagnitude(
double f,
double angle)
const 501 return getResponse(f,angle).getAbs();
504 double AnitaResponse::AbstractResponse::getPhase(
double f,
double angle)
const 506 return getResponse(f,angle).getPhase();
514 AnalysisWaveform* AnitaResponse::AbstractResponse::impulseResponse(
double dt,
int N )
const 518 convolveInPlace(out,0);
522 void AnitaResponse::AbstractResponse::convolveInPlace(
AnalysisWaveform * wf,
double angle)
const 524 int old_size = wf->
Neven();
526 int nf = wf->
Nfreq();
529 for (
int i = 0; i < nf; i++)
531 fft[i] *= getResponse(i*df, angle);
541 convolveInPlace(out, off_axis_angle);
545 AnalysisWaveform * AnitaResponse::AbstractResponse::deconvolve(
const AnalysisWaveform * in,
const DeconvolutionMethod * method,
double off_axis_angle)
const 550 deconvolveInPlace(out,method,off_axis_angle);
557 static __thread
int cache_Nt= 0;
558 static __thread
double cache_df= 0;
559 static __thread
double cache_angle= 0;
564 void AnitaResponse::AbstractResponse::deconvolveInPlace(
AnalysisWaveform * wf,
const DeconvolutionMethod * method,
double off_axis_angle)
const 568 int nt = wf->
Neven();
570 if (!cache_response || cache_Nt != nt || cache_df != df || !cache_V || cache_angle != off_axis_angle)
572 cache_response =
this;
575 cache_angle = off_axis_angle;
576 if (cache_V)
delete [] cache_V;
578 cache_V = getResponseArray(nf,df,off_axis_angle);
579 if (cache_response_wf)
delete cache_response_wf;
583 method->deconvolve(wf, cache_response_wf);
593 void AnitaResponse::CLEANDeconvolution::clearIntermediate()
const 596 for (
unsigned i = 0; i < save_xcorr.size(); i++)
delete save_xcorr[i];
597 for (
unsigned i = 0; i < save_ys.size(); i++)
delete save_ys[i];
598 for (
unsigned i = 0; i < save_subtracted.size(); i++)
delete save_subtracted[i];
601 save_subtracted.clear();
610 double t0 = y->
even()->GetX()[0];
613 double df = 1./dt/Nt;
618 if (!cached_restoring || Nt != cached_restoring->Neven() || dt != cached_restoring->deltaT())
620 if (cached_restoring)
delete cached_restoring;
623 for (
int i = 0; i < Nt; i++)
625 grestore->GetY()[i] = r->Eval(i*dt);
632 double hrms = h->getRMS();
633 double yrms = y->getRMS();
634 double power_ratio = yrms/hrms;
641 double sqrt_threshold = sqrt(threshold);
649 double maxcorr = xcorr->
even()->peakVal(&where,0,-1,
true);
650 if (xcorr->
even()->GetY()[where] < 0) maxcorr *=-1;
652 double lag = xcorr->
even()->GetX()[where]-t0;
657 cmp.updateEven()->GetY()[(int) (lag/dt)]+= maxcorr * gain;
663 save_ys.back()->setTitle(Form(
"iter%d pk2kpk = %g", iter, save_ys.back()->even()->pk2pk()));
669 const std::complex<double> * H = (
const std::complex<double>*) h->freq();
670 std::complex<double> *
Y = (std::complex<double>*) y->
updateFreq();
674 if (debug) save_subtracted.push_back(subtracted);
677 const double factor= (maxcorr*gain*power_ratio);
678 const double expo = -2./Nt*TMath::Pi()*lag/dt;
679 for (
int i = 0; i < Nf; i++)
682 std::complex<double> subtract = factor * (H[i] * std::exp(std::complex<double>(0,i*expo)));
685 if (debug) subtracted_freq[i] = subtract;
692 xcorr->setTitle(Form(
"lag=%g, max=%g",lag,maxcorr));
693 save_xcorr.push_back(xcorr) ;
700 if (y->getRMS() / yrms < sqrt_threshold || iter++ > max_iter)
break;
706 double cc_max = fabs(cmp.even()->peakVal(0,0,-1,
true));
707 cmp.
updateEven()->setBelow(cc_max/noiselevel);
710 if (convolve_residuals)
717 for (
int i = 0; i < Nf; i++)
724 AnalysisWaveform * convolved = AnalysisWaveform::convolution(y,cached_restoring, 0, cached_restoring->getRMS() *y->getRMS());
731 AnalysisWaveform * convolved = AnalysisWaveform::convolution(&cmp,cached_restoring, 0, cached_restoring->getRMS() *cmp.getRMS());
736 for (
int i = 0; i < Nt; i++)
738 g->GetY()[i] += convolved->
evalEven(g->GetX()[i]);
WienerDeconvolution(const TGraph *g_snr, const double *scale=0)
This is a wrapper class for a complex number.
Inelasticity distributions: stores parametrizations and picks inelasticities.