Source code for lsst.validate.drp.calcsrd.amx

# LSST Data Management System
# Copyright 2016 AURA/LSST.
#
# This product includes software developed by the
# LSST Project (http://www.lsst.org/).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the LSST License Statement and
# the GNU General Public License along with this program.  If not,
# see <https://www.lsstcorp.org/LegalNotices/>.

from __future__ import print_function, absolute_import

import numpy as np

from ..base import MeasurementBase, Metric
from ..util import radiansToMilliarcsec, calcRmsDistances


[docs]class AMxMeasurement(MeasurementBase): """Measurement of AMx (x=1,2,3): The maximum rms of the astrometric distance distribution for stellar pairs with separations of D arcmin (repeatability). Parameters ---------- x : int Variant of AMx metric (x=1, 2, 3), which in turn sets the radius of the annulus for selecting pairs of stars. matchedDataset : lsst.validate.drp.matchreduce.MatchedMultiVisitDataset bandpass : str Bandpass (filter name) used in this measurement (e.g., `'r'`). specName : str Name of a specification level to measure against (e.g., design, minimum, stretch). width : float Width around fiducial distance to include. [arcmin] magRange : 2-element list or tuple brighter, fainter limits of the magnitude range to include. E.g., `magRange=[17.5, 21.0]` verbose : bool, optional Output additional information on the analysis steps. job : :class:`lsst.validate.drp.base.Job`, optional If provided, the measurement will register itself with the Job object. linkedBlobs : dict, optional A `dict` of additional blobs (subclasses of BlobBase) that can provide additional context to the measurement, though aren't direct dependencies of the computation (e.g., `matchedDataset). Attributes ---------- rmsDistMas : ndarray RMS of distance repeatability between stellar pairs. blob : AMxBlob Blob with by-products from this measurement. Raises ------ ValueError If `x` isn't in [1, 2, 3]. Notes ----- This table below is provided ``validate_drp``\ 's :file:`metrics.yaml`. LPM-17 dated 2011-07-06 Specification: The rms of the astrometric distance distribution for stellar pairs with separation of D arcmin (repeatability) will not exceed AMx milliarcsec (median distribution for a large number of sources). No more than AFx % of the sample will deviate by more than ADx milliarcsec from the median. AMx, AFx, and ADx are specified for D=5, 20 and 200 arcmin for x= 1, 2, and 3, in the same order (Table 18). The three selected characteristic distances reflect the size of an individual sensor, a raft, and the camera. The required median astrometric precision is driven by the desire to achieve a proper motion accuracy of 0.2 mas/yr and parallax accuracy of 1.0 mas over the course of the survey. These two requirements correspond to relative astrometric precision for a single image of 10 mas (per coordinate). ========================= ====== ======= ======= Astrometric Repeatability Specification ------------------------- ---------------------- Metric Design Minimum Stretch ========================= ====== ======= ======= AM1 (milliarcsec) 10 20 5 AF1 (%) 10 20 5 AD1 (milliarcsec) 20 40 10 AM2 (milliarcsec) 10 20 5 AF2 (%) 10 20 5 AD2 (milliarcsec) 20 40 10 AM3 (milliarcsec) 15 30 10 AF3 (%) 10 20 5 AD3 (milliarcsec) 30 50 20 ========================= ====== ======= ======= Table 18: The specifications for astrometric precision. The three blocks of values correspond to D=5, 20 and 200 arcmin, and to astrometric measurements performed in the r and i bands. """ metric = None value = None units = 'milliarcsecond' label = 'AMx' def __init__(self, x, matchedDataset, bandpass, width=2., magRange=None, verbose=False, job=None, linkedBlobs=None, metricYamlDoc=None, metricYamlPath=None): MeasurementBase.__init__(self) if x not in [1, 2, 3]: raise ValueError('AMx x should be 1, 2, or 3.') self.label = 'AM{0:d}'.format(x) self.metric = Metric.fromYaml(self.label, yamlDoc=metricYamlDoc, yamlPath=metricYamlPath) DSpec = self.metric.D # Register measurement parameters for serialization self.registerParameter('D', datum=DSpec) self.registerParameter('width', units='arcsecond', label='Width', description='Width of annulus') self.registerParameter('annulus', units='arcsecond', label='annulus radii', description='Inner and outer radii of ' 'selection annulus.') self.registerParameter('magRange', units='mag', description='Stellar magnitude selection ' 'range.') # Register measurement extras self.registerExtra('rmsDistMas', label='RMS', units='milliarcsecond') self.bandpass = bandpass self.magRange = magRange self.width = width self.matchedDataset = matchedDataset # Add external blob so that links will be persisted with # the measurement if linkedBlobs is not None: for name, blob in linkedBlobs.items(): setattr(self, name, blob) matches = matchedDataset.safeMatches self.annulus = self.D + (self.width/2)*np.array([-1, +1]) rmsDistances, self.annulus, self.magRange = \ calcRmsDistances(matches, self.annulus, magRange=self.magRange, verbose=verbose) if not list(rmsDistances): # raise ValidateErrorNoStars( # 'No stars found that are %.1f--%.1f arcmin apart.' % # (annulus[0], annulus[1])) # FIXME should we still report that this measurement was # attempted instead of just crashing. print('No stars found that are %.1f--%.1f arcmin apart.' % (self.annulus[0], self.annulus[1])) self.rmsDistMas = None self.value = None else: self.rmsDistMas = np.asarray(radiansToMilliarcsec(rmsDistances)) self.value = np.median(self.rmsDistMas) if job: job.registerMeasurement(self)