Source code for allensdk.core.reference_space_cache

# Allen Institute Software License - This software license is the 2-clause BSD
# license plus a third clause that prohibits redistribution for commercial
# purposes without further permission.
#
# Copyright 2015-2017. Allen Institute. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# 3. Redistributions for commercial purposes are not permitted without the
# Allen Institute's written permission.
# For purposes of this license, commercial purposes is the incorporation of the
# Allen Institute's software into anything for which you will charge fees or
# other compensation. Contact terms@alleninstitute.org for commercial licensing
# opportunities.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
from allensdk.config.manifest_builder import ManifestBuilder
from allensdk.api.cache import Cache
from allensdk.api.queries.reference_space_api import ReferenceSpaceApi
from allensdk.api.queries.ontologies_api import OntologiesApi
from allensdk.deprecated import deprecated

from .ontology import Ontology
from .structure_tree import StructureTree
from .reference_space import ReferenceSpace


[docs]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'])
[docs] 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
[docs] 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
[docs] 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())
[docs] 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)
[docs] 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')
[docs] 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')
[docs] 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
[docs] @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
[docs] @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