Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SurfaceTransform class #203

Merged
merged 35 commits into from
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
17477ea
Skeleton code to save/load transforms using X5 format.
feilong May 15, 2024
00af8d9
Support I/O of npz format.
feilong May 15, 2024
2ca8630
Normalize the transform so that the sum or the value of each element …
feilong May 16, 2024
3dbcf18
NF: add surface index transforms
Shotgunosine May 17, 2024
ed81087
NF: add surface resampling and surfacecoordinate transform
Shotgunosine May 17, 2024
cbafa5d
NF: surface resampler can load from surfaces
Shotgunosine May 17, 2024
4ba0bdc
Merge branch 'master' into surface
oesteban May 20, 2024
7be1b57
fix flake8
Shotgunosine May 21, 2024
b20a4bc
add .DS_Store
Shotgunosine May 21, 2024
46aca57
DOC: add documentation for suface coordinate transform
Shotgunosine May 21, 2024
6daaef1
TEST: expand test coverage
Shotgunosine May 21, 2024
2496647
NF: Validate inputs to SurfaceResampler
Shotgunosine May 21, 2024
f7784bc
ADD: project-unproject functionality
Shotgunosine Jun 20, 2024
092e745
Merge branch 'nipy:master' into surface
Shotgunosine Jun 20, 2024
d5705fb
clean surface test
Shotgunosine Jun 20, 2024
043816b
Merge branch 'nipy:master' into surface
Shotgunosine Jun 20, 2024
fc06289
FIX: don't drop 3dNwarpApply from the dockerfile
Shotgunosine Jun 20, 2024
4e95fa3
Update Dockerfile
Shotgunosine Jun 21, 2024
884a81e
RF: don't decompose coordinates before transforming
Shotgunosine Jun 21, 2024
288fc7c
TEST: split out project unproject test
Shotgunosine Jun 21, 2024
c3587c1
TEST: cover some more error messages
Shotgunosine Jun 21, 2024
5e8b492
PL: lint surface
Shotgunosine Jun 21, 2024
e6a63d9
RF: reorganize x5 files
Shotgunosine Jun 21, 2024
f9cabec
Update nitransforms/surface.py
Shotgunosine Jun 22, 2024
a4d6df2
Update nitransforms/tests/test_surface.py
Shotgunosine Jun 22, 2024
79b7b50
Update nitransforms/tests/test_surface.py
Shotgunosine Jun 22, 2024
57222fd
fix_rebase
Shotgunosine Jun 22, 2024
2e7c7eb
TEST: drop unused path
Shotgunosine Jun 22, 2024
ef29204
Merge branch 'master' into surface
Shotgunosine Jun 22, 2024
454e289
TEST: Fix surface coordinate transfrom tests
Shotgunosine Jun 22, 2024
2082f76
Merge branch 'surface' of https://github.com/feilong/nitransforms int…
Shotgunosine Jun 22, 2024
bf80e71
PL: fix style regressions
Shotgunosine Jun 22, 2024
f34d609
PL: fix long lines
Shotgunosine Jun 22, 2024
f470a59
Apply suggestions from code review
oesteban Jun 22, 2024
f69faaf
doc: add new module to APIdoc
oesteban Jun 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me get this in in a separate PR

Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,5 @@ local_settings.py

*.swp
.vscode/

.DS_Store
4 changes: 3 additions & 1 deletion Dockerfile
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me get this in in a separate PR

Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ RUN mkdir -p /opt/afni-latest \
-name "3dTshift" -or \
-name "3dUnifize" -or \
-name "3dAutomask" -or \
-name "3dvolreg" \) -delete
-name "3dvolreg" -or \
-name "3dNwarpApply" \
\) -delete

# Micromamba
FROM downloader as micromamba
Expand Down
3 changes: 2 additions & 1 deletion nitransforms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

transform
"""
from . import linear, manip, nonlinear
from . import linear, manip, nonlinear, surface
from .linear import Affine, LinearTransformsMapping
from .nonlinear import DenseFieldTransform
from .manip import TransformChain
Expand All @@ -37,6 +37,7 @@
__copyright__ = "Copyright (c) 2021 The NiPy developers"

__all__ = [
"surface",
"linear",
"manip",
"nonlinear",
Expand Down
70 changes: 70 additions & 0 deletions nitransforms/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from nibabel import funcs as _nbfuncs
from nibabel.nifti1 import intent_codes as INTENT_CODES
from nibabel.cifti2 import Cifti2Image
import nibabel as nb

EQUALITY_TOL = 1e-5

Expand Down Expand Up @@ -88,6 +89,75 @@
return self._shape


class SurfaceMesh(SampledSpatialData):
"""Class to represent surface meshes."""

__slots__ = ["_triangles"]

def __init__(self, dataset):
"""Create a sampling reference."""
self._shape = None

if isinstance(dataset, SurfaceMesh):
self._coords = dataset._coords
self._triangles = dataset._triangles
self._ndim = dataset._ndim
self._npoints = dataset._npoints
self._shape = dataset._shape
return

if isinstance(dataset, (str, Path)):
dataset = _nbload(str(dataset))

if hasattr(dataset, "numDA"): # Looks like a Gifti file
_das = dataset.get_arrays_from_intent(INTENT_CODES["pointset"])
if not _das:
raise TypeError(
"Input Gifti file does not contain reference coordinates."
)
self._coords = np.vstack([da.data for da in _das])
_tris = dataset.get_arrays_from_intent(INTENT_CODES["triangle"])
self._triangles = np.vstack([da.data for da in _tris])
self._npoints, self._ndim = self._coords.shape
self._shape = self._coords.shape
return

if isinstance(dataset, Cifti2Image):
raise NotImplementedError

raise ValueError("Dataset could not be interpreted as an irregular sample.")

def check_sphere(self, tolerance=1.001):
"""Check sphericity of surface.
Based on https://github.com/Washington-University/workbench/blob/7ba3345d161d567a4b628ceb02ab4471fc96cb20/src/Files/SurfaceResamplingHelper.cxx#L503
oesteban marked this conversation as resolved.
Show resolved Hide resolved
"""
dists = np.linalg.norm(self._coords, axis=1)
return (dists.min() * tolerance) > dists.max()

def set_radius(self, radius=100):
if not self.check_sphere():
raise ValueError("You should only set the radius on spherical surfaces.")

Check warning on line 139 in nitransforms/base.py

View check run for this annotation

Codecov / codecov/patch

nitransforms/base.py#L139

Added line #L139 was not covered by tests
dists = np.linalg.norm(self._coords, axis=1)
self._coords = self._coords * (radius / dists).reshape((-1, 1))

@classmethod
def from_arrays(cls, coordinates, triangles):
darrays = [
nb.gifti.GiftiDataArray(
coordinates.astype(np.float32),
intent=nb.nifti1.intent_codes['NIFTI_INTENT_POINTSET'],
datatype=nb.nifti1.data_type_codes['NIFTI_TYPE_FLOAT32'],
),
nb.gifti.GiftiDataArray(
triangles.astype(np.int32),
intent=nb.nifti1.intent_codes['NIFTI_INTENT_TRIANGLE'],
datatype=nb.nifti1.data_type_codes['NIFTI_TYPE_INT32'],
),
]
gii = nb.gifti.GiftiImage(darrays=darrays)
return cls(gii)


class ImageGrid(SampledSpatialData):
"""Class to represent spaces of gridded data (images)."""

Expand Down
Loading
Loading