Source code for lsst.verify.measurementset

#
# LSST Data Management System
#
# This product includes software developed by the
# LSST Project (http://www.lsst.org/).
#
# See COPYRIGHT file at the top of the source tree.
#
# 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, division

__all__ = ['MeasurementSet']

from .measurement import Measurement
from .naming import Name
from .jsonmixin import JsonSerializationMixin


[docs]class MeasurementSet(JsonSerializationMixin): """A collection of `~lsst.verify.Measurement`\ s of `~lsst.verify.Metric`\ s. ``MeasurementSet`` provides a dict-like interface for getting, setting, and iterating over `Measurement`\ s. Parameters ---------- measurements : `list` of `lsst.verify.Measurement`\ s Measurements to include in the set. """ def __init__(self, measurements=None): self._items = {} if measurements is not None: for measurement in measurements: self[measurement.metric_name] = measurement @classmethod
[docs] def deserialize(cls, measurements=None, blob_set=None, metric_set=None): """Create a measurement set from a parsed JSON dataset. Parameters ---------- measurements : `list`, optional A list of `Measurement` JSON serializations. blob_set : `BlobSet`, optional A `BlobSet` instance that support measurement deserialization. metric_set : `MetricSet`, optional A `MetricSet` that supports measurement deserialization. If provided, measurements are validated for unit consistency with metric definitions. `Measurement` instances also gain a `Measurement.metric` attribute. Returns ------- instance : `MeasurementSet` A `MeasurementSet` instance. """ instance = cls() if measurements is None: measurements = [] if len(metric_set) == 0: # Job.deserialize may pass an empty MetricSet, so ignore that metric_set = None for meas_doc in measurements: if metric_set is not None: try: metric = metric_set[meas_doc['metric']] meas_doc['metric'] = metric except KeyError: # metric not in the MetricSet, but it's optional pass meas = Measurement.deserialize(blobs=blob_set, **meas_doc) instance.insert(meas) return instance
def __getitem__(self, key): if not isinstance(key, Name): key = Name(metric=key) return self._items[key] def __setitem__(self, key, value): if not isinstance(key, Name): key = Name(metric=key) if not key.is_metric: raise KeyError('Key {0} is not a metric name'.format(key)) if not isinstance(value, Measurement): message = ('Measurement {0} is not a ' 'lsst.verify.Measurement-type') raise TypeError(message.format(value)) if key != value.metric_name: message = ("Key {0} is inconsistent with the measurement's " "metric name, {1}") raise KeyError(message.format(key, value.metric_name)) self._items[key] = value def __len__(self): return len(self._items) def __contains__(self, key): if not isinstance(key, Name): key = Name(metric=key) return key in self._items def __delitem__(self, key): if not isinstance(key, Name): key = Name(metric=key) del self._items[key] def __iter__(self): for key in self._items: yield key def __eq__(self, other): return self._items == other._items def __ne__(self, other): return not self.__eq__(other) def __iadd__(self, other): """Merge another `MeasurementSet` into this one. Parameters ---------- other : `MeasurementSet` Another `MeasurementSet`. Measurements in ``other`` that do exist in this set are added to this one. Measurements in ``other`` replace measurements of the same metric in this one. Returns ------- self : `MeasurementSet` This `MeasurementSet`. Notes ----- Equivalent to `update`. """ self.update(other) return self def __str__(self): count = len(self) if count == 0: count_str = 'empty' elif count == 1: count_str = '1 Measurement' else: count_str = '{count:d} Measurements'.format(count=count) return '<MeasurementSet: {0}>'.format(count_str)
[docs] def keys(self): """Get a sequence of metric names contained in the measurement set. Returns ------- keys : sequence of `Name` Sequence of names of metrics for measurements in the set. """ return self._items.keys()
[docs] def items(self): """Iterete over (`Name`, `Measurement`) pairs in the set. Yields ------ item : `tuple` Tuple containing: - `Name` of the measurement's `Metric`. - `Measurement` instance. """ for item in self._items.items(): yield item
[docs] def insert(self, measurement): """Insert a measurement into the set.""" self[measurement.metric_name] = measurement
[docs] def update(self, other): """Merge another `MeasurementSet` into this one. Parameters ---------- other : `MeasurementSet` Another `MeasurementSet`. Measurements in ``other`` that do exist in this set are added to this one. Measurements in ``other`` replace measurements of the same metric in this one. """ for _, measurement in other.items(): self.insert(measurement)
[docs] def refresh_metrics(self, metric_set): """Refresh `Measurement.metric` attributes in `Measurement`\ s contained by this set. Parameters ---------- metric_set : `MetricSet` `Metric`\ s from this set are inserted into corresponding `Measurement`\ s contained in this `MeasurementSet`. Notes ----- This method is especially useful for inserting `Metric` instances into `Measurement`\ s that weren't originally created with `Metric` instances. By including a `Metric` in a `Measurement`, the serialized units of a measurment are normalized to the metric's definition. See also -------- lsst.verify.Job.reload_metrics_package """ for metric_name, measurement in self.items(): if metric_name in metric_set: measurement.metric = metric_set[metric_name]
@property def json(self): """A `dict` that can be serialized as JSON.""" json_doc = JsonSerializationMixin._jsonify_list( [meas for name, meas in self.items()] ) return json_doc