예제 #1
0
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
예제 #2
0
    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))
예제 #3
0
    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)
예제 #4
0
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
예제 #5
0
    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)
예제 #6
0
    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)
예제 #7
0
    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))
예제 #8
0
    def test_str(self):
        """Test the __str__ method"""

        segmentation = Segmentation('my-seg', [0, 0, 1, 2])
        self.assertEqual('my-seg', str(segmentation))