import torch
from ...param import forward
from ...backend_obj import ArrayLike
from ...utils.decorators import ignore_numpy_warnings
from .._shared_methods import parametric_initialize, parametric_segment_initialize
from ...utils.parametric_profiles import nuker_np
from .. import func
def _x0_func(model_params, R, F):
return R[4], 10 ** F[4], 1.0, 2.0, 0.5
[docs]
class NukerMixin:
"""Nuker radial light profile (Lauer et al. 1995).
This is a classic profile used widely in galaxy modelling. The functional
form of the Nuker profile is defined as:
.. math::
I(R) = I_b2^{\\frac{\\beta - \\gamma}{\\alpha}}\\left(\\frac{R}{R_b}\\right)^{-\\gamma}\\left[1 + \\left(\\frac{R}{R_b}\\right)^{\\alpha}\\right]^{\\frac{\\gamma-\\beta}{\\alpha}}
It is effectively a double power law profile. :math:`\\gamma` gives the inner
slope, :math:`\\beta` gives the outer slope, :math:`\\alpha` is somewhat degenerate with
the other slopes.
:param Rb: scale length radius
:param Ib: intensity at the scale length
:param alpha: sharpness of transition between power law slopes
:param beta: outer power law slope
:param gamma: inner power law slope
"""
_model_type = "nuker"
_parameter_specs = {
"Rb": {
"units": "arcsec",
"valid": (0, None),
"shape": (),
"dynamic": True,
"description": "scale length radius",
},
"Ib": {
"units": "flux/arcsec^2",
"valid": (0, None),
"shape": (),
"dynamic": True,
"description": "intensity at the scale length",
},
"alpha": {
"units": "none",
"valid": (0, None),
"shape": (),
"dynamic": True,
"description": "sharpness of transition between power law slopes",
},
"beta": {
"units": "none",
"valid": (0, None),
"shape": (),
"dynamic": True,
"description": "outer power law slope",
},
"gamma": {
"units": "none",
"shape": (),
"dynamic": True,
"description": "inner power law slope",
},
}
[docs]
@torch.no_grad()
@ignore_numpy_warnings
def initialize(self):
super().initialize()
parametric_initialize(
self,
self.target[self.window],
nuker_np,
("Rb", "Ib", "alpha", "beta", "gamma"),
_x0_func,
)
[docs]
@forward
def radial_model(
self,
R: ArrayLike,
Rb: ArrayLike,
Ib: ArrayLike,
alpha: ArrayLike,
beta: ArrayLike,
gamma: ArrayLike,
) -> ArrayLike:
return func.nuker(R, Rb, Ib, alpha, beta, gamma)
[docs]
class iNukerMixin:
"""Nuker radial light profile (Lauer et al. 1995).
This is a classic profile used widely in galaxy modelling. The functional
form of the Nuker profile is defined as:
.. math::
I(R) = I_b2^{\\frac{\\beta - \\gamma}{\\alpha}}\\left(\\frac{R}{R_b}\\right)^{-\\gamma}\\left[1 + \\left(\\frac{R}{R_b}\\right)^{\\alpha}\\right]^{\\frac{\\gamma-\\beta}{\\alpha}}
It is effectively a double power law profile. :math:`\\gamma` gives the inner
slope, :math:`\\beta` gives the outer slope, :math:`\\alpha` is somewhat degenerate with
the other slopes.
``Rb``, ``Ib``, ``alpha``, ``beta``, and ``gamma`` are batched by their first
dimension, allowing for multiple Nuker profiles to be defined at once.
:param Rb: scale length radius
:param Ib: intensity at the scale length
:param alpha: sharpness of transition between power law slopes
:param beta: outer power law slope
:param gamma: inner power law slope
"""
_model_type = "nuker"
_parameter_specs = {
"Rb": {
"units": "arcsec",
"valid": (0, None),
"shape": (None,),
"dynamic": True,
"description": "scale length radius",
},
"Ib": {
"units": "flux/arcsec^2",
"valid": (0, None),
"shape": (None,),
"dynamic": True,
"description": "intensity at the scale length",
},
"alpha": {
"units": "none",
"valid": (0, None),
"shape": (None,),
"dynamic": True,
"description": "sharpness of transition between power law slopes",
},
"beta": {
"units": "none",
"valid": (0, None),
"shape": (None,),
"dynamic": True,
"description": "outer power law slope",
},
"gamma": {
"units": "none",
"shape": (None,),
"dynamic": True,
"description": "inner power law slope",
},
}
[docs]
@torch.no_grad()
@ignore_numpy_warnings
def initialize(self):
super().initialize()
parametric_segment_initialize(
model=self,
target=self.target[self.window],
prof_func=nuker_np,
params=("Rb", "Ib", "alpha", "beta", "gamma"),
x0_func=_x0_func,
segments=self.segments,
)
[docs]
@forward
def iradial_model(
self,
i: int,
R: ArrayLike,
Rb: ArrayLike,
Ib: ArrayLike,
alpha: ArrayLike,
beta: ArrayLike,
gamma: ArrayLike,
) -> ArrayLike:
return func.nuker(R, Rb[i], Ib[i], alpha[i], beta[i], gamma[i])
[docs]
class NukerPSFMixin:
"""Nuker radial light profile (Lauer et al. 1995).
This is a classic profile used widely in galaxy modelling. The functional
form of the Nuker profile is defined as:
.. math::
I(R) = I_b2^{\\frac{\\beta - \\gamma}{\\alpha}}\\left(\\frac{R}{R_b}\\right)^{-\\gamma}\\left[1 + \\left(\\frac{R}{R_b}\\right)^{\\alpha}\\right]^{\\frac{\\gamma-\\beta}{\\alpha}}
It is effectively a double power law profile. :math:`\\gamma` gives the inner
slope, :math:`\\beta` gives the outer slope, :math:`\\alpha` is somewhat degenerate with
the other slopes.
:param Rb: scale length radius [pix]
:param Ib: intensity at the scale length [flux/pix^2]
:param alpha: sharpness of transition between power law slopes
:param beta: outer power law slope
:param gamma: inner power law slope
"""
_model_type = "nuker"
_parameter_specs = {
"Rb": {
"units": "pix",
"valid": (0, None),
"shape": (),
"dynamic": True,
"description": "scale length radius [pix]",
},
"Ib": {
"units": "flux/pix^2",
"valid": (0, None),
"shape": (),
"dynamic": False,
"value": 1.0,
"description": "intensity at the scale length [flux/pix^2]",
},
"alpha": {
"units": "none",
"valid": (0, None),
"shape": (),
"dynamic": True,
"description": "sharpness of transition between power law slopes",
},
"beta": {
"units": "none",
"valid": (0, None),
"shape": (),
"dynamic": True,
"description": "outer power law slope",
},
"gamma": {
"units": "none",
"shape": (),
"dynamic": True,
"description": "inner power law slope",
},
}
[docs]
@torch.no_grad()
@ignore_numpy_warnings
def initialize(self):
super().initialize()
parametric_initialize(
self,
self.target[self.window],
nuker_np,
("Rb", "Ib", "alpha", "beta", "gamma"),
_x0_func,
)
[docs]
@forward
def radial_model(
self,
R: ArrayLike,
Rb: ArrayLike,
Ib: ArrayLike,
alpha: ArrayLike,
beta: ArrayLike,
gamma: ArrayLike,
) -> ArrayLike:
return func.nuker(R, Rb, Ib, alpha, beta, gamma)