@@ -182,155 +182,3 @@ def test_to_mask(self):
182182 ],
183183 )
184184 assert np .array_equal (mask_img .affine , np .eye (4 ))
185-
186-
187- class H5ArrayProxy :
188- def __init__ (self , file_like , dataset_name ):
189- self .file_like = file_like
190- self .dataset_name = dataset_name
191- with h5 .File (file_like , 'r' ) as h5f :
192- arr = h5f [dataset_name ]
193- self ._shape = arr .shape
194- self ._dtype = arr .dtype
195-
196- @property
197- def is_proxy (self ):
198- return True
199-
200- @property
201- def shape (self ):
202- return self ._shape
203-
204- @property
205- def ndim (self ):
206- return len (self .shape )
207-
208- @property
209- def dtype (self ):
210- return self ._dtype
211-
212- def __array__ (self , dtype = None ):
213- with h5 .File (self .file_like , 'r' ) as h5f :
214- return np .asanyarray (h5f [self .dataset_name ], dtype )
215-
216- def __getitem__ (self , slicer ):
217- with h5 .File (self .file_like , 'r' ) as h5f :
218- return h5f [self .dataset_name ][slicer ]
219-
220-
221- class H5Geometry (ps .TriMeshFamily ):
222- """Simple Geometry file structure that combines a single topology
223- with one or more coordinate sets
224- """
225-
226- @classmethod
227- def from_filename (klass , pathlike ):
228- meshes = {}
229- with h5 .File (pathlike , 'r' ) as h5f :
230- triangles = H5ArrayProxy (pathlike , '/topology' )
231- for name in h5f ['coordinates' ]:
232- meshes [name ] = (H5ArrayProxy (pathlike , f'/coordinates/{ name } ' ), triangles )
233- return klass (meshes )
234-
235- def to_filename (self , pathlike ):
236- with h5 .File (pathlike , 'w' ) as h5f :
237- h5f .create_dataset ('/topology' , data = self .get_triangles ())
238- for name , coord in self ._coords .items ():
239- h5f .create_dataset (f'/coordinates/{ name } ' , data = coord )
240-
241-
242- class FSGeometryProxy :
243- def __init__ (self , pathlike ):
244- self ._file_like = str (Path (pathlike ))
245- self ._offset = None
246- self ._vnum = None
247- self ._fnum = None
248-
249- def _peek (self ):
250- from nibabel .freesurfer .io import _fread3
251-
252- with open (self ._file_like , 'rb' ) as fobj :
253- magic = _fread3 (fobj )
254- if magic != 16777214 :
255- raise NotImplementedError ('Triangle files only!' )
256- fobj .readline ()
257- fobj .readline ()
258- self ._vnum = np .fromfile (fobj , '>i4' , 1 )[0 ]
259- self ._fnum = np .fromfile (fobj , '>i4' , 1 )[0 ]
260- self ._offset = fobj .tell ()
261-
262- @property
263- def vnum (self ):
264- if self ._vnum is None :
265- self ._peek ()
266- return self ._vnum
267-
268- @property
269- def fnum (self ):
270- if self ._fnum is None :
271- self ._peek ()
272- return self ._fnum
273-
274- @property
275- def offset (self ):
276- if self ._offset is None :
277- self ._peek ()
278- return self ._offset
279-
280- @auto_attr
281- def coords (self ):
282- ap = ArrayProxy (self ._file_like , ((self .vnum , 3 ), '>f4' , self .offset ))
283- ap .order = 'C'
284- return ap
285-
286- @auto_attr
287- def triangles (self ):
288- offset = self .offset + 12 * self .vnum
289- ap = ArrayProxy (self ._file_like , ((self .fnum , 3 ), '>i4' , offset ))
290- ap .order = 'C'
291- return ap
292-
293-
294- class FreeSurferHemisphere (ps .TriMeshFamily ):
295- @classmethod
296- def from_filename (klass , pathlike ):
297- path = Path (pathlike )
298- hemi , default = path .name .split ('.' )
299- mesh_names = (
300- 'orig' ,
301- 'white' ,
302- 'smoothwm' ,
303- 'pial' ,
304- 'inflated' ,
305- 'sphere' ,
306- 'midthickness' ,
307- 'graymid' ,
308- ) # Often created
309- if default not in mesh_names :
310- mesh_names .append (default )
311- meshes = {}
312- for mesh in mesh_names :
313- fpath = path .parent / f'{ hemi } .{ mesh } '
314- if fpath .exists ():
315- meshes [mesh ] = FSGeometryProxy (fpath )
316- hemi = klass (meshes )
317- hemi ._default = default
318- return hemi
319-
320-
321- def test_FreeSurferHemisphere ():
322- lh = FreeSurferHemisphere .from_filename (FS_DATA / 'fsaverage/surf/lh.white' )
323- assert lh .n_coords == 163842
324- assert lh .n_triangles == 327680
325-
326-
327- @skipUnless (has_h5py , reason = 'Test requires h5py' )
328- def test_make_H5Geometry (tmp_path ):
329- lh = FreeSurferHemisphere .from_filename (FS_DATA / 'fsaverage/surf/lh.white' )
330- h5geo = H5Geometry ({name : lh .get_mesh (name ) for name in ('white' , 'pial' )})
331- h5geo .to_filename (tmp_path / 'geometry.h5' )
332-
333- rt_h5geo = H5Geometry .from_filename (tmp_path / 'geometry.h5' )
334- assert set (h5geo ._coords ) == set (rt_h5geo ._coords )
335- assert np .array_equal (lh .get_coords ('white' ), rt_h5geo .get_coords ('white' ))
336- assert np .array_equal (lh .get_triangles (), rt_h5geo .get_triangles ())
0 commit comments