Beispiel #1
0
class ReferenceSpaceCache(Cache):

    REFERENCE_SPACE_VERSION_KEY = 'REFERENCE_SPACE_VERSION'
    ANNOTATION_KEY = 'ANNOTATION'
    TEMPLATE_KEY = 'TEMPLATE'
    STRUCTURES_KEY = 'STRUCTURES'
    STRUCTURE_TREE_KEY = 'STRUCTURE_TREE'
    STRUCTURE_MASK_KEY = 'STRUCTURE_MASK'

    MANIFEST_VERSION = 1.1

    def __init__(self, 
                 resolution, 
                 reference_space_key,
                 **kwargs):

        if not 'version' in kwargs:
            kwargs['version'] = self.MANIFEST_VERSION

        if not 'base_uri' in kwargs:
            kwargs['base_uri'] = None

        super(ReferenceSpaceCache, self).__init__(**kwargs)

        self.resolution = resolution
        self.reference_space_key = reference_space_key        
        
        self.api = ReferenceSpaceApi(base_uri=kwargs['base_uri'])

        
    def get_annotation_volume(self, file_name=None):
        """
        Read the annotation volume.  Download it first if it doesn't exist.

        Parameters
        ----------

        file_name: string
            File name to store the annotation volume.  If it already exists,
            it will be read from this file.  If file_name is None, the
            file_name will be pulled out of the manifest.  Default is None.

        """

        file_name = self.get_cache_path(
            file_name, self.ANNOTATION_KEY, self.reference_space_key, self.resolution)

        annotation, info = self.api.download_annotation_volume(
            self.reference_space_key,
            self.resolution,
            file_name, 
            strategy='lazy')

        return annotation, info


    def get_template_volume(self, file_name=None):
        """
        Read the template volume.  Download it first if it doesn't exist.

        Parameters
        ----------

        file_name: string
            File name to store the template volume.  If it already exists,
            it will be read from this file.  If file_name is None, the
            file_name will be pulled out of the manifest.  Default is None.

        """

        file_name = self.get_cache_path(
            file_name, self.TEMPLATE_KEY, self.resolution)

        template, info = self.api.download_template_volume(self.resolution, 
                                                           file_name, 
                                                           strategy='lazy')

        return template, info


    def get_structure_tree(self, file_name=None, structure_graph_id=1):
        """
        Read the list of adult mouse structures and return an StructureTree 
        instance.

        Parameters
        ----------

        file_name: string
            File name to save/read the structures table.  If file_name is None,
            the file_name will be pulled out of the manifest.  If caching
            is disabled, no file will be saved. Default is None.
        structure_graph_id: int
            Build a tree using structure only from the identified structure graph.
        """
        
        file_name = self.get_cache_path(file_name, self.STRUCTURE_TREE_KEY)

        return OntologiesApi(self.api.api_url).get_structures_with_sets(
            strategy='lazy',
            path=file_name,
            pre=StructureTree.clean_structures,
            post=lambda x: StructureTree(StructureTree.clean_structures(x)), 
            structure_graph_ids=structure_graph_id,
            **Cache.cache_json())


    def get_reference_space(self, structure_file_name=None, 
                            annotation_file_name=None):
        """
        Build a ReferenceSpace from this cache's annotation volume and 
        structure tree. The ReferenceSpace does operations that relate brain 
        structures to spatial domains.
        
        Parameters
        ----------
        
        structure_file_name: string
            File name to save/read the structures table.  If file_name is None,
            the file_name will be pulled out of the manifest.  If caching
            is disabled, no file will be saved. Default is None.
            
        annotation_file_name: string
            File name to store the annotation volume.  If it already exists,
            it will be read from this file.  If file_name is None, the
            file_name will be pulled out of the manifest.  Default is None.
        
        """
        
        return ReferenceSpace(self.get_structure_tree(structure_file_name), 
                              self.get_annotation_volume(annotation_file_name)[0], 
                              [self.resolution] * 3)

    def get_structure_mask(self, structure_id, file_name=None, annotation_file_name=None):
        """
        Read a 3D numpy array shaped like the annotation volume that has non-zero values where
        voxels belong to a particular structure.  This will take care of identifying substructures.

        Notes
        -----
        This method downloads structure masks from the Allen Institute. To make your own locally, see 
        ReferenceSpace.many_structure_masks.
        
        Parameters
        ----------

        structure_id: int
            ID of a structure.

        file_name: string
            File name to store the structure mask.  If it already exists,
            it will be read from this file.  If file_name is None, the
            file_name will be pulled out of the manifest.  Default is None.

        annotation_file_name: string
            File name to store the annotation volume.  If it already exists,
            it will be read from this file.  If file_name is None, the
            file_name will be pulled out of the manifest.  Default is None.
        """
        structure_id = ReferenceSpaceCache.validate_structure_id(structure_id)

        file_name = self.get_cache_path(
            file_name, self.STRUCTURE_MASK_KEY, self.reference_space_key, 
            self.resolution, structure_id)

        return self.api.download_structure_mask(structure_id, 
                                                self.reference_space_key,
                                                self.resolution,
                                                file_name, 
                                                strategy='lazy')


    def add_manifest_paths(self, manifest_builder):
        """
        Construct a manifest for this Cache class and save it in a file.

        Parameters
        ----------

        file_name: string
            File location to save the manifest.

        """

        manifest_builder = super(ReferenceSpaceCache, self).add_manifest_paths(manifest_builder)
                                  
        manifest_builder.add_path(self.STRUCTURE_TREE_KEY,
                                  'structures.json',
                                  parent_key='BASEDIR',
                                  typename='file')

        manifest_builder.add_path(self.REFERENCE_SPACE_VERSION_KEY,
                                  '%s',
                                  parent_key='BASEDIR',
                                  typename='dir')

        manifest_builder.add_path(self.ANNOTATION_KEY,
                                  'annotation_%d.nrrd',
                                  parent_key=self.REFERENCE_SPACE_VERSION_KEY,
                                  typename='file')

        manifest_builder.add_path(self.TEMPLATE_KEY,
                                  'average_template_%d.nrrd',
                                  parent_key='BASEDIR',
                                  typename='file')

        manifest_builder.add_path(self.STRUCTURE_MASK_KEY,
                                  'structure_masks/resolution_%d/structure_%d.nrrd',
                                  parent_key=self.REFERENCE_SPACE_VERSION_KEY,
                                  typename='file')

        return manifest_builder


       
 
    @classmethod
    def validate_structure_id(cls, structure_id):

        try:
            structure_id = int(structure_id)
        except ValueError as e:
            raise ValueError("Invalid structure_id (%s): could not convert to integer." % str(structure_id))

        return structure_id


    @classmethod
    def validate_structure_ids(cls, structure_ids):

        for ii, sid in enumerate(structure_ids):
            structure_ids[ii] = cls.validate_structure_id(sid)

        return structure_ids
