def my_volshow_2channel(volume, view=(0, 0, 0), rotation=(0, 0, 0, 'XYZ'), perspective=None, plot_params=None, fig_width=400, fig_height=500): """Customized volume show function, with specified camera position and angle. Args: volume: multi-channnel volume data view: camera position rotation: camera angle perspective: alternatively, pre-saved camera perspective plot_params: list of key-word arguments as a dictionary for ipv.volshow """ n_channels = len(volume) if plot_params is None: plot_params = [{}] * n_channels assert len(plot_params) == n_channels ipv.pylab.figure(width=fig_width, height=fig_height) for ch in range(n_channels): ipv.volshow(volume[ch, :], **plot_params[ch]) ipv.show() # wait for plot to be generated (JavaScript) time.sleep(1) # set camera position and angle set_perspective(view=view, rotation=rotation, perspective=perspective)
def volshow_zoom_correct_scale(x_list, y_list, z_list, f, zoom_factor=0): # zoom_factor is the number of times the grid is doubled # (actually a zoom by 2 ** zoom_factor) # Assume constant spacing in each dimension dx = np.mean(np.diff(x_list)) dy = np.mean(np.diff(y_list)) dz = np.mean(np.diff(z_list)) # zoom x_grid, y_grid, z_grid = np.meshgrid(x_list, y_list, z_list, indexing='ij') new_f = double_n(f, zoom_factor) # data extent extent = ((min(x_list) - dx / 2, max(x_list) + dx / 2), (min(y_list) - dy / 2, max(y_list) + dy / 2), (min(z_list) - dz / 2, max(z_list) + dz / 2)) ipv.figure() # volshow ipv.volshow(new_f.T) # figure extent ipv.xlim(min(x_list) - dx / 2, max(x_list) + dx / 2) ipv.ylim(min(y_list) - dy / 2, max(y_list) + dy / 2) ipv.zlim(min(z_list) - dz / 2, max(z_list) + dz / 2) ipv.show()
def on_select_to_plot(self, change): """Call-back function for plotting a 3D visualisaiton of the segmentation""" #if the selected file has changed, import image, segmentation and global mask and plot if change['new'] != change['old']: print('new: ' + str(change['new'])) print('old: ' + str(change['old'])) image = skimage.io.imread(self.folder_name + '/' + self.select_file_to_plot.value, plugin='tifffile') image2 = skimage.io.imread( self.folder_name + '/' + os.path.splitext(self.select_file_to_plot.value)[0] + '_label.tif', plugin='tifffile') image3 = skimage.io.imread( self.folder_name + '/' + os.path.splitext(self.select_file_to_plot.value)[0] + '_region.tif', plugin='tifffile') #create ipyvolume figure ipv.figure() volume_image = ipv.volshow(image[0, :, :, :, 1], extent=[[0, 1024], [0, 1024], [-20, 20]], level=[0.3, 0.2, 0.2], opacity=[0.2, 0, 0]) volume_seg = ipv.plot_isosurface(np.swapaxes(image2 > 0, 0, 2), level=0.5, controls=True, color='green', extent=[[0, 1024], [0, 1024], [-20, 20]]) volume_reg = ipv.volshow(image3, extent=[[0, 1024], [0, 1024], [-20, 20]], level=[0.3, 0.2, 1], opacity=[0.0, 0, 0.5]) volume_reg.brightness = 10 volume_image.brightness = 10 volume_image.opacity = 100 ipv.xyzlim(0, 1024) ipv.zlim(-500, 500) ipv.style.background_color('black') #create additional controls to show/hide segmentation color = ColorPicker(description='Segmentation color') visible = ipw.Checkbox() jslink((volume_seg, 'color'), (color, 'value')) jslink((volume_seg, 'visible'), (visible, 'value')) ipv.show() with self.out: clear_output(wait=True) display(VBox([ipv.gcc(), color, visible])) viewer = napari.Viewer(ndisplay=3) viewer.add_image(image, colormap='red') viewer.add_image(image2, colormap='green', blending='additive') viewer.add_image(image3, colormap='blue', blending='additive')
def volshow_with_isoplanes_and_zoom(x_list, y_list, z_list, f, zoom_factor): # zoom_factor is the number of times the grid is doubled # (actually a zoom by 2 ** zoom_factor) # Assume constant spacing in each dimension dx = np.mean(np.diff(x_list)) dy = np.mean(np.diff(y_list)) dz = np.mean(np.diff(z_list)) # zoom x_grid, y_grid, z_grid = np.meshgrid(x_list, y_list, z_list, indexing='ij') new_f = double_n(f, zoom_factor) # data extent extent = ((min(x_list) - dx / 2, max(x_list) + dx / 2), (min(y_list) - dy / 2, max(y_list) + dy / 2), (min(z_list) - dz / 2, max(z_list) + dz / 2)) ipv.figure() # isosurfaces ipv.plot_isosurface(new_f) # volshow ipv.volshow(new_f.T) ipv.show()
def draw_tensor(tensor_img): ipv.figure() # ipv.volshow(tensor_img[...,0], level=[0.36, 0.55,1], opacity=[0.11,0.13, 0.13], level_width=0.05, data_min=0, data_max=1 ,lighting=True) ipv.volshow(tensor_img[...,0], level=[0.36, 0.17,0.36], opacity=[0.05,0.13, 0.10], level_width=0.05, data_min=0, data_max=1 ,lighting=True) ipv.view(-30, 45) ipv.show()
def update_volume_plot(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") F = self.func_3d( self.vX, self.vY, self.vZ, self.a_slider.value, self.b_slider.value ) # For whatever reason, we have to rearrange the dimensions # for the plot axes to be correct. # See numpy.rollaxis, numpy.meshgrid for more information. ipv.volshow( rollaxis(F, 2) )
def update(self): # print(self.layer) if isinstance(self.layer, Subset): try: mask = self.layer.to_mask() except IncompatibleAttribute: # The following includes a call to self.clear() self.disable("Subset cannot be applied to this data") return else: self._enabled = True # if self.state.subset_mode == 'outline': # data = mask.astype(np.float32) # else: data = self.layer.data[self.state.attribute].astype(np.float32) data *= mask else: data = self.layer[self.state.attribute] #data = self.layer.data[self.state.attribute].astype(np.float32) #print(data, data.shape, self.state.attribute) finite_mask = np.isfinite(data) finite_data = data[finite_mask] finite_mask_normalized = finite_data - finite_data.min() finite_mask_normalized = finite_mask_normalized / finite_mask_normalized.max( ) data_min, data_max = np.nanmin(data), np.nanmax( data ) #np.percentile(finite_data, 1), np.percentile(finite_data, 99) # data_min, data_max = 0, 1 # self.state.data_min = data_min # self.state.data_max = data_max #data_min, data_max = None, None self.last_shape = shape = data.shape if self.volume is None: with self.figure: self.volume = ipv.volshow( data, data_min=data_min, data_max=data_max, extent=[[0, shape[0]], [0, shape[1]], [0, shape[2]]], controls=False, tf=self.transfer_function ) #, volume_rendering_method=self.state.render_method) else: self.volume.extent_original = [[0, shape[0]], [0, shape[1]], [0, shape[2]]] self.volume.data_original = data self.volume.data_min = data_min self.volume.data_max = data_max self.widget_data_min.value = self.state.vmin self.widget_data_max.value = self.state.vmax # might be a bug in glue-core, it seems that for subsets vmin/vmax are # not calculated if self.state.vmin == self.state.vmax == 0: self.state.lim_helper.log = False self.state.percentile = 100
def quickvolshow( data, lighting=False, data_min=None, data_max=None, max_shape=256, level=[0.1, 0.5, 0.9], opacity=[0.01, 0.05, 0.1], level_width=0.1, extent=None, memorder='C', **kwargs ): """Visualize a 3d array using volume rendering. :param data: 3d numpy array :param lighting: boolean, to use lighting or not, if set to false, lighting parameters will be overriden :param data_min: minimum value to consider for data, if None, computed using np.nanmin :param data_max: maximum value to consider for data, if None, computed using np.nanmax :param int max_shape: maximum shape for the 3d cube, if larger, the data is reduced by skipping/slicing (data[::N]), set to None to disable. :param extent: list of [[xmin, xmax], [ymin, ymax], [zmin, zmax]] values that define the bounds of the volume, otherwise the viewport is used :param level: level(s) for the where the opacity in the volume peaks, maximum sequence of length 3 :param opacity: opacity(ies) for each level, scalar or sequence of max length 3 :param level_width: width of the (gaussian) bumps where the opacity peaks, scalar or sequence of max length 3 :param kwargs: extra argument passed to Volume and default transfer function :return: """ ipv.figure() ipv.volshow( data, lighting=lighting, data_min=data_min, data_max=data_max, max_shape=max_shape, level=level, opacity=opacity, level_width=level_width, extent=extent, memorder=memorder, **kwargs ) return ipv.gcc()
def ball(rmax=3, rmin=0, shape=128, limits=[-4, 4], **kwargs): __, __, __, r, theta, phi = xyz(shape=shape, limits=limits, spherical=True) data = r * 0 data[(r < rmax) & (r >= rmin)] = 0.5 if "data_min" not in kwargs: kwargs["data_min"] = 0 if "data_max" not in kwargs: kwargs["data_max"] = 1 return ipyvolume.volshow(data=data.T, **kwargs)
def test_limits(): f = p3.figure() p3.xlim(-10, 11) assert f.xlim[0] == -10 assert f.xlim[1] == 11 p3.ylim(-12, 13) assert f.ylim[0] == -12 assert f.ylim[1] == 13 p3.zlim(-14, 15) assert f.zlim[0] == -14 assert f.zlim[1] == 15 p3.xyzlim(-17, 17) assert f.xlim[0] == -17 assert f.xlim[1] == 17 assert f.ylim[0] == -17 assert f.ylim[1] == 17 assert f.zlim[0] == -17 assert f.zlim[1] == 17 # TODO: actually, default xlim should be None, and the limits should # then now grow, but 'move' around the new point f = ipv.figure() assert f.xlim == [0, 1] ipv.ylim(0, 10) ipv.zlim(-10, 0) ipv.scatter(3, 4, 5) assert f.xlim == [0, 3] assert f.ylim == [0, 10] assert f.zlim == [-10, 5] f = ipv.figure() ipv.volshow(np.random.rand(5, 5, 5), extent=[[0.1, 0.9], [0.5, 2], [-2, 5]]) assert f.xlim == [0, 1] assert f.ylim == [0, 2] assert f.zlim == [-2, 5]
def update(self): if isinstance(self.layer, Subset): try: mask = self.layer.to_mask() except IncompatibleAttribute: # The following includes a call to self.clear() self.disable("Subset cannot be applied to this data") return else: self.enable() data = self.layer.data[self.state.attribute].astype(np.float32) data *= mask else: data = self.layer[self.state.attribute] finite_mask = np.isfinite(data) finite_data = data[finite_mask] finite_mask_normalized = finite_data - finite_data.min() finite_mask_normalized = finite_mask_normalized / finite_mask_normalized.max( ) data_min, data_max = np.nanmin(data), np.nanmax(data) self.last_shape = shape = data.shape if self.volume is None: with self.figure: self.volume = ipv.volshow(data, data_min=data_min, data_max=data_max, extent=[[0, shape[0]], [0, shape[1]], [0, shape[2]]], controls=False, tf=self.transfer_function) else: self.volume.extent_original = [[0, shape[0]], [0, shape[1]], [0, shape[2]]] self.volume.data_original = data self.volume.data_min = data_min self.volume.data_max = data_max self.state.data_min = self.state.vmin self.state.data_max = self.state.vmax # might be a bug in glue-core, it seems that for subsets vmin/vmax are # not calculated if self.state.vmin == self.state.vmax == 0: self.state.lim_helper.log = False self.state.percentile = 100
def head(draw=True, show=True, max_shape=256): """Show a volumetric rendering of a human male head""" # inspired by http://graphicsrunner.blogspot.com/2009/01/volume-rendering-102-transfer-functions.html import ipyvolume as ipv from scipy.interpolate import splrep, splev, interp1d # First part is a simpler version of setting up the transfer function. Interpolation with higher order # splines does not work well, the original must do sth different colors = [[.91, .7, .61, 0.], [.91, .7, .61, 80.], [1.0, 1.0, .85, 82.], [1.0, 1.0, .85, 256]] x = np.array([k[-1] for k in colors]) rgb = np.array([k[:3] for k in colors]) N = 256 xnew = np.linspace(0, 256, N) tf_data = np.zeros((N, 4)) k = 1 s = 1 # kind = 'quadratic' kind = 'linear' for channel in range(3): # spline_data = splrep(x, rgb[:,channel], k=k, s=s) # ynew = splev(xnew, spline_data) f = interp1d(x, rgb[:,channel], kind=kind) ynew = f(xnew) tf_data[:,channel] = ynew alphas = [[0, 0], [0, 40], [0.2, 60], [0.05, 63], [0, 80], [0.9, 82], [1., 256]] x = np.array([k[1]*1. for k in alphas]) y = np.array([k[0]*1. for k in alphas]) # spline_data = splrep(x, y, k=k, s=s) # ynew = splev(xnew, spline_data) f = interp1d(x, y, kind=kind) ynew = f(xnew) tf_data[:,3] = ynew tf = ipv.TransferFunction(rgba=tf_data.astype(np.float32)) head_data = ipv.datasets.head.fetch().data if draw: vol = ipv.volshow(head_data, tf=tf, max_shape=max_shape) if show: ipv.show() return vol else: return head_data
def example_ylm(m=0, n=2, shape=128, limits=[-4, 4], **kwargs): __, __, __, r, theta, phi = xyz(shape=shape, limits=limits, spherical=True) radial = np.exp(-(r - 2)**2) data = np.abs(scipy.special.sph_harm(m, n, theta, phi)**2) * radial return ipyvolume.volshow(data=data.T, **kwargs)
# Here we can show the thickness map in an interactive 3D manner using the ipyvolume tools (probably only works in the Chrome browser) # In[29]: import ipyvolume as p3 fig = p3.figure() # create a custom LUT temp_tf = plt.cm.nipy_spectral(np.linspace(0, 1, 256)) # make transparency more aggressive temp_tf[:, 3] = np.linspace(-0.3, 0.5, 256).clip(0, 1) tf = p3.transferfunction.TransferFunction(rgba=temp_tf) p3.volshow( (thickness_map[::2, ::2, ::2] / thickness_map.max()).astype(np.float32), lighting=True, max_opacity=0.5, tf=tf, controls=True, ) p3.show() p3.save("bubbles.html") # # Interfaces / Surfaces # # Many physical and chemical processes occur at surfaces and interfaces and consequently these structures are important in material science and biology. For this lecture surface and interface will be used interchangebly and refers to the boundary between two different materials (calcified bone and soft tissue, magma and water, liquid and gas) Through segmentation we have identified the unique phases in the sample under investigation. # # - Segmentation identifying volumes (3D) or areas (2D) # - Interfaces are one dimension lower corresponding to surface area (3D) or perimeter (2D) # - Interfaces are important for # - connectivity of cell networks, particularly neurons
import ipyvolume as ipv import h5py import numpy as np file_name = '../model_normalized_64.h5' model = h5py.File(file_name, 'r') data = np.array(model['data'][:]) X = data[:,:,:,0] Y = data[:,:,:,1] Z = data[:,:,:,2] fig = ipv.figure() ipv.volshow(X, controls=False, max_shape=64) ipv.volshow(Y, controls=False, max_shape=64) ipv.volshow(Z, controls=False, max_shape=64) ipv.show()
def on_select_to_plot(self, b): """Call-back function for plotting a 3D visualisaiton of the segmentation""" self.out.clear_output() image = skimage.io.imread(self.folders.cur_dir.as_posix() + '/' + self.folders.file_list.value[0], plugin='tifffile') image2 = skimage.io.imread( self.folders.cur_dir.as_posix() + '/' + os.path.splitext(self.folders.file_list.value[0])[0] + '_label.tif', plugin='tifffile') image3 = skimage.io.imread( self.folders.cur_dir.as_posix() + '/' + os.path.splitext(self.folders.file_list.value[0])[0] + '_region.tif', plugin='tifffile') scalez = 1024 / (int(self.scalingfactor.value)) xy_extent = [0, 1024] #create ipyvolume figure with self.out: ipv.figure() self.volume_image = ipv.volshow( image[0, :, :, :, 1], extent=[xy_extent, xy_extent, [-scalez, scalez]], level=[0.3, 0.2, 0.2], opacity=[0.2, 0, 0], controls=False) self.volume_seg = ipv.plot_isosurface( np.swapaxes(image2 > 0, 0, 2), level=0.5, controls=False, color='green', extent=[xy_extent, xy_extent, [-scalez, scalez]]) self.volume_reg = ipv.plot_isosurface( np.swapaxes(image3 > 0, 0, 2), level=0.5, controls=False, color='blue', extent=[xy_extent, xy_extent, [-scalez, scalez]]) self.volume_reg.brightness = 10 self.volume_image.brightness = 10 self.volume_image.opacity = 100 ipv.xyzlim(0, 1024) ipv.zlim(-500, 500) ipv.style.background_color('white') minval_data = ipw.IntSlider(min=0, max=255, value=255, description='min val') maxval_data = ipw.IntSlider(min=0, max=255, value=255, description='max val') brightness_data = ipw.FloatSlider(min=0, max=100, value=7.0, description='brightness') opacity_data = ipw.FloatSlider(min=0, max=100, value=7.0, description='opacity') level_data = ipw.FloatSlider(min=0, max=1, value=0.3, step=0.01, description='level') levelwidth_data = ipw.FloatSlider(min=0, max=1, value=0.1, step=0.01, description='level width') color = ColorPicker(description='Segmentation color') color2 = ColorPicker(description='Segmentation color') visible_seg = ipw.Checkbox() visible_reg = ipw.Checkbox() jslink((self.volume_image, 'show_min'), (minval_data, 'value')) jslink((self.volume_image, 'show_max'), (maxval_data, 'value')) jslink((self.volume_image, 'brightness'), (brightness_data, 'value')) jslink((self.volume_image.tf, 'opacity1'), (opacity_data, 'value')) jslink((self.volume_image.tf, 'level1'), (level_data, 'value')) jslink((self.volume_image.tf, 'width1'), (levelwidth_data, 'value')) jslink((self.volume_seg, 'color'), (color, 'value')) jslink((self.volume_reg, 'color'), (color2, 'value')) jslink((self.volume_seg, 'visible'), (visible_seg, 'value')) jslink((self.volume_reg, 'visible'), (visible_reg, 'value')) ipv.show() image_controls = HBox([ VBox([minval_data, maxval_data]), VBox([ brightness_data, opacity_data, level_data, levelwidth_data ]) ]) display( VBox([ HBox([color, visible_seg]), HBox([color2, visible_reg]), image_controls ]))
# In[10]: from scipy.ndimage import zoom # we downsample the image to make 3d rendering quicker fossil_downscale = zoom(closed_fossil_data.astype(np.float32), 0.25) # now we display it with a nice mesh _ = show_3d_mesh(fossil_downscale, 0.5) # # Tasks # # 1. Adjust the threshold and angles to try and see the gut structure better # 2. Improve the filters by using more advanced techniques and windows (bonus for non-local means) # 3. Apply the same analysis to the teeth fossil data (teeth_fossil.tif) # 4. Show the inside of the fossil and try to visualize different structures there # # Fun Bonus # You can use ipyvolume to interactively view the volume in the browser (a lower resolution version) # In[11]: import ipyvolume as p3 p3.volshow(fossil_downscale) # In[ ]:
def show_attention_volume( scan, attention_maps, tasks=[], show_ct=True, show_pet=False, downscale=1, exam_id="", movie_dir=None, colormap=None, flip_axes=None, ): colors = plt.get_cmap("Set1").colors widgets = [] def add_controls(volume, name, color=None): """ """ level = FloatLogSlider( base=10, min=-0.5, max=0, step=0.01, description=f"{name} level:" ) opacity = FloatLogSlider( base=10, min=-2, max=0.6, step=0.01, description=f"{name} opacity:" ) jslink((volume.tf, "level1"), (level, "value")) jslink((volume.tf, "level2"), (level, "value")) jslink((volume.tf, "level3"), (level, "value")) jslink((volume, "opacity_scale"), (opacity, "value")) button = Button(description=name) if color is not None: button.style.button_color = color controls = HBox([button, level, opacity]) widgets.append(controls) ipv.clear() f = ipv.figure() for idx, task in enumerate(tasks): attention_map = attention_maps[task] attention_map = attention_map.cpu().detach().numpy() attention_map = np.mean(attention_map, axis=1) attention_map = attention_map[0, :, ::].squeeze() # scale volume up scan_shape = scan[:, :, :, :, 0].squeeze().shape for dim_idx, scan_dim in enumerate(scan_shape): repeat = np.round(scan_dim / attention_map.shape[dim_idx]) attention_map = np.repeat(attention_map, repeat, axis=dim_idx) # set color if colormap is None: color = np.array(colors[idx % len(colors)]) else: color = np.array(colormap[task]) / 256 opacity = color * 0.2 color = "#%02x%02x%02x" % tuple(map(int, color * 255)) attention_map = attention_map[::downscale, ::downscale, ::downscale] if flip_axes is not None: for flip_axis in flip_axes: attention_map = np.flip(attention_map, axis=flip_axis) saliency_vol = ipv.volshow( attention_map, level=(1.0, 1.0, 1.0), opacity=opacity, controls=True, extent=[ [0, attention_map.shape[0]], [0, attention_map.shape[1]], [0, attention_map.shape[2]], ], ) add_controls(saliency_vol, name=task, color=color) if show_ct: ct = scan[:, :, :, :, 0].squeeze() ct = ct[::downscale, ::downscale, ::downscale] if flip_axes is not None: for flip_axis in flip_axes: ct = np.flip(ct, axis=flip_axis) ct_vol = ipv.volshow( ct, downscale=100, level=(0.7, 0.7, 0.7), opacity=(0.2, 0.2, 0.2), extent=[[0, ct.shape[0]], [0, ct.shape[1]], [0, ct.shape[2]]], ) add_controls(ct_vol, name="ct") if show_pet: pet = scan[:, :, :, :, 1].squeeze() pet = pet[::downscale, ::downscale, ::downscale] if flip_axes is not None: for flip_axis in flip_axes: pet = np.flip(pet, axis=flip_axis) color = np.array(colors[0 % len(colors)]) opacity = color * 0.2 pet_vol = ipv.volshow( pet, downscale=100, level=(0.7, 0.7, 0.7), opacity=opacity ) add_controls(pet_vol, name="pet") # ipv.xlim(0,attention_map.shape[0]) # ipv.ylim(0,attention_map.shape[1]) # ipv.zlim(0,attention_map.shape[2]) # ipv.squarelim() # f.camera.up = (-1, -1, -1) # f.camera.lookAt = (0, 0, 0) ipv.pylab.view(0, 0, 0) if movie_dir is not None: ipv.pylab.movie(f=os.path.join(movie_dir, f"{exam_id}.gif")) ipv.style.use("minimal") widgets.append(ipv.gcf()) return VBox(widgets)
def viz_particle_trails(swarm, topN=None, globalBestIndicatorFlag=True, tabbedPlot=False): startTime = time.time() targetMedianParticleSize = 3 nTreesDescaler = np.median(swarm.nTreesHistory) / targetMedianParticleSize minParticleSize = 2.5 maxParticleSize = 10 ipvFig = ipv.figure(width=ipvPlotWidth, height=ipvPlotHeight) # find top performing particles to show additional detail [ size scaled based on nTrees ] if topN is None: topN = swarm.nParticles topN = np.max((1, topN)) particleMaxes = {} for key, iParticle in swarm.particles.items(): if len(iParticle.testDataPerfHistory): particleMaxes[key] = max(iParticle.testDataPerfHistory) else: particleMaxes[key] = 0 sortedParticles = pd.DataFrame.from_dict( particleMaxes, orient='index').sort_values(by=0, ascending=False) topParticles = sortedParticles.index[0:np.min((np.max((topN, 1)), swarm.nParticles))] for iParticle in range(swarm.nParticles): if len(swarm.particles[iParticle].posHistory): particlePosHistory = np.matrix( swarm.particles[iParticle].posHistory) # plot markers along the particle's journey over the epoch sequence if iParticle in topParticles: # draw top particles with their unique color and scaled by the number of trees sortedIndex = np.where(topParticles == iParticle)[0][0] particleColor = rapidsColorsHex[sortedIndex % nRapidsColors] particleSizes = {} for iEval in range(swarm.particles[iParticle].nEvals): particleSizes[iEval] = np.clip( swarm.particles[iParticle].nTreesHistory[iEval] / nTreesDescaler, minParticleSize, maxParticleSize) #import pdb; pdb.set_trace() ipv.scatter(particlePosHistory[:, 0].squeeze(), particlePosHistory[:, 1].squeeze(), particlePosHistory[:, 2].squeeze(), size=np.array(list(particleSizes.values())), marker='sphere', color=particleColor, grow_limits=False) else: # draw non-top particle locations in gray particleColor = (.7, .7, .7, .9) ipv.scatter(particlePosHistory[:, 0].squeeze(), particlePosHistory[:, 1].squeeze(), particlePosHistory[:, 2].squeeze(), size=1.5, marker='sphere', color=particleColor, grow_limits=False) # plot line trajectory [ applies to both top and non-top particles ] ipv.plot(particlePosHistory[:, 0].squeeze(), particlePosHistory[:, 1].squeeze(), particlePosHistory[:, 2].squeeze(), color=particleColor) # draw an intersecting set of lines/volumes to indicate the location of the best particle / parameter-set if globalBestIndicatorFlag: bestXYZ = np.matrix(swarm.globalBest['params']) ipv.scatter(bestXYZ[:, 0], bestXYZ[:, 1], bestXYZ[:, 2], color=rapidsColorsHex[1], size=3, marker='box') data = np.ones((100, 2, 2)) xSpan = np.clip( (swarm.paramRanges[0][2] - swarm.paramRanges[0][1]) / 200, .007, 1) ySpan = np.clip( (swarm.paramRanges[1][2] - swarm.paramRanges[1][1]) / 200, .007, 1) zSpan = np.clip( (swarm.paramRanges[2][2] - swarm.paramRanges[2][1]) / 200, .007, 1) xMin = swarm.globalBest['params'][0] - xSpan xMax = swarm.globalBest['params'][0] + xSpan yMin = swarm.globalBest['params'][1] - ySpan yMax = swarm.globalBest['params'][1] + ySpan zMin = swarm.globalBest['params'][2] - zSpan zMax = swarm.globalBest['params'][2] + zSpan ipv.volshow(data=data.T, opacity=.15, level=[0.25, 0., 0.25], extent=[[xMin, xMax], [yMin, yMax], [swarm.paramRanges[2][1], swarm.paramRanges[2][2]]], controls=False) ipv.volshow(data=data.T, opacity=.15, level=[0.25, 0., 0.25], extent=[[swarm.paramRanges[0][1], swarm.paramRanges[0][2]], [yMin, yMax], [zMin, zMax]], controls=False) comboBox = append_label_buttons(swarm, ipvFig) if tabbedPlot: return comboBox display(comboBox) return None
def show_saliency_volume( saliency_maps, tasks=[], show_ct=True, show_pet=False, colormap=None ): colors = plt.get_cmap("Set1").colors widgets = [] def add_controls(volume, name, color=None): """ """ level = FloatLogSlider( base=10, min=-0.5, max=0, step=0.0002, description=f"{name} level:" ) opacity = FloatLogSlider( base=10, min=-2, max=1.0, step=0.01, description=f"{name} opacity:" ) jslink((volume.tf, "level1"), (level, "value")) jslink((volume.tf, "level2"), (level, "value")) jslink((volume.tf, "level3"), (level, "value")) jslink((volume, "opacity_scale"), (opacity, "value")) button = Button(description=name) if color is not None: button.style.button_color = color controls = HBox([button, level, opacity]) widgets.append(controls) ipv.clear() ipv.figure() data = {} for idx, task in enumerate(tasks): saliency_map = saliency_maps[task] scan_grad = saliency_map["scan_grad"] scan_grad = torch.max(scan_grad, dim=4)[0].unsqueeze(0) scan_grad = ( scan_grad.squeeze() ) # torch.nn.functional.max_pool3d(scan_grad, kernel_size=(7, 21, 21)).squeeze() scan_grad = scan_grad.numpy() scan_grad = scan_grad - scan_grad.min() scan_grad /= scan_grad.max() saliency_tensor = scan_grad saliency_tensor -= saliency_tensor.min() saliency_tensor /= saliency_tensor.max() if colormap is None: color = np.array(colors[idx % len(colors)]) else: color = np.array(colormap[task]) / 256 opacity = color * 0.2 color = "#%02x%02x%02x" % tuple(map(int, color * 256)) saliency_vol = ipv.volshow( saliency_tensor, downscale=100, level=(0.5, 0.5, 0.5), opacity=opacity, controls=True, ) data[task] = saliency_tensor add_controls(saliency_vol, name=task, color=color) scan = saliency_map["scan"].numpy() if show_ct: ct = scan[:, :, :, :, 0].squeeze() data["ct"] = ct ct_vol = ipv.volshow( ct, downscale=100, level=(1.0, 1.0, 1.0), opacity=(0.2, 0.2, 0.2) ) add_controls(ct_vol, name="ct") if show_pet: pet = scan[:, :, :, :, 1].squeeze() data["pet"] = pet opacity = (np.array((228, 26, 28)) / 256) * 0.2 pet_vol = ipv.volshow( pet, downscale=100, level=(0.7, 0.7, 0.7), opacity=opacity ) add_controls(pet_vol, name="pet") ipv.style.use("minimal") widgets.append(ipv.gcf()) return VBox(widgets), data