Source code for sunkit_spex.models.scaling
import numpy as np
import astropy.units as u
from astropy.modeling import FittableModel, Parameter
from astropy.units import Quantity
__all__ = ["Constant", "InverseSquareFluxScaling"]
[docs]
class InverseSquareFluxScaling(FittableModel):
"""
InverseSqaureFluxScaling model converts luminosity output of physical models to a distance scaled flux.
Parameters
==========
energy_edges :
Energy edges associated with input spectrum
observer_distance:
Distance of the observer from the source.
Examples
========
.. plot::
:include-source:
import astropy.units as u
import numpy as np
import matplotlib.pyplot as plt
from sunkit_spex.models.scaling import InverseSquareFluxScaling
from sunkit_spex.models.models import StraightLineModel
y_units = u.ph*u.keV**-1*u.s**-1
x_units = u.keV
ph_energies = np.arange(4, 100, 0.5)*x_units
ph_energies_centers = ph_energies[:-1] + 0.5*np.diff(ph_energies)
sim_cont = {"slope": -2*y_units/x_units, "intercept": 100*y_units}
source = StraightLineModel(**sim_cont)
plt.figure()
for i, d in enumerate([0.25,0.5,1]):
distance = InverseSquareFluxScaling(observer_distance=d*u.AU)
observed = source * distance
plt.plot(ph_energies_centers , observed(ph_energies), label='D = '+str(d)+' AU')
plt.loglog()
plt.legend()
plt.show()
"""
name = "InverseSquareFluxScaling"
n_inputs = 1
n_outputs = 1
observer_distance = Parameter(
name="observer_distance",
default=1,
unit=u.AU,
description="Distance to the observer in AU",
fixed=True,
)
_input_units_allow_dimensionless = True
[docs]
def evaluate(self, x, observer_distance):
if isinstance(observer_distance, Quantity):
if observer_distance.unit.is_equivalent(u.AU):
observer_distance_cm = observer_distance.to(u.cm)
else:
raise ValueError("Observer distance input must be an Astropy length convertible to AU.")
else:
AU_distance_cm = (1 * u.AU).to_value(u.cm)
observer_distance_cm = observer_distance * AU_distance_cm
return 1 / (4 * np.pi * (observer_distance_cm**2))
@property
def return_units(self):
return {"y": u.cm**-2}
def _parameter_units_for_data_units(self, inputs_unit, outputs_unit):
return {"observer_distance": u.AU}
[docs]
class Constant(FittableModel):
"""
A model which returns an array with dimensions n-1 of the input dimension populated with a constant value,
of whichever units specified by the user.
Parameters
==========
energy_edges :
Energy edges associated with input spectrum
constant :
A constant value which populates the output array
Examples
========
.. plot::
:include-source:
import astropy.units as u
import numpy as np
import matplotlib.pyplot as plt
from sunkit_spex.models.scaling import Constant
from sunkit_spex.models.models import StraightLineModel
y_units = u.ph*u.keV**-1*u.s**-1
x_units = u.keV
ph_energies = np.arange(4, 100, 0.5)*x_units
ph_energies_centers = ph_energies[:-1] + 0.5*np.diff(ph_energies)
sim_cont = {"slope": -2*y_units/x_units, "intercept": 100*y_units}
source = StraightLineModel(**sim_cont)
plt.figure()
for i, c in enumerate([0.25,0.5,1,2,4]):
constant = Constant(constant=c)
observed = source * constant
plt.plot(ph_energies_centers , observed(ph_energies), label='Const = '+str(c))
plt.loglog()
plt.legend()
plt.show()
"""
n_inputs = 1
n_outputs = 1
constant = Parameter(
name="constant",
default=1,
description="Constant",
fixed=True,
)
_input_units_allow_dimensionless = True
name = "Constant"
def __init__(self, constant=u.Quantity(constant.default)):
super().__init__(constant=constant)
[docs]
def evaluate(self, x, constant):
return constant
@property
def return_units(self):
if isinstance(self.constant, Quantity):
return {"y": self.constant.unit}
return None
def _parameter_units_for_data_units(self, inputs_unit, outputs_unit):
return {"constant": outputs_unit["y"]}