Coverage for python/lsst/daf/butler/core/dimensions/elements.py : 26%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# This file is part of daf_butler. # # Developed for the LSST Data Management System. # This product includes software developed by the LSST Project # (http://www.lsst.org). # See the COPYRIGHT file at the top-level directory of this distribution # for details of code ownership. # # 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 GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Base class for elements in the dimension schema.
`DimensionElement` has exactly two subclasses: `Dimension` and `DimensionJoin`.
`DimensionElement` objects are not directly constructable; they can only be obtained (possibly indirectly) from a special "universe" `DimensionGraph` loaded from configuration. """
# # Constructor is private, so its docs are just comments. # # Parameters # ---------- # universe : `DimensionGraph` # Ultimate-parent `DimensionGraph` that constructed this element. # name : `str` # Name of the element. Also the name of any SQL table or view # associated with it. # hasRegion : `bool` # Whether entries for this dimension are associated with a region # on the sky. # links : iterable of `str` # The names of primary key fields used by this element but not any of # its dependencies. # required : iterable of `str` # The names of the `Dimension`\ s whose primary keys are a subset of # this element's primary key. # implied : iterable of `str` # The names of the `Dimension`\ s whose primary keys are specified by # foreign keys in this element. # doc : `str` # Documentation string for this element. # from .sets import DimensionSet self._universe = universe self._name = name self._hasRegion = hasRegion self._localLinks = frozenset(links) self._doc = doc self._requiredDependencies = DimensionSet(universe, required, expand=True, implied=False) self._impliedDependencies = DimensionSet(universe, implied, expand=False) self._allDependencies = self._requiredDependencies | self._impliedDependencies expandedLinks = set(self._localLinks) for dimension in self.dependencies(implied=False): expandedLinks |= dimension.links(expand=True) self._expandedLinks = frozenset(expandedLinks) expandedImpliedLinks = set(self._localLinks) for dimension in self.dependencies(implied=True): expandedImpliedLinks |= dimension.links(expand=True) self._expandedImpliedLinks = frozenset(expandedImpliedLinks)
try: return self.universe is other.universe and self.name == other.name except AttributeError: return NotImplemented
return hash(self.name)
def universe(self): """The graph of all dimensions compatible with self (`DimensionGraph`). """ return self._universe
def name(self): """Name of this dimension (`str`, read-only).
Also assumed to be the name of any associated table or view. """ return self._name
def hasRegion(self): """Whether this dimension is associated with a region on the sky (`bool`). """ return self._hasRegion
def doc(self): """Documentation for this dimension (`str`). """ return self._doc
"""Return the names of fields that uniquely identify this dimension in a data ID dict.
Parameters ---------- expand: `bool` If `True` (default) include links associated with required dependencies. implied: `bool` If `True`, expand to include the links of implied dpendencies as well. Ignored if ``expand`` is `False`.
Returns ------- links : `frozenset` of `str` Set of field names. """ if expand: if implied: return self._expandedImpliedLinks else: return self._expandedLinks else: return self._localLinks
"""Return the set of dimensions this dimension depends on.
Parameters ---------- required : `bool` If `True` (default), include required dependencies. Required dependences are always expanded recursively. implied : `bool` If `True`, return implied dependencies.
Returns ------- dependencies : `DimensionSet` """ if required: if implied: return self._allDependencies else: return self._requiredDependencies elif implied: return self._impliedDependencies raise ValueError("At least one of 'required' and 'implied' must be True.")
"""Return the minimal `DimensionGraph` that contains ``self``.
Parameters ---------- implied : `bool` If `True`, include implied as well as required dependencies.
Returns ------- graph : `DimensionGraph` """ return self.universe.extract([self], implied=implied)
r"""A discrete dimension of data used to organize Datasets and associate them with metadata.
`Dimension` instances represent concepts such as "instrument", "detector", "visit" and "skymap", which are usually associated with database tables. A `DatasetType` is associated with a fixed combination of `Dimension`\s.
`Dimension` objects are not directly constructable; they can only be obtained from a `DimensionGraph`. """
# # Constructor is private, so its docs are just comments. # # Parameters # ---------- # universe : `DimensionGraph` # Ultimate-parent DimensionGraph that constructed this element. # name : `str` # Name of the element. Also the name of any SQL table or view # associated with it. # config : `Config` # Sub-config corresponding to this `Dimension`. # super().__init__(universe, name, hasRegion=config.get("hasRegion", False), links=config["link"], required=config.get(".dependencies.required", ()), implied=config.get(".dependencies.implied", ()), doc=config["doc"])
return "Dimension({})".format(self.name)
r"""A join that relates two or more `Dimension`\s.
`DimensionJoin`\s usually map to many-to-many join tables or views that relate `Dimension` tables.
`DimensionJoin` objects are not directly constructable; they can only be obtained from a `DimensionGraph`. """
# # Constructor is private, so its docs are just comments. # # Parameters # ---------- # universe : `DimensionGraph` # Ultimate-parent DimensionGraph that constructed this element. # name : `str` # Name of the element. Also the name of any SQL table or view # associated with it. # config : `Config` # Sub-config corresponding to this `DimensionJoin`. # from .sets import DimensionSet
lhs = list(config["lhs"]) rhs = list(config["rhs"]) super().__init__(universe, name, hasRegion=config.get("hasRegion", False), links=(), required=lhs + rhs, implied=(), doc=config["doc"]) self._lhs = DimensionSet(universe, lhs, implied=False) self._rhs = DimensionSet(universe, rhs, implied=False) self._asNeeded = config.get("asNeeded", False) # self._summarizes initialized later in DimensionGraph.fromConfig.
def lhs(self): r"""The `Dimension`\s on the left hand side of the join (`DimensionSet`).
Left vs. right is completely arbitrary; the terminology simply provides an easy way to distinguish between the two sides. """ return self._lhs
def rhs(self): r"""The `Dimension`\s on the right hand side of the join (`DimensionSet`).
Left vs. right is completely arbitrary; the terminology simply provides an easy way to distinguish between the two sides. """ return self._rhs
def asNeeded(self): """Whether this join only be included in a query when required, as opposed to whenever its dependencies are included (`bool`). """ return self._asNeeded
def summarizes(self): r"""A set of other `DimensionJoin`\s that provide more fine-grained relationships than this one (`DimensionJoinSet`).
When a join "summarizes" another, it means the table for that join could (at least conceptually) be defined as an aggregate view on the summarized join table. For example, "tract_skypix_join" summarizes "patch_skypix_join", because the set of skypix rows associated with a tract row is just the set of skypix rows associated with all patches associated with that tract. Or, in SQL:
.. code-block:: sql
CREATE VIEW tract_skypix_join AS SELECT DISTINCT skymap, tract, skypix FROM patch_skypix_join; """ return self._summarizes
return "DimensionJoin({})".format(self.name) |