will package

Submodules

will.create module

Pulse creation routines.

class will.create.GaussPulse(relative_intensities: Union[Sequence, float], sigma_times: Union[Sequence, float], sigma_freqs: Union[Sequence, float], center_freqs: Union[Sequence, float], pulse_thetas: Union[Sequence, float], offsets: Union[Sequence, float], dm: float, tau: float, chan_freqs: ndarray, tsamp: float, spectral_index_alpha: float, nscint: int, phi: float, bandpass: Optional[ndarray] = None, dm_interchan_smear: bool = False)

Bases: object

Class to create a pulse from a 2D Gaussian.

The PDF is created ith the object. To sample use sample_pulse(nsamps).

Parameters:
  • relative_intensities – The relative intensities of the pule components.

  • sigma_time – time sigma [second].

  • sigma_freq – Frequency Sigma [MHz].

  • chan_freq – Array of channel frequencies [MHz].

  • tsamp – Sampling time of dynamic spectra [second].

  • pulse_theta – Angle of pulse components.

  • nsamp – Number of samples to add.

  • dm – Dispersion Measure [pc/cm^3].

  • tau – Scatter parameter.

  • tsamp – Sampling time of dynamic spectra in second.

  • spectra_index_alpha – Spectral index power around center_freq.

  • nscint – Number of frequency scintills.

  • phi – Phase of frequency scintillation.

  • bandpass – Scale frequency structure with bandpass if not None (Optional).

  • dm_interchan_smear – Interchannel DM smearing simulated by boxcar convolution (Optional).

bandpass: Optional[ndarray] = None
center_freqs: Union[Sequence, float]
chan_freqs: ndarray
create_pulse() None

Create the pulse.

dm: float
dm_interchan_smear: bool = False
nscint: int
offsets: Union[Sequence, float]
property optimal_boxcar_width: int64

Find the optimal boxcar width.

Parameters:

None

Returns:

Optimal Boxcar width in number of samples.

phi: float
property pulse_center: int

The location of the pulse maximum in time samples.

Parameters:

None

Returns:

Index of pulse maximum.

pulse_thetas: Union[Sequence, float]
relative_intensities: Union[Sequence, float]
sample_pulse(nsamp: int, dtype: type = <class 'numpy.uint32'>) ndarray

Sample the pulse with nsamp samples.

Parameters:
  • nsamp – Number of samples in the pulse.

  • dtype – Data type of the pulse.

Returns:

2D ndarray with disperesed pulse.

sigma_freqs: Union[Sequence, float]
sigma_times: Union[Sequence, float]
spectral_index_alpha: float
tau: float
tsamp: float
class will.create.SimpleGaussPulse(sigma_time: float, sigma_freq: float, center_freq: float, dm: float, tau: float, chan_freqs: ndarray, tsamp: float, spectral_index_alpha: float, nscint: int, phi: float, bandpass: Optional[ndarray] = None)

Bases: object

Create a pulse from Gaussians in time and frequency. The time and frequency profiles are created with the object. To sample use .sample_pulse(nsamps) to sample the pulse.

Parameters:
  • sigma_time – Time sigma in seconds.

  • dm – Dispersion Measure [pc/cm^3].

  • tau – Scatter.

  • sigma_freq – Frequency Sigma [MHz].

  • center_freq – Center Frequency [MHz].

  • chan_freq – Array of channel frequencies [MHz].

  • tsamp – sampling time of dynamic spectra [second].

  • spectra_index_alpha – spectral index around center_freq.

  • nscint – Number of scintills.

  • phi – Pase of of scintillation.

  • bandpass – Scale frequency structure with bandpass if not None (Optional).

bandpass: Optional[ndarray] = None
center_freq: float
chan_freqs: ndarray
create_pulse() None

Create the pulse.

dm: float
nscint: int
property optimal_boxcar_width: int64

Find the optimal boxcar width.

Parameters:

None.

Returns:

Optimal Boxcar width.

phi: float
property pulse_center: int64

The location of the pulse maximum in time samples.

Parameters:

None.

Returns:

Index of pulse maximum.

