Skip to content

Commit

Permalink
Add DataCoordinate.values_tuple() and optimizations based on it.
Browse files Browse the repository at this point in the history
  • Loading branch information
TallJimbo committed Aug 19, 2023
1 parent dfee9be commit 155aaa2
Showing 1 changed file with 32 additions and 5 deletions.
37 changes: 32 additions & 5 deletions python/lsst/daf/butler/core/dimensions/_coordinate.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,12 +340,12 @@ def fromFullValues(graph: DimensionGraph, values: tuple[DataIdValue, ...]) -> Da
return _BasicTupleDataCoordinate(graph, values)

def __hash__(self) -> int:
return hash((self.graph,) + tuple(self[d.name] for d in self.graph.required))
return hash((self.graph,) + self.values_tuple())

def __eq__(self, other: Any) -> bool:
if not isinstance(other, DataCoordinate):
other = DataCoordinate.standardize(other, universe=self.universe)
return self.graph == other.graph and all(self[d.name] == other[d.name] for d in self.graph.required)
return self.graph == other.graph and self.values_tuple() == other.values_tuple()

def __repr__(self) -> str:
# We can't make repr yield something that could be exec'd here without
Expand Down Expand Up @@ -513,6 +513,7 @@ def hasFull(self) -> bool:
raise NotImplementedError()

@property
@abstractmethod
def full(self) -> NamedKeyMapping[Dimension, DataIdValue]:
"""Return mapping for all dimensions in ``self.graph``.
Expand All @@ -524,8 +525,17 @@ def full(self) -> NamedKeyMapping[Dimension, DataIdValue]:
when implied keys are accessed via the returned mapping, depending on
the implementation and whether assertions are enabled.
"""
assert self.hasFull(), "full may only be accessed if hasFull() returns True."
return _DataCoordinateFullView(self)
raise NotImplementedError()

@abstractmethod
def values_tuple(self) -> tuple[DataIdValue, ...]:
"""Return the required values (only) of this data ID as a tuple.
In contexts where all data IDs have the same dimensions, comparing and
hashing these tuples can be *much* faster than comparing the original
`DataCoordinate` instances.
"""
raise NotImplementedError()

@abstractmethod
def hasRecords(self) -> bool:
Expand Down Expand Up @@ -779,7 +789,7 @@ class _DataCoordinateFullView(NamedKeyMapping[Dimension, DataIdValue]):
The `DataCoordinate` instance this object provides a view of.
"""

def __init__(self, target: DataCoordinate):
def __init__(self, target: _BasicTupleDataCoordinate):
self._target = target

__slots__ = ("_target",)
Expand Down Expand Up @@ -892,6 +902,13 @@ def __getitem__(self, key: DataIdKey) -> DataIdValue:
# values for the required ones.
raise KeyError(key) from None

def byName(self) -> dict[str, DataIdValue]:
# Docstring inheritance.
# Reimplementation is for optimization; `values_tuple()` is much faster
# to iterate over than values() because it doesn't go through
# `__getitem__`.
return dict(zip(self.names, self.values_tuple(), strict=True))

def subset(self, graph: DimensionGraph) -> DataCoordinate:
# Docstring inherited from DataCoordinate.
if self._graph == graph:
Expand Down Expand Up @@ -933,6 +950,12 @@ def union(self, other: DataCoordinate) -> DataCoordinate:
values.update(other.full.byName() if other.hasFull() else other.byName())
return DataCoordinate.standardize(values, graph=graph)

@property
def full(self) -> NamedKeyMapping[Dimension, DataIdValue]:
# Docstring inherited.
assert self.hasFull(), "full may only be accessed if hasFull() returns True."
return _DataCoordinateFullView(self)

def expanded(
self, records: NameLookupMapping[DimensionElement, DimensionRecord | None]
) -> DataCoordinate:
Expand All @@ -954,6 +977,10 @@ def hasRecords(self) -> bool:
# Docstring inherited from DataCoordinate.
return False

def values_tuple(self) -> tuple[DataIdValue, ...]:
# Docstring inherited from DataCoordinate.
return self._values[: len(self._graph.required)]

def _record(self, name: str) -> DimensionRecord | None:
# Docstring inherited from DataCoordinate.
raise AssertionError()
Expand Down

0 comments on commit 155aaa2

Please sign in to comment.