FluctSpectStats.h
1 //-*-C++-*-
2 /***************************************************************************
3  *
4  * Copyright (C) 2023 by Willem van Straten
5  * Licensed under the Academic Free License version 2.1
6  *
7  ***************************************************************************/
8 
9 // psrchive/More/Polarimetry/Pulsar/FluctSpectStats.h
10 
11 #ifndef __Pulsar_FluctSpectStats_h
12 #define __Pulsar_FluctSpectStats_h
13 
14 #include "Pulsar/Algorithm.h"
15 #include "Pulsar/PhaseWeight.h"
16 
17 #include "FTransformAgent.h"
18 
19 namespace Pulsar {
20 
22  template<class ProfileType, class ProfileStatsType>
23  class FluctSpectStats : public Algorithm
24  {
25  public:
26 
29 
31  void set_profile (const ProfileType*);
32 
34  void select_profile (const ProfileType*);
35 
37  void set_regions (const PhaseWeight& pulse, const PhaseWeight& baseline);
38 
40  void get_regions (PhaseWeight& on, PhaseWeight& off) const { on = onpulse; off = baseline; }
41 
43  unsigned get_last_harmonic () const { return last_harmonic; }
44 
46  const ProfileType* get_fourier () const { return fourier; }
47 
49  const ProfileStatsType* get_real () const { return real; }
50 
52  const ProfileStatsType* get_imag () const { return imag; }
53 
55  void set_plan (FTransform::Plan* p) { plan = p; }
56 
57  protected:
58 
61 
64 
67 
70 
72  bool regions_set;
73 
74  PhaseWeight onpulse;
75  PhaseWeight baseline;
76 
77  unsigned last_harmonic;
78 
80  virtual void preprocess (ProfileType* fourier_transform) { /* do nothing */ }
81 
83  virtual const Profile* reference (const ProfileType*) = 0;
84 
86  void build ();
87 
90 
91  };
92 
93 }
94 
95 
96 #include "Pulsar/Fourier.h"
97 #include "Pulsar/LastHarmonic.h"
98 #include "Pulsar/BaselineEstimator.h"
99 #include "Pulsar/ExponentialBaseline.h"
100 
101 // #define _DEBUG 1
102 #include "debug.h"
103 
105 template<class ProfileType, class ProfileStatsType>
107 {
108  real = new ProfileStatsType;
109  imag = new ProfileStatsType;
110 
111  regions_set = false;
112  last_harmonic = 0;
113  plan = 0;
114 }
115 
117 template<class ProfileType, class ProfileStatsType>
119 {
120  profile = _profile;
121  build ();
122 }
123 
125 
127 template<class ProfileType, class ProfileStatsType>
129 {
130  profile = _profile;
131  regions_set = false;
132  build ();
133  if (profile)
134  regions_set = true;
135 }
136 
138 template<class ProfileType, class ProfileStatsType>
140 {
141  real->set_regions (on, off);
142  imag->set_regions (on, off);
143 
144  onpulse = on;
145  baseline = off;
146 
147  regions_set = true;
148  build ();
149 }
150 
151 template<class ProfileType>
152 ProfileType* fourier_to_psd (const ProfileType* fourier)
153 {
154  Reference::To<ProfileType> psd = fourier->clone();
155  detect (psd);
156  return psd.release();
157 }
158 
159 template<class ProfileType>
160 ProfileType* fourier_to_psd (Reference::To<ProfileType>& fourier)
161 {
162  return fourier_to_psd (fourier.get());
163 }
164 
165 void copy_pad (Pulsar::PhaseWeight& into, Pulsar::PhaseWeight& from, float remainder);
166 
167 template<class ProfileType, class ProfileStatsType>
169 {
170  if (!profile)
171  return;
172 
173  fourier = fourier_transform (profile, plan);
174  // drop the Nyquist bin, if any
175  fourier->resize( profile->get_nbin() );
176 
177  // perform any required pre-processing required by derived types
178  preprocess (fourier);
179 
180  // form the power spectral density
181  Reference::To<ProfileType> psd = fourier_to_psd (fourier);
182 
183  // separate fourier into real and imaginary components
184  // (psd is cloned only because it has the correct number of phase bins;
185  // the amplitudes are correctly set in the following for loop)
186  Reference::To<ProfileType> re = psd->clone();
187  Reference::To<ProfileType> im = psd->clone();
188 
189  fourier_to_re_im (fourier, re, im);
190 
191  if (!regions_set)
192  {
193  LastHarmonic last;
194  last.set_Profile( reference(psd) );
195 
196  last.get_weight (&onpulse);
197  last.get_baseline_estimator()->get_weight (&baseline);
198 
199  last_harmonic = last.get_last_harmonic();
200 
201  DEBUG("Pulsar::FluctSpectStats::build last harmonic=" << last_harmonic << " nbin on=" << onpulse.get_weight_sum());
202 
203  real->set_regions (onpulse, baseline);
204  imag->set_regions (onpulse, baseline);
205  }
206 
207  if (onpulse.get_nbin () != re->get_nbin())
208  {
209  PhaseWeight on_temp = onpulse;
210  PhaseWeight off_temp = baseline;
211 
212  DEBUG("Pulsar::FluctSpectStats::build masks nbin=" << onpulse.get_nbin () << " != obs nbin=" << re->get_nbin());
213 
214  on_temp.resize( re->get_nbin() );
215  off_temp.resize( re->get_nbin() );
216 
217  if (re->get_nbin() > onpulse.get_nbin ())
218  {
219  // the observation has more bins than the template; pad the masks
220  copy_pad( on_temp, onpulse, 0 );
221  copy_pad( off_temp, baseline, 1 );
222  }
223  else
224  {
225  // the observation has fewer bins than the template;
226  // therefore, the baseline of the standard might start after the last harmonic of the observation
227  // therefore, compute a new baseline
228 
229  // the ExponentialBaseline is suitable for the PSD (which is distributed like chi^2 with 2 DOF)
230  ExponentialBaseline baseline_estimator;
231  baseline_estimator.set_Profile( reference(psd) );
232  baseline_estimator.get_weight(&off_temp);
233  }
234 
235  real->set_regions (on_temp, off_temp);
236  imag->set_regions (on_temp, off_temp);
237  }
238 
239  real->set_profile (re.release());
240  imag->set_profile (im.release());
241 }
242 catch (Error& error)
243 {
244  throw error += "Pulsar::FluctSpectStats::build";
245 }
246 
247 #endif // __Pulsar_FluctSpectStats_h
void get_regions(PhaseWeight &on, PhaseWeight &off) const
Set the on-pulse and baseline regions.
Definition: FluctSpectStats.h:50
virtual void preprocess(ProfileType *fourier_transform)
Perform any preprocessing on fourier_transform.
Definition: FluctSpectStats.h:90
virtual const Profile * reference(const ProfileType *)=0
Extract the reference profile.
const BaselineEstimator * get_baseline_estimator() const
Get the BaselineEstimator used to find the off-pulse phase bins.
Definition: LastHarmonic.C:92
Stores a weight for each Profile phase bin.
Definition: PhaseWeight.h:29
void resize(unsigned nbin)
Resize the weights array.
Definition: PhaseWeight.h:67
unsigned get_last_harmonic() const
Get the index of the last significant harmonic.
Definition: LastHarmonic.C:75
FluctSpectStats()
Default constructor.
Definition: FluctSpectStats.h:106
Reference::To< ProfileStatsType > real
Computes the statistics of the real component.
Definition: FluctSpectStats.h:76
Any quantity recorded as a function of pulse phase.
Definition: Profile.h:45
void fourier_to_re_im(const PolnProfile *fourier, PolnProfile *re, PolnProfile *im)
Divide the output of fourier_transform into its real and imaginary components.
Definition: Fourier.C:158
Reference::To< const ProfileType > profile
The Profile from which statistics will be derived.
Definition: FluctSpectStats.h:70
Type * release()
void select_profile(const ProfileType *)
Set the Profile that defines the last harmonic and baseline.
Definition: FluctSpectStats.h:128
Type * get() const
void set_Profile(const Profile *psd)
Set the flucuation power spectral density from which the last harmonic will be computed.
Definition: LastHarmonic.C:37
void set_profile(const ProfileType *)
Set the Profile from which statistics will be derived.
Definition: FluctSpectStats.h:118
const ProfileType * get_fourier() const
Get the fourier transform of the last set profile.
Definition: FluctSpectStats.h:56
Profile * fourier_transform(const Profile *, FTransform::Plan *=0)
Return the forward Fourier transform of the input Profile.
Definition: Fourier.C:41
const ProfileStatsType * get_real() const
Get the real component statistics.
Definition: FluctSpectStats.h:59
Finds the last significant harmonic in a flucuation power spectral density.
Definition: LastHarmonic.h:37
void set_plan(FTransform::Plan *p)
Set the fourier transform plan.
Definition: FluctSpectStats.h:65
virtual void get_weight(PhaseWeight *weight)
Returns a PhaseWeight with the Profile attribute set.
Definition: ProfileWeightFunction.C:26
unsigned get_last_harmonic() const
Return the last harmonic chosen in the on-pulse signal.
Definition: FluctSpectStats.h:53
virtual void set_Profile(const Profile *)
Set the Profile from which the PhaseWeight will be derived.
Definition: ProfileWeightFunction.C:20
Finds a baseline that contains gaussian white noise.
Definition: ExponentialBaseline.h:24
FTransform::Plan * plan
The fourier transform plan (useful in multi-threaded applications)
Definition: FluctSpectStats.h:99
void detect(Profile *input)
Square-law detect the input complex-valued Profile.
Definition: Fourier.C:103
void build()
Computes the phase bin masks.
Definition: FluctSpectStats.h:168
const ProfileStatsType * get_imag() const
Get the imaginary component statistics.
Definition: FluctSpectStats.h:62
bool regions_set
When, true the onpulse and baseline estimators have been selected.
Definition: FluctSpectStats.h:82
Reference::To< ProfileStatsType > imag
Computes the statistics of the imaginary component.
Definition: FluctSpectStats.h:79
Defines the PSRCHIVE library.
Definition: CalSource.h:17
Reference::To< ProfileType > fourier
The Fourier transform of the profile.
Definition: FluctSpectStats.h:73
void set_regions(const PhaseWeight &pulse, const PhaseWeight &baseline)
Set the on-pulse and baseline regions.
Definition: FluctSpectStats.h:139

Generated using doxygen 1.8.17