API Documentation

Main routines

class alpro.main.Survival(ModelType=None, implementation='numba', pol_matrix=False, xmin=3.5, xmax=10.0)

High-level class which interfaces with actual ALP calculation as well as cluster models to compute survival probability curves. This is the starting point for any calculation.

analytic_pga(energies)

wrapper to util.P_gamma_analytic that passes the arguments stored in the Survival class

default_plot(plot_kwargs={}, mode='conversion', theory=None, theory_kwargs={})

Make a basic plot of the survival probability against energy using most recent calculation stored in Survival class.

Parameters:
plot_kwargs dict

dictionary of kwargs to pass to plt.plot

mode str

where to plot “conversion” or “survival” probability

theory function

function to overlay on plot, e.g. s.analytic_pga

theory_kwargs dict

dictionary of kwargs to pass to plt.plot for theory overlay

Returns:
fig matplotlib.pyplot.figure

figure instance

init_model(lcorr=None)

Initialise the ALP model. Sets up an appropriate domain.

propagate(domain=None, energies=None, pol='both', pol_matrix=None)

Propagate an unpolarised beam through a domain and calculate conversion into axion-like particles

Parameters:
domain object

an alpro.models.FieldModel instance containing magnetic field components, individual cell sizes and densities. default is the domain stored in the class instance.

energies array-like

array of photon energies in electron volts. default is the array stored in the class instance.

pol string (optional)

which polarization state to consider. must be ‘x’, ‘y’ or ‘both’

pol_matrix bool or Nonetype

whether to use the polarization matrix pr just average the two polarization states. if ==None, then use the value stored in self.pol_matrix_bool Both produce the same results but using the polarization matrix could be used to future to predict polarization signatures.

Returns:
P array-like

conversion probability as a function of energy

Pradial array-like (2D)

conversion probability as a function of energy and distance (evaluated at cell centers)

propagate_fourier(domain=None, pol='both', mode='auto', N=100000, f_res=2000, pad_factor=40.0)

Propagate an unpolarised beam through a domain and calculate conversion into axion-like particles using the fourier formalism

Parameters:
domain object

an alpro.models.FieldModel instance containing magnetic field components, individual cell sizes and densities. default is the domain stored in the class instance.

pol string (optional)

which polarization state to consider. must be ‘x’, ‘y’ or ‘both’

mode string (optional)

How to decide which Fourier formalism to use. The default, “auto” is recommended, in which case the decision is made by comparing the plasma frequency and the mass. However, you can force a calculation in the massive or massless regime.

N int

How to decide which Fourier formalism to use. The default, “auto” is recommended, in which case the decision is made by comparing the plasma frequency and the mass. However, you can force a calculation in the massive or massless regime. Recommended value around 1e4 to 1e5.

f_res int

factor by which to resample the resolution of the grid compared to the original resolution. The domain is zero padded out to a factor (N/f_res) times the original size. Recommended value is around N/40.

Returns:
E array-like

Energy in eV

P array-like

conversion probability as a function of energy

set_churazov_density()

Manually override a density or B field function to the churazov profile

set_coherence_pl(n=1.2, xmin=3.5, xmax=10.0, r0=None)

setup a powerlaw distribution of coherence lengths / box sizes

set_coherence_r0(r0)

Set the scale length over which the coherence length varies with radius.

set_params(g=1e-22, mass=1e-13, invgev=False)

Set the ALP coupling constant and mass

Parameters:
g float

ALP coupling constant in units set by invgev boolean

mass float

ALP mass in eV

invgev bool

False = g is in eV^-1, True = g is in GeV^-1

setup_regular_model(B=None, L=None, ne=None, N=1, phi=0.0)

set up a regular field model

Model setup

class alpro.models.ClusterProfile(model='a', plasma_beta=100, B_rms=None, n=None)

container for a magnetic field and density profile for a cluster

B_modA(r)

Model A from Reynolds et al. 2020

Parameters:
r float

distance from cluster centre in kpc

B_modB(r, B25=7.5e-06)

Model B from Reynolds et al. 2020

Parameters:
r float

distance from cluster centre in kpc

BendingPL_B(r)

bending power law density.

Bflat()

uniform magentic field

beta_density(r)

beta law density.

nflat()

uniform density

pl_density(r)

power law density.

profile(r)

wrapper to the density and magentic field functions

alpro.models.churazov_density(r)

Density function from churazov et al 2003 Given as equation (2) of Reynolds et al. 2020

Parameters:
r float

distance from cluster centre in kpc

alpro.models.omega_p(ne)

calculate the plasma frequency in natural (eV) units from an electron density

Parameters:
ne float/array-like

electron density in cm^-3

alpro.models.random_angle(size=None)

compute theta and phi coordinates for a random isotropic angle

class alpro.models.units

class containing some units. Should probably use astropy units but I find them a bit annoying.

Fourier scheme

alpro.fourier.get_phi_numerical(s)

Calculate phi numerically from an alpro.Survival class instance using Simpsons integration. Used in the massless ALP Fourier formalism

Parameters:
s alpro.Survival

survival class instance to use for calculation

Returns:
phi array-like

phi coordinate

alpro.fourier.pga_massive(s, Nsamples=200000, f_res=4, pol='both', return_autocorr=False)

calculate the conversion probability

Parameters:
s alpro.Survival