sample_pulse(nsamp: int, dtype: type = <class 'numpy.uint32'>) ndarray

Sample the pulse with nsamp samples.

Parameters:
  • nsamp – Number of samples in the pulse.

  • dtype – Data type of the pulse (Optional).

Returns:

2D ndarray with disperesed pulse.

sigma_freq: float
sigma_time: float
spectral_index_alpha: float
tau: float
tsamp: float
class will.create.TwoDimensionalPulse(pulse_pdf: ndarray, chan_freqs: ndarray, tsamp: float, dm: float)

Bases: object

Create a pulse from a 2D pulse Probability Distribution Function (PDF).

Parameters:
  • pulse_pdf – The 2D array containing pulse the pulse profile at 0 DM.

  • chan_freq – Array of channel frequencies [MHz].

  • tsamp – sampling time of dynamic spectra [second].

  • dm – Dispersion Measure [pc/cm^3].

chan_freqs: ndarray
dm: float
property optimal_boxcar_width: int64

Find the optimal boxcar width.

Parameters:

None

Returns:

S/N Optimizing boxcar width.

property pulse_center: int

The location of the pulse maximum in time samples.

Parameters:

None

Returns:

Argument of pulse center.

pulse_pdf: ndarray
sample_pulse(nsamp: int, dtype: type = <class 'numpy.uint32'>) ndarray

Sample the pulse with nsamp samples.

Parameters:
  • nsamp – Number of samples in the pulse.

  • dtype – Data type of the pulse (Optional).

Returns:

2D ndarray with disperesed pulse.

tsamp: float
will.create.apply_scatter_profile(time_profile: ndarray, chan_freqs: ndarray, ref_freq: float, tau: float = 1.0, axis: Union[None, int] = None) ndarray

Create exponential scattering profile.

Parameters:
  • freq – Frequencies array.

  • ref_freq – Reference Frequency.

  • tau – Scattering parameter (Optional).

  • axis – Axis to perform convolution (Optional).

Returns:

Exponential scattering profile.

will.create.arbitrary_array_cdf(array: ndarray, locations: float, num_samples: int) ndarray

Calculate the time locations from a given array.

Parameters:
  • times – Array with times to consider.

  • tau – Pulse width.

Returns:

Values sampled from pulse with tail distribution.

Notes

based on https://harry45.github.io/blog/2016/10/Sampling-From-Any-Distribution

will.create.build_pulse(num_times: int, num_chans: int, locations: Union[ndarray, Tuple[ndarray, ndarray]]) ndarray

Build the pulse from locations tuple.

Parameters:
  • num_times – Length of the time samples axis.

  • num_chans – Length of channel axis.

  • locations – Locations of the points to increase the energy given as two arrays.

Returns:

2D float array with the pulse, time on the ventricle axis.

Example

pulse = build_pulse(10, 10, [[2, 2, 2], [2, 0, 2]]) will make a point value 2 at pulse[2,2] and one at pulse[2,0]

will.create.clone_spectra(dynamic_spectra: ndarray, median_filter_length: int = 0) ndarray

Clone a section of dynamic spectra using Gaussian random numbers.

Parameters:
  • dynamic_spectra – 2D array of dynamic spectra.

  • median_filter_lenght – Run the standard devaitions and medians through a filter with this lenght (Optional).

Returns:

Dynamic spectra that has simlar statstics as the given dynamic spectra.

will.create.dynamic_from_statistics(medians: ndarray, stds: ndarray, dtype: dtype, nsamps: int = 65536) ndarray

Make a dynamic spectra from statistics.

Parameters:
  • medians – Bandpass medians.

  • stds – Standard deviation of the bandpass.

  • dtype – data type of fake file.

  • nsamps – Number of time samples (Optional).

Returns:

2D array of randim numbers with the specified characteristics.

will.create.filter_weights(dynamic_spectra: ~numpy.ndarray, metric: ~typing.Callable = <function median>, bandpass_smooth_length: int = 50, cut_sigma: float = 0.6666666666666666, smooth_sigma: int = 30) ndarray

