Skip to content

Commit

Permalink
ENH: Avoid duplicating objects, note that coordinate family mappings …
Browse files Browse the repository at this point in the history
…are shared after with_name()
  • Loading branch information
effigies committed Sep 22, 2023
1 parent 107ead6 commit 368c145
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 3 deletions.
7 changes: 6 additions & 1 deletion nibabel/pointset.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,12 @@ def get_names(self):
return list(self._coords)

def with_name(self, name: str) -> Self:
new = replace(self, coordinates=self._coords[name])
new_coords = self._coords[name]
if new_coords is self.coordinates:
return self
# Make a copy, preserving all dataclass fields
new = replace(self, coordinates=new_coords)
# Conserve exact _coords mapping
new._coords = self._coords
return new

Expand Down
19 changes: 17 additions & 2 deletions nibabel/tests/test_pointset.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,13 +250,28 @@ def test_names(self):
assert np.allclose(cfm.with_name('original').coordinates, coords)

cfm.add_coordinates('shifted', coords + 1)
assert cfm.get_names() == ['original', 'shifted']
assert set(cfm.get_names()) == {'original', 'shifted'}
shifted = cfm.with_name('shifted')
assert np.allclose(shifted.coordinates, coords + 1)
assert shifted.get_names() == ['original', 'shifted']
assert set(shifted.get_names()) == {'original', 'shifted'}
original = shifted.with_name('original')
assert np.allclose(original.coordinates, coords)

# Avoid duplicating objects
assert original.with_name('original') is original
# But don't try too hard
assert original.with_name('original') is not cfm

# with_name() preserves the exact coordinate mapping of the source object.
# Modifications of one are immediately available to all others.
# This is currently an implementation detail, and the expectation is that
# a family will be created once and then queried, but this behavior could
# potentially become confusing or relied upon.
# Change with care.
shifted.add_coordinates('shifted-again', coords + 2)
shift2 = shifted.with_name('shifted-again')
shift3 = cfm.with_name('shifted-again')


class H5ArrayProxy:
def __init__(self, file_like, dataset_name):
Expand Down

0 comments on commit 368c145

Please sign in to comment.