survival class instance to use for calculation

Nsamples int

number of Fourier samples

f_res int

resolution factor

pol string

Returns:
E array-like

energies as obtained from Fourier samples

P array-like

conversion probability

r_to_return array-like

resampled points at which autocorrelation function is evaluated (only returned if return_autocorr==True)

corr array-like

autocorrelation function of magnetic field (only returned if return_autocorr==True)

alpro.fourier.pga_massless(s, Nsamples=200000, f_res=4, pol='both')

calculate the conversion probability using the massless Fourier formalism

Parameters:
s alpro.Survival

survival class instance to use for calculation

Nsamples int

number of Fourier samples

f_res int

resolution factor

pol string

which polarization state to consider. must be ‘x’, ‘y’ or ‘both’

Returns:
E array-like

energies as obtained from Fourier samples

P array-like

conversion probability

alpro.fourier.physical_from_numerics(s, Nsamples=100000, pad_factor=10.0, pol='both')

Calculate a new grid for phi, numerically, and inerpolate the plasma frequency and magnetic field components on to this grid

calculate the conversion probability using the massless Fourier formalism

Parameters:
s alpro.Survival

survival class instance to use for calculation

Nsamples int

number of Fourier samples

pad_factor int

factor by which to pad out solution with zeros

pol string

which polarization state to consider. must be ‘x’, ‘y’ or ‘both’

Returns:
E array-like

energies as obtained from Fourier samples

P array-like

conversion probability

alpro.fourier_core.autocorr(x)

get the (unitless) autocorrelation function of the array “x”

alpro.fourier_core.get_autocorr(dx, y)

get the autocorrelation function in the right units for a spacing dx

alpro.fourier_core.get_pga_autocorr(x, g, B, omegap=None, mass=None, mode='massive', return_autocorr=False, transform_type=1, coord_units='kpc')

Calculate a conversion probability using the cosine and sine transforms

Parameters:
x array-like

the coordinate for the calculation - either physical space or phi

g float

coupling constant in eV^-1

B array-like

magnetic field in Gauss

omegap array-like

plasma frequency in eV

mode string

whether to use massive ALPs or massless ALPs formalism

return_autocorr bool

whether to return the autocorrelation function

Returns:
E array-like

energies in eV

P array-like

conversion probability at these energies

kfreq array-like

conjugate variable - either lambda or eta depending on mode

c_f array-like

autocorrelation function

alpro.fourier_core.get_pga_transforms(x, g, B, omegap=None, mass=None, mode='massive', transform_type=1, coord_units='kpc', return_transforms=True)

Calculate a conversion probability using the autocorrelation function

Parameters:
x array-like

the coordinate for the calculation - either physical space or phi

g float

coupling constant in eV^-1

B array-like

magnetic field in Gauss

omegap array-like

plasma frequency in eV

mode string

whether to use massive ALPs or massless ALPs formalism

return_autocorr bool

whether to return the autocorrelation function

Returns:
E array-like

energies in eV

P array-like

conversion probability at these energies

kfreq array-like

conjugate variable - either lambda or eta depending on mode

c_f array-like

autocorrelation function

alpro.fourier_core.get_transforms(x, g, B, omegap=None, mass=None, mode='massive', transform_type=1, coord_units='kpc')

calculate the cosine and sine transforms of B

Parameters:
x array-like

the coordinate for the calculation - either physical space or phi

g float

coupling constant in eV^-1

B array-like

magnetic field in Gauss

mass float or Nonetype

ALP mass in eV

mode str

massive or massless

Returns:
kfreq array-like

Fourier samples of eta or lambda (conjugate variable depends on regime)

dsx array-like

the discrete sine transform

dcx array-like

the discrete cosine transform

Utilities

alpro.util.Losc(energy, B, ne, mass, g_a)

calculate the ALP oscillation length in cm

alpro.util.P_gamma_analytic(energy, B, ne, mass, g_a, L)

L should be in kpc! ne, B in CGS everything else in eV or 1/eV

alpro.util.delta_eff(energy, ne, mass)

Calculate delta_eff for an electron density in CGS, a mass in eV and a photon energy in eV \(\Delta_{\rm eff} = (m_A^2 - \omega_p^2)/(4 \omega)\)

class alpro.util.my_powerlaw(n=1.2, xmin=3.5, xmax=10.0)

container for generating random numbers from a powerlaw with slope < 1. For a power of form x**-n, with b>1, from xmin to xmax, the resulting CDF can be shown to take the analytic form

\(CDF(x) = (x_{\rm min}^\alpha - x^\alpha) / (x_{\rm min}^\alpha - x_{\rm max}^\alpha)\)

where \(\alpha = 1-n\). Thus, if z is a random number in range (0,1), then a random variable rv can be found by inverting this expression, i.e. rv = [z * (b^alpha - a^alpha) + a^alpha] ^ (1/alpha).

This is embedded in a class so an individual function can be passed without additional arguments, the function rvs() generates the actual random numbers similarly to scipy.stats distribution syntax.

rvs(size=None)

generate (size) random variables. if size is None, generate a single float.

alpro.util.theta(energy, B, ne, mass, g_a)

Calculate capital Theta for a B field in Gauss, a mass in eV and a photon energy in eV \(\Theta = \frac{2 B_\perp \omega g_a}{m_A^2 - \omega_p^2}\).