Source code for brainglobe_atlasapi.structure_class
"""
Provide a class for representing hierarchical structures,
such as brain regions in an atlas.
"""
import warnings
from collections import UserDict
import meshio as mio
from brainglobe_atlasapi.structure_tree_util import get_structures_tree
[docs]
class Structure(UserDict):
    """Class implementing the lazy loading of a mesh if the dictionary is
    queried for it.
    """
    def __getitem__(self, item):
        """
        Retrieve an item from the structure's data.
        If the item is `mesh` and the mesh data is currently None, it attempts
        to load the mesh from the `mesh_filename` if available.
        Parameters
        ----------
        item : str
            The key of the item to retrieve.
        Returns
        -------
        meshio.Mesh or None or any
            - If `item` is "mesh" and the mesh data is successfully loaded,
              returns a `meshio.Mesh` object.
            - If `item` is "mesh" and `mesh_filename` is None, returns `None`.
            - For other keys, returns the value associated with the given item,
              which can be of any type depending on the stored data.
        Raises
        ------
        meshio.ReadError
            If `item` is "mesh" and the mesh cannot be read.
            The value associated with the given item.
        """
        if item == "mesh" and self.data[item] is None:
            if self.data["mesh_filename"] is None:
                warnings.warn(
                    "No mesh filename for region {}".format(
                        self.data["acronym"]
                    )
                )
                return None
            try:
                self.data[item] = mio.read(self.data["mesh_filename"])
            except (TypeError, mio.ReadError):
                raise mio.ReadError(
                    "No valid mesh for region: {}".format(self.data["acronym"])
                )
        return self.data[item] 
[docs]
class StructuresDict(UserDict):
    """Class to handle dual indexing by either acronym or id.
    Parameters
    ----------
    mesh_path : str or Path object
        path to folder containing all meshes .obj files
    """
    def __init__(self, structures_list):
        super().__init__()
        # Acronym to id map:
        self.acronym_to_id_map = {
            r["acronym"]: r["id"] for r in structures_list
        }
        for struct in structures_list:
            sid = struct["id"]
            self.data[sid] = Structure(**struct, mesh=None)
        self.tree = get_structures_tree(structures_list)
    def __getitem__(self, item):
        """Core implementation of the class support for different indexing.
        Parameters
        ----------
        item : str or int
            The acronym (str) or id (int) of the requested structure.
        Returns
        -------
        Structure
            The Structure requested.
        """
        try:
            item = int(item)
        except ValueError:
            item = self.acronym_to_id_map[item]
        return self.data[int(item)]
    def __repr__(self):
        """Return string representation of the class,
        showing all region names.
        """
        return self.tree.show(stdout=False)