DynamicSpectrum

class screens.dynspec.DynamicSpectrum(dynspec, f, t, noise=None, d_eff=None, mu_eff=None, theta=None, magnification=None)[source] [edit on github]

Bases: object

Dynamic spectrum and methods to fit it.

The code is meant to be agnostic to which axes are which, but some may assume a shape of (..., time_axis, frequency_axis).

Parameters:
dynspecndarray

Intensities as a function of time and frequency.

tQuantity

Times of the dynamic spectrum. Should have the proper shape to broadcast with dynspec.

fQuantity

Frequencies of the dynamic spectrum. Should have the proper shape to broadcast with dynspec.

noisefloat

The uncertainty in the intensities in the dynamic spectrum.

d_effQuantity

Assumed effective distance. This is used throughout and not fit, but can be treated as a scaling parameters.

mu_effQuantity, optional

Initial guess for the effective proper motion, v_eff/d_eff.

thetaQuantity, optional

Grid of theta angles to use for modelling the dynamic spectrum. Probably more usefully calculated later using theta_grid.

magnificationQuantity, optional

Magnifications at each theta. More typically inferred by fitting the dynamic spectrum.

Methods Summary

cleanup_fit([max_abs_err, max_rel_err, verbose])

Remove highly degenerate configurations from the fit.

dynamic_bases([mu_eff])

Calculate the amplitude infererence patterns for current fit.

fit([guess, verbose])

Fit the dynamic spectrum directly.

fromfile(filename[, d_eff, mu_eff, noise])

Read a dynamic spectrum from an HDF5 file.

jacobian(magnification, mu_eff)

Derivatives of the model dynamic spectrum to all parameters.

locate_mu_eff([mu_eff_trials, verbose, use])

Try reproducing the dynamic spectrum for a range of proper motion.

model([magnification, mu_eff])

Calculate a model dynamic spectrum.

residuals([magnification, mu_eff])

Residuals compared to the model.

theta_grid([oversample_tau, oversample_fd])

Calculate a grid of theta for modelling the dynamic spectrum.

theta_theta([mu_eff, theta_grid])

Create a theta-theta array from the dynamic spectrum.

Methods Documentation

cleanup_fit(max_abs_err=0.1, max_rel_err=1000.0, verbose=True)[source] [edit on github]

Remove highly degenerate configurations from the fit.

Works by doing an singular value decomposition on the fit and removing very small values, those that are either smaller than max_abs_err or max_rel_err times the largest value.

dynamic_bases(mu_eff=None)[source] [edit on github]

Calculate the amplitude infererence patterns for current fit.

The power of the sum of these amplitudes is a dynamic spectrum.

Explicitly assumes that time and frequency are the last two axes of the dynamic spectrum. (TODO: lift this restriction.)

Parameters:
mu_effQuantity, optional

Effective proper motion to use. Defaults to that stored on the instance. Will not update the instance.

Notes

The calculated dynamic bases are cached for a given mu_eff.

fit(guess=None, verbose=2, **kwargs)[source] [edit on github]

Fit the dynamic spectrum directly.

This needs good guesses, such as can be gotten from screens.dynspec.DynamicSpectrum.locate_mu_eff().

Parameters:
guessinitial guesses, optional

If None, use the current magnification and mu_eff on the instance. If curvature, select the best value from the curvature table on the instance (created by locate_mu_eff). If a tuple, guesses for magnification and mu_eff. If a single number, treat it as a guess for mu_eff and determine initial guesses for the magnification using eigen-value decomposition.

verboseint

How much information to print during fitting. A value of 3 forces the class itself to print a reduced chi2 any time mu_eff is updated.

**kwargs

Any further keyword arguments to pass on to scipy.optimize.curve_fit().

Notes

This uses the model and jacobian methods on the instance.

classmethod fromfile(filename, d_eff=None, mu_eff=None, noise=None)[source] [edit on github]

Read a dynamic spectrum from an HDF5 file.

This includes its time and frequency axes.

Note: this needs the baseband-tasks package for HDF5 file access.

jacobian(magnification, mu_eff)[source] [edit on github]

Derivatives of the model dynamic spectrum to all parameters.

The model dynamic spectrum is

\[\begin{split}w(f, t) &= \sum_k \mu_k \exp[j\phi(\theta_i, \mu_{\rm eff}, f, t)] &\equiv \sum_k \mu_k \Phi_k \\ DS(f,t) &= |w(f, t)|^2 = w \bar{w}\end{split}\]