class ReferenceSpaceCache(Cache):

    REFERENCE_SPACE_VERSION_KEY = 'REFERENCE_SPACE_VERSION'
    ANNOTATION_KEY = 'ANNOTATION'
    TEMPLATE_KEY = 'TEMPLATE'
    STRUCTURES_KEY = 'STRUCTURES'
    STRUCTURE_TREE_KEY = 'STRUCTURE_TREE'
    STRUCTURE_MASK_KEY = 'STRUCTURE_MASK'
    STRUCTURE_MESH_KEY = 'STRUCTURE_MESH'

    MANIFEST_VERSION = 1.2

    def __init__(self, 
                 resolution, 
                 reference_space_key,
                 **kwargs):

        if not 'version' in kwargs:
            kwargs['version'] = self.MANIFEST_VERSION

        if not 'base_uri' in kwargs:
            kwargs['base_uri'] = None

        super(ReferenceSpaceCache, self).__init__(**kwargs)

        self.resolution = resolution
        self.reference_space_key = reference_space_key        
        
        self.api = ReferenceSpaceApi(base_uri=kwargs['base_uri'])

        
    def get_annotation_volume(self, file_name=None):
        """
        Read the annotation volume.  Download it first if it doesn't exist.

        Parameters
        ----------

        file_name: string
            File name to store the annotation volume.  If it already exists,
            it will be read from this file.  If file_name is None, the
            file_name will be pulled out of the manifest.  Default is None.

        """

        file_name = self.get_cache_path(
            file_name, self.ANNOTATION_KEY, self.reference_space_key, self.resolution)

        annotation, info = self.api.download_annotation_volume(
            self.reference_space_key,
            self.resolution,
            file_name, 
            strategy='lazy')

        return annotation, info


    def get_template_volume(self, file_name=None):
        """
        Read the template volume.  Download it first if it doesn't exist.

        Parameters
        ----------

        file_name: string
            File name to store the template volume.  If it already exists,
            it will be read from this file.  If file_name is None, the
            file_name will be pulled out of the manifest.  Default is None.

        """

        file_name = self.get_cache_path(
            file_name, self.TEMPLATE_KEY, self.resolution)

        template, info = self.api.download_template_volume(self.resolution, 
                                                           file_name, 
                                                           strategy='lazy')

        return template, info


    def get_structure_tree(self, file_name=None, structure_graph_id=1):
        """
        Read the list of adult mouse structures and return an StructureTree 
        instance.

        Parameters
        ----------

        file_name: string
            File name to save/read the structures table.  If file_name is None,
            the file_name will be pulled out of the manifest.  If caching
            is disabled, no file will be saved. Default is None.
        structure_graph_id: int
            Build a tree using structure only from the identified structure graph.
        """
        
        file_name = self.get_cache_path(file_name, self.STRUCTURE_TREE_KEY)

        return OntologiesApi(self.api.api_url).get_structures_with_sets(
            strategy='lazy',
            path=file_name,
            pre=StructureTree.clean_structures,
            post=lambda x: StructureTree(StructureTree.clean_structures(x)), 
            structure_graph_ids=structure_graph_id,
            **Cache.cache_json())


    def get_reference_space(self, structure_file_name=None, 
                            annotation_file_name=None):
        """
        Build a ReferenceSpace from this cache's annotation volume and 
        structure tree. The ReferenceSpace does operations that relate brain 
        structures to spatial domains.
        
        Parameters
        ----------
        
        structure_file_name: string
            File name to save/read the structures table.  If file_name is None,
            the file_name will be pulled out of the manifest.  If caching
            is disabled, no file will be saved. Default is None.
            
        annotation_file_name: string
            File name to store the annotation volume.  If it already exists,
            it will be read from this file.  If file_name is None, the
            file_name will be pulled out of the manifest.  Default is None.
        
        """
        
        return ReferenceSpace(self.get_structure_tree(structure_file_name), 
                              self.get_annotation_volume(annotation_file_name)[0], 
                              [self.resolution] * 3)

    def get_structure_mask(self, structure_id, file_name=None, annotation_file_name=None):
        """
        Read a 3D numpy array shaped like the annotation volume that has non-zero values where
        voxels belong to a particular structure.  This will take care of identifying substructures.

        Notes
        -----
        This method downloads structure masks from the Allen Institute. To make your own locally, see 
        ReferenceSpace.many_structure_masks.
        
        Parameters
        ----------

        structure_id: int
            ID of a structure.

        file_name: string
            File name to store the structure mask.  If it already exists,
            it will be read from this file.  If file_name is None, the
            file_name will be pulled out of the manifest.  Default is None.

        annotation_file_name: string
            File name to store the annotation volume.  If it already exists,
            it will be read from this file.  If file_name is None, the
            file_name will be pulled out of the manifest.  Default is None.
        """
        structure_id = ReferenceSpaceCache.validate_structure_id(structure_id)

        file_name = self.get_cache_path(
            file_name, self.STRUCTURE_MASK_KEY, self.reference_space_key, 
            self.resolution, structure_id)

        return self.api.download_structure_mask(structure_id, 
                                                self.reference_space_key,
                                                self.resolution,
                                                file_name, 
                                                strategy='lazy')


    def get_structure_mesh(self, structure_id, file_name=None):
        """Obtain a 3D mesh specifying the surface of an annotated structure.
    
        Parameters
        -----------
        structure_id: int
            ID of a structure.
        file_name: string
            File name to store the structure mesh.  If it already exists,
            it will be read from this file.  If file_name is None, the
            file_name will be pulled out of the manifest.  Default is None.

        Returns
        -------
        vertices : np.ndarray
            Dimensions are (nSamples, nCoordinates=3). Locations in the reference space
            of vertices
        vertex_normals : np.ndarray
            Dimensions are (nSample, nElements=3). Vectors normal to vertices.
        face_vertices : np.ndarray
            Dimensions are (sample, nVertices=3). References are given in indices 
            (0-indexed here, but 1-indexed in the file) of vertices that make up each face.
        face_normals : np.ndarray
            Dimensions are (sample, nNormals=3). References are given in indices 
            (0-indexed here, but 1-indexed in the file) of vertex normals that make up each face.

        Notes
        -----
        These meshes are meant for 3D visualization and as such have been smoothed. 
        If you are interested in performing quantative analyses, we recommend that you 
        use the structure masks instead.

        """
        structure_id = ReferenceSpaceCache.validate_structure_id(structure_id)

        file_name = self.get_cache_path(
            file_name, self.STRUCTURE_MESH_KEY, self.reference_space_key, structure_id)

        return self.api.download_structure_mesh(structure_id, 
                                                self.reference_space_key,
                                                file_name, 
                                                strategy='lazy')


    def add_manifest_paths(self, manifest_builder):
        """
        Construct a manifest for this Cache class and save it in a file.

        Parameters
        ----------

        file_name: string
            File location to save the manifest.

        """

        manifest_builder = super(ReferenceSpaceCache, self).add_manifest_paths(manifest_builder)
                                  
        manifest_builder.add_path(self.STRUCTURE_TREE_KEY,
                                  'structures.json',
                                  parent_key='BASEDIR',
                                  typename='file')

        manifest_builder.add_path(self.REFERENCE_SPACE_VERSION_KEY,
                                  '%s',
                                  parent_key='BASEDIR',
                                  typename='dir')

        manifest_builder.add_path(self.ANNOTATION_KEY,
                                  'annotation_%d.nrrd',
                                  parent_key=self.REFERENCE_SPACE_VERSION_KEY,
                                  typename='file')

        manifest_builder.add_path(self.TEMPLATE_KEY,
                                  'average_template_%d.nrrd',
                                  parent_key='BASEDIR',
                                  typename='file')

        manifest_builder.add_path(self.STRUCTURE_MASK_KEY,
                                  'structure_masks/resolution_%d/structure_%d.nrrd',
                                  parent_key=self.REFERENCE_SPACE_VERSION_KEY,
                                  typename='file')

        manifest_builder.add_path(self.STRUCTURE_MESH_KEY,
                                  'structure_meshes/structure_%d.obj',
                                  parent_key=self.REFERENCE_SPACE_VERSION_KEY,
                                  typename='file')

        return manifest_builder


       
 
    @classmethod
    def validate_structure_id(cls, structure_id):

        try:
            structure_id = int(structure_id)
        except ValueError as e:
            raise ValueError("Invalid structure_id (%s): could not convert to integer." % str(structure_id))

        return structure_id


    @classmethod
    def validate_structure_ids(cls, structure_ids):

        for ii, sid in enumerate(structure_ids):
            structure_ids[ii] = cls.validate_structure_id(sid)

        return structure_ids
Beispiel #3
0
import numpy as np
from allensdk.api.queries.reference_space_api import ReferenceSpaceApi
from allensdk.config.manifest import Manifest

# the annotation download writes a file, so we will need somwhere to put it
annotation_dir = 'annotation'
Manifest.safe_mkdir(annotation_dir)

annotation_path = os.path.join(annotation_dir, 'annotation.nrrd')

# this is a string which contains the name of the latest ccf version
annotation_version = ReferenceSpaceApi.CCF_VERSION_DEFAULT

# download annotations
mcapi = ReferenceSpaceApi()
mcapi.download_annotation_volume(annotation_version, 50, annotation_path)
annotation = nrrd.read(annotation_path)

# read nrrd data and header
_nrrd = nrrd.read(annotation_path)
data = _nrrd[0]
header = _nrrd[1]

# create header and for RAS orientation
space_value = header['space directions']
affine = np.eye(4) * 0.001 * space_value[0, 0]
affine[3][3] = 1
# ensure RAS orientation
data = np.swapaxes(data, 2, 0)
data = np.flip(data, 2)