Source code for rubin_sim.maf.metrics.dcr_metric
__all__ = ("DcrPrecisionMetric",)
import numpy as np
import rubin_scheduler.utils as utils
import rubin_sim.maf.utils as mafUtils
from .base_metric import BaseMetric
[docs]
class DcrPrecisionMetric(BaseMetric):
"""Determine how precise a DCR correction could be made
Parameters
----------
atm_err : `float`
Minimum error in photometry centroids introduced by the atmosphere
(arcseconds). Default 0.01.
"""
def __init__(
self,
metric_name="DCRprecision",
seeing_col="seeingFwhmGeom",
m5_col="fiveSigmaDepth",
ha_col="HA",
pa_col="paraAngle",
filter_col="filter",
atm_err=0.01,
sed_template="flat",
rmag=20.0,
**kwargs,
):
self.m5_col = m5_col
self.filter_col = filter_col
self.pa_col = pa_col
self.seeing_col = seeing_col
self.mags = {}
self.filters = ["u", "g", "r", "i", "z", "y"]
if sed_template == "flat":
for f in self.filters:
self.mags[f] = rmag
else:
self.mags = utils.stellarMags(sed_template, rmag=rmag)
cols = [
"ra_dcr_amp",
"dec_dcr_amp",
seeing_col,
m5_col,
filter_col,
"zenithDistance",
pa_col,
]
units = "arcseconds"
self.atm_err = atm_err
super(DcrPrecisionMetric, self).__init__(cols, metric_name=metric_name, units=units, **kwargs)
[docs]
def run(self, data_slice, slice_point=None):
snr = np.zeros(len(data_slice), dtype="float")
for filt in self.filters:
in_filt = np.where(data_slice[self.filter_col] == filt)
snr[in_filt] = mafUtils.m52snr(self.mags[filt], data_slice[self.m5_col][in_filt])
position_errors = np.sqrt(
mafUtils.astrom_precision(data_slice[self.seeing_col], snr) ** 2 + self.atm_err**2
)
x_coord = np.tan(np.radians(data_slice["zenithDistance"])) * np.sin(
np.radians(data_slice[self.pa_col])
)
x_coord2 = np.tan(np.radians(data_slice["zenithDistance"])) * np.cos(
np.radians(data_slice[self.pa_col])
)
# Things should be the same for RA and dec.
# Now I want to compute the error if I interpolate/extrapolate to +/-1.
# function is of form, y=ax. a=y/x. da = dy/x.
# Only strictly true if we know the unshifted position.
# But this should be a reasonable approx.
slope_uncerts = position_errors / x_coord
slope_uncerts2 = position_errors / x_coord2
total_slope_uncert = 1.0 / np.sqrt(np.sum(1.0 / slope_uncerts**2) + np.sum(1.0 / slope_uncerts2**2))
# So, this will be the uncertainty in the RA or Dec offset at
# x= +/- 1. A.K.A., the uncertainty in the slope
# of the line made by tan(zd)*sin(PA) vs RA offset
# or the line tan(zd)*cos(PA) vs Dec offset
# Assuming we know the unshfted position of the object
# (or there's little covariance if we are fitting for both)
result = total_slope_uncert
return result