Makes weights based on low values of some meteric. This is designed to ignore bandpass filters or tapers at the end of the bandpass.

Parameters:
  • dynamic_spectra – 2D dynamic spectra with time on the vertical axis.

  • metric – The statistic to sample (Optional).

  • bandpass_smooth_length – length of the median filter to smooth the bandpass (Optional).

  • sigma_cut – Cut values below (standard deviation)*(sigma cut) (Optional).

  • smooth_sigma – Gaussian filter smoothing sigma. If =0, return the mask where True=good channels (Optional).

Returns:

Bandpass weights for sections of spectra with low values. 0 where the value is below the threshold and 1 elsewhere, with a Gaussian taper.

will.create.gauss_with_tail_cdf(times: ndarray, tau: float) ndarray

Calculate the time locations for a Gaussian pulse with exponential tail.

Parameters:
  • times – Array with times to consider.

  • tau – Pulse width.

Returns:

Values sampled from pulse with tail distribution.

Notes

based on https://harry45.github.io/blog/2016/10/Sampling-From-Any-Distribution

will.create.gauss_with_tail_locations(start: int, stop: int, tau: int, num_locations: int, back_end: str = 'cdf') ndarray

Locations based on Gaussian with an exponential tail. You probably want to use GaussPulse or Simple Gauss pulse. This provides a comparison between the cdf and rvs samplers.

Parameters:
  • start – Start index.

  • stop – Stop index.

  • sigma – Gaussian sigma.

  • num_locations – The number of locations to generate.

  • back_end – How the samples are calculated [rvs] uses the rv_continuous class, cdf creates a CDF an linearly interpolates it. The latter is much faster. (Optional)

Returns:

Location indices for one axis.

Example

gauss_with_tail_locations(0.1, 1024, 20, int(5e2), back_end=”rvs”)

will.create.gaussian(domain: ndarray, mu: float, sig: float) ndarray

A Gaussian Function.

Parameters:
  • domain – Domain to calculate the Gaussian.

  • mu – Center location.

  • sig – Pulse width.

Returns:

Gaussian evaluated over x.

will.create.optimal_boxcar_width(time_profile: ndarray, boxcar_widths: ndarray) int64

Find the best boxcar width for a given time profile and array of boxcar widths.

Parameters:
  • time_profile – The time profile of the pulse.

  • boxcar_widths – Array of boxcar widths.

Returns:

Length of the optimal boxcar.

will.create.pulse_with_tail(times: ndarray, tau: float = 50) ndarray

Create a Gaussian Pulse with a scattering tail.

Parameters:
  • Times – Time array.

  • tau – Width parameter (Optional).

Returns:

pulse profile.

Notes: Based on Ian P. Williamson, Pulse Broadening due to Multiple Scattering in the Interstellar Medium https://academic.oup.com/mnras/article/157/1/55/2604596

I tried moving the center to match the other Gaussian, but this slows down the rvs sampler by a factor of ~4.

Example: times = np.linspace(1, 256, 256) pulse = create.pulse_with_tail(times, 50)

class will.create.pulse_with_tail_dist(momtype=1, a=None, b=None, xtol=1e-14, badvalue=None, name=None, longname=None, shapes=None, extradoc=None, seed=None)

Bases: rv_continuous

Class to create a pulse with a tail.

Parameters:

class (rv_continuous) –

Thanks to https://harry45.github.io/blog/2016/10/Sampling-From-Any-Distribution

will.create.scatter_profile(chan_freqs: ndarray, ref_freq: float, tau: float = 1.0) ndarray

Create exponential scattering profile.

Parameters:
  • freq – Frequencies array.

  • ref_freq – Reference Frequency.

  • tau – Scattering parameter (Optional).

Returns:

Exponential scattering profile.

Notes

Bases on https://github.com/liamconnor/injectfrb/blob/a4dd5f22438ba7bdfaa2eb792eb54736cde53fed/injectfrb/simulate_frb.py#L111

will.create.scintillation(chan_freqs: ndarray, freq_ref: float, nscint: int = 3, phi: float = 0) ndarray

Adds Scintillation that is abs(cos(band)).

