Source code for lsst.verify.spec.base
#
# 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__ = ["Specification"]
import abc
from future.utils import with_metaclass
from past.builtins import basestring
from ..jsonmixin import JsonSerializationMixin
from ..metaquery import MetadataQuery
from ..naming import Name
[docs]class Specification(with_metaclass(abc.ABCMeta, JsonSerializationMixin)):
"""Specification base class.
Specification classes must implement:
- `type`
- `_serialize_type`
- `check`
Subclasses should also call ``Specification.__init__`` to initialize
the specifications ``name`` attribute (a `~lsst.verify.Name`
instance).
"""
def __init__(self, name, **kwargs):
# interal object behind self.tags
self._tags = set()
# name attibute must be a Name instance representing a specification
if not isinstance(name, Name):
self._name = Name(spec=name)
else:
self._name = name
if not self._name.is_spec:
message = 'name {0!r} does not represent a specification'
raise TypeError(message.format(self._name))
if 'metadata_query' in kwargs:
self._metadata_query = MetadataQuery(kwargs['metadata_query'])
else:
self._metadata_query = MetadataQuery()
if 'tags' in kwargs:
self.tags = kwargs['tags']
@property
def name(self):
"""Specification name (`lsst.verify.Name`)."""
return self._name
@property
def metric_name(self):
"""Name of the metric this specification corresponds to
(`lsst.verify.Name`)."""
return Name(package=self.name.package, metric=self.name.metric)
@property
def tags(self):
"""Tag labels (`set` of `str`)."""
return self._tags
@tags.setter
def tags(self, t):
# Ensure that tags is always a set.
if isinstance(t, basestring):
t = [t]
self._tags = set(t)
@abc.abstractproperty
def type(self):
"""Specification type (`str`)."""
pass
@abc.abstractmethod
def _serialize_type(self):
"""Serialize type-specific specification data to a JSON-serializable
`dict`.
This method is used by the `json` property as the value associated
with the key named for `type`.
"""
pass
@property
def json(self):
"""`dict` that can be serialized as semantic JSON, compatible with
the SQUASH metric service.
"""
return JsonSerializationMixin.jsonify_dict(
{
'name': str(self.name),
'type': self.type,
self.type: self._serialize_type(),
'metadata_query': self._metadata_query,
'tags': self.tags
}
)
@abc.abstractmethod
[docs] def check(self, measurement):
"""Check if a measurement passes this specification.
Parameters
----------
measurement : `astropy.units.Quantity`
The measurement value. The measurement `~astropy.units.Quantity`
must have units *compatible* with the specification.
Returns
-------
passed : `bool`
`True` if the measurement meets the specification,
`False` otherwise.
"""
pass