def refreshImageTexture(self): """Makes sure that the :class:`.ImageTexture`, used to store the :class:`.Image` data, is up to date. """ opts = self.opts texName = '{}_{}'.format(type(self).__name__, id(self.image)) unsynced = (opts.getParent() is None or not opts.isSyncedToParent('volume')) if unsynced: texName = '{}_unsync_{}'.format(texName, id(opts)) if self.imageTexture is not None: if self.imageTexture.name == texName: return self.imageTexture.deregister(self.name) glresources.delete(self.imageTexture.name) if opts.interpolation == 'none': interp = gl.GL_NEAREST else: interp = gl.GL_LINEAR self.imageTexture = glresources.get(texName, textures.ImageTexture, texName, self.image, interp=interp, volume=opts.index()[3:], notify=False) self.imageTexture.register(self.name, self.__imageTextureChanged)
def refreshAuxTexture(self, which, **kwargs): """Create/re-create an auxillary :class:`.ImageTexture`. The previous ``ImageTexture`` (if one exists) is destroyed. If no :class:`.Image` of type ``which`` is currently registered, a small dummy ``Image`` and ``ImageTexture`` is created. :arg which: Name of the auxillary image All other arguments are passed through to the :class:`.ImageTexture.__init__` method. """ self.__destroyAuxTexture(which) image = self.__auximages[which] opts = self.__auxopts[which] tex = self.__auxtextures[which] if image is None: textureData = np.zeros((3, 3, 3), dtype=np.uint8) textureData[:] = 255 image = fslimage.Image(textureData) norm = None else: norm = image.dataRange # by default we use a name which # is not coupled to the aux opts # instance, as the texture may be # sharable. texName = '{}_{}_{}_{}'.format( type(self).__name__, id(self.image), id(image), which) # check to see whether the aux # opts object is unsynced from # its parent - if so, we have to # create a dedicated texture if opts is not None: unsynced = (opts.getParent() is None or not opts.isSyncedToParent('volume')) if unsynced: texName = '{}_unsync_{}'.format(texName, id(opts)) if opts is not None: volume = opts.index()[3:] else: volume = 0 tex = glresources.get(texName, textures.ImageTexture, texName, image, normaliseRange=norm, volume=volume, notify=False, **kwargs) self.__auxtextures[which] = tex
def __init__(self, annot, selection, displayToVoxMat, voxToDisplayMat, voxToTexMat, offsets=None, *args, **kwargs): """Create a ``VoxelSelection`` annotation. :arg annot: The :class:`Annotations` object that owns this ``VoxelSelection``. :arg selection: A :class:`.Selection` instance which defines the voxels to be highlighted. :arg displayToVoxMat: A transformation matrix which transforms from display space coordinates into voxel space coordinates. :arg voxToDisplayMat: A transformation matrix which transforms from voxel coordinates into display space coordinates. :arg voxToTexMat: Transformation matrix which transforms from voxel coordinates to equivalent texture coordinates. :arg offsets: If ``None`` (the default), the ``selection`` must have the same shape as the image data being annotated. Alternately, you may set ``offsets`` to a sequence of three values, which are used as offsets for the xyz voxel values. This is to allow for a sub-space of the full image space to be annotated. All other arguments are passed through to the :meth:`AnnotationObject.__init__` method. """ AnnotationObject.__init__(self, annot, *args, **kwargs) if offsets is None: offsets = [0, 0, 0] self.selection = selection self.displayToVoxMat = displayToVoxMat self.voxToDisplayMat = voxToDisplayMat self.voxToTexMat = voxToTexMat self.offsets = offsets texName = '{}_{}'.format(type(self).__name__, id(selection)) self.texture = glresources.get(texName, textures.SelectionTexture, texName, selection)
def __init__(self, annot, selection, opts, offsets=None, *args, **kwargs): """Create a ``VoxelSelection`` annotation. :arg annot: The :class:`Annotations` object that owns this ``VoxelSelection``. :arg selection: A :class:`.selection.Selection` instance which defines the voxels to be highlighted. :arg opts: A :class:`.NiftiOpts` instance which is used for its voxel-to-display transformation matrices. :arg offsets: If ``None`` (the default), the ``selection`` must have the same shape as the image data being annotated. Alternately, you may set ``offsets`` to a sequence of three values, which are used as offsets for the xyz voxel values. This is to allow for a sub-space of the full image space to be annotated. All other arguments are passed through to the :meth:`AnnotationObject.__init__` method. """ AnnotationObject.__init__(self, annot, *args, **kwargs) if offsets is None: offsets = [0, 0, 0] self.__selection = selection self.__opts = opts self.__offsets = offsets texName = '{}_{}'.format(type(self).__name__, id(selection)) ndims = texdata.numTextureDims(selection.shape) if ndims == 2: ttype = textures.SelectionTexture2D else: ttype = textures.SelectionTexture3D self.__texture = glresources.get( texName, ttype, texName, selection)
def updateVertices(self): """Creates/refreshes the :class:`.GLLineVertices` instance which is used to generate line vertices and texture coordinates. If the ``GLLineVertices`` instance exists and is up to date (see the :meth:`.GLLineVertices.calculateHash` method), this function does nothing. """ if self.lineVertices is None: self.lineVertices = glresources.get(self._vertexResourceName, gllinevector.GLLineVertices, self) if hash(self.lineVertices) != self.lineVertices.calculateHash(self): log.debug('Re-generating line vertices ' 'for {}'.format(self.vectorImage)) self.lineVertices.refresh(self) glresources.set(self._vertexResourceName, self.lineVertices, overwrite=True)
def refreshImageTexture(self): """(Re-)creates an :class:`.ImageTexture` or :class:`.ImageTexture2D` to store the image data. """ texName = '{}_{}'.format(type(self).__name__, id(self.image)) nvals = self.overlay.nvals if self.opts.interpolation == 'none': interp = gl.GL_NEAREST else: interp = gl.GL_LINEAR if nvals == 1: nvals = self.overlay.shape[-1] self.imageTexture = glresources.get(texName, textures.createImageTexture, texName, self.overlay, nvals=nvals, interp=interp, notify=False) self.imageTexture.register(self.name, self.__imageTextureChanged)
def __init__(self, image, overlayList, displayCtx, canvas, threedee): """Create a ``GLTensor``. Prepares the eigenvalue and eigenvector textures, and calls the :func:`.gl21.gltensor_funcs.init` function. :arg image: A :class:`.DTIFitTensor` or compatible :class:`.Image` overlay. :arg overlayList: The :class:`.OverlayList` :arg displayCtx: The :class:`.DisplayContext` managing the scene. :arg canvas: The canvas doing the drawing. :arg threedee: 2D or 3D rendering. """ prefilter = np.abs def prefilterRange(dmin, dmax): return max((0, dmin)), max((abs(dmin), abs(dmax))) # The overlay must either be a DTIFitTensor if isinstance(image, dtifit.DTIFitTensor): v1 = image.V1() v2 = image.V2() v3 = image.V3() l1 = image.L1() l2 = image.L2() l3 = image.L3() # Or an Image with 6 volumes containing # the unique tensor matrix elements else: decomp = dtifit.decomposeTensorMatrix(image.nibImage.get_data()) v1 = fslimage.Image(decomp[0]) v2 = fslimage.Image(decomp[1]) v3 = fslimage.Image(decomp[2]) l1 = fslimage.Image(decomp[3]) l2 = fslimage.Image(decomp[4]) l3 = fslimage.Image(decomp[5]) self.v1 = v1 self.v2 = v2 self.v3 = v3 self.l1 = l1 self.l2 = l2 self.l3 = l3 # Create a texture for each eigenvalue/ # vector, and add each of them as suitably # named attributes on this GLTensor # instance. def vPrefilter(d): return d.transpose((3, 0, 1, 2)) names = ['v1', 'v2', 'v3', 'l1', 'l2', 'l3'] imgs = [v1, v2, v3, l1, l2, l3] for name, img in zip(names, imgs): texName = '{}_{}_{}'.format(type(self).__name__, name, id(img)) if name[0] == 'v': texPrefilter = vPrefilter nvals = 3 else: texPrefilter = None nvals = 1 tex = glresources.get(texName, textures.ImageTexture, texName, img, nvals=nvals, normaliseRange=img.dataRange, prefilter=texPrefilter) setattr(self, '{}Texture'.format(name), tex) glvector.GLVector.__init__( self, image, overlayList, displayCtx, canvas, threedee, prefilter=prefilter, prefilterRange=prefilterRange, vectorImage=v1, init=lambda: fslgl.gltensor_funcs.init(self))