Source code for ForMoSA.transform.photometric_effects
from ForMoSA.core.errors import ForMoSAError
import ForMoSA.utils.logL_functions as logL_functions
from ForMoSA.observation.observation_base import Observation
from ForMoSA.transform.observed import ObservedModel, ObservedParameters
from ForMoSA.core.enums import ParameterKind, ObservationType, LogLikelihoodType
from ForMoSA.transform.apply_effects import ApplyPhysicsEffects, ApplyObservationEffects
[docs]
class PhotometricEffects:
'''
Physical effects applied to a photometric model.
Notes
-----
Authors: Allan Denis
'''
@staticmethod
def _apply_physics(observed_model: ObservedModel, observed_params: ObservedParameters) -> ObservedModel:
'''
Apply the physics effects relevant to photometry.
Parameters
----------
observed_model : ObservedModel
Instance of class ObservedModel
params : ObservedParameters
Instance of class ObservedParameters
Returns
-------
(ObservedModel): Instance of class ObservedModel transformed by the physics effects
Notes
-----
Authors: Allan Denis
'''
# ======================
# Initial checkins
# ======================
# Instance of observed_model
if not isinstance(observed_model, ObservedModel):
raise ForMoSAError(f' Wrong type for observed_model: {type(observed_model)}. Expected an ObservedModel')
# Instance of observed_params
if not isinstance(observed_params, ObservedParameters):
raise ForMoSAError(f' Wrong type for observed_params: {type(observed_params)}. Expected an ObservedParameters')
values_by_kind = observed_params.values_by_kind
# ======================
# Reddening
# ======================
if ParameterKind.AV in values_by_kind:
observed_model = ApplyPhysicsEffects._apply_reddening(observed_model, values_by_kind[ParameterKind.AV])
# ======================
# CPD
# ======================
if ParameterKind.BB_T in values_by_kind:
if ParameterKind.BB_R not in values_by_kind:
raise ForMoSAError(' Black Body radius is required when a Black Body temperature is given')
if ParameterKind.DISTANCE not in values_by_kind:
raise ForMoSAError(' Distance is required to add a CPD contribution')
observed_model = ApplyPhysicsEffects._apply_cpd(observed_model, values_by_kind[ParameterKind.BB_T], values_by_kind[ParameterKind.BB_R], values_by_kind[ParameterKind.DISTANCE],)
# ======================
# Scaling (R, D, alpha)
# ======================
if ParameterKind.DISTANCE in values_by_kind and ParameterKind.RADIUS in values_by_kind:
observed_model = ApplyPhysicsEffects._apply_scaling(observed_model, values_by_kind.get(ParameterKind.RADIUS), values_by_kind.get(ParameterKind.DISTANCE))
alpha = values_by_kind.get(ParameterKind.ALPHA, 1.0)
observed_model.flux *= alpha
return observed_model
@staticmethod
def _apply_observation(observed_model: ObservedModel, obs: Observation, bounds: tuple[float, float] = (-float('inf'), float('inf'))) -> ObservedModel:
'''
For photometry, no observation effect is relevant to photometry, so this method does not implement anything.
Parameters
----------
observed_model : ObservedModel
Instance of class ObservedModel
obs : Observation
Instance of class Observation
bounds : tuple[float, float]
Bounds for the least squares
Returns
-------
ObservedModel
Instance of class ObservedModel transformed by the observational effects
Notes
-----
Authors: Allan Denis
'''
# ======================
# Initial checkins
# ======================
# Instance of observed_model
if not isinstance(observed_model, ObservedModel):
raise ForMoSAError(f' Wrong type for observed_model: {type(observed_model)}. Expected a ObservedModel')
# Instance of observation
if not isinstance(obs, Observation):
raise ForMoSAError(f' Wrong obs type: {type(obs)}. Expected an Observation')
# ObsType
if obs.ObsType != ObservationType.PHOTOMETRIC.value:
raise ForMoSAError(f' Wrong observation type: {obs.ObsType}. Expected {ObservationType.PHOTOMETRIC.value}')
# ======================
# Scaling
# ======================
if observed_model.scaling == 'analytic':
observed_model = ApplyObservationEffects._apply_scaling(observed_model, obs, bounds=bounds)
return observed_model
@staticmethod
def _compute_loglike(observed_model: ObservedModel, obs: Observation, logL_type: LogLikelihoodType = LogLikelihoodType.CHI2) -> float:
'''
Compute the loglikelihood given a transformed model, an observation and a loglikelihood function
Parameters
----------
observed_model : ObservedModel
Instance of class ObservedModel
obs : Observation
Observation
logL_type : LogLikelihoodType
Loglikelihood function
Returns
-------
float
logL value
Notes
-----
Authors: Simon Petrus, Matthieu Ravet and Allan Denis
'''
# ======================
# Initial checks
# ======================
if not isinstance(observed_model, ObservedModel):
raise ForMoSAError(f' Wrong type for model: {type(observed_model)}. Require an ObservedModel')
if not isinstance(obs, Observation):
raise ForMoSAError(f' Wrong type for observation: {type(obs)}. Require an Observation')
if obs.ObsType is not ObservationType.PHOTOMETRIC.obstype:
raise ForMoSAError(f' Wrong Observation type: {obs.ObsType}. Use a photometric observation')
if len(observed_model.flux) != len(obs.flux):
raise ForMoSAError(f' Wrong length for model: {len(observed_model.flux)}. Expected the same length as the observations: {len(obs.flux)}')
# ======================
# Compute loglikelihood
# ======================
residuals = observed_model.residuals(obs.flux)
return logL_functions.logL_chi2(residuals, obs.err)