player_position_y >= self.height def draw_positions(self, new_positions, value): """bring position lists in the right format and draw the list of coordinates in a given color on the playground. """ positions = cle.push(np.asarray(new_positions)) values_and_positions = cle.create( [positions.shape[0] + 1, positions.shape[1]]) cle.set(values_and_positions, value) cle.paste(positions, values_and_positions, 0, 0) cle.write_values_to_positions(values_and_positions, self.temp) # start up napari with napari.gui_qt(): viewer = napari.Viewer(title="natari") game = Game() # Key bindings for user control @viewer.bind_key(player1_up_key) def player1_up_event(viewer): game.set_player1_direction(-1, 0) @viewer.bind_key(player1_down_key) def player1_down_event(viewer): game.set_player1_direction(1, 0) @viewer.bind_key(player1_left_key) def player1_left_event(viewer): game.set_player1_direction(0, -1)
def napari_process( data_channel: mp.Queue, initial_data: Dict[str, Dict[str, Any]], t_initial: float = None, viewer_args: Dict[str, Any] = None, ): """:mod:`multiprocessing.Process` running `napari <https://napari.org>`__ Args: data_channel (:class:`multiprocessing.Queue`): queue instance to receive data to view initial_data (dict): Initial data to be shown by napari. The layers are named according to the keys in the dictionary. The associated value needs to be a tuple, where the first item is a string indicating the type of the layer and the second carries the associated data t_initial (float): Initial time viewer_args (dict): Additional arguments passed to the napari viewer """ logger = logging.getLogger(__name__ + ".napari_process") try: import napari from napari.qt import thread_worker except ModuleNotFoundError: logger.error( "The `napari` python module could not be found. This module needs to be " "installed to use the interactive tracker." ) return logger.info("Start napari process") # ignore keyboard interrupts in this process signal.signal(signal.SIGINT, signal.SIG_IGN) if viewer_args is None: viewer_args = {} # start napari Qt GUI with napari.gui_qt(): # create and initialize the viewer viewer = napari.Viewer(**viewer_args) napari_add_layers(viewer, initial_data) # add time if given if t_initial is not None: from qtpy.QtWidgets import QLabel label = QLabel() label.setText(f"Time: {t_initial}") viewer.window.add_dock_widget(label) else: label = None def check_signal(msg: Optional[str]): """helper function that processes messages by the listener thread""" if msg is None: return # do nothing elif msg == "close": viewer.close() else: raise RuntimeError(f"Unknown message from listener: {msg}") @thread_worker(connect={"yielded": check_signal}) def update_listener(): """helper thread that listens to the data_channel """ logger.info("Start napari thread to receive data") # infinite loop waiting for events in the queue while True: # get all items from the queue and display the last update update_data = None # nothing to update yet while True: time.sleep(0.02) # read queue with 50 fps try: action, data = data_channel.get(block=False) except queue.Empty: break if action == "close": logger.info("Forced closing of napari...") yield "close" # signal to napari process to shut down break elif action == "update": update_data = data # continue running until the queue is empty else: logger.warning(f"Unexpected action: {action}") # update napari view when there is data if update_data is not None: logger.debug(f"Update napari layer...") layer_data, t = update_data if label is not None: label.setText(f"Time: {t}") for name, layer_data in layer_data.items(): viewer.layers[name].data = layer_data["data"] yield # start worker thread that listens to the data_channel update_listener() logger.info("Shutting down napari process")
def test_filter_docking(): viewer = napari.Viewer() viewer.window.add_dock_widget(filter_widget()) assert "Dock widget 1" in viewer.window._dock_widgets, 'filter widget has not been docked'
def show_napari_2d(): x = test_image_nuclei_2d() viewer = napari.Viewer() viewer.add_image(x) viewer.window.add_plugin_dock_widget("stardist-napari", "StarDist")
lines.append( np.stack([ points[np.arange(n_frames) + j[0] * n_frames], points[np.arange(n_frames) + j[1] * n_frames] ], axis=1)) lines = np.concatenate(lines, axis=0) lines[:, 1, :] = lines[:, 1, :] - lines[:, 0, :] return lines folder = 'data-njs/anipose/hand-demo/2019-08-02/' points = points_from_csv(folder + 'pose-3d/2019-08-02-vid01.csv') lines = lines_from_points(points[0]) base_colors = [[0, 1, 0], [1, 0, 1], [0, 1, 1], [1, 0, 0], [0, 0, 1]] digit_colors = base_colors[1:] + base_colors + base_colors + [[1, 1, 1] ] + base_colors multipliers = np.array([3] * 4 + [1] * 5 + [2] * 5 + [1] + [4] * 5) colors = np.expand_dims((5 - multipliers) / 4, axis=1) * digit_colors with napari.gui_qt(): viewer = napari.Viewer(title='2019-08-02-vid01', ndisplay=3) viewer.add_vectors(lines, name='lines', edge_color='white', edge_width=4) viewer.add_points(points[0], name='spots', properties=points[1], face_color='bodyparts', face_color_cycle=colors)
""" Display a 3D surface """ import numpy as np from skimage import data import napari with napari.gui_qt(): # create the viewer and window viewer = napari.Viewer(ndisplay=3) data = np.array([[0, 0, 0], [0, 20, 10], [10, 0, -10], [10, 10, -10]]) faces = np.array([[0, 1, 2], [1, 2, 3]]) values = np.linspace(0, 1, len(data)) # add the surface layer = viewer.add_surface((data, faces, values))
#supervoxels #filename = name + '/sv.h5' #f = open_file(data_path_1 + filename, 'r') #sv_test.append( f['data'][:,:,:].astype(np.float32)) #ground truth #ground_truth_1 = np.zeros_like(mem_test[-1], dtype = 'float32') #ground_truth_1[128:384, 128:384, 128:384] = dmv_test[-1] #ground_truth.append(ground_truth_1) #multicut filename = name + '_mc_blockwise.h5' #filename = name + '_mc.h5' f = open_file(data_path_results + filename, 'r') multicut.append(f['data'][:, :, :].astype(np.float32)) filename = 'result_lmc_test_' + name + '.h5' f = open_file(data_path_results_Julian + filename, 'r') multicut_Julian.append(f['data'][:, :, :].astype(np.float32)) n = len(names) viewer = [] with napari.gui_qt(): for i in range(n): viewer.append(napari.Viewer()) viewer[-1].add_image(raw_test[i], name=names[i] + 'raw') #viewer[-1].add_image(mem_test[i], name = 'membrane_prediction') viewer[-1].add_labels(multicut[i], name='multicut') viewer[-1].add_labels(multicut_Julian[i], name='multicut_J') #viewer[-1].add_image(ground_truth[i], name = 'DMV')
def __init__(self, path='', theStack=None, myStackWidget=None): print('=== bNapari.__init__() path:', path) self.myStackWidget = myStackWidget filename = os.path.basename(path) # load stack if neccessary if theStack is not None: self.mySimpleStack = theStack else: self.mySimpleStack = bimpy.bStack(path) # title = filename # todo oct 2020, add all open channels/masks stack = self.mySimpleStack.getStack('raw', channel=1) stack_nDim = len(stack.shape) self.viewer = napari.Viewer(title=title, ndisplay=stack_nDim) # # abb 20191216 removed self.bShapeAnalysisWidget = None #self.bShapeAnalysisWidget = bShapeAnalysisWidget(self.viewer, self.mySimpleStack) # xVoxel = self.mySimpleStack.xVoxel yVoxel = self.mySimpleStack.yVoxel zVoxel = self.mySimpleStack.zVoxel colormap = 'gray' if stack_nDim == 2: scale = (xVoxel, yVoxel) elif stack_nDim == 3: scale = (zVoxel, xVoxel, yVoxel) # (z, x, y) else: print('error: napari got stack dim it does not understand') colorMaps = ['green', 'red', 'blue'] # raw data for idx in range(self.mySimpleStack.numChannels): channel = idx + 1 colormap = colorMaps[idx] stack = self.mySimpleStack.getStack('raw', channel=channel) self.viewer.add_image(stack, name=str(channel), blending='additive', colormap=colormap, scale=scale) # mask data for idx in range(self.mySimpleStack.numChannels): channel = idx + 1 colormap = colorMaps[idx] stack = self.mySimpleStack.getStack('mask', channel=channel) self.viewer.add_image(stack, name='mask ' + str(channel), blending='additive', colormap=colormap, scale=scale) ''' dvMask = self.mySimpleStack.getDeepVessMask() if dvMask is not None: self.viewer.add_image(data=dvMask, contrast_limits=[0,1], opacity=0.8, colormap='gray', scale=scale, name='dvMask') ''' ''' @self.viewer.bind_key('u') def keyboard_u(viewer): shapeType, data = self._getSelectedLine() print(' keyboard_u()', shapeType, data) if shapeType == 'line': src = data[0] dst = data[1] self.bShapeAnalysisWidget.updateStackLineProfile(src, dst) if shapeType in ['rectangle', 'polygon']: self.bShapeAnalysisWidget.updateStackPolygon(data) ''' if self.mySimpleStack.slabList is not None: x = self.mySimpleStack.slabList.x * xVoxel y = self.mySimpleStack.slabList.y * yVoxel z = self.mySimpleStack.slabList.z * zVoxel d = self.mySimpleStack.slabList.d * xVoxel # use x d2 = self.mySimpleStack.slabList.d2 * xVoxel # use x nodeIdx = self.mySimpleStack.slabList.nodeIdx # this has nans which I assume will lead to some crashes ... points = np.column_stack(( z, x, y, )) scaleFactor = 0.6 print( 'warning: bNapari is scaling diameters by scaleFactor ... d = d *', scaleFactor) dCopy = d * scaleFactor d2Copy = d2 * scaleFactor fixedNodeSize = 4 # size_myNodes = [] face_color_myNodes = [] slabs_nodes = [] # size_myEdges = [] face_color_myEdges = [] slabs_edge = [] for idx in range(len(x)): if np.isnan(dCopy[idx]): thisSize = 5 else: thisSize = dCopy[idx] if nodeIdx[idx] >= 0: intNodeIdx = int(float(nodeIdx[idx])) nEdges = self.mySimpleStack.slabList.nodeDictList[ intNodeIdx]['nEdges'] #nodeSize = thisSize # dynamic size nodeSize = fixedNodeSize # fixed size slabs_nodes.append(idx) size_myNodes.append(nodeSize) if nEdges == 1: # dead end face_color_myNodes.append('orange') else: face_color_myNodes.append('red') else: slabSize = thisSize #slabSize = 5 # fixed size slabs_edge.append(idx) size_myEdges.append(slabSize) face_color_myEdges.append('cyan') # remember, (size, face_color), etc. Can be a scalar to set one value # debug if 0: print(' points:', points.shape) print(' len(size)', len(size)) print(' len(face_color)', len(face_color)) # nodes points_nodes = np.column_stack(( z[slabs_nodes], x[slabs_nodes], y[slabs_nodes], )) self.pointLayer = self.viewer.add_points( points_nodes, size=size_myNodes, face_color=face_color_myNodes) #, n_dimensional=False) self.pointLayer.name = 'Nodes' # edges points_edges = np.column_stack(( z[slabs_edge], x[slabs_edge], y[slabs_edge], )) self.pointLayer = self.viewer.add_points( points_edges, size=size_myEdges, face_color=face_color_myEdges) #, n_dimensional=False) self.pointLayer.name = 'Edges' # # connect edges with shape layer of 'path' print( 'making edge vector layer ... WE WILL ONLY DO THIS FOR 800 edges !!!' ) defaultWidth = 2 masterEdgeList = [] myPathColors = [] myPathEdgeWidths = [] for idx, edge in enumerate(self.mySimpleStack.slabList.edgeIter()): if idx > 800: continue edgeColor = edge[ 'color'] # when i make edges, i was not assigning color if edgeColor is None: edgeColor = 'cyan' slabList = edge['slabList'] #print('edge idx:', idx, 'edgeColor:', edgeColor, 'len(slabList):', len(slabList)) currentEdgeList = [] for slab in slabList: slabWidth = d2Copy[ slab] #* xVoxel # my slab width is still in pixels if np.isnan(slabWidth): #print('edge', idx, 'slab', slab, 'has nan width') slabWidth = defaultWidth currentEdgeList.append([z[slab], x[slab], y[slab]]) myPathColors.append(edgeColor) myPathEdgeWidths.append(slabWidth) masterEdgeList.append( currentEdgeList) # this will be list of list myEdgesPaths = [ np.array(xx) for xx in masterEdgeList ] # always give napari a list where each[i] is a np.array ??? # self.myShapePathLayer = self.viewer.add_shapes( myEdgesPaths, shape_type='path', edge_width=myPathEdgeWidths, edge_color=myPathColors, name='Edges Paths') self.myShapePathLayer.editable = True self.connectNapari() # connect signals and slots # # make selection layers if self.mySimpleStack.slabList is not None: # edge selection selectionSize = 7 * xVoxel #np.column_stack((6,6,6,)) face_color = 'yellow' tmpData = np.column_stack(( np.nan, np.nan, np.nan, )) #todo: fix this self.edgeSelectionLayer = self.viewer.add_points( tmpData, size=selectionSize, face_color=face_color, n_dimensional=False) self.edgeSelectionLayer.name = 'Edge Selection' # flashSize = 10 * xVoxel flashColor = 'magenta' self.edgeSelectionLayerFlash = self.viewer.add_points( tmpData, size=flashSize, face_color=flashColor, n_dimensional=False) self.edgeSelectionLayerFlash.name = 'Flash Selection' # node selection selectionSize = 7 * xVoxel #np.column_stack((6,6,6,)) face_color = 'yellow' tmpData = np.column_stack(( np.nan, np.nan, np.nan, )) #todo: fix this self.nodeSelectionLayer = self.viewer.add_points( tmpData, size=selectionSize, face_color=face_color, n_dimensional=False) self.nodeSelectionLayer.name = 'Node Selection' # flashSize = 15 * xVoxel flashColor = 'magenta' self.nodeSelectionLayerFlash = self.viewer.add_points( tmpData, size=flashSize, face_color=flashColor, n_dimensional=False) self.nodeSelectionLayerFlash.name = 'Node Selection'
def view_plate( image_data, label_data=None, image_settings=None, label_settings=None, well_measurements=None, well_shape=None, zero_based=True, well_spacing=16, site_spacing=4, show=True, ): """Visualize data from a multi-well plate using napari. Args: image_data dict[str, [dict[str, list[np.array]]]]: list of image sources, each list contains a dict which maps the well names (e.g. A1, B3) to the image data for this well (one array per well position) label_data dict[str, [dict[str, list[np.array]]]]: list of label sources, each list contains a dict which maps the well names (e.g. A1, B3) to the label data for this well (one array per well position) (default: None) image_settings dict[str, dict]: image settings for the channels (default: None) label_settings dict[str, dict]: settings for the label channels (default: None) well_measurements dict[str, dict[str, [float, int, str]]]: measurements associated with the wells well_shape tuple[int]: the 2D shape of a well in terms of images, if not given will be derived. Well shape can only be derived for square wells and must be passed otherwise (default: None) zero_based bool: whether the well indexing is zero-based (default: True) well_sources int: spacing between wells, in pixels (default: 12) site_spacing int: spacing between sites, in pixels (default: 4) show bool: whether to show the viewer (default: True) """ # find the number of positions per well first_channel_sources = next(iter(image_data.values())) pos_per_well = len(next(iter(first_channel_sources.values()))) # find the well shape if well_shape is None: # well shape can only be derived for square wells assert pos_per_well in (1, 4, 9, 25, 36, 49), f"well is not square: {pos_per_well}" well_len = int(np.sqrt(pos_per_well)) well_shape = (well_len, well_len) else: assert len(well_shape) == 2 pos_per_well_exp = np.prod(list(well_shape)) assert pos_per_well_exp == pos_per_well, f"{pos_per_well_exp} != {pos_per_well}" def process_sources(sources, well_names): for well_sources in sources.values(): # make sure all wells have the same number of label n_pos_well = [len(sources) for sources in well_sources.values()] assert all( n_pos == pos_per_well for n_pos in n_pos_well), f"{pos_per_well} != {n_pos_well}" well_names.extend(list(well_sources.keys())) return well_names # find the well names for all sources well_names = process_sources(image_data, []) if label_data is not None: well_names = process_sources(label_data, well_names) well_names = list(set(well_names)) well_names.sort() # compute the well extent and well positions well_positions, well_start, well_stop = parse_wells(well_names, zero_based) assert len(well_positions) == len(well_names) # start the veiwer and add all sources viewer = napari.Viewer() shape = add_grid_sources(image_data, well_positions, well_shape, well_spacing, site_spacing, viewer.add_image, image_settings) if label_data is not None: add_grid_sources(label_data, well_positions, well_shape, well_spacing, site_spacing, viewer.add_labels, label_settings) # add shape layer corresponding to the well positions add_plate_layout(viewer, well_names, well_positions, well_shape, well_spacing, site_spacing, shape, measurements=well_measurements) # set the camera so that the initial view is centered around the existing wells # and zoom out so that the central well is fully visible set_camera(viewer, well_start, well_stop, well_shape, well_spacing, site_spacing, shape) if show: napari.run() return viewer
dmv.append(f['data'][:, :, ].astype(np.float32)) #supervoxels filename = name + '_sv.h5' f = open_file(data_path + filename, 'r') supervoxels.append(f['data'][:, :, :].astype(np.float32)) #results of multicut segmentation filename = name + '_mc.h5' f = open_file(data_path + filename, 'r') multicut.append(f['data'][:, :, :].astype(np.float32)) ground_truth_1 = np.zeros_like(membrane_prediction[-1], dtype='float32') ground_truth_1[128:384, 128:384, 128:384] = dmv[-1] ground_truth.append(ground_truth_1) with napari.gui_qt(): viewer = napari.Viewer() viewer.add_image(raw[0], name='raw') viewer.add_image(membrane_prediction[0], name='membrane_prediction') viewer.add_labels(multicut[0], name='multicut') viewer.add_image(ground_truth[0], name='DMV') viewer.add_image(supervoxels[0], name='supervoxels') viewer1 = napari.Viewer() viewer1.add_image(raw[1], name='raw') viewer1.add_image(membrane_prediction[1], name="membrane_prediction") viewer1.add_labels(multicut[1], name='multicut') viewer1.add_image(ground_truth[1], name='DMV') viewer1.add_image(supervoxels[1], name='supervoxels')
random_forest_labels = imread(str(rf_labels_path))[-1, :, :] data_with_labels[t, z, -2, :, :] = random_forest_labels # Load neural network-generated labels: nn_labels_path = nn_labels_dir / tif_name if nn_labels_path.is_file(): nn_output = imread(str(nn_labels_path)) # Convert from softmax 1-hot to labels: neural_network_labels = 1 + np.argmax(nn_output, axis=0) data_with_labels[t, z, -1, :, :] = neural_network_labels return data_with_labels with napari.gui_qt(): data_with_labels = load() viewer = napari.Viewer( title="Mister Clicky instructions: " + "Draw annotations in the 'Human labels' layer. " + "Press 'S' to save annotations, and 'R' to reload annotations.") for i in reversed(range(data_with_labels.shape[2] - 3)): layer = viewer.add_image(data_with_labels[:, :, i, :, :], name='Image ch %i' % i) layer.selected = False layer.blending = 'additive' layer.contrast_limits = (data_with_labels[:, :, i, :, :].min(), data_with_labels[:, :, i, :, :].max()) if i in range(4): layer.colormap = ('gray', 'red', 'green', 'blue')[i] viewer.add_labels(data_with_labels[:, :, -1, :, :], name='Neural net labels') viewer.layers['Neural net labels'].opacity = 0.25 viewer.layers['Neural net labels'].visible = False viewer.layers['Neural net labels'].editable = False
def view_zarr(input_path, scale=(1, 1, 1, 1, 4)): arr = da.from_zarr(input_path) with napari.gui_qt(): viewer = napari.Viewer() viewer.add_image(arr, name='all_channels', scale=scale)
def segmentation_correction(project_path, raw_path=None, raw_key=None, seg_path=None, seg_key=None, node_label_path=None, node_label_key=None, n_threads=8): """ """ # run preprocessing config = preprocess(project_path, raw_path, raw_key, seg_path, seg_key, node_label_path, node_label_key, n_threads=n_threads) node_labels = config['node_labels'] next_id = config['next_id'] n_threads = config['n_threads'] with napari.gui_qt(): viewer = napari.Viewer() viewer.add_image(config['raw'], name='raw') viewer.add_labels(config['seg'], name='seg') viewer.add_labels(config['merged_seg'], name='merged_seg') def _update_merged_seg(viewer, node_labels): seg = viewer.layers['seg'].data merged_seg = merge_seg_from_node_labels(seg, node_labels, n_threads) viewer.layers['merged_seg'].data = merged_seg # TODO this should be Shift + Right Click @viewer.bind_key('Shift-D') def split(viewer): nonlocal next_id nonlocal node_labels position = _get_cursor_position(viewer) if position is None: print("No layer was selected, aborting split") return # get the segmentation value under the cursor label_val = viewer.layers['seg'].data[position] if label_val == 0: print("Cannot split background label, aborting split") return prev_id = node_labels[label_val] print("Splitting label", label_val, "from id", prev_id, "and assigning id", next_id) node_labels[label_val] = next_id next_id += 1 _update_merged_seg(viewer, node_labels) print("split done") # TODO this should be Shift + Left Click AND should support selecting multiple # segments -> check out the new label properties functionality ! @viewer.bind_key('Shift-A') def merge(viewer): nonlocal node_labels position = _get_cursor_position(viewer) if position is None: print("No layer was selected, aborting detach") return # get the segmentation value under the cursor label_val = viewer.layers['seg'].data[position] if label_val == 0: print("Cannot merge background label, aborting merge") return # get the selected id in the merged seg layer src_id = viewer.layers['merged_seg'].selected_label if src_id == 0: print("Cannot merge into background value") return target_id = node_labels[label_val] print("Merging id", target_id, "into id", src_id) node_labels = { k: src_id if v == target_id else v for k, v in node_labels.items() } _update_merged_seg(viewer, node_labels) print("Merge done") @viewer.bind_key('s') def save(viewer): merged_seg = viewer.layers['merged_seg'].data with open_file(project_path, 'a') as f: f.attrs['next_id'] = next_id ds = f.require_dataset(MERGED_SEG_KEY, shape=merged_seg.shape, dtype=merged_seg.dtype, compression='gzip', chunks=(64, 64, 64)) ds.n_threads = n_threads ds[:] = merged_seg print("saving done")
def setup(self, n): _ = QApplication.instance() or QApplication([]) np.random.seed(0) self.data = np.random.random((n, n)) self.viewer = napari.Viewer()
# for lazy loading use dask reader movies.append( da_imread(folder + 'videos-raw/2019-08-02-vid01-' + n + '.MOV')) p = points_from_csv(folder + 'pose-2d/2019-08-02-vid01-' + n + '.csv') points.append(p) lines.append(lines_from_points(p[0])) #multipliers = np.array([1 + i for i in range(4)] + list(range(5)) + list(range(5)) + [4] + list(range(5))) #base_colors = np.array([[0, 1, 0]] * 4 + [[1, 0, 1]] * 5 + [[0, 1, 1]] * 5 + [[1, 1, 1]] + [[1, 1, 0]] * 5) base_colors = [[0, 1, 0], [1, 0, 1], [0, 1, 1], [1, 0, 0], [0, 0, 1]] digit_colors = base_colors[1:] + base_colors + base_colors + [[1, 1, 1] ] + base_colors multipliers = np.array([3] * 4 + [1] * 5 + [2] * 5 + [1] + [4] * 5) colors = np.expand_dims((5 - multipliers) / 4, axis=1) * digit_colors #print([m.shape for m in movies]) with napari.gui_qt(): viewer = napari.Viewer(title='2019-08-02-vid01') for n, m, p, l in zip(video_names, movies, points, lines): print(' adding ' + n) viewer.add_image(m, name=n) viewer.add_vectors(l, name=n + '-lines', edge_color='red', edge_width=5) #print(p[1]) #viewer.add_points(p[0], name=n+'-spots', properties=p[1], face_color='bodyparts', face_color_cycle=colors) viewer.grid.enabled = True viewer.grid_view(n_column=2, n_row=2, stride=2)
def main(): args = parser_3d_view().parse_args() data = brainio.load_any(args.image, load_parallel=args.parallel) with napari.gui_qt(): v = napari.Viewer(title="Cellfinder 3D viewer", ndisplay=3) v.add_image(data)
def run(self): # get the initial mws segmentation _print_help() # add initial layers to the viewer with napari.gui_qt(): viewer = napari.Viewer() # add image layers and point layer for seeds for name, img in self.data.items(): viewer.add_image(img, name=name) points_layer = viewer.add_points( # properties={'label': labels}, edge_color='#ff7f0e', # edge_color_cycle='#ff7f0e', symbol='o', face_color='transparent', edge_width=2, size=1, # ndim=2 ) # def next_on_click(layer, event): # """Mouse click binding to advance the label when a point is added""" # if layer.mode == 'add': # next_label() # # by default, napari selects the point that was just added # # disable that behavior, as the highlight gets in the way # layer.selected_data = {} # # save the current segmentation @viewer.bind_key('s') def segment(viewer): support_position = points_layer._data support_index = np.unique(points_layer.edge_color, axis=0, return_inverse=True)[1] # Todo: filter points outside of data # load embeddings test_spatial_embeddings = test_semantic_embeddings = spatial_matching_log_probas(train_spatial_embeddings, train_semantic_embeddings, test_spatial_embeddings, test_semantic_embeddings, train_targets, test_targets, args.num_ways, eps=1e-8) # nonlocal seg_path # seg_path = _read_file_path(seg_path) # seg = viewer.layers['segmentation'].data # _save(seg_path, seg) # @viewer.bind_key('v') # def save_seeds(viewer): # nonlocal seed_path # seed_path = _read_file_path(seed_path) # seeds = viewer.layers['seeds'].data # _save(seed_path, seeds) # display help @viewer.bind_key('h') def print_help(viewer): _print_help()
def demo( image_clipped: np.ndarray, two_pass: bool = False, inv_mse_before_forward_model: bool = False, inv_mse_lambda: float = 2.0, learning_rate: float = 0.01, max_epochs: int = 3000, patience: int = 1000, masking_density: float = 0.01, training_noise: float = 0.1, output_dir: str = "demo_results", loss: str = "l2", check: bool = False, optimizer: str = "esadam", scheduler: str = "plateau", clip_before_psf: bool = True, fft_psf: Union[str, bool] = "auto", standardize: bool = False, amp: bool = False, ): image_clipped = normalise(image_clipped.astype(numpy.float32)) blurred_image, psf_kernel = add_microscope_blur_2d(image_clipped) # noisy_blurred_image = add_noise(blurred_image, intensity=None, variance=0.01, sap=0.01, clip=True) noisy_blurred_image = add_poisson_gaussian_noise(blurred_image, alpha=0.001, sigma=0.1, sap=0.01, quant_bits=10) lr = ImageTranslatorLRDeconv(psf_kernel=psf_kernel, backend="cupy") lr.train(noisy_blurred_image) lr.max_num_iterations = 2 lr_deconvolved_image_2 = lr.translate(noisy_blurred_image) lr.max_num_iterations = 5 lr_deconvolved_image_5 = lr.translate(noisy_blurred_image) lr.max_num_iterations = 10 lr_deconvolved_image_10 = lr.translate(noisy_blurred_image) lr.max_num_iterations = 20 lr_deconvolved_image_20 = lr.translate(noisy_blurred_image) it_deconv = SSIDeconvolution( max_epochs=max_epochs, patience=patience, batch_size=8, learning_rate=learning_rate, normaliser_type="identity", psf_kernel=psf_kernel, model_class=UNet, masking=True, masking_density=masking_density, training_noise=training_noise, loss=loss, two_pass=two_pass, inv_mse_before_forward_model=inv_mse_before_forward_model, inv_mse_lambda=inv_mse_lambda, check=check, optimizer=optimizer, scheduler=scheduler, clip_before_psf=clip_before_psf, fft_psf=fft_psf, standardize_image=standardize, amp=amp, ) start = time.time() it_deconv.train(noisy_blurred_image) stop = time.time() print(f"Training: elapsed time: {stop - start} ") if not check: wandb.run.summary["training_time"] = stop - start start = time.time() deconvolved_image = it_deconv.translate(noisy_blurred_image) stop = time.time() print(f"inference: elapsed time: {stop - start} ") if not check: wandb.run.summary["inference_time"] = stop - start image_clipped = numpy.clip(image_clipped, 0, 1) lr_deconvolved_image_2_clipped = numpy.clip(lr_deconvolved_image_2, 0, 1) lr_deconvolved_image_5_clipped = numpy.clip(lr_deconvolved_image_5, 0, 1) lr_deconvolved_image_10_clipped = numpy.clip(lr_deconvolved_image_10, 0, 1) lr_deconvolved_image_20_clipped = numpy.clip(lr_deconvolved_image_20, 0, 1) deconvolved_image_clipped = numpy.clip(deconvolved_image, 0, 1) columns = ["PSNR", "norm spectral mutual info", "norm mutual info", "SSIM"] print_header(columns) print_score( "blurry image", psnr(image_clipped, blurred_image), spectral_mutual_information(image_clipped, blurred_image), mutual_information(image_clipped, blurred_image), ssim(image_clipped, blurred_image), ) print_score( "noisy and blurry image", psnr(image_clipped, noisy_blurred_image), spectral_mutual_information(image_clipped, noisy_blurred_image), mutual_information(image_clipped, noisy_blurred_image), ssim(image_clipped, noisy_blurred_image), ) print_score( "lr deconv (n=2)", psnr(image_clipped, lr_deconvolved_image_2_clipped), spectral_mutual_information(image_clipped, lr_deconvolved_image_2_clipped), mutual_information(image_clipped, lr_deconvolved_image_2_clipped), ssim(image_clipped, lr_deconvolved_image_2_clipped), ) print_score( "lr deconv (n=5)", psnr(image_clipped, lr_deconvolved_image_5_clipped), spectral_mutual_information(image_clipped, lr_deconvolved_image_5_clipped), mutual_information(image_clipped, lr_deconvolved_image_5_clipped), ssim(image_clipped, lr_deconvolved_image_5_clipped), ) print_score( "lr deconv (n=10)", psnr(image_clipped, lr_deconvolved_image_10_clipped), spectral_mutual_information(image_clipped, lr_deconvolved_image_10_clipped), mutual_information(image_clipped, lr_deconvolved_image_10_clipped), ssim(image_clipped, lr_deconvolved_image_10_clipped), ) print_score( "lr deconv (n=20)", psnr(image_clipped, lr_deconvolved_image_20_clipped), spectral_mutual_information(image_clipped, lr_deconvolved_image_20_clipped), mutual_information(image_clipped, lr_deconvolved_image_20_clipped), ssim(image_clipped, lr_deconvolved_image_20_clipped), ) psnr_deconv = psnr(image_clipped, deconvolved_image_clipped) smi_deconv = spectral_mutual_information(image_clipped, deconvolved_image_clipped) mi_deconv = mutual_information(image_clipped, deconvolved_image_clipped) ssim_deconv = ssim(image_clipped, deconvolved_image_clipped) if not check: wandb.run.summary["psnr"] = psnr_deconv wandb.run.summary["smi"] = smi_deconv wandb.run.summary["mi"] = mi_deconv wandb.run.summary["ssim"] = ssim_deconv print_score( "ssi deconv", psnr_deconv, smi_deconv, mi_deconv, ssim_deconv, ) print( "NOTE: if you get a bad results for ssi, blame stochastic optimisation and retry..." ) print( " The training is done on the same exact image that we infer on, very few pixels..." ) print(" Training should be more stable given more data...") if use_napari: with napari.gui_qt(): viewer = napari.Viewer() viewer.add_image(image_clipped, name="image") viewer.add_image(blurred_image, name="blurred") viewer.add_image(noisy_blurred_image, name="noisy_blurred_image") viewer.add_image(lr_deconvolved_image_2_clipped, name="lr_deconvolved_image_2") viewer.add_image(lr_deconvolved_image_5_clipped, name="lr_deconvolved_image_5") viewer.add_image(lr_deconvolved_image_10_clipped, name="lr_deconvolved_image_10") viewer.add_image(lr_deconvolved_image_20_clipped, name="lr_deconvolved_image_20") viewer.add_image(deconvolved_image_clipped, name="ssi_deconvolved_image") else: output_dir = Path(output_dir) output_dir.mkdir(parents=True, exist_ok=True) imwrite(output_dir / "image.png", image_clipped, format="png") imwrite(output_dir / "blurred.png", blurred_image, format="png") imwrite(output_dir / "noisy_blurred_image.png", noisy_blurred_image, format="png") imwrite( output_dir / "lr_deconvolved_image_2.png", lr_deconvolved_image_2_clipped, format="png", ) imwrite( output_dir / "lr_deconvolved_image_5.png", lr_deconvolved_image_5_clipped, format="png", ) imwrite( output_dir / "lr_deconvolved_image_10.png", lr_deconvolved_image_10_clipped, format="png", ) imwrite( output_dir / "lr_deconvolved_image_20.png", lr_deconvolved_image_20_clipped, format="png", ) imwrite( output_dir / "ssi_deconvolved_image.png", deconvolved_image_clipped, format="png", )
cache = Cache(8e9) # Leverage eight gigabytes of memory cache.register() # Turn cache on globally # Read the zarr images memimage = da.from_zarr( 'W:/SV3/RC_15-06-11/Dme_E2_His2AvRFP_spiderGFP_12-03_20150611_155054.corrected/Results/zarr/membrane.zarr' ) nucimage = da.from_zarr( 'W:/SV3/RC_15-06-11/Dme_E2_His2AvRFP_spiderGFP_12-03_20150611_155054.corrected/Results/zarr/nuclei.zarr' ) print(type(memimage), memimage.shape, memimage.dtype) # create Qt GUI context with napari.gui_qt(): # create a Viewer and add the images as layers viewer = napari.Viewer(axis_labels=['view', 't', 'z', 'y', 'x']) viewer.add_image(memimage, scale=[1, 1, 8, 1, 1], colormap='inferno', blending='additive', name='membrane', is_pyramid=False, rgb=False, contrast_limits=[10, 255]) viewer.add_image(nucimage, scale=[1, 1, 8, 1, 1], colormap='green', blending='additive', name='nuclei', is_pyramid=False, rgb=False,
import napari from magicgui import magicgui, register_type def get_viewers(gui, *args): """Get the viewer that the magicwidget is in.""" try: return (gui.parent().qt_viewer.viewer, ) except AttributeError: return tuple(v for v in globals().values() if isinstance(v, napari.Viewer)) register_type(napari.Viewer, choices=get_viewers) with napari.gui_qt(): # create a viewer and add some images viewer = napari.Viewer(title="Viewer A") viewer.add_image(skimage.data.astronaut(), name="astronaut") @magicgui(call_button="call", viewer={"visible": False}) def takes_viewer(viewer: napari.Viewer): """Just print the viewer.""" print(viewer) # instantiate the widget gui = takes_viewer.Gui() # Add it to the napari viewer viewer.window.add_dock_widget(gui)
def segment_from_directory( directory, suffix, affinities_channels, centroids_channel, thresholding_channel, scale = (4, 1, 1), w_scale=None, compactness=0., display=True, validation=False, **kwargs # ): images, _, output, GT = get_dataset(directory, GT=True, validation=validation) images = da.squeeze(images) print(output.shape) segmentations = [] masks = [] scores = {'GT | Output' : [], 'Output | GT' : []} for i in range(output.shape[0]): gt = GT[i].compute() seg, _, mask = segment_output_image( output[i], affinities_channels, centroids_channel, thresholding_channel, scale=w_scale, compactness=0.) vi = variation_of_information(gt, seg) scores['GT | Output'].append(vi[0]) scores['Output | GT'].append(vi[1]) seg = da.from_array(seg) segmentations.append(seg) masks.append(mask) segmentations = da.stack(segmentations) masks = da.stack(masks) # Save the VI data scores = pd.DataFrame(scores) if validation: s = 'validation_VI.csv' else: s = '_VI.csv' s_path = os.path.join(directory, suffix + s) scores.to_csv(s_path) gt_o = scores['GT | Output'].mean() o_gt = scores['Output | GT'].mean() print(f'Conditional entropy H(GT|Output): {gt_o}') print(f'Conditional entropy H(Output|GT): {o_gt}') if display: # Now Display z_affs = output[:, affinities_channels[0], ...] y_affs = output[:, affinities_channels[1], ...] x_affs = output[:, affinities_channels[2], ...] c = output[:, thresholding_channel, ...] cl = output[:, centroids_channel, ...] v_scale = [1] * len(images.shape) v_scale[-3:] = scale print(images.shape, v_scale, z_affs.shape, masks.shape) v = napari.Viewer() v.add_image(images, name='Input images', blending='additive', visible=True, scale=v_scale) v.add_image(c, name='Thresholding channel', blending='additive', visible=False, scale=v_scale) v.add_image(cl, name='Centroids channel', blending='additive', visible=False, scale=v_scale) v.add_image(z_affs, name='z affinities', blending='additive', visible=False, scale=v_scale, colormap='bop purple') v.add_image(y_affs, name='y affinities', blending='additive', visible=False, scale=v_scale, colormap='bop orange') v.add_image(x_affs, name='x affinities', blending='additive', visible=False, scale=v_scale, colormap='bop blue') v.add_labels(masks, name='Masks', blending='additive', visible=False, scale=v_scale) v.add_labels(GT, name='Ground truth', blending='additive', visible=False, scale=v_scale) v.add_labels(segmentations, name='Segmentations', blending='additive', visible=True, scale=v_scale) napari.run()
def run_cli(args): LI = calciumcharacterisation.LazyImarisTSReader(args.imarisfile[0]) v = napari.Viewer() l = v.add_image(LI.daskseries(), multiscale=False, name=args.imarisfile[0]) napari.run()
def demo(image_clipped): image_clipped = normalise(image_clipped.astype(numpy.float32)) blurred_image, psf_kernel = add_microscope_blur_2d(image_clipped) # noisy_blurred_image = add_noise(blurred_image, intensity=None, variance=0.01, sap=0.01, clip=True) noisy_blurred_image = add_poisson_gaussian_noise(blurred_image, alpha=0.001, sigma=0.1, sap=0.01, quant_bits=10) lr = ImageTranslatorLRDeconv(psf_kernel=psf_kernel, max_num_iterations=30, backend="cupy") lr.train(noisy_blurred_image) lr_deconvolved_image = lr.translate(noisy_blurred_image) it_deconv = PTCNNDeconvolution(max_epochs=3000, patience=100, batch_size=8, learning_rate=0.01, normaliser_type='identity', psf_kernel=psf_kernel, model_class=UNet, masking=True, masking_density=0.05, loss='l2', bounds_loss=0.1, sharpening=0, entropy=0, broaden_psf=1) start = time.time() it_deconv.train(noisy_blurred_image) stop = time.time() print(f"Training: elapsed time: {stop - start} ") start = time.time() deconvolved_image = it_deconv.translate(noisy_blurred_image) stop = time.time() print(f"inference: elapsed time: {stop - start} ") image_clipped = numpy.clip(image_clipped, 0, 1) lr_deconvolved_image_clipped = numpy.clip(lr_deconvolved_image, 0, 1) deconvolved_image_clipped = numpy.clip(deconvolved_image, 0, 1) print( "Below in order: PSNR, norm spectral mutual info, norm mutual info, SSIM: " ) printscore( "blurry image : ", psnr(image_clipped, blurred_image), spectral_mutual_information(image_clipped, blurred_image), mutual_information(image_clipped, blurred_image), ssim(image_clipped, blurred_image), ) printscore( "noisy and blurry image: ", psnr(image_clipped, noisy_blurred_image), spectral_mutual_information(image_clipped, noisy_blurred_image), mutual_information(image_clipped, noisy_blurred_image), ssim(image_clipped, noisy_blurred_image), ) printscore( "lr deconv : ", psnr(image_clipped, lr_deconvolved_image_clipped), spectral_mutual_information(image_clipped, lr_deconvolved_image_clipped), mutual_information(image_clipped, lr_deconvolved_image_clipped), ssim(image_clipped, lr_deconvolved_image_clipped), ) printscore( "ssi deconv : ", psnr(image_clipped, deconvolved_image_clipped), spectral_mutual_information(image_clipped, deconvolved_image_clipped), mutual_information(image_clipped, deconvolved_image_clipped), ssim(image_clipped, deconvolved_image_clipped), ) with napari.gui_qt(): viewer = napari.Viewer() viewer.add_image(image, name='image') viewer.add_image(blurred_image, name='blurred') viewer.add_image(noisy_blurred_image, name='noisy_blurred_image') viewer.add_image(lr_deconvolved_image, name='lr_deconvolved_image') viewer.add_image(deconvolved_image, name='ssi_deconvolved_image')
def open_interactive_histogram(img: np.ndarray, convert_3ch_image: bool = True, convert: int = cv2.COLOR_BGR2RGB): """ The goal of this tool is for analysing the grayvalue distribution thanks to an interactive rectangle you can move on the image. This is usefull when you want to check the contrasts and estimate local threshold values (i.e. for color segementation, edges etc.) This function opens a napari viewer with an interactive rectangle. In parallel, there is a matplotlib figure showing, with 1 or 3 graphs(depending on the number of channels). The histogram(s) of the grayvalues inside the rectangle are printed in the graph(s). Resize and move the rectangle in the regions where you want to study the grayvalues distributions. Parameters ---------- img : np.ndarray The RGB image, or the BGR image (convert_3ch_image == True, convert == cv2.COLOR_BGR2RGB), or the grayscale image. convert_3ch_image : bool, optional If you want to enable an opencv convertion. The default is True. convert : int, optional The convertion to apply on the input image. See opencv cv2.cvtColor documentation. The default is cv2.COLOR_BGR2RGB. Returns ------- None. """ _init_global() img_rgb = convert_BGR2RGB(img, convert_3ch_image, convert) global _nbChannels if (splitable_in_3(img_rgb)): _nbChannels = 3 else: _nbChannels = 1 rollback, back_prev = set_backend_qt() global _fig, _axs _fig, _axs = plt.subplots(1, _nbChannels, figsize=(15, 5), sharey=True) if (_nbChannels == 1): _axs = [_axs] _fig.suptitle( 'Grayvalues histograms.You can click somewhere on a line. Right-click to deselect.' ) if (rollback and back_prev != NOT_IMPLEMENTED): set_backend(back_prev) viewer = napari.Viewer() global _img_layer _img_layer = viewer.add_image(img_rgb) viewer.title = 'Interactive histogram' global _roi_layer _roi_layer = _layer_rect(img_rgb, viewer) _roi_layer.mode = 'select' _update_bars_with_roi() @_roi_layer.mouse_drag_callbacks.append def click_drag(layer, event): # print('mouse down') dragged = False yield # on move while event.type == 'mouse_move': # print(event.position) dragged = True yield # on release if dragged: # print('drag end') _update_bars_with_roi() # else: # print('clicked!') viewer.show(block=True) plt.close(_fig)
def main(): args = parser().parse_args() args = define_pixel_sizes(args) if args.output is None: output = Path(args.cells_xml) output_directory = output.parent print(f"No output directory given, so setting output " f"directory to: {output_directory}") else: output_directory = Path(args.output) ensure_directory_exists(str(output_directory)) output_filename = output_directory / OUTPUT_NAME img_paths = get_sorted_file_paths(args.signal_image_paths, file_extension=".tif") cells, labels = get_cell_labels_arrays(args.cells_xml) properties = {"cell": labels} with napari.gui_qt(): viewer = napari.Viewer(title="Cellfinder cell curation") images = magic_imread(img_paths, use_dask=True, stack=True) max_value = estimate_image_max(img_paths) viewer.add_image(images, contrast_limits=[0, max_value]) face_color_cycle = ["lightskyblue", "lightgoldenrodyellow"] points_layer = viewer.add_points( cells, properties=properties, symbol=args.symbol, n_dimensional=True, size=args.marker_size, face_color="cell", face_color_cycle=face_color_cycle, name="Cell candidates", ) @viewer.bind_key("t") def toggle_point_property(viewer): """Toggle point type""" selected_points = viewer.layers[1].selected_data if selected_points: selected_properties = viewer.layers[1].properties["cell"][ selected_points] toggled_properties = np.logical_not(selected_properties) viewer.layers[1].properties["cell"][ selected_points] = toggled_properties # Add curated cells to list CURATED_POINTS.extend(selected_points) print(f"{len(selected_points)} points " f"toggled and added to the list ") # refresh the properties colour viewer.layers[1].refresh_colors(update_color_mapping=False) @viewer.bind_key("c") def confirm_point_property(viewer): """Confirm point type""" selected_points = viewer.layers[1].selected_data if selected_points: # Add curated cells to list CURATED_POINTS.extend(selected_points) print(f"{len(selected_points)} points " f"confirmed and added to the list ") @viewer.bind_key("Control-S") def save_curation(viewer): """Save file""" if not CURATED_POINTS: print("No cells have been confirmed or toggled, not saving") else: unique_cells = unique_elements_lists(CURATED_POINTS) points = viewer.layers[1].data[unique_cells] labels = viewer.layers[1].properties["cell"][unique_cells] labels = labels.astype("int") labels = labels + 1 cells_to_save = [] for idx, point in enumerate(points): cell = Cell([point[2], point[1], point[0]], labels[idx]) cells_to_save.append(cell) print(f"Saving results to: {output_filename}") save_cells(cells_to_save, output_filename) @viewer.bind_key("Alt-E") def start_cube_extraction(viewer): """Extract cubes for training""" if not output_filename.exists(): print("No curation results have been saved. " "Please save before extracting cubes") else: print(f"Saving cubes to: {output_directory}") run_extraction( output_filename, output_directory, args.signal_image_paths, args.background_image_paths, args.cube_depth, args.cube_width, args.cube_height, args.x_pixel_um, args.y_pixel_um, args.z_pixel_um, args.x_pixel_um_network, args.y_pixel_um_network, args.z_pixel_um_network, args.max_ram, args.n_free_cpus, args.save_empty_cubes, ) print("Saving yaml file to use for training") save_yaml_file(output_directory) print("Closing window") QApplication.closeAllWindows() print("Finished! You may now annotate more " "datasets, or go straight to training")
""" Displays an 100GB zarr file of lattice light sheet data """ import numpy as np import napari import dask.array as da file_name = 'data/LLSM/AOLLSM_m4_560nm.zarr' data = da.from_zarr(file_name) with napari.gui_qt(): viewer = napari.Viewer(axis_labels='tzyx') viewer.add_image(data, name='AOLLSM_m4_560nm', multiscale=False, scale=[1, 3, 1, 1], contrast_limits=[0, 150_000], colormap='magma')
def test_blob_docking(): viewer = napari.Viewer() viewer.window.add_dock_widget(blob_detection()) assert "Dock widget 1" in viewer.window._dock_widgets, 'blob detection has not been docked'
import napari from skimage import data, segmentation astro = data.astronaut() segmented = segmentation.slic( astro, compactness=20, sigma=1, start_label=1 ) with napari.gui_qt(): v = napari.Viewer() imglayer = v.add_image(astro) seglayer = v.add_labels(segmented) seglayer.mode = 'fill'
""" Display a points layer on top of an image layer using the add_points and add_image APIs """ import numpy as np from skimage import data from skimage.color import rgb2gray import napari with napari.gui_qt(): # create the viewer window viewer = napari.Viewer() # add the image viewer.add_image(rgb2gray(data.astronaut())) # add the points points = np.array([[100, 100], [200, 200], [333, 111]]) size = np.array([10, 20, 20]) viewer.add_points(points, size=size) # unselect the image layer viewer.layers[0].selected = False # adjust some of the points layer properties layer = viewer.layers[1] # change the layer name layer.name = 'points' # change the layer visibility
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Image Widget addNapariGrayclipColormap() self.napariViewer = napari.Viewer(show=False) self.imgLayer = self.napariViewer.add_image(np.zeros((1, 1)), rgb=False, name='Reconstruction', colormap='grayclip') # Slider and edit box for choosing slice sliceLabel = QtWidgets.QLabel('Slice # ') self.sliceNum = QtWidgets.QLabel('0') self.sliceSlider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self) self.sliceSlider.setMinimum(0) self.sliceSlider.setMaximum(0) self.sliceSlider.setTickInterval(5) self.sliceSlider.setSingleStep(1) self.sliceSlider.valueChanged[int].connect(self.sliceSliderMoved) baseLabel = QtWidgets.QLabel('Base # ') self.baseNum = QtWidgets.QLabel('0') self.baseSlider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self) self.baseSlider.setMinimum(0) self.baseSlider.setMaximum(0) self.baseSlider.setTickInterval(5) self.baseSlider.setSingleStep(1) self.baseSlider.valueChanged[int].connect(self.baseSliderMoved) timeLabel = QtWidgets.QLabel('Time point # ') self.timeNum = QtWidgets.QLabel('0') self.timeSlider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self) self.timeSlider.setMinimum(0) self.timeSlider.setMaximum(0) self.timeSlider.setTickInterval(5) self.timeSlider.setSingleStep(1) self.timeSlider.valueChanged[int].connect(self.timeSliderMoved) datasetLabel = QtWidgets.QLabel('Dataset # ') self.datasetNum = QtWidgets.QLabel('0') self.datasetSlider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self) self.datasetSlider.setMinimum(0) self.datasetSlider.setMaximum(0) self.datasetSlider.setTickInterval(5) self.datasetSlider.setSingleStep(1) self.datasetSlider.valueChanged[int].connect(self.datasetSliderMoved) # Button group for choosing view self.chooseViewGroup = QtWidgets.QButtonGroup() self.chooseViewBox = QtWidgets.QGroupBox('Choose view') self.viewLayout = QtWidgets.QVBoxLayout() self.standardView = QtWidgets.QRadioButton('Standard view') self.standardView.viewName = 'standard' self.chooseViewGroup.addButton(self.standardView) self.viewLayout.addWidget(self.standardView) self.bottomView = QtWidgets.QRadioButton('Bottom side view') self.bottomView.viewName = 'bottom' self.chooseViewGroup.addButton(self.bottomView) self.viewLayout.addWidget(self.bottomView) self.leftView = QtWidgets.QRadioButton('Left side view') self.leftView.viewName = 'left' self.chooseViewGroup.addButton(self.leftView) self.viewLayout.addWidget(self.leftView) self.chooseViewBox.setLayout(self.viewLayout) self.chooseViewGroup.buttonClicked.connect(self.sigViewChanged) # List for storing sevral data sets self.reconList = QtWidgets.QListWidget() self.reconList.currentItemChanged.connect(self.sigItemSelected) self.reconList.setSelectionMode( QtWidgets.QAbstractItemView.ExtendedSelection) removeReconBtn = BetterPushButton('Remove current') removeReconBtn.clicked.connect(self.removeRecon) removeAllReconBtn = BetterPushButton('Remove all') removeAllReconBtn.clicked.connect(self.removeAllRecon) # Set initial states self.standardView.setChecked(True) # Set layout layout = QtWidgets.QGridLayout() self.setLayout(layout) layout.addWidget(self.napariViewer.window._qt_window, 0, 0, 2, 1) layout.addWidget(self.chooseViewBox, 0, 1, 1, 2) layout.addWidget(self.reconList, 0, 3, 2, 1) layout.addWidget(self.sliceSlider, 2, 0) layout.addWidget(sliceLabel, 2, 1) layout.addWidget(self.sliceNum, 2, 2) layout.addWidget(self.baseSlider, 3, 0) layout.addWidget(baseLabel, 3, 1) layout.addWidget(self.baseNum, 3, 2) layout.addWidget(self.timeSlider, 4, 0) layout.addWidget(timeLabel, 4, 1) layout.addWidget(self.timeNum, 4, 2) layout.addWidget(self.datasetSlider, 5, 0) layout.addWidget(datasetLabel, 5, 1) layout.addWidget(self.datasetNum, 5, 2) layout.addWidget(removeReconBtn, 2, 3) layout.addWidget(removeAllReconBtn, 3, 3) layout.setRowStretch(1, 1) layout.setColumnStretch(0, 100) layout.setColumnStretch(2, 5)