Source code for tvb.adapters.datatypes.h5.tracts_h5

# -*- coding: utf-8 -*-
#
#
# TheVirtualBrain-Framework Package. This package holds all Data Management, and
# Web-UI helpful to run brain-simulations. To use it, you also need to download
# TheVirtualBrain-Scientific Package (for simulators). See content of the
# documentation-folder for more details. See also http://www.thevirtualbrain.org
#
# (c) 2012-2023, Baycrest Centre for Geriatric Care ("Baycrest") and others
#
# This program is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.  See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with this
# program.  If not, see <http://www.gnu.org/licenses/>.
#
#
#   CITATION:
# When using The Virtual Brain for scientific publications, please cite it as explained here:
# https://www.thevirtualbrain.org/tvb/zwei/neuroscience-publications
#
#
import numpy
from tvb.core.neotraits.h5 import H5File, DataSet, Reference
from tvb.datatypes.tracts import Tracts


[docs] class TractsH5(H5File): MAX_N_VERTICES = 2 ** 16 def __init__(self, path): super(TractsH5, self).__init__(path) self.vertices = DataSet(Tracts.vertices, self, expand_dimension=0) self.tract_start_idx = DataSet(Tracts.tract_start_idx, self) self.tract_region = DataSet(Tracts.tract_region, self) self.region_volume_map = Reference(Tracts.region_volume_map, self)
[docs] def get_tract(self, i): """ get a tract by index """ start, end = self.tract_start_idx[i:i + 2] return self.vertices[start:end]
def _get_tract_ids(self, region_id): tract_ids = numpy.where(self.tract_region.load() == region_id)[0] return tract_ids def _get_track_ids_webgl_chunks(self, region_id): """ webgl can draw up to MAX_N_VERTICES vertices in a draw call. Assuming that no one track exceeds this limit we partition the tracts such that each track bundle has fewer than the max vertices :return: the id's of the tracts in a region chunked by the above criteria. """ # We have to split the int64 range in many uint16 ranges tract_ids = self._get_tract_ids(region_id) tract_id_chunks = [] chunk = [] count = 0 tidx = 0 while tidx < len(tract_ids): # tidx always grows tid = tract_ids[tidx] start, end = self.tract_start_idx[tid:tid + 2] track_len = end - start if track_len >= self.MAX_N_VERTICES: raise ValueError('Currently tracts are too long to be handled!') count += track_len if count < self.MAX_N_VERTICES: # add this track to the current chunk and advance to next track chunk.append(tid) tidx += 1 else: # stay with the same track and start a new chunk tract_id_chunks.append(chunk) chunk = [] count = 0 if chunk: tract_id_chunks.append(chunk) return tract_id_chunks
[docs] def get_vertices(self, region_id, slice_number=0): """ Concatenates the vertices for all tracts starting in region_id. Returns a completely flat array as required by gl.bindBuffer apis """ region_id = int(region_id) slice_number = int(slice_number) chunks = self._get_track_ids_webgl_chunks(region_id) tract_ids = chunks[slice_number] tracts_vertices = [] for tid in tract_ids: tracts_vertices.append(self.get_tract(tid)) self.close() if tracts_vertices: tracts_vertices = numpy.concatenate(tracts_vertices) return tracts_vertices.ravel() else: return numpy.array([])
[docs] def get_line_starts(self, region_id): """ Returns a compact representation of the element buffers required to draw the streams via gl.drawElements A list of indices that describe where the first vertex for a tract is in the vertex array returned by get_tract_vertices_starting_in_region """ region_id = int(region_id) chunks = self._get_track_ids_webgl_chunks(region_id) chunk_line_starts = [] tract_start_idx = self.tract_start_idx # traits make the . expensive for tract_ids in chunks: offset = 0 tract_offsets = [0] for tid in tract_ids: start, end = tract_start_idx[tid:tid + 2] track_len = end - start offset += track_len tract_offsets.append(offset) chunk_line_starts.append(tract_offsets) return chunk_line_starts
[docs] def write_vertices_slice(self, partial_result): """ Append a new value to the ``vertices`` attribute. """ self.vertices.append(partial_result, close_file=False)