1 #include "AnalysisWaveform.h" 4 #include "RFInterpolate.h" 5 #include "TDirectory.h" 13 #ifdef ENABLE_VECTORIZE 14 #include "vectorclass.h" 19 static VEC INDEX(0,1,2,3);
27 #define likely(x) __builtin_expect((!!x),1) 28 #define unlikely(x) __builtin_expect((!!x),0) 30 const int minPointsForGslInterp = 6;
32 #ifdef ANITA_ANALYSIS_DEBUG 33 static bool DEBUGON =
false;
40 static bool ALLOW_EVEN_TO_UNEVEN =
false;
44 static __thread
bool nag_if_not_zero_padded =
false;
48 volatile static unsigned counter = 0;
51 static void fillEven(
int N,
double * x,
double dt,
double t0)
53 #ifdef ENABLE_VECTORIZE 55 int leftover = N % VEC_N;
56 int nit = N / VEC_N + (leftover ? 1 : 0);
60 for (
int i = 0; i < nit; i++)
64 VEC vx = mul_add(index,vdt,vt0);
66 if (i == nit-1 && leftover > 0)
68 vx.store_partial(leftover, &x[i*VEC_N]);
72 vx.store(&x[i * VEC_N]);
76 for (
int i = 0; i < N; i++)
86 int old_size = g->GetN();
88 double dt = g->GetX()[1] - g->GetX()[0];
91 fillEven(size-old_size, g->GetX() + old_size, dt, g->GetX()[old_size-1] + dt);
96 static int complaints = 0;
100 : g_uneven(N,x,y), dt(nominal_dt), fft(0), theEvenAkimaInterpolator(0,ROOT::Math::Interpolation::kAKIMA),
101 interpolation_type(interp_type), must_update_uneven(false), must_update_freq(true), must_update_even(true),
102 uneven_equals_even(false), hilbert_transform(0), force_even_size(0)
105 if (opt) interpolation_options = *opt;
107 hilbert_dirty =
true;
108 even_akima_interpolator_dirty =
true;
109 power_db_dirty =
true;
110 hilbert_envelope_dirty =
true;
112 group_delay_dirty =
true;
116 uid = __sync_fetch_and_add(&counter,1);
121 for (
int i = 1; i < g_uneven.GetN(); i++)
123 if (g_uneven.GetX()[i] < g_uneven.GetX()[i-1])
125 if (complaints++ < 100)
127 fprintf(stderr,
"WARNING: truncating graph to %d points to make monotonic\n",i);
128 if (complaints == 100)
130 fprintf(stderr,
" shutting up about truncating graphs after 100 complaints... I think I've made my point clear!\n");
139 while (g_uneven.GetN() < minPointsForGslInterp) {
140 g_uneven.SetPoint(g_uneven.GetN(), g_uneven.GetX()[g_uneven.GetN()-1] + 1, 0);
147 : g_even(N), dt(dt), fft(0), theEvenAkimaInterpolator(0,ROOT::Math::Interpolation::kAKIMA),
148 interpolation_type(AKIMA), must_update_uneven(false), must_update_freq(true), must_update_even(false),
149 uneven_equals_even(true), hilbert_transform(0), force_even_size(0)
151 fillEven(N,g_even.GetX(),dt,t0);
152 memcpy(g_even.GetY(), y,
sizeof(double) * N);
156 hilbert_dirty =
true;
157 power_db_dirty =
true;
158 hilbert_envelope_dirty =
true;
159 even_akima_interpolator_dirty =
true;
161 group_delay_dirty =
true;
163 uid = __sync_fetch_and_add(&counter,1);
169 : g_even(N), dt(dt), fft(0), theEvenAkimaInterpolator(0,ROOT::Math::Interpolation::kAKIMA),
170 interpolation_type(AKIMA), must_update_uneven(false), must_update_freq(true),
171 must_update_even(false), uneven_equals_even(true), hilbert_transform(0), force_even_size(0)
174 fillEven(N,g_even.GetX(),dt,t0);
175 memset(g_even.GetY(),0,
sizeof(double) * N);
179 hilbert_dirty =
true;
180 power_db_dirty =
true;
182 group_delay_dirty =
true;
183 hilbert_envelope_dirty =
true;
184 even_akima_interpolator_dirty =
true;
185 uid = __sync_fetch_and_add(&counter,1);
192 : g_even(N), df(df), theEvenAkimaInterpolator(0,ROOT::Math::Interpolation::kAKIMA), interpolation_type(AKIMA),
193 must_update_uneven(false), must_update_freq(false), must_update_even(true), uneven_equals_even(true),
194 hilbert_transform(0), force_even_size(0)
197 int ret = posix_memalign( (
void**) &fft, ALIGNMENT,
sizeof(
FFTWComplex) * fft_len);
203 fillEven(N,g_even.GetX(),dt,t0);
204 memset(g_even.GetY(),0,
sizeof(double) * N);
206 even_akima_interpolator_dirty =
true;
208 hilbert_dirty =
true;
209 hilbert_envelope_dirty =
true;
210 power_db_dirty =
true;
212 group_delay_dirty =
true;
213 uid = __sync_fetch_and_add(&counter,1);
215 even_akima_interpolator_dirty =
true;
223 if (uneven_equals_even)
return even();
231 #ifdef ANITA_ANALYSIS_DEBUG 232 if (DEBUGON) printf(
"Called even()!\n");
233 if (DEBUGON) printf (
"[%p]: \tmust_update_even=%d, must_update_freq=%d, must_update_uneven=%d\n",
this, must_update_even, must_update_freq, must_update_uneven);
236 assert (!(must_update_even && must_update_freq && must_update_uneven));
238 if ((must_update_even && must_update_freq))
240 calculateEvenFromUneven();
242 else if ((must_update_even))
244 calculateEvenFromFreq();
254 #ifdef ANITA_ANALYSIS_DEBUG 255 if (DEBUGON) printf(
"Called freq()!\n");
256 if (DEBUGON) printf (
"[%p] \tmust_update_even=%d, must_update_freq=%d, must_update_uneven=%d\n",
this, must_update_even, must_update_freq, must_update_uneven);
259 if (must_update_freq)
261 calculateFreqFromEven();
273 #ifdef ANITA_ANALYSIS_DEBUG 274 if (DEBUGON) printf(
"Called updateEven(replace)!\n");
275 if (DEBUGON) printf (
"[%p] \tmust_update_even=%d, must_update_freq=%d, must_update_uneven=%d\n",
this, must_update_even, must_update_freq, must_update_uneven);
278 g_even.Set(replace->GetN());
279 memcpy(g_even.GetX(), replace->GetX(), replace->GetN() *
sizeof(double));
280 memcpy(g_even.GetY(), replace->GetY(), replace->GetN() *
sizeof(double));
281 if (!ALLOW_EVEN_TO_UNEVEN) uneven_equals_even =
true;
282 must_update_uneven = !uneven_equals_even;
283 must_update_freq =
true;
284 must_update_even =
false;
285 even_akima_interpolator_dirty =
true;
287 hilbert_dirty =
true;
288 hilbert_envelope_dirty =
true;
289 dt = replace->GetX()[1]-replace->GetX()[0];
290 df = 1./(
Neven() * dt);
297 #ifdef ANITA_ANALYSIS_DEBUG 298 if (DEBUGON) printf(
"Called updateEven()!\n");
299 if (DEBUGON) printf (
"\tmust_update_even=%d, must_update_freq=%d, must_update_uneven=%d\n", must_update_even, must_update_freq, must_update_uneven);
303 if (!ALLOW_EVEN_TO_UNEVEN) uneven_equals_even =
true;
304 must_update_uneven = !uneven_equals_even;
305 must_update_freq =
true;
306 even_akima_interpolator_dirty =
true;
308 hilbert_envelope_dirty =
true;
309 hilbert_dirty =
true;
315 #ifdef ANITA_ANALYSIS_DEBUG 316 if (DEBUGON) printf(
"Called updateUneven()!\n");
317 if (DEBUGON) printf (
"[%p]: \tmust_update_even=%d, must_update_freq=%d, must_update_uneven=%d\n",
this, must_update_even, must_update_freq, must_update_uneven);
320 uneven_equals_even =
false;
321 must_update_even =
true;
322 must_update_freq =
true;
324 even_akima_interpolator_dirty =
true;
325 hilbert_dirty =
true;
326 hilbert_envelope_dirty =
true;
333 #ifdef ANITA_ANALYSIS_DEBUG 334 if (DEBUGON) printf(
"Called updateFreq()!\n");
335 if (DEBUGON) printf (
"[%p]: \tmust_update_even=%d, must_update_freq=%d, must_update_uneven=%d\n",
this, must_update_even, must_update_freq, must_update_uneven);
340 power_db_dirty =
true;
341 hilbert_dirty =
true;
342 hilbert_envelope_dirty =
true;
344 group_delay_dirty =
true;
347 even_akima_interpolator_dirty =
true;
348 must_update_even =
true;
349 if (!ALLOW_EVEN_TO_UNEVEN) uneven_equals_even =
true;
350 must_update_uneven = !uneven_equals_even;
356 #define DO_FOR_ALL(THING) g_uneven.THING; g_hilbert_envelope.THING; g_even.THING; g_power.THING; g_power_db.THING; g_phase.THING; g_group_delay.THING; 357 #define DO_FOR_TIME(THING) g_uneven.THING; g_hilbert_envelope.THING; g_even.THING; 358 #define DO_FOR_FREQ(THING) g_power.THING; g_power_db.THING; g_phase.THING; g_group_delay.THING; 360 void AnalysisWaveform::setColor(
int c)
362 DO_FOR_ALL(SetLineColor(c));
363 DO_FOR_ALL(SetMarkerColor(c));
366 void AnalysisWaveform::setTitle(
const char * title)
368 DO_FOR_ALL(SetTitle(title));
371 void AnalysisWaveform::setFreqDisplayRange(
double l,
double h)
373 DO_FOR_FREQ(GetXaxis()->SetRangeUser(l,h));
376 void AnalysisWaveform::setTimeDisplayRange(
double l,
double h)
378 DO_FOR_TIME(GetXaxis()->SetRangeUser(l,h));
381 void AnalysisWaveform::setWidth(
int w)
383 DO_FOR_ALL(SetLineWidth(w));
393 #ifdef ANITA_ANALYSIS_DEBUG 394 if (DEBUGON) printf(
"Called updateUneven(replace)!\n");
395 if (DEBUGON) printf (
"[%p]: \tmust_update_even=%d, must_update_freq=%d, must_update_uneven=%d\n",
this, must_update_even, must_update_freq, must_update_uneven);
399 g_uneven.Set(replace->GetN());
400 memcpy(g_uneven.GetX(), replace->GetX(), replace->GetN() *
sizeof(double));
401 memcpy(g_uneven.GetY(), replace->GetY(), replace->GetN() *
sizeof(double));
403 uneven_equals_even =
false;
405 must_update_even =
true;
406 must_update_uneven =
false;
407 must_update_freq =
true;
408 even_akima_interpolator_dirty =
true;
411 void AnalysisWaveform::calculateUnevenFromEven()
const 416 if (interpolation_type == AKIMA)
420 const ROOT::Math::Interpolator * irp = evenAkimaInterpolator();
421 for (
int i = 0; i < g_uneven.GetN(); i++)
423 if (g_uneven.GetX()[i] < g->GetX()[g->GetN()-1])
424 g_uneven.GetY()[i] = irp->Eval(g_uneven.GetX()[i]);
430 FFTtools::getInterpolatedGraphSparseInvert(g, &g_uneven, interpolation_options.max_distance, 0, 0,
431 interpolation_type == SPARSE_YEN ? 0 : interpolation_options.mu,
432 interpolation_options.regularization_order);
437 must_update_uneven =
false;
440 const ROOT::Math::Interpolator * AnalysisWaveform::evenAkimaInterpolator()
const 443 if (even_akima_interpolator_dirty)
446 if(g->GetN() >= minPointsForGslInterp){
447 theEvenAkimaInterpolator.SetData(g->GetN(),g->GetX(),g->GetY());
448 even_akima_interpolator_dirty=
false;
452 std::cerr <<
"Error in " << __PRETTY_FUNCTION__ <<
": Insufficient points for Akima interpolation." << std::endl;
455 return &theEvenAkimaInterpolator;
458 void AnalysisWaveform::calculateEvenFromUneven()
const 463 int npoints = (g->GetX()[g->GetN()-1] - g->GetX()[0]) / dt;
464 g_even.Set(force_even_size ? force_even_size : npoints);
469 double t0 = g->GetX()[0];
470 for (
int i = 0; i < g_even.GetN(); i++)
472 double x = t0 + i * dt;
473 g_even.GetX()[i] = x;
477 if (interpolation_type == AKIMA)
479 ROOT::Math::Interpolator irp(g->GetN(), ROOT::Math::Interpolation::kAKIMA);
480 if(g->GetN() >= minPointsForGslInterp){
481 irp.SetData(g->GetN(),g->GetX(),g->GetY());
485 std::cerr <<
"Error in " << __PRETTY_FUNCTION__ <<
": Insufficient points for Akima interpolation." << std::endl;
490 for (
int i = 0; i < g_even.GetN(); i++)
492 if (g_even.GetX()[i] > g->GetX()[g->GetN()-1])
494 memset(g_even.GetY()+i, 0, (g_even.GetN() - i )*
sizeof(
double));
502 g_even.GetY()[i] = irp.Eval(g_even.GetX()[i]);
510 FFTtools::getInterpolatedGraphSparseInvert(g, &g_even, interpolation_options.max_distance, 0, 0,
511 interpolation_type == SPARSE_YEN ? 0 : interpolation_options.mu,
512 interpolation_options.regularization_order);
515 hilbert_envelope_dirty =
true;
517 must_update_even =
false;
520 void AnalysisWaveform::calculateEvenFromFreq()
const 524 double t0 = g_even.GetX()[0];
528 setNewSize(&g_even, force_even_size);
531 if (g_even.GetX()[1] - t0 != dt)
533 fillEven(g_even.GetN(), g_even.GetX(), dt,t0);
536 hilbert_envelope_dirty =
true;
538 must_update_even =
false;
541 void AnalysisWaveform::calculateFreqFromEven()
const 546 assert(g->GetN() > 0);
547 dt = g->GetX()[1] - g->GetX()[0];
548 int old_fft_len = fft_len;
549 fft_len = g->GetN()/2+1;
550 df = 1./ (g->GetN() * dt);
553 if (fft && old_fft_len != fft_len)
562 int ret = posix_memalign( (
void**) &fft, ALIGNMENT,
sizeof(
FFTWComplex) * fft_len);
568 must_update_freq =
false;
570 hilbert_dirty =
true;
571 hilbert_envelope_dirty =
true;
572 power_db_dirty =
true;
574 group_delay_dirty =
true;
582 #ifdef ANITA_ANALYSIS_DEBUG 583 if (DEBUGON) printf(
"Called updateFreq(replace)!\n");
584 if (DEBUGON) printf (
"[%p]: \tmust_update_even=%d, must_update_freq=%d, must_update_uneven=%d\n",
this, must_update_even, must_update_freq, must_update_uneven);
587 if (new_N && new_N != g_even.GetN())
591 fft_len = new_N/2 + 1;
592 int ret = posix_memalign( (
void**) &fft, ALIGNMENT,
sizeof(
FFTWComplex) * fft_len);
597 memcpy(fft, new_fft, fft_len *
sizeof(
FFTWComplex));
602 dt = 1./ (g_even.GetN() * df);
604 must_update_freq =
false;
605 must_update_even =
true;
606 if (!ALLOW_EVEN_TO_UNEVEN) uneven_equals_even =
true;
607 must_update_uneven = !uneven_equals_even;
608 hilbert_dirty =
true;
609 hilbert_envelope_dirty =
true;
611 power_db_dirty =
true;
613 group_delay_dirty =
true;
623 g_phase.Set(fft_len);
624 for (
int i = 0; i < fft_len; i++)
626 g_phase.SetPoint(i, i * df, the_fft[i].getPhase());
637 if (group_delay_dirty)
640 g_group_delay.adopt(
phase());
642 FFTtools::unwrap( g_group_delay.GetN(), g_group_delay.GetY(), 2 * TMath::Pi());
644 double last = g_group_delay.GetY()[0];
645 double dw = df * 2 * TMath::Pi();
646 for (
int i = 1; i < fft_len; i++)
648 double current = g_group_delay.GetY()[i] ;
649 g_group_delay.GetY()[i-1] = (last - current) /dw;
653 g_group_delay.GetY()[g_group_delay.GetN()-1] = 0;
654 group_delay_dirty =
false;
657 return &g_group_delay;
666 g_power_db.adopt(the_power);
668 power_db_dirty =
false;
682 if (hilbert_transform)
delete hilbert_transform;
686 for (
int i = 0; i < fft_len; i++)
688 double temp_im = hilbert[i].
im;
689 hilbert[i].
im = hilbert[i].
re;
690 hilbert[i].
re = - temp_im;
693 hilbert_dirty =
false;
697 return hilbert_transform;
704 if (hilbert_envelope_dirty)
706 g_hilbert_envelope.adopt(the_even);
709 double * y = g_hilbert_envelope.GetY();
710 const double * H = hilbert->
even()->GetY();
711 for (
int i = 0; i < g_hilbert_envelope.GetN(); i++)
713 y[i] = sqrt(y[i] * y[i] + H[i]*H[i]);
716 hilbert_envelope_dirty =
false;
720 return &g_hilbert_envelope;
729 if (power_options.method == PowerCalculationOptions::FFT)
732 g_power.Set(fft_len);
733 for (
int i = 0; i < fft_len; i++)
735 if (i == 0 || i == fft_len -1)
737 g_power.SetPoint(i, i * df, the_fft[i].getAbsSq()/fft_len/50/1000);
741 g_power.SetPoint(i, i * df, the_fft[i].getAbsSq()*2/fft_len/50/1000);
749 if (power_options.method == PowerCalculationOptions::BARTLETT)
765 AnalysisWaveform::~AnalysisWaveform()
772 if (hilbert_transform)
773 delete hilbert_transform;
779 if (must_update_even)
781 force_even_size = size;
784 setNewSize(&g_even, size);
791 if (type == EVAL_LINEAR)
796 const double *y = g->GetY();
801 double t0 = g->GetX()[0];
805 #ifndef ENABLE_VECTORIZE 806 for (
int i = 0; i < N; i++)
808 double xval = (t[i]-t0) / dt;
809 int bin_low = int(xval);
811 int branchless_too_low = bin_low < 0;
812 int branchless_too_high = bin_low >= Ng;
813 int branchless_on_edge = bin_low == Ng-1;
815 int bin_high = bin_low+1;
816 bin_low *= (1-branchless_too_high) * (1-branchless_too_low);
817 bin_high *= (1-branchless_too_high) * (1-branchless_too_low) * (1-branchless_on_edge);
818 double val_low = y[bin_low];
819 double val_high = y[bin_high];
820 double frac = xval - bin_low;
821 double val = val_low + frac * (val_high - val_low);
823 v[i] = val * (1-branchless_too_low) * (1-branchless_too_high) * (1-branchless_on_edge) + branchless_on_edge * y[Ng-1];
827 int leftover = N % VEC_N;
828 int nit = N / VEC_N + (leftover ? 1 : 0);
833 IVEC dont_get_out_of_bounds;
835 for (
int i = 0; i < VEC_N; i++)
837 dont_get_out_of_bounds.insert(i, i >= leftover ? 1 : 0 );
840 for (
int i = 0; i < nit; i++)
842 if (i < nit -1 || !leftover)
844 v_t.load(t + i * VEC_N);
848 v_t.load_partial(leftover, t+i*VEC_N) ;
851 VEC xval = (v_t - v_t0) * inv_dt;
852 VEC truncated_xval = truncate(xval);
853 VEC frac = xval - truncated_xval;
854 IVEC bin_low = truncate_to_int(truncated_xval);
856 IVEC branchless_too_low = bin_low < IVEC(0);
857 IVEC branchless_too_high = bin_low >= IVEC(Ng);
858 IVEC branchless_on_edge = bin_low== IVEC(Ng-1);
860 int scalar_out_of_bounds = int(i == nit-1 && leftover > 0);
861 IVEC out_of_bounds = scalar_out_of_bounds * dont_get_out_of_bounds;
863 IVEC bin_high = bin_low+1;
866 __builtin_prefetch(y+bin_low[0]);
868 IVEC too_low_or_too_high = (1-branchless_too_low) * (1-branchless_too_high) * (1-out_of_bounds);
869 IVEC kill_it = too_low_or_too_high * ( 1- branchless_on_edge);
871 bin_low *= too_low_or_too_high;
876 for (
int j = 0; j < VEC_N; j++)
878 lowv[j] = y[bin_low[j]];
879 highv[j] = y[bin_high[j]];
882 VEC val_low; val_low.load(lowv);
883 VEC val_high; val_high.load(highv);
885 VEC val = mul_add(frac , (val_high - val_low), val_low);
887 if (scalar_out_of_bounds)
889 val.store_partial(leftover, v + i * VEC_N);
893 val.store(v + i * VEC_N);
901 else if (type == EVAL_AKIMA)
903 const ROOT::Math::Interpolator * irp = evenAkimaInterpolator();
906 for (
int i = 0; i < N; i++)
908 v[i] = irp->Eval(t[i]);
913 fprintf(stderr,
"Bad even evaluation type\n");
920 if (typ == EVAL_AKIMA)
922 return evenAkimaInterpolator()->Eval(t);
924 else if (typ == EVAL_LINEAR)
927 double t0 = g->GetX()[0];
928 double xval = (t-t0) / dt;
930 int bin_low = int (xval);
932 if (bin_low < 0)
return 0;
933 if (bin_low >= g->GetN())
return 0;
934 if (bin_low == g->GetN()-1)
return g->GetY()[g->GetN()-1];
936 int bin_high = bin_low + 1;
937 double val_low = g->GetY()[bin_low];
938 double val_high = g->GetY()[bin_high];
940 double frac = xval - bin_low;
942 return val_low + frac*(val_high-val_low);
945 fprintf(stderr,
"Bad EvenEvaluationType\n");
954 g_uneven.adopt(&other.g_uneven);
955 g_even.adopt(&other.g_even);
959 interpolation_type = other.interpolation_type;
960 interpolation_options = other.interpolation_options;
962 uneven_equals_even = other.uneven_equals_even;
963 must_update_even = other.must_update_even;
964 must_update_freq = other.must_update_freq;
965 must_update_uneven = other.must_update_uneven;
966 just_padded = other.just_padded;
967 force_even_size = other.force_even_size;
973 power_db_dirty =
true;
975 group_delay_dirty =
true;
976 hilbert_dirty =
true;
977 hilbert_envelope_dirty =
true;
978 hilbert_transform = 0;
981 fft_len = g_even.GetN()/2+1;
983 if (!must_update_freq)
985 int ret = posix_memalign( (
void**) &fft, ALIGNMENT,
sizeof(
FFTWComplex) * fft_len);
987 memcpy(fft, other.fft, fft_len *
sizeof(
FFTWComplex));
1000 g_uneven(other.uneven_equals_even ? 0 : other.g_uneven.GetN()),
1001 g_even(other.Neven())
1010 interpolation_type = other.interpolation_type;
1011 interpolation_options = other.interpolation_options;
1013 uneven_equals_even = other.uneven_equals_even;
1014 must_update_even = other.must_update_even;
1015 must_update_freq = other.must_update_freq;
1016 must_update_uneven = other.must_update_uneven;
1017 just_padded = other.just_padded;
1018 force_even_size = other.force_even_size;
1024 power_db_dirty =
true;
1026 group_delay_dirty =
true;
1027 hilbert_dirty =
true;
1028 hilbert_envelope_dirty =
true;
1029 hilbert_transform = 0;
1034 if (!uneven_equals_even)
1036 memcpy(g_uneven.GetX(), other.g_uneven.GetX(), g_uneven.GetN() *
sizeof(double));
1038 if (!must_update_uneven)
1040 memcpy(g_uneven.GetY(), other.g_uneven.GetY(), g_uneven.GetN() *
sizeof(double));
1045 if (!must_update_even)
1047 memcpy(g_even.GetY(), other.g_even.GetY(), g_even.GetN() *
sizeof(double));
1048 memcpy(g_even.GetX(), other.g_even.GetX(), g_even.GetN() *
sizeof(double));
1051 fft_len = g_even.GetN()/2+1;
1053 if (!must_update_freq)
1055 int ret = posix_memalign( (
void**) &fft, ALIGNMENT,
sizeof(
FFTWComplex) * fft_len);
1057 memcpy(fft, other.fft, fft_len *
sizeof(
FFTWComplex));
1071 fprintf(stderr,
"convolution does not handle the case where A and B are of different lengths (%d vs. %d)!\n", A->
Nfreq(), B->
Nfreq());
1075 double offset = A->
even()->GetX()[0] - B->
even()->GetX()[0];
1080 int N = answer->
even()->GetN();
1087 for (
int i = 0; i < B->
Nfreq(); i++)
1091 update[i] = vA * vB;
1096 N = answer->
even()->GetN();
1099 double dt = answer->
deltaT();
1100 memcpy(g.GetY(), answer->
even()->GetY() + N/2, N/2 *
sizeof(double));
1101 memcpy(g.GetY()+ N/2, answer->
even()->GetY(), N/2 *
sizeof(double));
1103 for (
int i = 0; i < N; i++)
1105 g.GetX()[i] =(i - N/2) * dt + offset;
1120 fprintf(stderr,
"correlation does not handle the case where A and B are of different lengths (%d vs. %d)!\n", A->
Nfreq(), B->
Nfreq());
1128 fprintf(stderr,
"warning: waveforms don't appear to be padded in time, will be computing circular correlation!\n");
1130 double offset = A->
even()->GetX()[0] - B->
even()->GetX()[0];
1135 int N = answer->
even()->GetN();
1139 double inv = 1./(N*scale);
1142 for (
int i = 0; i < B->
Nfreq(); i++)
1146 update[i].
re = (vA.
re * vB.
re + vA.
im * vB.
im) *inv;
1147 update[i].
im = (vA.
im * vB.
re - vA.
re * vB.
im) *inv;
1153 N = answer->
even()->GetN();
1156 double dt = answer->
deltaT();
1157 memcpy(g.GetY(), answer->
even()->GetY() + N/2, N/2 *
sizeof(double));
1158 memcpy(g.GetY()+ N/2, answer->
even()->GetY(), N/2 *
sizeof(double));
1162 if (window_normalize)
1165 std::vector <double> sum2A(A->
Neven());
1166 std::vector <double> sum2B(B->
Neven());
1168 const double * Ay = A->
even()->GetY();
1169 const double * By = B->
even()->GetY();
1171 for (
int i = 0; i < A->
Neven(); i++)
1173 sum2A[i] = (i == 0 ? 0 : sum2A[i-1]) + Ay[i]*Ay[i];
1176 for (
int i = B->
Neven()-1; i >= 0; i--)
1178 sum2B[i] = (i == B->
Neven()-1 ? 0 : sum2B[i+1]) + By[i]*By[i];
1184 int end = g.GetN()-1;
1186 while(!g.GetY()[start]) start++;
1187 while(!g.GetY()[end]) end--;
1189 for (
int i = start+window_normalize; i <= end-window_normalize+1; i++)
1191 double this_norm = sqrt (sum2A[i] * sum2B[i])/(i-start);
1194 g.GetY()[i]/=this_norm;
1195 if ( i == window_normalize + start)
1197 for (
int ii = start; ii < i; ii++) g.GetY()[ii]/=this_norm;
1200 if (i == end-window_normalize + 1)
1202 for (
int ii = end-window_normalize+2; ii <= end; ii++) g.GetY()[ii]/=this_norm;
1208 for (
int i = 0; i < N; i++)
1210 g.GetX()[i] =(i - N/2) * dt + offset;
1222 if (npad < 1)
return;
1227 if (g_even.GetN() ==0) (
void)
even();
1228 int new_N = g_even.GetN() * (1+npad);
1231 int ret = posix_memalign( (
void**) &new_fft, ALIGNMENT,
sizeof(
FFTWComplex) * (new_N/2+1));
1238 memcpy(new_fft, old_freq, TMath::Min(new_N/2+1,fft_len) *
sizeof(
FFTWComplex));
1241 double scale = (1 + npad);
1242 for (
int i =0; i <
Nfreq(); i++) { new_fft[i].re *= scale; new_fft[i].im *= scale; }
1246 memset(new_fft + fft_len, 0, (new_N/2 + 1 - fft_len) *
sizeof(
FFTWComplex));
1249 fft_len = new_N/2 + 1;
1251 dt = 1./ (g_even.GetN() * df);
1259 must_update_even =
true;
1260 must_update_uneven = !uneven_equals_even;
1261 must_update_freq =
false;
1263 power_db_dirty =
true;
1265 group_delay_dirty =
true;
1266 hilbert_dirty =
true;
1267 hilbert_envelope_dirty =
true;
1268 just_padded =
false;
1275 if (npad < 1)
return;
1280 if (g_even.GetN() ==0) (
void)
even();
1281 int old_N = g_even.GetN();
1282 int new_N = g_even.GetN() + npad;
1285 int ret = posix_memalign( (
void**) &new_fft, ALIGNMENT,
sizeof(
FFTWComplex) * (new_N/2+1));
1292 memcpy(new_fft, old_freq, TMath::Min(new_N/2+1,fft_len) *
sizeof(
FFTWComplex));
1295 double scale = (double(new_N) / old_N);
1296 for (
int i =0; i <
Nfreq(); i++) {
1297 new_fft[i].re *= scale;
1298 new_fft[i].im *= scale; }
1302 memset(new_fft + fft_len, 0, (new_N/2 + 1 - fft_len) *
sizeof(
FFTWComplex));
1305 fft_len = new_N/2 + 1;
1307 dt = 1./ (g_even.GetN() * df);
1315 must_update_even =
true;
1316 must_update_uneven = !uneven_equals_even;
1317 must_update_freq =
false;
1319 power_db_dirty =
true;
1321 group_delay_dirty =
true;
1322 hilbert_dirty =
true;
1323 hilbert_envelope_dirty =
true;
1324 just_padded =
false;
1331 power_options = opt;
1333 power_db_dirty =
true;
1338 if (npad < 1)
return;
1340 int old_n = g->GetN();
1341 g->Set(g->GetN() *(1+npad));
1348 for (
int i = old_n; i < g->GetN(); i++)
1350 g->GetX()[i] = g->GetX()[i-1] + dt;
1356 memcpy(g->GetY() + old_n, g->GetY(), old_n *
sizeof(double));
1357 memcpy(g->GetX() + old_n, g->GetX(), old_n *
sizeof(double));
1358 for (
int i = old_n-1; i >= 0; i--)
1360 g->GetX()[i] = g->GetX()[i+1] - dt;
1365 else if (where == 0)
1367 memmove(g->GetY() + old_n/2, g->GetY(), old_n *
sizeof(double));
1368 memmove(g->GetX() + old_n/2, g->GetX(), old_n *
sizeof(double));
1370 for (
int i = old_n/2-1; i >= 0; i--)
1372 g->GetX()[i] = g->GetX()[i+1] - dt;
1375 for (
int i = old_n + old_n/2; i < g->GetN(); i++)
1377 g->GetX()[i] = g->GetX()[i-1] + dt;
1383 if (npad >= 1) just_padded =
true;
1388 if (just_padded)
return true;
1392 for (
int i = g->GetN()/2; i <g->GetN(); i++)
1394 if (g->GetY()[i] !=0)
return false;
1400 static void doDraw(
const TGraphAligned * cg,
const char * opt,
int color)
1406 g->SetLineColor(color);
1407 g->SetMarkerColor(color);
1433 int N = TMath::Min(x->Neven(), y->Neven());
1441 const double one_over_sqrt2 = 1./sqrt(2);
1446 for (
int i = 0; i < N; i++)
1448 new_x[i] = one_over_sqrt2 * ( g_xh->GetY()[i] + g_y->GetY()[i]);
1449 new_y[i] = one_over_sqrt2 * ( g_x->GetY()[i] + g_yh->GetY()[i]);
1453 memcpy(x->updateEven()->GetY(), new_x, N *
sizeof(double));
1454 memcpy(y->updateEven()->GetY(), new_y, N *
sizeof(double));
1456 x->forceEvenSize(N);
1457 y->forceEvenSize(N);
1463 int N = TMath::Min(x->Neven(), y->Neven());
1472 for (
int i = 0; i < N; i++)
1474 new_x[i] = 0.5 * ( g_x->GetY()[i] + g_y->GetY()[i] );
1475 new_y[i] = 0.5 * ( g_x->GetY()[i] - g_y->GetY()[i] );
1479 memcpy(x->updateEven()->GetY(), new_x, N *
sizeof(double));
1480 memcpy(y->updateEven()->GetY(), new_y, N *
sizeof(double));
1482 x->forceEvenSize(N);
1483 y->forceEvenSize(N);
1504 double mean = g->GetMean(2);
1505 for (
int i = 0; i <g->GetN(); i++)
1511 void AnalysisWaveform::setCorrelationNag(
bool nag)
1514 nag_if_not_zero_padded = nag;
1517 void AnalysisWaveform::nameGraphs()
1520 #pragma omp critical 1523 TDirectory * old_dir = gDirectory;
1526 DO_FOR_TIME(GetXaxis()->SetTitle(
"ns"));
1527 DO_FOR_FREQ(GetXaxis()->SetTitle(
"Ghz"));
1529 g_uneven.SetName(TString::Format(
"wf_uneven_%d", uid));
1531 g_even.SetName(TString::Format(
"wf_even_%d", uid));
1533 g_hilbert_envelope.SetName(TString::Format(
"wf_hilbert_env_%d", uid));
1534 g_hilbert_envelope.GetYaxis()->SetTitle(
"Analytic Envelope");
1536 g_power.SetName(TString::Format(
"wf_power_%d", uid));
1537 g_power.GetYaxis()->SetTitle(
"Power (arb) ");
1539 g_power_db.SetName(TString::Format(
"wf_power_db_%d", uid));
1540 g_power_db.GetYaxis()->SetTitle(
"Power (dbSomething) ");
1542 g_phase.SetName(TString::Format(
"wf_phase_%d", uid));
1543 g_phase.GetYaxis()->SetTitle(
"Phase");
1545 g_group_delay.SetName(TString::Format(
"wf_group_delay_%d", uid));
1546 g_group_delay.GetYaxis()->SetTitle(
"Group Delay (ns)");
1547 gDirectory = old_dir;
1552 double AnalysisWaveform::getRMS()
const 1556 if (!must_update_even)
1559 even()->getMeanAndRMS(&mean,&rms);
1563 if(!must_update_uneven && !uneven_equals_even)
1567 uneven()->getMeanAndRMS(&mean,&rms);
1577 for (
int i = 1; i < N; i++)
1579 sum2+= f[i].getAbsSq();
1582 return sqrt(sum2/2)/(N-1);
1588 double dt0 = g->GetX()[1]-g->GetX()[0];
1594 for (
int i = 2; i < g->GetN(); i++)
1596 if (g->GetX()[i]-g->GetX()[i-1] != dt0)
1608 for (
int i = 1; i < g->GetN(); i++)
1610 sumdt += g->GetX()[i] - g->GetX()[i-1];
1612 dt0 = sumdt / (g->GetN()-1.);
1616 wf->~AnalysisWaveform();
struct __attribute__((packed))
Debugging use only TURF scaler data.
double im
The imaginary part.
This is a wrapper class for a complex number.