Parameters:
  • chan_freqs – Array of channel Frequencies.

  • freq_freq – Reference Frequency.

  • nscint – Number of scintills (Optional).

  • phi – Phase of of scintillation (Optional).

Returns:

Scintillation intensities.

Notes

Similar to https://arxiv.org/abs/2003.14272 and https://github.com/liamconnor/injectfrb/blob/a4dd5f22438ba7bdfaa2eb792eb54736cde53fed/injectfrb/simulate_frb.py#L77 added abs as it seems more relativistic to me

will.create.skewed_gauss(x: ndarray, y: ndarray, x_mu: float, y_mu: float, x_sig: float, y_sig: float, theta: float) ndarray

Two dimensional Gaussian with an angle theta.

Parameters:
  • x – Horizontal Domain from np.meshgrid.

  • y – Vertical Domain from np.meshgrid.

  • x_mu – Horizontal Location.

  • y_mu – Vertical Distance.

  • x_sig – Horizontal sigma.

  • y_sig – Vertical Sigma.

  • theta – Rotation angle increasing counterclockwise [radians].

Returns:

2D gaussian with amplitude one.

Notes

Based on https://docs.astropy.org/en/stable/api/astropy.modeling.functional_models.Gaussian2D.html

will.create.spectral_index(chan_freqs: ndarray, freq_ref: float, spectral_index_alpha: float) ndarray

Add spectral index to pulse profile.

Parameters:
  • frequencies – Frequencies of the bandpass.

  • freq_ref – Reference frequency.

  • index (spectral) – Spectral index.

Returns:

Pulse profile modulated by spectral index.

will.create.uniform_locations(start: int, stop: int, num_locations: int) ndarray

Locations based on uniform sampling.

Parameters:
  • start – Start index.

  • stop – Stop index.

  • num_locations – The number of locations to generate.

Returns:

Location indices for one axis.

will.detect module

Pulse analysis routine

class will.detect.ExtractPulses(dynamic_spectra: ndarray, bandpass_labels: ndarray, times: ndarray, centering_means: ndarray)

Bases: object

Results of extracting single pulses.

Parameters:
  • dynamic_spectra – Pulse dynamic spectra.

  • bandpass_labels – Frequency labels.

  • times – Time labels.

  • centering_means – The means used to center the pulses.

bandpass_labels: ndarray
centering_means: ndarray
dynamic_spectra: ndarray
times: ndarray
class will.detect.MaxPulse(location: Union[int64, float], snr: Union[float64, float])

Bases: object

Max pulse location

Parameters:
  • location – Sample location of max pulse

  • snr – Signal to noise ratio

If None, no pulse fitting requirements found.

location: Union[int64, float]
snr: Union[float64, float]
class will.detect.PulseInfo(locations: Union[int64, float, ndarray], snrs: float, std: float64)

Bases: object

Pulse info result.

Parameters:
  • locations – sample location of the pulses

  • snrs – Signal to noise of pulses

  • std – Standard deviation of time series

locations: Union[int64, float, ndarray]
snrs: float
std: float64
class will.detect.PulseSNRs(snrs: ndarray, stds: ndarray, folded: ndarray, pulse_search_params: PulseSearchParamters, pulse_locations: ndarray)

Bases: object

Results of pulse search

Parameters:
  • snrs – Pulse Signal to Noise Ratio.

  • stds – Standard Deviations of pulse block Computed via Median Abs Deviation.

folded: Folded dynamic spectra.

folded: ndarray
property folded_properties: PulseInfo

Get the pulse properties of the folded profile.

Returns:

Info about pulse.

property percent_with_pulses: float

The percent of pulse bins with a single above snr present.

Returns:

Percent of windows with pulses above cutoff.

plot_folded_dynamic(median_filter_length: int = 29) None

Plot the folded dynamic spectra.

Parameters:

median_filter_length – The length of the median filter used to remove the bandpass (Optional).

Returns:

None.

plot_folded_profile() None

Plot the folded pulse profile and print the Signal to Noise.

Returns:

None.

plot_snrs(cut_snrs: bool = False, title: Union[None, str] = None) None

