def _udpate_obytes(self): if self.over==None: self._over_idx = np.array([], np.int32) self._adapt_to_slicer() return # define the axes order to resample onto if self.vtk_order: ax_order = vtk_ax_order elif self.main: ax_order = vu.find_spatial_correspondence(self.main.coordmap) else: ax_order = None if type(self.over)==ni_api.Image: over = ResampledIndexVolumeSlicer( self.over, norm=self.over_norm, spatial_axes=ax_order, order=self.over_spline_order ) # go ahead and be re-entrant self.over = over return if type(self.over) != ResampledIndexVolumeSlicer: raise ValueError('over image should be a NIPY Image, or '\ 'a ResampledIndexVolumeSlicer') # self.over is definitely the right type, but is it aligned? if ax_order: axes = vu.find_spatial_correspondence(self.over.coordmap) if axes != ax_order: print 'Re-mapping because original mapping is not aligned '\ 'to the main image' # re-make a NIPY Image, and send it back! ni_image = ni_api.Image( self.over.image_arr, self.over.coordmap ) self.over = ResampledIndexVolumeSlicer( ni_image, norm=False, spatial_axes=ax_order, order=self.over_spline_order ) return temp_idx = self.over.image_arr if not self.main: self._over_idx = temp_idx self._adapt_to_slicer() else: self.trait_setq(_over_idx=temp_idx) self._resample_over_into_main()
def _update_mbytes(self): """Makes a ResampledIndexVolumeSlicer out of the argument, and enforces the spatial-to-array correspondence set up in the transpose mode. """ if self.main==None: # "unload" main image self._main_idx = np.array([], np.int32) # trigger remapping of over index self.over = self.over return if isinstance(self.main, ni_api.Image): img = self.main spatial_axes = vtk_ax_order if self.vtk_order else None main = ResampledIndexVolumeSlicer( img, norm=self.main_norm, spatial_axes=spatial_axes, order=self.main_spline_order ) # go ahead and be re-entrant self.main = main return if not isinstance(self.main, ResampledIndexVolumeSlicer): raise ValueError('main image should be a NIPY Image, or '\ 'a ResampledIndexVolumeSlicer') # self.main is definitely the right type, but is it aligned? if self.vtk_order: # with VTK order, x,y,z must be aligned with k, j, i axes = vu.find_spatial_correspondence(self.main.coordmap) if axes != vtk_ax_order: # re-make a NIPY Image, and send it back! ni_image = ni_api.Image( self.main.image_arr, self.main.coordmap ) self.main = ni_image return if len(self._over_idx) and \ self.main.image_arr.shape != self._over_idx.shape: # in case anything is watching main_rgba, (which will change with # this update), temporarily set over_idx to an empty array so that # the blending is valid over_img = self.over self.over = None self._main_idx = self.main.image_arr # send the over image back through its vetting process self.over = over_img else: self._main_idx = self.main.image_arr # remap the over image (??) self.over = self.over self._adapt_to_slicer()
def __init__(self, image, bbox=None, mask=False, grid_spacing=None, spatial_axes=None, **interp_kws): """ Creates a new ResampledVolumeSlicer Parameters ---------- image : a NIPY Image The image to slice bbox : iterable (optional) The {x,y,z} limits of the enrounding volume box. If None, then slices planes in the natural box of the image. This argument is useful for overlaying an image onto another image's volume box mask : bool or ndarray (optional) A binary mask, with same shape as image, with unmasked points marked as True (opposite of MaskedArray convention) grid_spacing : sequence (optional) New grid spacing for the sliced planes. If None, then the natural voxel spacing is used. spatial_axes : sequence (optional) Normally the image will not be resampled as long as there is a one-to-one correspondence from array axes to spatial axes. However, a desired correspondence can be specified here. List in 'x, y, z' order. interp_kws : dict Keyword args for the interpolating machinery.. eg: * order -- spline order * mode -- Points outside the boundaries of the input are filled according to the given mode ('constant', 'nearest', 'reflect' or 'wrap'). Default is 'constant'. * cval -- fill value if mode is 'constant' """ # XYZ: NEED TO BREAK API HERE FOR MASKED ARRAY xyz_image = ni_api.Image( image._data, image.coordmap.reordered_range(xipy_ras) ) native_spacing = vu.voxel_size(xyz_image.affine) zoom_grid = grid_spacing is not None and \ (np.array(grid_spacing) != native_spacing).any() # if no special instructions and image is somewhat aligned, # don't bother with rotations aligned = vu.is_spatially_aligned(image.coordmap) and not zoom_grid self.__resamp_kws = dict() if aligned: # if aligned, double check that it is also aligned with # spatial_axes (if present) axes = vu.find_spatial_correspondence(image.coordmap) if spatial_axes and axes != spatial_axes: # XYZ: IF ARRAY IS ALIGNED IN SOME ORIENTATION, COULD # RE-ALIGN WITH "spatial_axes" WITH A SIMPLE TRANSFORM aligned = False interp_kws['order'] = 0 else: world_image = xyz_image if not aligned: print 'resampling entire Image volume' self.__resamp_kws.update(interp_kws) self.__resamp_kws.update( dict(grid_spacing=grid_spacing, axis_permutation=spatial_axes) ) world_image = vu.resample_to_world_grid( image, **self.__resamp_kws ) self.coordmap = world_image.coordmap self.image_arr = np.asanyarray(world_image) self.grid_spacing = vu.voxel_size(world_image.affine) # take down the final bounding box; this will define the # field of the overlay plot self.bbox = vu.world_limits(world_image) # now find the logical axis to array axis mapping self._ax_lookup = vu.spatial_axes_lookup(self.coordmap) w_shape = world_image.shape # these planes are shaped as if the image_arr were # sliced along a given axis self.null_planes = [np.ma.masked_all((w_shape[0], w_shape[1]),'B'), np.ma.masked_all((w_shape[0], w_shape[2]),'B'), np.ma.masked_all((w_shape[1], w_shape[2]),'B')] # finally, update mask if necessary mask = np.ma.getmask(image._data) if mask is not np.ma.nomask: mask = ni_api.Image(mask, image.coordmap) self.update_mask(mask, positive_mask=False)