def load_segmentation(filename: str) -> Segmentation: """Loads a segmentation from a FreeSurfer annot file. Loads the a segmentation from a FreeSurfer annotation file. Because annot files do not have a segmentation name, the file name is used instead. Args: filename: The name of the annot file that is loaded. Returns: segmentation: A segmentation whose name is `filename`. """ keys, ctab, names = nibfs.read_annot(filename) segmentation = Segmentation(os.path.basename(filename), keys) def rgbt2rgba(color): return color[0], color[1], color[2], 255 # Add the label names. for i, (color, name) in enumerate(zip(ctab, names)): segmentation.add_label(i, Label(name.decode(), rgbt2rgba(color[:4]))) return segmentation
def test_segmentation_save_load(self): """Test saving a loading segmentations.""" segmentation = Segmentation('test', [0, 0, 1, 1, 2, 2, 3, 3]) segmentation.add_label(0, Label('unknown')) segmentation.add_label(1, Label('red', (1, 0, 0, 1))) segmentation.add_label(2, Label('green', (0, 1, 0, 1))) segmentation.add_label(3, Label('blue', (0, 0, 1, 1))) # Work in a temporary directory. This guarantees cleanup even on error. with tempfile.TemporaryDirectory() as directory: # Save the mesh and reload it. filename = os.path.join(directory, 'segmentation.gii') nimesh.io.gifti.save_segmentation(filename, segmentation) loaded = nimesh.io.gifti.load_segmentation(filename) # The loaded data should match the saved data. np.testing.assert_array_almost_equal(segmentation.keys, loaded.keys) # Verify that the labels where loaded correctly. self.assertEqual(len(loaded.labels), 4) self.assertEqual(loaded.labels[0].name, 'unknown') self.assertTupleEqual(loaded.labels[0].color, (0, 0, 0, 0)) self.assertEqual(loaded.labels[1].name, 'red') self.assertTupleEqual(loaded.labels[1].color, (1, 0, 0, 1)) self.assertEqual(loaded.labels[2].name, 'green') self.assertTupleEqual(loaded.labels[2].color, (0, 1, 0, 1)) self.assertEqual(loaded.labels[3].name, 'blue') self.assertTupleEqual(loaded.labels[3].color, (0, 0, 1, 1))
def test_mesh_segmentation_save_load(self): """Test saving a mesh with a segmentation.""" mesh = minimal_mesh() # Add a segmentation. segmentation = Segmentation('seg', [0, 0, 1, 1]) mesh.add_segmentation(segmentation) # Work in a temporary directory. This guarantees cleanup even on error. with tempfile.TemporaryDirectory() as directory: # Save the mesh and reload it. filename = os.path.join(directory, 'mesh-segmentation.gii') nimesh.io.save(filename, mesh) loaded = nimesh.io.load(filename) # The coordinate system should not have changed. self.assertEqual(mesh.coordinate_system, loaded.coordinate_system) # The loaded data should match the saved data. Because there is no # data manipulation, this should be bit perfect. np.testing.assert_array_equal(mesh.vertices, loaded.vertices) np.testing.assert_array_equal(mesh.triangles, loaded.triangles) # The segmentation should be present. self.assertEqual(len(loaded.segmentations), 1) loaded_segmentation = loaded.segmentations[0] self.assertEqual(loaded_segmentation.name, segmentation.name) np.testing.assert_array_almost_equal(loaded_segmentation.keys, segmentation.keys)
def _get_segmentation_from_gii(gii) -> Segmentation: """Creates a segmentation from a nibabel GIfTI object. Creates a new segmentation from the data array of a nibabel GIfTI object. If none of the data arrays have an intent of NIFTI_INTENT_LABEL, None is returned. Args: gii: The nibabel GIfTI object from which to create the segmentation. Returns: segmentation: The loaded segmentation or None. """ # Get the labels array. If there is more than one, warn the user and # use the first one. label_arrays = gii.get_arrays_from_intent('NIFTI_INTENT_LABEL') if len(label_arrays) == 0: return None elif len(label_arrays) > 1: warnings.warn( 'The file contains more than one label array. The ' 'first one was used. Proceed with caution.', RuntimeWarning) label_array = label_arrays[0] labels = label_array.data # If a segmentation name was not saved, tell the user and give it a name. if 'name' in label_array.metadata: name = label_array.metadata['name'] else: warnings.warn('The name of the segmentation was not saved. Naming ' 'it as "unknown".') name = 'unknown' segmentation = Segmentation(name, labels) # Add the labels. for label in gii.labeltable.labels: # Convert the color back to integers. color = np.round(np.array(label.rgba) * 255).astype(int) segmentation.add_label(label.key, Label(label.label, color)) return segmentation
def test_segmentation_save_load(self): """Test saving and loading a segmentation.""" segmentation = Segmentation('test.annot', [1, 1, 2, 2]) segmentation.add_label(0, Label('no label', (0, 0, 0, 255))) segmentation.add_label(1, Label('label 0', (255, 0, 0, 255))) segmentation.add_label(2, Label('label 1', (0, 255, 0, 255))) # Work in a temporary directory. This guarantees cleanup even on error. with tempfile.TemporaryDirectory() as directory: # Save and reload the test data. filename = os.path.join(directory, segmentation.name) nimesh.io.freesurfer.save_segmentation(filename, segmentation) loaded = nimesh.io.freesurfer.load_segmentation(filename) np.testing.assert_array_almost_equal(segmentation.keys, loaded.keys) self.assertEqual(segmentation.name, loaded.name) # The labels should also match. items = zip(segmentation.labels.items(), loaded.labels.items()) for (k1, l1), (k2, l2) in items: self.assertEqual(k1, k2) self.assertEqual(l1.color, l2.color)
def test_segmentation_fail_on_duplicate_color(self): """Test that meshes with duplicate colors cannot be saved.""" segmentation = Segmentation('test.annot', [1, 1, 2, 2]) segmentation.add_label(0, Label('no label', (0, 0, 0, 255))) segmentation.add_label(1, Label('label 0', (255, 0, 0, 255))) segmentation.add_label(2, Label('label 1', (0, 255, 0, 255))) segmentation.add_label(3, Label('label 2', (0, 255, 0, 255))) # Segmentation with identical colors cannot be saved. with tempfile.TemporaryDirectory() as directory: filename = os.path.join(directory, segmentation.name) self.assertRaises(ValueError, nimesh.io.freesurfer.save_segmentation, filename, segmentation)
def test_repr(self): """Test the __repr__ method""" segmentation = Segmentation('my-seg', [0, 0, 1, 2]) expected_str = 'Segmentation(name=my-seg, keys=[0 0 1 2])' self.assertEqual(expected_str, repr(segmentation))
def test_str(self): """Test the __str__ method""" segmentation = Segmentation('my-seg', [0, 0, 1, 2]) self.assertEqual('my-seg', str(segmentation))