Plot Signal to Noise Ratios as a function of time.

Parameters:
  • cut_snrs – Don’t plot SNRs below the cutoff specified in PulseSearchParamters (Optional).

  • title – The title of the plot, default SNR vs. Time (Optional)

Returns:

None.

plot_stds(title: Union[None, str] = None) None

Plot Standard Deviation (As calculated via Median Absolute Deviation) as a function of time.

Parameters:

title – The tile of the plot, default Standard Deviation vs. Time (Optional).

Returns:

None.

pulse_locations: ndarray
pulse_search_params: PulseSearchParamters
snrs: ndarray
stds: ndarray
class will.detect.PulseSearchParamters(file: str, first_pulse: int, period: int, dm: float, box_car_length: int, samples_around_pulse: int, search_window_frac: float = 0.5, sigma: float = 6, start: int = 0, stop: int = - 1)

Bases: object

The parameters to use for the single pulse search.

file: Fits for Fil containing the pulse.

first_pulse: Location of the first pulse (in seconds).

period: Period of the pulse (in seconds).

dm: Dispersion Measure of the pulse (pc/cm^3).

box_car_length: Length of the boxcar for the matched filter.

samples_around_pulse: The number of samples on either side of

of the boxcar.

search_window_frac: The fraction, around the center, of the time

series search for a pulse (Optional).

sigma: Pulse threshold (Optional).

start: Start sample to process (default to first sample) (Optional).

stop: Final sample to process (default is EOF) (Optional).

box_car_length: int
dm: float
file: str
first_pulse: int
period: int
samples_around_pulse: int
search_window_frac: float = 0.5
sigma: float = 6
start: int = 0
stop: int = -1
will.detect.dedisped_time_series(dynamic_spectra: ndarray, dm: float, tsamp: float, chan_freqs: ndarray) ndarray

Get the dedispered time series from a chunk of dynamic spectra.

Parameters:
  • dynamic_spectra – 2D spectra with time on the vertical axis.

  • dm – The Dispersion Measure.

  • tsamp – Time sample of the data.

  • chan_freqs – The channel frequencies.

Returns:

Time series at a the given DM.

will.detect.detect_all_pulses(time_series: ndarray, box_car_length: int, sigma: float = 6, smoothing_factor: int = 4) PulseInfo

Detect pulses in a dedisperesed series.

Parameters:
  • time_series – The dedispersed time series.

  • box_car_length – Length of the boxcar.

  • sigma – Return pulses with significance above this value (Optional).

  • smoothing_factor – Median filter is smoothing_factor*box_car_length (Optional).

Returns:

PulseInfo[Locations, SNRs]

Deterned the time series by subtracting off the running median Thesis described in Barsdell Thesis, but Heimdall uses a different method

Don’t scale SNR as described in https://arxiv.org/pdf/2011.10191.pdf because we want the actual SNR of the time series.

will.detect.detect_max_pulse(time_series: ndarray, box_car_length: int, smoothing_factor: int = 4, search_window_frac: float = 0.5) PulseInfo

Detect the largest pulse in a dedisperesed series. reports back the location, pulse SNR and time series standard deviation as computed by Median Absolute Deviation.

Parameters:
  • time_series – The dedispersed time series.

  • box_car_length – Length of the boxcar

  • smoothing_factor – Median filter is smoothing_factor*box_car_length (Optional).

Returns:

dataclass[Locations, SNRs]

Detrend the time series by subtracting off the running median Thesis described in Barsdell Thesis, but Heimdall uses a different method

Don’t scale SNR as described in https://arxiv.org/pdf/2011.10191.pdf because we want the actual SNR of the time series.

will.detect.extract_pulses(pulse_search_params: ~will.detect.PulseSearchParamters, pulse_locations: ~numpy.ndarray, sigma: float = 0, dtype: type = <class 'numpy.float32'>) ExtractPulses

Search a Fil or Fits file for pulses. :param pulse_search_params: dataclass with the pulse search paramters. :param pulse_locations: Array with the locations of the center of the pulse. :param sigma: Sigma of Gauss filter, if 0 no filter is applied

