def Step3(self): """ Step3() Process graph to remove unwanted edges. """ # Check if we can go if self._vol is None or self._params is None: raise ValueError('Data or params not yet given.') if self._nodes2 is None: raise ValueError('Edges not yet calculated.') # Get nodes and params #nodes = stentgraph.StentGraph() #nodes.unpack( self._nodes2.pack() ) nodes = self._nodes2.copy() params = self._params # Init times t_start = time.time() t_clean = 0 print('Step3 in StentDirect_test is indeed used :)') # Iteratively prune the graph. The order of operations should # not matter too much, although in practice there is a # difference. In particular the prune_weak and prune_redundant # have a similar function and should be executed in this order. cur_edges = 0 count = 0 while cur_edges != nodes.number_of_edges(): count += 1 cur_edges = nodes.number_of_edges() ene = params.graph_expectedNumberOfEdges stentgraph.prune_very_weak(nodes, params.graph_weakThreshold) stentgraph.prune_weak(nodes, ene, params.graph_strongThreshold) stentgraph.prune_redundant(nodes, params.graph_strongThreshold) stentgraph.prune_clusters(nodes, params.graph_minimumClusterSize) stentgraph.prune_tails(nodes, params.graph_trimLength) stentgraph.pop_nodes(nodes) stentgraph.add_corner_nodes(nodes) stentgraph.smooth_paths(nodes) t0 = time.time() - t_start tmp = "Reduced to %i edges, " tmp += "which took %1.2f s (%i iters)" print(tmp % (nodes.number_of_edges(), t0, count)) print("****************************************") # Finish self._nodes3 = nodes if self._draw: self.Draw(3) return nodes
def test_prune_clusters(self): # Create two small cliques graph = StentGraph() graph.add_edge(1, 2, cost=2, ctvalue=50) graph.add_edge(2, 3, cost=2, ctvalue=50) graph.add_edge(3, 1, cost=2, ctvalue=50) # graph.add_edge(4, 5, cost=2, ctvalue=50) graph.add_edge(5, 6, cost=2, ctvalue=50) graph.add_edge(6, 7, cost=2, ctvalue=50) graph.add_edge(7, 4, cost=2, ctvalue=50) # Connect them graph.add_edge(1, 4, cost=3, ctvalue=50) # Also add loose node graph.add_nodes_from([101, 102]) # Remove cliques and check that nothing happened prune_clusters(graph, 4) assert graph.number_of_edges() == 8 assert graph.number_of_nodes() == 7 # Remove connection graph.remove_edge(1, 4) # Remove cliques and check that one clique is removed prune_clusters(graph, 4) assert graph.number_of_edges() == 4 assert graph.number_of_nodes() == 4 # Remove cliques and check that one clique is removed prune_clusters(graph, 5) assert graph.number_of_edges() == 0 assert graph.number_of_nodes() == 0
def on_key(event): """KEY commands for user interaction 'UP/DOWN = show/hide nodes' 'DELETE = remove edge [select 2 nodes] or pop node [select 1 node] ' 'or remove seed in nodes1 closest to [picked point]' 'p = remove seeds posterior (y-axis) to [picked point] (use for spine seeds)' 'o = remove seeds anterior (y-axis) to [picked point]' 'i = remove seeds proximal (z-axis) to [picked point]' 'k = remove seeds distal (z-axis) to [picked point]' 'l = remove seeds left (x-axis) to [picked point]' 'j = remove seeds right (x-axis) to [picked point]' 'ALT = clean graph: remove residual clusters, pop, corner' 'PageUp= protect node closest to picked point in nodes1 axes, no pop 'n = add [picked point] (SHIFT+R-click) as seed' '1 = redo step 1; 2 = redo step 2; 3 = redo step 3' 'z/x/a/d = axis invisible/visible/rotate' """ global label global node_points global sd if event.key == vv.KEY_DOWN: # hide nodes t1.visible = False t2.visible = False t3.visible = False if 'node_points' in globals(): for node_point in node_points: node_point.visible = False if event.key == vv.KEY_UP: # show nodes if 'node_points' in globals(): for node_point in node_points: node_point.visible = True if event.key == vv.KEY_DELETE: if len(selected_nodes) == 0: # remove node closest to picked point node = _utils_GUI.snap_picked_point_to_graph(sd._nodes1, vol, label, nodesOnly=True) sd._nodes1.remove_node(node) view = a1.GetView() a1.Clear() label = DrawModelAxes(vol, sd._nodes1, a1, clim=clim, showVol=showVol, removeStent=False) a1.SetView(view) if len(selected_nodes) == 2: # remove edge select1 = selected_nodes[0].node select2 = selected_nodes[1].node c = sd._nodes3.edge[select1][select2]['cost'] ct = sd._nodes3.edge[select1][select2]['ctvalue'] path = sd._nodes3.edge[select1][select2]['path'] l = stentgraph._edge_length(sd._nodes3, select1, select2) sd._nodes3.remove_edge(select1, select2) stentgraph.pop_nodes(sd._nodes3) # pop residual nodes # Visualize removed edge, show keys and deselect nodes selected_nodes[1].faceColor = 'b' selected_nodes[0].faceColor = 'b' selected_nodes.clear() t1.text = 'Edge ctvalue: \b{%1.2f HU}' % ct t2.text = 'Edge cost: \b{%1.7f }' % c t3.text = 'Edge length: \b{%1.2f mm}' % l t1.visible = True t2.visible = True t3.visible = True view = a3.GetView() pp = Pointset(path) line = vv.solidLine(pp, radius = 0.2) line.faceColor = 'r' a3.SetView(view) if len(selected_nodes) == 1: # pop node select1 = selected_nodes[0].node stentgraph._pop_node(sd._nodes3, select1) # asserts degree == 2 selected_nodes[0].faceColor = 'w' selected_nodes.clear() if event.key == vv.KEY_ALT: # ALT will FINISH model stentgraph.prune_clusters(sd._nodes3, 3) #remove residual nodes/clusters stentgraph.pop_nodes(sd._nodes3) stentgraph.add_corner_nodes(sd._nodes3, th=sd._params.graph_angleVector, angTh=sd._params.graph_angleTh) # Create mesh and visualize view = a3.GetView() a3.Clear() DrawModelAxes(vol, sd._nodes3, a3, meshColor=meshColor, clim=clim, showVol=showVol, lc='g', mw=8, lw=0.2) # _utils_GUI.vis_spared_edges(sd._nodes3) a3.SetView(view) print('----DO NOT FORGET TO SAVE THE MODEL TO DISK; RUN _SAVE_SEGMENTATION----') if event.text == 'n': # add picked seed to nodes_1 coord2 = get_picked_seed(vol, label) sd._nodes1.add_node(tuple(coord2)) view = a1.GetView() point = vv.plot(coord2[0], coord2[1], coord2[2], mc= 'b', ms = 'o', mw= 8, alpha=0.5, axes=a1) a1.SetView(view) if event.key == vv.KEY_PAGEUP: # protect node from pop pickedNode = _utils_GUI.snap_picked_point_to_graph(sd._nodes1, vol, label, nodesOnly=True) sd._nodes1.add_node(pickedNode, nopop = True) sd._nodes2.add_node(pickedNode, nopop = True) view = a1.GetView() point = vv.plot(pickedNode[0], pickedNode[1], pickedNode[2], mc= 'y', ms = 'o', mw= 8, alpha=0.5, axes=a1) a1.SetView(view) # now rerun step 3 if event.text == 'p': # remove false seeds posterior to picked point, e.g. for spine _utils_GUI.remove_nodes_by_selected_point(sd._nodes2, vol, a2, label, clim, location='posterior', showVol=showVol) label = _utils_GUI.remove_nodes_by_selected_point(sd._nodes1, vol, a1, label, clim, location='posterior', showVol=showVol) if event.text == 'o': # remove seeds prox to selected point _utils_GUI.remove_nodes_by_selected_point(sd._nodes2, vol, a1, label, clim, location='anterior', showVol=showVol) label = _utils_GUI.remove_nodes_by_selected_point(sd._nodes1, vol, a1, label, clim, location='anterior', showVol=showVol) if event.text == 'i': # remove seeds prox to selected point _utils_GUI.remove_nodes_by_selected_point(sd._nodes2, vol, a1, label, clim, location='proximal', showVol=showVol) label = _utils_GUI.remove_nodes_by_selected_point(sd._nodes1, vol, a1, label, clim, location='proximal', showVol=showVol) if event.text == 'k': # remove seeds dist to selected point _utils_GUI.remove_nodes_by_selected_point(sd._nodes2, vol, a1, label, clim, location='distal', showVol=showVol) label = _utils_GUI.remove_nodes_by_selected_point(sd._nodes1, vol, a1, label, clim, location='distal', showVol=showVol) if event.text == 'l': # remove seeds left to selected point _utils_GUI.remove_nodes_by_selected_point(sd._nodes2, vol, a1, label, clim, location='left', showVol=showVol) label = _utils_GUI.remove_nodes_by_selected_point(sd._nodes1, vol, a1, label, clim, location='left', showVol=showVol) if event.text == 'j': # remove seeds right to selected point _utils_GUI.remove_nodes_by_selected_point(sd._nodes2, vol, a1, label, clim, location='right', showVol=showVol) label = _utils_GUI.remove_nodes_by_selected_point(sd._nodes1, vol, a1, label, clim, location='right', showVol=showVol) if event.text == '1': # redo step1 view = a1.GetView() a1.Clear(); a2.Clear(); a3.Clear() sd._params = p sd.Step1() label = DrawModelAxes(vol, sd._nodes1, a1, clim=clim, showVol=showVol, removeStent=False) # lc, mc a1.SetView(view) if event.text == '2': # redo step2 view = a2.GetView() a2.Clear(); a3.Clear() sd._params = p sd.Step2() DrawModelAxes(vol, sd._nodes2, a2, clim=clim, showVol=showVol,removeStent=False) a2.SetView(view) if event.text == '3': # redo step3 view = a3.GetView() a3.Clear() sd._params = p sd.Step3(cleanNodes=True) DrawModelAxes(vol, sd._nodes3, a3, meshColor=meshColor, clim=clim, showVol=showVol,removeStent=False) node_points = _utils_GUI.interactive_node_points(sd._nodes3, scale=0.6) _utils_GUI.node_points_callbacks(node_points, selected_nodes, pick=False) a3.SetView(view)
def on_key(event): """KEY commands for user interaction 'UP/DOWN = show/hide nodes' 'DELETE = remove edge [select 2 nodes] or pop node [select 1 node] ' 'or remove seed in nodes1 closest to [picked point]' 'PageDown = remove graph posterior (y-axis) to [picked point] (use for spine seeds)' 'ALT = clean graph: remove residual clusters, pop, corner' 'CTRL+SHIFT = add [picked point] (SHIFT+R-click) as seed' """ global label global node_points global sd if event.key == vv.KEY_DOWN: # hide nodes t1.visible = False t2.visible = False t3.visible = False for node_point in node_points: node_point.visible = False if event.key == vv.KEY_UP: # show nodes for node_point in node_points: node_point.visible = True if event.key == vv.KEY_DELETE: if len(selected_nodes) == 0: # remove node closest to picked point node = _utils_GUI.snap_picked_point_to_graph(sd._nodes1, vol, label, nodesOnly=True) sd._nodes1.remove_node(node) view = a1.GetView() a1.Clear() label = DrawModelAxes(vol, sd._nodes1, a1, clim=clim, showVol=showVol, removeStent=False) a1.SetView(view) if len(selected_nodes) == 2: # remove edge select1 = selected_nodes[0].node select2 = selected_nodes[1].node c = sd._nodes3.edge[select1][select2]['cost'] ct = sd._nodes3.edge[select1][select2]['ctvalue'] path = sd._nodes3.edge[select1][select2]['path'] l = stentgraph._edge_length(sd._nodes3, select1, select2) sd._nodes3.remove_edge(select1, select2) stentgraph.pop_nodes(sd._nodes3) # pop residual nodes # Visualize removed edge, show keys and deselect nodes selected_nodes[1].faceColor = 'b' selected_nodes[0].faceColor = 'b' selected_nodes.clear() t1.text = 'Edge ctvalue: \b{%1.2f HU}' % ct t2.text = 'Edge cost: \b{%1.7f }' % c t3.text = 'Edge length: \b{%1.2f mm}' % l t1.visible = True t2.visible = True t3.visible = True view = a3.GetView() pp = Pointset(path) line = vv.solidLine(pp, radius=0.2) line.faceColor = 'r' # a3.SetView(view) if len(selected_nodes) == 1: # pop node select1 = selected_nodes[0].node stentgraph._pop_node(sd._nodes3, select1) # asserts degree == 2 selected_nodes[0].faceColor = 'w' selected_nodes.clear() if event.key == vv.KEY_ALT: # ALT will FINISH model stentgraph.prune_clusters(sd._nodes3, 3) #remove residual nodes/clusters stentgraph.pop_nodes(sd._nodes3) stentgraph.add_corner_nodes(sd._nodes3, th=sd._params.graph_angleVector, angTh=sd._params.graph_angleTh) # Create mesh and visualize view = a3.GetView() a3.Clear() DrawModelAxes(vol, sd._nodes3, a3, meshColor=meshColor, clim=clim, showVol=showVol, lc='b', mw=8, lw=0.2) _utils_GUI.vis_spared_edges(sd._nodes3) a3.SetView(view) print( '----DO NOT FORGET TO SAVE THE MODEL TO DISK; RUN _SAVE_SEGMENTATION----' ) if event.text == 'n': # add picked seed to nodes_1 coord2 = get_picked_seed(vol, label) sd._nodes1.add_node(tuple(coord2)) view = a1.GetView() point = vv.plot(coord2[0], coord2[1], coord2[2], mc='b', ms='o', mw=8, alpha=0.5, axes=a1) a1.SetView(view) if event.text == 'p': # protect node from pop pickedNode = _utils_GUI.snap_picked_point_to_graph(sd._nodes1, vol, label, nodesOnly=True) sd._nodes1.add_node(pickedNode, nopop=True) sd._nodes2.add_node(pickedNode, nopop=True) view = a1.GetView() point = vv.plot(pickedNode[0], pickedNode[1], pickedNode[2], mc='y', ms='o', mw=8, alpha=0.5, axes=a1) a1.SetView(view) # now rerun step 3 if event.key == vv.KEY_PAGEDOWN: # remove false seeds posterior to picked point, e.g. for spine try: _utils_GUI.remove_nodes_by_selected_point(sd._nodes3, vol, a3, label, clim, showVol=showVol) except ValueError: # false nodes already cleaned by Step3 pass _utils_GUI.remove_nodes_by_selected_point(sd._nodes2, vol, a2, label, clim, showVol=showVol) label = _utils_GUI.remove_nodes_by_selected_point(sd._nodes1, vol, a1, label, clim, showVol=showVol) if event.text == '1': # redo step1 view = a1.GetView() a1.Clear() a2.Clear() a3.Clear() sd._params = p sd.Step1() label = DrawModelAxes(vol, sd._nodes1, a1, clim=clim, showVol=showVol, removeStent=False) # lc, mc a1.SetView(view) if event.text == '2': # redo step2 and 3 view = a2.GetView() a2.Clear() a3.Clear() sd._params = p sd.Step2() sd.Step3(cleanNodes=cleanNodes) DrawModelAxes(vol, sd._nodes2, a2, clim=clim, showVol=showVol, removeStent=False) DrawModelAxes(vol, sd._nodes3, a3, meshColor=meshColor, clim=clim, showVol=showVol, removeStent=False) a2.SetView(view) if event.text == '3': view = a3.GetView() a3.Clear() sd._params = p sd.Step3(cleanNodes=cleanNodes) DrawModelAxes(vol, sd._nodes3, a3, meshColor=meshColor, clim=clim, showVol=showVol, removeStent=False) node_points = _utils_GUI.interactive_node_points(sd._nodes3, scale=0.6) _utils_GUI.node_points_callbacks(node_points, selected_nodes, pick=False) a3.SetView(view) if event.text == 's': # SAVE SEGMENTATION # make centerline points of segmentation paths_as_pp = points_from_edges_in_graph(sd._nodes3, type='order') ringpoints = paths_as_pp[0].T # Get graph model model = sd._nodes3 seeds = sd._nodes1 Draw = sd.Draw # Build struct s2 = vv.ssdf.new() # We do not need croprange, but keep for reference s2.sampling = s.sampling s2.origin = s.origin s2.stenttype = s.stenttype s2.croprange = s.croprange for key in dir(s): if key.startswith('meta'): suffix = key[4:] s2['meta' + suffix] = s['meta' + suffix] s2.what = what s2.params = p s2.stentType = stentType # Store model s2.model = model.pack() s2.seeds = seeds.pack() s2.Draw = Draw s2.ringpoints = ringpoints #s2.mesh = ssdf.new() # Save savedir = select_dir( r'C:\Users\Gebruiker\Google Drive\Afstuderen\Rings') filename = '%s_%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, 'model' + what, ring) ssdf.save(os.path.join(savedir, filename), s2) print('saved to disk in {} as {}.'.format(savedir, filename))
def on_key(event): """KEY commands for user interaction UP/DOWN = show/hide nodes ENTER = restore edge [select 2 nodes] DELETE = remove edge [select 2 ndoes] or pop node [select 1 node]' ALT = clean graph: pop, crossings, corner ESCAPE = FINISH: refine, smooth """ global node_points global nodes3copy if event.key == vv.KEY_DOWN: # hide nodes t1.visible = False t2.visible = False t3.visible = False for node_point in node_points: node_point.visible = False if event.key == vv.KEY_UP: # show nodes for node_point in node_points: node_point.visible = True if event.key == vv.KEY_ENTER: # restore edge assert len(selected_nodes) == 2 select1 = selected_nodes[0].node select2 = selected_nodes[1].node c = sd._nodes2.edge[select1][select2]['cost'] ct = sd._nodes2.edge[select1][select2]['ctvalue'] p = sd._nodes2.edge[select1][select2]['path'] sd._nodes3.add_edge(select1, select2, cost=c, ctvalue=ct, path=p) l = stentgraph._edge_length(sd._nodes3, select1, select2) # Visualize restored edge and deselect nodes selected_nodes[1].faceColor = 'b' selected_nodes[0].faceColor = 'b' selected_nodes.clear() t1.text = 'Edge ctvalue: \b{%1.2f HU}' % ct t2.text = 'Edge cost: \b{%1.7f }' % c t3.text = 'Edge length: \b{%1.2f mm}' % l t1.visible = True t2.visible = True t3.visible = True view = a3.GetView() pp = Pointset(p) # visvis meshes do not work with PointSet line = vv.solidLine(pp, radius=0.2) line.faceColor = 'g' a3.SetView(view) if event.key == vv.KEY_DELETE: if len(selected_nodes) == 2: # remove edge select1 = selected_nodes[0].node select2 = selected_nodes[1].node c = sd._nodes3.edge[select1][select2]['cost'] ct = sd._nodes3.edge[select1][select2]['ctvalue'] p = sd._nodes3.edge[select1][select2]['path'] l = stentgraph._edge_length(sd._nodes3, select1, select2) sd._nodes3.remove_edge(select1, select2) # visualize removed edge, show keys and deselect nodes selected_nodes[1].faceColor = 'b' selected_nodes[0].faceColor = 'b' selected_nodes.clear() t1.text = 'Edge ctvalue: \b{%1.2f HU}' % ct t2.text = 'Edge cost: \b{%1.7f }' % c t3.text = 'Edge length: \b{%1.2f mm}' % l t1.visible = True t2.visible = True t3.visible = True view = a3.GetView() pp = Pointset(p) line = vv.solidLine(pp, radius=0.2) line.faceColor = 'r' a3.SetView(view) if len(selected_nodes) == 1: # pop node select1 = selected_nodes[0].node stentgraph._pop_node(sd._nodes3, select1) # asserts degree == 2 selected_nodes[0].faceColor = 'w' selected_nodes.clear() if event.key == vv.KEY_ALT: #backup to restore nodes3copy = sd._nodes3.copy() # clean nodes if stentType == 'anacondaRing': stentgraph.add_nodes_at_crossings(sd._nodes3) stentgraph.pop_nodes( sd._nodes3) # pop before corner detect or angles can not be found stentgraph.add_corner_nodes(sd._nodes3, th=sd._params.graph_angleVector, angTh=sd._params.graph_angleTh) stentgraph.pop_nodes( sd._nodes3 ) # because removing edges/add nodes can create degree 2 nodes stentgraph.prune_tails(sd._nodes3, sd._params.graph_trimLength) stentgraph.prune_clusters(sd._nodes3, 3) #remove residual nodes/clusters # visualize result view = a3.GetView() a3.Clear() DrawModelAxes(vol, sd._nodes3, a3, clim=clim, showVol=showVol, mw=8, lw=0.2, climEditor=False) node_points = _utils_GUI.interactive_node_points(sd._nodes3, scale=0.6) _utils_GUI.node_points_callbacks(node_points, selected_nodes, pick=False) a3.SetView(view) print('----Press ESCAPE to FINISH model----') if event.text == 'u': # undo and restore nodes3 sd._nodes3 = nodes3copy view = a3.GetView() a3.Clear() DrawModelAxes(vol, sd._nodes3, a3, clim=clim, showVol=showVol, mw=8, lw=0.2, climEditor=False) node_points = _utils_GUI.interactive_node_points(sd._nodes3, scale=0.6) _utils_GUI.node_points_callbacks(node_points, selected_nodes, pick=False) a3.SetView(view) if event.key == vv.KEY_ESCAPE: #backup to restore nodes3copy = sd._nodes3.copy() # ESCAPE will FINISH model stentgraph.pop_nodes(sd._nodes3) sd._nodes3 = sd._RefinePositions(sd._nodes3) # subpixel locations stentgraph.smooth_paths(sd._nodes3, 4) # Create mesh and visualize view = a3.GetView() a3.Clear() DrawModelAxes(vol, sd._nodes3, a3, meshColor='g', clim=clim, showVol=showVol, lc='w', mw=8, lw=0.2, climEditor=False) node_points = _utils_GUI.interactive_node_points(sd._nodes3, scale=0.6) _utils_GUI.node_points_callbacks(node_points, selected_nodes, pick=False) a3.SetView(view) print( '----DO NOT FORGET TO SAVE THE MODEL TO DISK; RUN _SAVE_SEGMENTATION----' ) if event.text == 'r': # restore this node pickedNode = _utils_GUI.snap_picked_point_to_graph( sd._nodes2, vol, label, nodesOnly=True) # x,y,z sd._nodes3.add_node(pickedNode) view = a3.GetView() a3.Clear() DrawModelAxes(vol, sd._nodes3, a3, clim=clim, showVol=showVol, mw=8, lw=0.2, climEditor=False) node_points = _utils_GUI.interactive_node_points(sd._nodes3, scale=0.6) _utils_GUI.node_points_callbacks(node_points, selected_nodes, pick=False) a3.SetView(view) if event.text == 's': # additional smooth stentgraph.smooth_paths(sd._nodes3, 2) view = a3.GetView() a3.Clear() DrawModelAxes(vol, sd._nodes3, a3, clim=clim, showVol=showVol, mw=8, lw=0.2, climEditor=False) node_points = _utils_GUI.interactive_node_points(sd._nodes3, scale=0.6) _utils_GUI.node_points_callbacks(node_points, selected_nodes, pick=False) a3.SetView(view) if event.text == 'e': # smooth selected edge edgegraph = stentgraph.StentGraph() #empty graph select1 = selected_nodes[0].node select2 = selected_nodes[1].node edge_info = sd._nodes3.edge[select1][select2] edgegraph.add_edge(select1, select2, **edge_info) stentgraph.smooth_paths(edgegraph, 4) sd._nodes3.edge[select1][select2]['path'] = edgegraph.edge[select1][ select2]['path'] view = a3.GetView() a3.Clear() DrawModelAxes(vol, sd._nodes3, a3, clim=clim, showVol=showVol, mw=8, lw=0.2, climEditor=False) node_points = _utils_GUI.interactive_node_points(sd._nodes3, scale=0.6) _utils_GUI.node_points_callbacks(node_points, selected_nodes, pick=False) # see if node_points are still selected to color them red for node_point in node_points: node_point.visible = True for i, node in enumerate(selected_nodes): if node_point.node == node.node: selected_nodes[i] = node_point node_point.faceColor = (1, 0, 0) a3.SetView(view) if event.text == 'w': for n in selected_nodes: n.faceColor = 'b' selected_nodes.clear() if event.text == 'q': view = a3.GetView() _utils_GUI.interactiveClusterRemoval(sd._nodes3) a3.SetView(view)