|
| 1 | +import operator as op |
| 2 | +from functools import reduce |
| 3 | + |
| 4 | +import numpy as np |
| 5 | + |
| 6 | +from nibabel.affines import apply_affine |
| 7 | + |
| 8 | + |
1 | 9 | class Pointset:
|
2 | 10 | @property
|
3 | 11 | def n_coords(self):
|
@@ -51,6 +59,32 @@ class NdGrid(Pointset):
|
51 | 59 | number of coordinates in each dimension of grid
|
52 | 60 | """
|
53 | 61 |
|
| 62 | + def __init__(self, shape, affines): |
| 63 | + self.shape = tuple(shape) |
| 64 | + try: |
| 65 | + self._affines = dict(affines) |
| 66 | + except (TypeError, ValueError): |
| 67 | + self._affines = {'world': np.array(affines)} |
| 68 | + if 'voxels' not in self._affines: |
| 69 | + self._affines['voxels'] = np.eye(4, dtype=np.uint8) |
| 70 | + |
54 | 71 | def get_affine(self, name=None):
|
55 | 72 | """4x4 array"""
|
56 |
| - raise NotImplementedError |
| 73 | + if name is None: |
| 74 | + name = next(iter(self._affines)) |
| 75 | + return self._affines[name] |
| 76 | + |
| 77 | + def get_coords(self, name=None): |
| 78 | + if name is None: |
| 79 | + name = next(iter(self._affines)) |
| 80 | + aff = self.get_affine(name) |
| 81 | + dt = np.result_type(*(np.min_scalar_type(dim) for dim in self.shape)) |
| 82 | + # This is pretty wasteful; we almost certainly want instead an |
| 83 | + # object that will retrieve a coordinate when indexed, but where |
| 84 | + # np.array(obj) returns this |
| 85 | + ijk_coords = np.array(list(np.ndindex(self.shape)), dtype=dt) |
| 86 | + return apply_affine(aff, ijk_coords) |
| 87 | + |
| 88 | + @property |
| 89 | + def n_coords(self): |
| 90 | + return reduce(op.mul, self.shape) |
0 commit comments