Returns:

Dataclass that has the pulse dynamic spectra,

bandpass labels, times, and means used to center

Return type:

ExtractPulses

will.detect.find_first_pulse(file: str, dm: float, start: int, gulp: int, box_car_length: int = 1) None

Help to find the index of the first pulse by plotting the dedispersed dynamic spectra and time series.

Parameters:
  • file – Path to the file to investigate.

  • dm – Dispersion measure of the pulsar.

  • start – Index of first sample to get from the file.

  • gulp – Number of samples to get from file.

  • box_car_length – If > 1, dynamic spectra and time series get convolved with a boxcar of this length (optional).

Returns:

None

will.detect.find_max_pulse(pulses: PulseInfo, start_idx: int = 0, end_idx: int = - 1) MaxPulse

Find the maximum pulse between two indices.

Parameters:
  • pulses – The dataclass from detected pulses.

  • start_idx – Start index of the the range (Optional).

  • end_idx – End index of range (Optional).

Returns:

dataclass(location index, SNR) if no pulse in range, returns (None, None).

will.detect.locations_of_pulses(pulse_search_params: PulseSearchParamters) ndarray

Make an array of pulse locations from the start location and period.

Parameters:

pulse_search_params – The dataclass that has the search parameters

Returns:

Location of the pulses in samples

will.detect.process_dynamic_spectra(dynamic_spectra: ndarray, sigma: float, dtype: type) ndarray

Process the dynamic spectra for PCA by subtracting off the bandpass, optionally running a Gaussain filter, and zero centering.

Parameters:
  • dynamic_spectra – dynamic spectra to process.

  • sigma – Sigma for Gaussian filter, if zero filter not applied.

  • dtype – data type of output file.

Returns:

Processed to dynamic spectra, mean used to center the data.

will.detect.search_file(pulse_search_params: PulseSearchParamters, pulse_locations: ndarray) PulseSNRs

Search a Fil or Fits file for pulses.

Parameters:
  • pulse_search_params – dataclass with the pulse search paramters.

  • pulse_locations – Array with the locations of the center of the pulse.

Returns:

Dataclass that has the pulse snrs, standard deviations, and

the folded profile.

Return type:

PulseSNRs

will.inject module

Pulse injection routines

will.inject.inject_constant_into_file(yr_input: Your, pulse: ndarray, start: float = 0, period: Optional[float] = None, gulp: int = 65536, out_fil: Optional[str] = None, clip_powers: bool = True) Optional[ndarray]

Inject a (the same) pulse(s) into a file.

Parameters:
  • yr_inputYour object for file to inject pulse.

  • pulse – 2D array that contains the pulse.

  • start – Start sample of the pulse.

  • period – Sample period of injected pulse (Optional).

  • out_fil – Out filterbank, if None, returns array (Optional).

  • clip_powers – Clip powers instead of wrap (Optional).

Returns:

None if out_fil, else dynamic spectra with injected pulse

will.inject.inject_distribution_into_file(yr_input: Your, pulse_obj: GaussPulse, pulse_counts: ndarray, start: float = 0, period: Optional[float] = None, gulp: int = 65536, out_fil: Optional[str] = None, clip_powers: bool = True) Optional[ndarray]

Inject a pulse(s) into a file. From a given distributution.

Parameters:
  • yr_inputYour object for file to inject pulse.

  • pulse_obj – Object that creates the pulses.

  • pulse_counts – The number of samples for each pulse.

  • start – Start sample of the pulse (Optional).

  • period – Sample period of injected pulse (Optional).

  • out_fil – Out filterbank, if None, returns array (Optional).

  • clip_powers – Clip powers instead of wrap (Optional).

Returns:

None if out_fil, else dynamic spectra with injected pulse

will.inject.num_pulses(period: float, nspectra: int, start: int = 0) int

Calculate the number of pulses needed for a chunk of data

Parameters:
  • period – Period of pulse.

  • nspectra – Number of spectra in chunk.

  • start – Start of first pulse (Optional).

Returns:

Number of pulses within a data chunk, including partial pulses.

Module contents