It is easiest to use Wirtinger derivatives:

\[\begin{split}\frac{\partial}{\partial x} &= \left(\frac{\partial}{\partial z} + \frac{\partial}{\partial\bar{z}}\right) \\ \frac{\partial}{\partial y} &= j \left(\frac{\partial}{\partial z} - \frac{\partial}{\partial\bar{z}}\right)\end{split}\]

Using this for the magnifications:

\[\begin{split}\frac{\partial DS}{\partial\mu} &= \bar{w}\frac{\partial w}{\partial\mu} = \bar{w}\Phi \\ \frac{\partial DS}{\partial\bar{\mu}} &= w \frac{\partial\bar{w}}{\partial\bar{\mu}} = w \bar{\Phi} \\ \frac{\partial DS}{\partial x} &= \left(\bar{w} \Phi + w \bar{\Phi}\right) = 2\Re(w\bar{\Phi}) \\ \frac{\partial DS}{\partial y} &= j\left(\bar{w} \Phi - w \bar{\Phi}\right) = 2\Im(w\bar{\Phi})\end{split}\]

And for \(\mu_{\rm eff}\):

\[\begin{split}\frac{\partial w}{\partial\mu_{\rm eff}} &= \sum_k\mu_k\Phi_k \frac{\partial j\phi_k}{\partial\mu_{\rm eff}} \\ \frac{\partial\bar{w}}{\partial\mu_{\rm eff}} &= \sum_k\bar{\mu}_k\bar{\Phi}_k \frac{\partial -j\phi_k}{\partial\mu_{\rm eff}} \\ \frac{\partial DS}{\partial\mu_{\rm eff}} &= \bar{w} \frac{\partial w}{\partial\mu_{\rm eff}} + w \frac{\partial\bar{w}}{\partial\mu_{\rm eff}} = 2j\sum_k\mu_k \Phi_k \frac{\partial\phi}{\partial\mu_{\rm eff}}\end{split}\]
locate_mu_eff(mu_eff_trials=None, verbose=True, use=True, **kwargs)[source] [edit on github]

Try reproducing the dynamic spectrum for a range of proper motion.

For each proper motion, construct a theta-theta array, calculte the largest eigenvalue and use the corresponding eigenvector as the model one-dimensional screen.

Parameters:
mu_eff_trialsQuantity

Proper motions to try.

verbosebool

Whether or not to give summary statistics for each trial.

usebool

Whether to store the best-fit proper motion and corresponding theta grid and magnifications on the instance.

**kwargs

Further parameters to use in calculating the theta grid for each proper motion.

Returns:
curvatureQTable

Table with the following columns: - mu_eff : Input proper motions. - theta : grid in theta used. - w : Largest eigenvalue. - recovered : corresponding eigenvector, i.e., magnifications. - th_ms : Mean-square residual in theta-theta space. - ndof : degrees of freedom n_dynspec - n_theta - 2. - redchi2 : reduced chi2 ((dynspec - model)/noise)**2/ndof.

Notes

The resulting table is also stored on the instance, as curvature.

model(magnification=None, mu_eff=None)[source] [edit on github]

Calculate a model dynamic spectrum.

Uses parameters on the instance if not otherwise specified.

Parameters:
magnificationarray-like, optional

Complex magnification for each theta value.

mu_effQuantity, optional

Effective proper motion.

residuals(magnification=None, mu_eff=None)[source] [edit on github]

Residuals compared to the model.

Parameters as for model():

theta_grid(oversample_tau=1.3, oversample_fd=1.69, **kwargs)[source] [edit on github]

Calculate a grid of theta for modelling the dynamic spectrum.

Wraps screens.fields.theta_grid with defaults from the class. See that function for details.

Note that this does not set the angles on the class, so typical usage is ds.theta = ds.theta_grid().

theta_theta(mu_eff=None, theta_grid=None, **kwargs)[source] [edit on github]

Create a theta-theta array from the dynamic spectrum.

For a given grid in theta (possibly calculated) and a set of pairs found using screens.fields.theta_theta_indices, this brute-force estimates the amplitudes at each pair by cross-multiplying their expected signature in the dynamic spectrum.

Parameters:
mu_effQuantity, optional

Effective proper motion to use. Defaults to that stored on the instance. Will update the instance if given.

theta_gridbool, optional

Whether to calculate a new theta grid, or use the one stored on the instance. By default, calculate it only if mu_eff is passed in. If True, this will update the grid stored on the instance.

**kwargs

Any further arguments are passed on to theta_grid