XSPEC models
SpectralFitting can vendor the XSPEC model library through the utility package XSPECModels.jl. You can install this package directly from the University of Bristol's AstroRegistry:
pkg> registry add https://github.com/astro-group-bristol/AstroRegistry
pkg> add XSPECModels
Using the package is straight forward once installed:
using SpectralFitting, XSPECModels
The convention is that models that have are imported from XSPEC or have XSPEC ABI are prefixed with XS_
in their name. For example, the XSPEC equivalent of PowerLaw
is XS_PowerLaw
.
The XSPEC models are wrapped into SpectralFitting models using the [@xspecmodel
] macro. If a model you require is not already wrapped, this macro will make that easy to do. Please consider upstreaming your wrapper via a PR to the SpectralFitting GitHub repository.
XSPECModels.@xspecmodel
— Macro@xspecmodel [type=Float64] [ff_call_site] model
Used to wrap additional XSPEC models, generating the needed AbstractSpectralModel
implementation.
The type
keyword specifies the underlying type to coerce input and output arrays to, as different implementations may have incompatible number of bits. The ff_call_site
is the foreign fuction call site, which is the first argument to ccall
, and follows the same conventions. The model
is a struct, which must subtype AbstractSpectralModel
.
If the callsite is not specified, the user must implement _unsafe_ffi_invoke!
.
Examples
@xspecmodel :C_powerlaw struct XS_PowerLaw{T} <: AbstractSpectralModel{T, Additive}
"Normalisation."
K::T
"Photon index."
a::T
end
# constructor has default values
function XS_PowerLaw(; K = FitParam(1.0), a = FitParam(1.0))
XS_PowerLaw{typeof(K)}(K, a)
end
We define a new structure XS_PowerLaw
with two parameters, but since the model is Additive
, only a single parameter (a
) is passed to the XSPEC function. The function we bind to this model is :C_powerlaw
from the XSPEC C wrappers.
The macro will then generate the following functions
If a callsite was specified, it will also generate:
XSPEC models frequently have tabular data dependencies, without which the models fail to invoke (see Model data availability). If the data files are known but not present, the XSPEC models will throw an error with instructions for downloading the missing data. If the data files are unknown, Julia may crash catastrophically. If this is the case, often a single line will be printed with the LibXSPEC error, specifying the name of the missing source file. This can be registered as a data dependency of a model using SpectralFitting.register_model_data
.
The first time any XSPEC model is invoked, SpectralFitting checks to see whether requisite data is needed, and whether the data is downloaded. Subsequent calls will hit a lookup cache instead to avoid run-time costs of performing this check.
Additive
XSPECModels.XS_PowerLaw
— TypeXS_PowerLaw(K, a)
K
: Normalisation.a
: Photon index.
Example
energy = collect(range(0.1, 20.0, 100))
invokemodel(energy, XS_PowerLaw())
XS_PowerLaw
┌────────────────────────────────────────┐
0.5 │ │
│: │
│: │
│: │
│: │
│: │
│: │
│ : │
│ : │
│ : │
│ :. │
│ ':.. │
│ ''':...... │
│ ''''''''''''''........│
0 │ │
└────────────────────────────────────────┘
0 20
E (keV)
XSPECModels.XS_BlackBody
— TypeXS_BlackBody(K, T)
K
: Normalisation.T
: Temperature (keV).
Example
energy = collect(range(0.1, 20.0, 100))
invokemodel(energy, XS_BlackBody())
XS_BlackBody
┌────────────────────────────────────────┐
0.2 │ │
│ │
│ │
│ │
│ │
│ │
│ .:''':.. │
│ .: ''. │
│ .' ':. │
│ : ''.. │
│ : ':. │
│ : '':. │
│.: ''.. │
│: '':.... │
0 │' '''│
└────────────────────────────────────────┘
0 20
E (keV)
XSPECModels.XS_BremsStrahlung
— TypeXS_BremsStrahlung(K, T)
K
: Normalisation.T
: Plasma temperature (keV).
Example
energy = collect(range(0.1, 20.0, 100))
invokemodel(energy, XS_BremsStrahlung())
XS_BremsStrahlung
┌────────────────────────────────────────┐
2 │ │
│. │
│: │
│: │
│: │
│: │
│: │
│: │
│: │
│: │
│: │
│: │
│'. │
│ : │
0 │ ':....................................│
└────────────────────────────────────────┘
0 20
E (keV)
XSPECModels.XS_Gaussian
— TypeXS_Gaussian(K, E, σ)
K
: NormalisationE
: Line wavelength in Angstrom.σ
: Line width in Angstrom.
Example
energy = collect(range(4.0, 8.0, 100))
invokemodel(energy, XS_Gaussian())
XS_Gaussian
┌────────────────────────────────────────┐
0.09 │ │
│ . │
│ : : │
│ : : │
│ : '. │
│ .' : │
│ : : │
│ : : │
│ : '. │
│ : : │
│ : : │
│ : : │
│ .' : │
│ : : │
0 │.......: :......................│
└────────────────────────────────────────┘
0 20
E (keV)
XSPECModels.XS_Laor
— TypeXS_Laor(K, lineE, a, inner_r, outer_r, incl)
K
: Normalisation.lineE
: Rest frame line energy (keV).a
: Power law dependence of emissitivy. Scales R⁻ᵅ.inner_r
: Inner radius of the accretion disk (GM/c).outer_r
: Outer radius of the accretion disk (GM/c).θ
: Disk inclination angle to line of sight (degrees, 0 is pole on).
Example
energy = collect(range(0.1, 10.0, 100))
invokemodel(energy, XS_Laor())
XS_Laor
┌────────────────────────────────────────┐
0.06 │ │
│ │
│ :: │
│ :: │
│ : : │
│ : : │
│ : : │
│ :' : │
│ .: : │
│ :' : │
│ .' : │
│ .:' : │
│ ..' : │
│ .:' : │
0 │.......:'' :............│
└────────────────────────────────────────┘
0 10
E (keV)
XSPECModels.XS_DiskLine
— TypeXS_DiskLine(K, lineE, β, inner_r, outer_r, incl)
K
: Normalisation.lineE
: Rest frame line energy (keV).β
: Power law dependence of emissitivy. If < 10, scales Rᵅ.inner_r
: Inner radius of the accretion disk (GM/c).outer_r
: Outer radius of the accretion disk (GM/c).θ
: Disk inclination angle to line of sight (degrees, 0 is pole on).
Example
energy = collect(range(4.0, 8.0, 100))
invokemodel(energy, XS_DiskLine())
XS_DiskLine
┌────────────────────────────────────────┐
0.09 │ │
│ . │
│ : │
│ :: │
│ . :: │
│ : :: │
│ :'': │
│ .' : │
│ : : │
│ : : │
│ .' : │
│ : : │
│ .: '. │
│ .:' : │
0 │...............:''' :.........│
└────────────────────────────────────────┘
4 8
E (keV)
XSPECModels.XS_PhotoelectricAbsorption
— TypeXS_PhotoelectricAbsorption(ηH)
ηH
: Equivalent hydrogen column (units of 10²² atoms per cm⁻²).
Example
energy = collect(range(0.1, 20.0, 100))
invokemodel(energy, XS_PhotoelectricAbsorption())
XS_PhotoelectricAbsorption
┌────────────────────────────────────────┐
1 │ ...''''''''''''''''''''''''''''''│
│ .' │
│ : │
│ :' │
│ : │
│ : │
│ : │
│ : │
│ : │
│ : │
│ : │
│ : │
│ : │
│ : │
0 │.: │
└────────────────────────────────────────┘
0 20
E (keV)
XSPECModels.XS_WarmAbsorption
— TypeXS_WarmAbsorption(ηH, Ew)
ηH
: Equivalent hydrogen column (units of 10²² atoms per cm⁻²).Ew
: Window energy (keV).
Example
energy = collect(range(0.1, 20.0, 100))
invokemodel(energy, XS_WarmAbsorption())
XS_WarmAbsorption
┌────────────────────────────────────────┐
1 │': ...''':'''''''''''''''''''''''''│
│ : .:' │
│ : .' │
│ : .: │
│ : : │
│ : : │
│ : : │
│ : : │
│ : : │
│ : : │
│ :: │
│ :: │
│ : │
│ : │
0.2 │ : │
└────────────────────────────────────────┘
0 20
E (keV)
XSPECModels.XS_CalculateFlux
— TypeXS_CalculateFlux(E_min, E_max, lg10Flux)
E_min
: Minimum energy.E_max
: Maximum energy.log10Flux
: log (base 10) flux in erg / cm^2 / s
XSPECModels.XS_KerrDisk
— TypeXS_KerrDisk(K, lineE, index1, index2, break_r, a, θ, inner_r, outer_r)
K
: Normalisation.lineE
: Rest frame line energy (keV).index1
: Emissivity index for inner disk.index2
: Emissivity index for outer disk.break_r
: Break radius seperating inner and outer disk (gᵣ).a
: Dimensionless black hole spin.θ
: Disk inclination angle to line of sight (degrees).inner_r
: Inner radius of the disk in units of rₘₛ.outer_r
: Outer radius of the disk in units of rₘₛ.z
: Redshift.
Example
energy = collect(range(0.1, 20.0, 100))
invokemodel(energy, XS_KerrDisk())
XS_KerrDisk
┌────────────────────────────────────────┐
0.05 │ │
│ │
│ . │
│ .: │
│ ::: │
│ .:' '. │
│ .: : │
│ ..' : │
│ :' : │
│ .' : │
│ .:' : │
│ .:'' : │
│ .::' : │
│ ..:' : │
0 │.........:''' :......│
└────────────────────────────────────────┘
0 8
E (keV)
XSPECModels.XS_KyrLine
— TypeXS_KyrLine(K, a, θ_obs, inner_r, ms_flag, outer_r, lineE, α, β, break_r, z, limb)
K
: Normalisation.a
: Dimensionless black hole spin.θ
: Observer inclination (0 is on pole, degrees).inner_r
: Inner radius of the disk in units of GM/c²ms_flag
: 0: integrate from rᵢₙ. 1: integrate from rₘₛ.outer_r
: Outer radius of the disk in units of GM/c²lineE
: Rest frame line energy (keV).α
β
break_r
: Break radius seperating inner and outer disk (GM/c²).z
: Overall Doppler shift.limb
: 0: isotropic emission, 1: Laor's limb darkening, 2: Haard's limb brightening.
Example
energy = collect(range(0.1, 20.0, 100))
invokemodel(energy, XS_KyrLine())
XS_KyrLine
┌────────────────────────────────────────┐
0.05 │ │
│ │
│ : │
│ :. │
│ :.': │
│ :' : │
│ : : │
│ .' : │
│ .:' : │
│ .' : │
│ .: : │
│ .' : │
│ .:' : │
│ ..:' : │
0 │.........:''' :......│
└────────────────────────────────────────┘
0 8
E (keV)