def saveLandmarkModel(ls, dirsave, ptcode, ctcode, cropname, what): """ Save graph with landmarks; do not store volumes again Use within or outside class LandmarkSelector """ import os s = ls.s s2 = ls.s_landmarks s2.sampling = s.sampling s2.origin = s.origin s2.stenttype = s.stenttype s2.croprange = s.croprange # keep for reference for key in dir(s): if key.startswith('meta'): suffix = key[4:] s2['meta' + suffix] = s['meta' + suffix] s2.what = what s2.params = 'LandmarkSelector' s2.stentType = s.stenttype # Save filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, 'landmarks' + what) ssdf.save(os.path.join(dirsave, filename), s2) print('') print('saved to disk to {}.'.format(os.path.join(dirsave, filename)))
def set(self, key, object, save_now=True): """ set(key, object, save_now=True) Add an object to the database, using the given key. If save_now is True, will save the database to disk now. """ # Correct key key = self._key2key(key) #print 'set', key # Test object if ssdf.isstruct(object): pass if isinstance(object, (int, float, str, np.ndarray, tuple, list)): pass # Default ssdf compatible elif ssdf.is_compatible_class(object): pass # Compatible else: raise ValueError('The given object is not ssdf compatible.') # Store last key self._lastkey = key # Store object in db self._db[key] = object # Save? if save_now and self._fname: ssdf.save(self._fname, self._db)
def save_segmentation(basedir, ptcode, ctcode, cropname, seeds, model, s, stentType=None, what='avgreg', params=None): """ store segmentation in new ssdf or load and add s = ssdf of volume from which we segment s2 = ssdf of segmentation model """ # 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 = params s2.stentType = stentType # Store model s2.model = model.pack() s2.seeds = seeds.pack() # Save filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, 'model'+what) ssdf.save(os.path.join(basedir, ptcode, filename), s2) print('saved to disk in {} as {}.'.format(basedir, filename) )
def add_segmentation_ssdf(basedir, ptcode, ctcode, cropname, seeds, model, graphname, s2=None, modelname='modelavgreg', stentType=None, params=None): """ Add a model to an existing ssdf but separate from the existing graph s2 = ssdf of existing model to add new segmentation graph in ssdf graphname = name of new graph to save in ssdf """ if s2 is None: s2 = loadmodel(basedir, ptcode, ctcode, cropname, modelname) # unpacks to graph s2['params'+graphname] = params s2['stentType'+graphname] = stentType # Store model if model is not None: # step 2 and 3 were performed otherwise NoneType s2['model'+graphname] = model s2['seeds'+graphname] = seeds else: # store seeds as model s2['model'+graphname] = seeds.copy() s2['seeds'+graphname] = seeds # pack all graphs to ssdf for save for key in dir(s2): if key.startswith('model'): s2[key] = s2[key].pack() if key.startswith('seeds'): s2[key] = s2[key].pack() # Save filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, modelname) ssdf.save(os.path.join(basedir, ptcode, filename), s2) print('saved to disk in {} as {}.'.format(basedir, filename) )
def make_model_dynamic(basedir, ptcode, ctcode, cropname, what='avgreg'): """ Read deforms and model to make model dynamic, ie, add deforms to edges and nodes in the graph """ # Load deforms s = loadvol(basedir, ptcode, ctcode, cropname, 'deforms') deformkeys = [] for key in dir(s): if key.startswith('deform'): deformkeys.append(key) deforms = [s[key] for key in deformkeys] deforms = [pirt.DeformationFieldBackward(*fields) for fields in deforms] paramsreg = s.params # Load model s = loadmodel(basedir, ptcode, ctcode, cropname, 'model'+what) for key in dir(s): if key.startswith('model'): model = s[key] # Combine ... incorporate_motion_nodes(model, deforms, s.origin) # adds deforms PointSets incorporate_motion_edges(model, deforms, s.origin) # adds deforms PointSets s[key] = model.pack() # also pack seeds before save if key.startswith('seeds'): s[key] = s[key].pack() # Save back filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, 'model'+what) s.paramsreg = paramsreg ssdf.save(os.path.join(basedir, ptcode, filename), s) print('saved dynamic to disk in {} as {}.'.format(basedir, filename) )
def cropaveraged(basedir, ptcode, ctcode, crop_in='stent', what='avg5090', crop_out='body'): """ Crop averaged volume of stent With loadvol, load ssdf containing an averaged volume and save new cropped ssdf """ s = loadvol(basedir, ptcode, ctcode, crop_in, what) vol = s.vol # Open cropper tool print('Set the appropriate cropping range for "%s" ' 'and click finish to continue' % crop_out) print('Loading... be patient') fig = vv.figure() fig.title = 'Cropping for "%s"' % crop_out vol_crop = cropper.crop3d(vol, fig) fig.Destroy() if vol_crop.shape == vol.shape: raise RuntimeError('User cancelled (no crop)') # Calculate crop range from origin rz = int(vol_crop.origin[0] / vol_crop.sampling[0] + 0.5) rz = rz, rz + vol_crop.shape[0] ry = int(vol_crop.origin[1] / vol_crop.sampling[1] + 0.5) ry = ry, ry + vol_crop.shape[1] rx = int(vol_crop.origin[2] / vol_crop.sampling[2] + 0.5) rx = rx, rx + vol_crop.shape[2] # Initialize struct s2 = ssdf.new() s2.sampling = vol_crop.sampling # z, y, x voxel size in mm s2.stenttype = s.stenttype for key in dir(s): if key.startswith('meta'): suffix = key[4:] s2['meta' + suffix] = s['meta' + suffix] # Set new croprange, origin and vol offset = [i[0] for i in s.croprange] # origin of crop_in s2.croprange = ([rz[0] + offset[0], rz[1] + offset[0] ], [ry[0] + offset[1], ry[1] + offset[1]], [rx[0] + offset[2], rx[1] + offset[2]]) s2.origin = vol_crop.origin s2.vol = vol_crop # Export and save filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, crop_out, what) file_out = os.path.join(basedir, ptcode, filename) ssdf.save(file_out, s2)
def test_pack1(self): # Custom stent g = StentGraph(summary='dit is een stent!', lala=3) g.add_node((10, 20), foo=3) g.add_node((30, 40), foo=5) g.add_edge((1, 1), (2, 2), bar=10) g.add_edge((10, 20), (1, 1), bar=20) fname = '/home/almar/test.ssdf' ssdf.save(fname, g.pack()) g2 = StentGraph() g2.unpack(ssdf.load(fname)) #print(nx.is_isomorphic(g, g2)) assert nx.is_isomorphic(g, g2)
def makeLandmarkModelDynamic(basedir, ptcode, ctcode, cropname, what='landmarksavgreg', savedir=None): """ Make model dynamic with deforms from registration (and store/overwrite to disk) """ #todo: change in default and merge with branch landmarks? import pirt from stentseg.motion.dynamic import (incorporate_motion_nodes, incorporate_motion_edges) from visvis import ssdf import os if savedir is None: savedir = basedir # Load deforms s = loadvol(basedir, ptcode, ctcode, cropname, 'deforms') deformkeys = [] for key in dir(s): if key.startswith('deform'): deformkeys.append(key) deforms = [s[key] for key in deformkeys] deforms = [pirt.DeformationFieldBackward(*fields) for fields in deforms] paramsreg = s.params # Load model where landmarks were stored # s2 = loadmodel(savedir, ptcode, ctcode, cropname, what) fname = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, what) s2 = ssdf.load(os.path.join(savedir, fname)) # Turn into graph model model = stentgraph.StentGraph() model.unpack(s2[what]) # Combine ... incorporate_motion_nodes(model, deforms, s2.origin) incorporate_motion_edges(model, deforms, s2.origin) # Save back filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, what) s2.model = model.pack() s2.paramsreg = paramsreg ssdf.save(os.path.join(savedir, filename), s2) print('saved to disk to {}.'.format(os.path.join(savedir, filename)))
def test_pack2(self): # Auto generate import random n = 500 p = dict( (i, (random.gauss(0, 2), random.gauss(0, 2))) for i in range(n)) g_ = nx.random_geometric_graph(n, 0.1, dim=3, pos=p) g = StentGraph(summary='dit is een stent!', lala=3) g.add_nodes_from(g_.nodes_iter()) g.add_edges_from(g_.edges_iter()) fname = '/home/almar/test.ssdf' ssdf.save(fname, g.pack()) g2 = StentGraph() g2.unpack(ssdf.load(fname)) #print(nx.is_isomorphic(g, g2)) assert nx.is_isomorphic(g, g2)
def save(self, fname=None): """ save(fname=None) Save the results to disk now. If fname is not given, the last used fname is used. If there is no fname available, will raise a runtime error. """ # Use given or stored fname? if fname is None: fname = self._fname else: self._fname = fname # Check if there is an fname available if fname is None: raise RuntimeError('No known filename to write to.') # Save ssdf.save(fname, self._db)
def saveaveraged(basedir, ptcode, ctcode, cropname, phases): """ Step C: Save average of a number of volumes (phases in cardiac cycle) Load ssdf containing all phases and save averaged volume as new ssdf """ filename = '%s_%s_%s_phases.ssdf' % (ptcode, ctcode, cropname) file_in = os.path.join(basedir, ptcode, filename) if not os.path.exists(file_in): raise RuntimeError('Could not find ssdf for given input %s' % ptcode, ctcode, cropname) s = ssdf.load(file_in) s_avg = ssdf.new() averaged = np.zeros(s.vol0.shape, np.float64) if phases[1] < phases[0]: phaserange = list(range(0, 100, 10)) for i in range(phases[1] + 10, phases[0], 10): phaserange.remove(i) else: phaserange = range(phases[0], phases[1] + 10, 10) for phase in phaserange: averaged += s['vol%i' % phase] s_avg['meta%i' % phase] = s['meta%i' % phase] averaged *= 1.0 / len(phaserange) averaged = averaged.astype('float32') s_avg.vol = averaged s_avg.sampling = s.sampling # z, y, x voxel size in mm s_avg.origin = s.origin s_avg.stenttype = s.stenttype s_avg.croprange = s.croprange s_avg.ctcode = s.ctcode s_avg.ptcode = s.ptcode avg = 'avg' + str(phases[0]) + str(phases[1]) filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, avg) file_out = os.path.join(basedir, ptcode, filename) ssdf.save(file_out, s_avg)
def add_segmentation_graph(basedir, ptcode, ctcode, cropname, seeds, model, s2=None, graphname='', modelname='modelavgreg'): """ add segmentation to an existing graph s2 = ssdf of existing segmentation model to add graph to this model graphname = model is default storename for model but can also be modelbranch for example if this was used in add_segmentation_ssdf """ if s2 is None: s2 = loadmodel(basedir, ptcode, ctcode, cropname, modelname) # unpacks graphold = s2['model'+graphname] seedsold = s2['seeds'+graphname] # add seeds graph seedsold.add_nodes_from(seeds.nodes(data=True)) # including attributes if any # add nodes and edges to graph model if model is not None: # step 2 and 3 were performed otherwise NoneType graphold.add_nodes_from(model.nodes(data=True)) graphold.add_edges_from(model.edges(data=True)) else: # store seeds with model graphold.add_nodes_from(seeds.nodes(data=True)) # Store model s2['model'+graphname] = graphold s2['seeds'+graphname] = seedsold # pack all graphs to ssdf for save for key in dir(s2): if key.startswith('model'): s2[key] = s2[key].pack() if key.startswith('seeds'): s2[key] = s2[key].pack() # Save filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, modelname) ssdf.save(os.path.join(basedir, ptcode, filename), s2) print('saved to disk in {} as {}.'.format(basedir, filename) )
# s2.stenttype = s.stenttype # s2.croprange = s.croprange # Obtain deform fields for i in range(N): fields = [field for field in reg.get_deform(i).as_backward() ] # fields of z,y,x s2['deform%i' % i] = fields s2.sampling = s2.deform0[ 0].sampling # Sampling of deform is different! s2.originDeforms = s2.deform0[0].origin # But origin is zero s2.params = reg.params # Save filename = '%s_%s.ssdf' % (fileTr, 'deforms') ssdf.save(os.path.join(dirsaveinsilico, ptcode, filename), s2) print("deforms saved to disk.") # Store averaged volume, where the volumes are registered # create average volume from *all* volumes deformed to the "center" N = len(reg._ims) mean_vol = np.zeros(reg._ims[0].shape, 'float64') for i in range(N): vol, deform = reg._ims[i], reg.get_deform(i) # reg._ims[0]==volOr mean_vol += deform.as_backward().apply_deformation(vol) mean_vol *= 1.0 / N # Create struct s_avg = ssdf.new() #s_avg.meta = s['meta'+oriPhase] s_avg.sampling = sampling2 # z, y, x
s = processFont(fontname) ss.append(s) # process to pack together sr, sb, si = ss[0], ss[1], ss[2] for fonttype in ['b', 'i']: s = ss[{'b': 1, 'i': 2}[fonttype]] # cut interesting part of image in i or b [Iy, Ix] = np.where(s.data > 0) y1 = Iy.max() data = s.data[0:y1 + 1, :] # paste that part in image of regular [Iy, Ix] = np.where(sr.data > 0) y1 = Iy.max() y2 = y1 + data.shape[0] sr.data[y1:y2] = data # correct origin of chars for i in range(s.origin.shape[0]): s.origin[i, 1] += y1 # copy information to struct of sr sr['charcodes_' + fonttype] = s.charcodes sr['origin_' + fonttype] = s.origin sr['size_' + fonttype] = s.size sr['width_' + fonttype] = s.width # store base[font] = sr ssdf.save(path + 'fonts.ssdf', base) ssdf.save(path + '../visvisResources/fonts.ssdf', base)
def on_key(event): """KEY commands for user interaction 'DELETE = remove seed in nodes1 closest to [picked point]' 'PageDown = remove graph posterior (y-axis) to [picked point] (use for spine seeds)' 'n = add [picked point] (SHIFT+R-click) as seed' """ global label global sd 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 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_PAGEDOWN: # remove false seeds posterior to picked point, e.g. for spine label = _utils_GUI.remove_nodes_by_selected_point(sd._nodes1, vol, a1, label, clim, showVol=showVol) if event.text == 't': # redo step1 view = a1.GetView() a1.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.key == vv.KEY_ESCAPE: model = sd._nodes1 # 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() # get filename filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, 'stentseeds' + what) # check if file already exists to not overwrite automatically if os.path.exists(os.path.join(dirsave, ptcode, filename)): #todo: shell jams after providing answer? print('File already exists') answer = str( input("\nWould you like to" " overwrite (y), save different (u) or cancel (c)? ")) if answer == 'u': filename = '%s_%s_%s_%s_2.ssdf' % (ptcode, ctcode, cropname, 'stentseeds' + what) ssdf.save(os.path.join(dirsave, ptcode, filename), s2) print("Ssdf saved to:") print(os.path.join(dirsave, ptcode)) elif answer == 'y': ssdf.save(os.path.join(dirsave, ptcode, filename), s2) print("Ssdf saved to:") print(os.path.join(dirsave, ptcode)) else: try: # check folder existance ssdf.save(os.path.join(dirsave, ptcode, filename), s2) except FileNotFoundError: # if dirsave does not exist, create os.makedirs(os.path.join(dirsave, ptcode)) ssdf.save(os.path.join(dirsave, ptcode, filename), s2) print("Ssdf saved to:") print(os.path.join(dirsave, ptcode))
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 __init__(self,ptcode,ctcode,basedir, seed_th=[600], show=True, normalize=False, modelname='model'): import os import numpy as np import visvis as vv from visvis import ssdf from stentseg.utils import PointSet, _utils_GUI from stentseg.utils.datahandling import select_dir, loadvol, loadmodel from stentseg.stentdirect.stentgraph import create_mesh from stentseg.stentdirect import stentgraph, StentDirect, getDefaultParams from stentseg.stentdirect import AnacondaDirect, EndurantDirect, NellixDirect from stentseg.utils.visualization import show_ctvolume from stentseg.utils.picker import pick3d, label2worldcoordinates, label2volindices import scipy from scipy import ndimage import copy # Select dataset to register cropname = 'prox' # phase = 10 #dataset = 'avgreg' #what = str(phase) + dataset # avgreg what = 'avgreg' # Load volumes s = loadvol(basedir, ptcode, ctcode, cropname, what) # sampling was not properly stored after registration for all cases: reset sampling vol_org = copy.deepcopy(s.vol) s.vol.sampling = [vol_org.sampling[1], vol_org.sampling[1], vol_org.sampling[2]] # z,y,x s.sampling = s.vol.sampling vol = s.vol ## Initialize segmentation parameters stentType = 'nellix' # 'zenith';'nellix' runs modified pruning algorithm in Step3 p = getDefaultParams(stentType) p.seed_threshold = seed_th # step 1 [lower th] or [lower th, higher th] # p.seedSampleRate = 7 # step 1, nellix p.whatphase = what ## Perform segmentation # Instantiate stentdirect segmenter object if stentType == 'anacondaRing': sd = AnacondaDirect(vol, p) # inherit _Step3_iter from AnacondaDirect class #runtime warning using anacondadirect due to mesh creation, ignore elif stentType == 'endurant': sd = EndurantDirect(vol, p) elif stentType == 'nellix': sd = NellixDirect(vol, p) else: sd = StentDirect(vol, p) ## show histogram and normalize # f = vv.figure(3) # a = vv.gca() # vv.hist(vol, drange=(300,vol.max())) # normalize vol to certain limit if normalize: sd.Step0(3071) vol = sd._vol # b= vv.hist(vol, drange=(300,3071)) # b.color = (1,0,0) ## Perform step 1 for seeds sd.Step1() ## Visualize if show: fig = vv.figure(2); vv.clf() fig.position = 0.00, 22.00, 1920.00, 1018.00 clim = (0,2000) # Show volume and model as graph a1 = vv.subplot(121) a1.daspect = 1,1,-1 # t = vv.volshow(vol, clim=clim) t = show_ctvolume(vol, axis=a1, showVol='MIP', clim =clim, isoTh=250, removeStent=False, climEditor=True) label = pick3d(vv.gca(), vol) sd._nodes1.Draw(mc='b', mw = 2) # draw seeded nodes #sd._nodes2.Draw(mc='b', lc = 'g') # draw seeded and MCP connected nodes vv.xlabel('x (mm)');vv.ylabel('y (mm)');vv.zlabel('z (mm)') # Show volume and cleaned up graph a2 = vv.subplot(122) a2.daspect = 1,1,-1 sd._nodes1.Draw(mc='b', mw = 2) # draw seeded nodes # t = vv.volshow(vol, clim=clim) # label = pick3d(vv.gca(), vol) # sd._nodes2.Draw(mc='b', lc='g') # sd._nodes3.Draw(mc='b', lc='g') vv.xlabel('x (mm)');vv.ylabel('y (mm)');vv.zlabel('z (mm)') # # Show the mesh #=============================================================================== # a3 = vv.subplot(133) # a3.daspect = 1,1,-1 # t = vv.volshow(vol, clim=clim) # pick3d(vv.gca(), vol) # #sd._nodes3.Draw(mc='b', lc='g') # m = vv.mesh(bm) # m.faceColor = 'g' # # _utils_GUI.vis_spared_edges(sd._nodes3) # vv.xlabel('x (mm)');vv.ylabel('y (mm)');vv.zlabel('z (mm)') #=============================================================================== # Use same camera a1.camera = a2.camera #= a3.camera switch = True a1.axis.visible = switch a2.axis.visible = switch #a3.axis.visible = switch ## Store segmentation to disk # Get graph model model = sd._nodes1 # Build struct s2 = vv.ssdf.new() 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 (not also volume) s2.model = model.pack() # Save filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, modelname+ what) ssdf.save(os.path.join(basedir, ptcode, filename), s2) print('saved to disk as {}.'.format(filename) ) ## Make model dynamic (and store/overwrite to disk) #=============================================================================== # # import pirt # from stentsegf.motion.dynamic import incorporate_motion_nodes, incorporate_motion_edges # # # Load deforms # s = loadvol(basedir, ptcode, ctcode, cropname, '10deforms') # deformkeys = [] # for key in dir(s): # if key.startswith('deform'): # deformkeys.append(key) # deforms = [s[key] for key in deformkeys] # deforms = [pirt.DeformationFieldBackward(*fields) for fields in deforms] # paramsreg = s.params # # # Load model # s = loadmodel(basedir, ptcode, ctcode, cropname, 'model'+what) # model = s.model # # # Combine ... # incorporate_motion_nodes(model, deforms, s.origin) # incorporate_motion_edges(model, deforms, s.origin) # # # Save back # filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, 'model'+what) # s.model = model.pack() # s.paramsreg = paramsreg # ssdf.save(os.path.join(basedir, ptcode, filename), s) # print('saved to disk as {}.'.format(filename) ) #===============================================================================
def savecropvols(vols, basedir, ptcode, ctcode, cropname, stenttype, sampling=None, meta=None): """ Step B: Crop and Save SSDF Input: vols from Step A Save 2 or 10 volumes (cardiac cycle phases) in one ssdf file Cropper tool opens to manually set the appropriate cropping range in x,y,z Click 'finish' to continue saving Meta information (dicom), origin, stenttype and cropping range are saved """ try: vol0 = vv.Aarray( vols[0], vols[0].meta.sampling) # vv.Aarray defines origin: 0,0,0 except AttributeError: print('AttributeError no meta with vol, use given sampling') vol0 = vv.Aarray(vols[0], sampling) # Open cropper tool print('Set the appropriate cropping range for "%s" ' 'and click finish to continue' % cropname) print('Loading... be patient') fig = vv.figure() fig.title = 'Cropping for "%s"' % cropname #vol_crop = cropper.crop3d(vol0, fig) vol_crop = crop3d(vol0, fig) # use local while error with cropper fig.Destroy() if vol_crop.shape == vol0.shape: print('User did not crop') # Calculate crop range from origin rz = int(vol_crop.origin[0] / vol_crop.sampling[0] + 0.5) rz = rz, rz + vol_crop.shape[0] ry = int(vol_crop.origin[1] / vol_crop.sampling[1] + 0.5) ry = ry, ry + vol_crop.shape[1] rx = int(vol_crop.origin[2] / vol_crop.sampling[2] + 0.5) rx = rx, rx + vol_crop.shape[2] # Initialize struct s = ssdf.new() s.sampling = vol_crop.sampling # z, y, x voxel size in mm s.origin = vol_crop.origin s.croprange = rz, ry, rx # in world coordinates s.stenttype = stenttype s.ctcode = ctcode s.ptcode = ptcode # Export and save if len(vols) == 1: # when static ct s.vol = vols[0][rz[0]:rz[1], ry[0]:ry[1], rx[0]:rx[1]] s.meta = vols[0].meta vols[0].meta.PixelData = None # avoid ssdf warning filename = '%s_%s_%s_phase.ssdf' % (ptcode, ctcode, cropname) else: # dynamic ct for volnr in range(0, len(vols)): phase = volnr * 10 if len(vols) == 2: # when only diastolic/systolic volume try: phase = vols[ volnr].meta.SeriesDescription[:2] # '78%, iDose' phase = int(phase) except AttributeError: # has no meta phase = volnr s['vol%i' % phase] = vols[volnr][rz[0]:rz[1], ry[0]:ry[1], rx[0]:rx[1]] try: s['meta%i' % phase] = vols[volnr].meta vols[volnr].meta.PixelData = None # avoid ssdf warning except AttributeError: # has no meta pass # s['meta%i'% phase] = meta # given input var # todo: meta type now error TypeError: unorderable types: DataElement() < DataElement() filename = '%s_%s_%s_phases.ssdf' % (ptcode, ctcode, cropname) file_out = os.path.join(basedir, ptcode, filename) ssdf.save(file_out, s) print() print('ssdf saved to {}.'.format(file_out))
# get deforms of centerline path as array assert model.number_of_edges() == 1 # cll should be 1 path centerlineEdge = model.edges()[0] # the two nodes that define the edge centerlineDeforms = model.edge[centerlineEdge[0]][ centerlineEdge[1]]['pathdeforms'] # store in dict of centerlineMat if key == 'model': centerlineMat[ 'centerline_deforms'] = centerlineDeforms # list with PointSet arrays elif key == 'model_2': centerlineMat[ 'centerline2_2_deforms'] = centerlineDeforms # list with PointSet arrays else: print('No model found with known name') # pack model for save s[key] = model.pack() # Save back ssdf filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, what + '_dynamic') s.paramsreg = paramsreg ssdf.save(os.path.join(basedirstl, ptcode, filename), s) print('saved dynamic to disk in {} as {}.'.format(basedirstl, filename)) # Save back mat newMatName = '%s_%s_%s_%s.mat' % (ptcode, ctcode, cropname, what + '_dynamic') scipy.io.savemat(os.path.join(basedirstl, ptcode, newMatName), centerlineMat) print('') print('Dynamic centerline was stored as {}'.format(newMatName)) print('')
storevar['startpoint'] = start1 storevar['endpoint'] = end1 scipy.io.savemat(storemat, storevar) print('') print('centerline2 was stored as.mat to {}'.format(storemat)) print('') # save ssdf model = centerline_nodes # Build struct s2 = vv.ssdf.new() 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 # Store model s2.startpoint = start1 s2.endpoint = end1 s2.params = params s2.centerline = centerline2 s2.model = model.pack() # get filename filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, 'centerline') ssdf.save(os.path.join(targetdir, filename), s2) print("Centerline saved to ssdf in :") print(os.path.join(targetdir, filename))
def _Save(self): try: ssdf.save(self._fname, self._s) except IOError: pass # Maybe an installed frozen application (no write-rights)
s2.croprange = s.croprange # Obtain deform fields for i in range(N): phase = i * 10 fields = [field for field in reg.get_deform(i).as_backward()] s2['deform%i' % phase] = fields s2.sampling = s2.deform0[ 0].sampling # Sampling of deform is different! #s2.origin = s2.deform0[0].origin # But origin is zero s2.originDeforms = s2.deform0[0].origin # But origin is zero s2.params = reg.params # Save filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, 'deforms') ssdf.save(os.path.join(basedir, ptcode, filename), s2) print("deforms saved to disk.") # Store averaged volume, where the volumes are registered from visvis import ssdf # Create average volume from *all* volumes deformed to the "center" N = len(reg._ims) mean_vol = np.zeros(reg._ims[0].shape, 'float64') for i in range(N): vol, deform = reg._ims[i], reg.get_deform(i) mean_vol += deform.as_backward().apply_deformation(vol) mean_vol *= 1.0 / N # Create struct
def __init__(self, ptcode, ctcode, basedir): ## Perform image registration import os, time import numpy as np import visvis as vv import pirt.reg # Python Image Registration Toolkit from stentseg.utils.datahandling import select_dir, loadvol import scipy from scipy import ndimage # Select dataset to register cropname = 'prox' what = 'phases' # Load volumes s = loadvol(basedir, ptcode, ctcode, cropname, what) vols = [] phases = [] for key in dir(s): if key.startswith('vol'): print(key) # create vol with zoom in z-direction zscale = (s[key].sampling[0] / s[key].sampling[1]) # z / y # resample vol using spline interpolation, 3rd order piecewise polynomial vol_zoom = scipy.ndimage.interpolation.zoom( s[key], [zscale, 1, 1], 'float32') s[key].sampling = [ s[key].sampling[1], s[key].sampling[1], s[key].sampling[2] ] # set scale and origin vol_zoom_type = vv.Aarray(vol_zoom, s[key].sampling, s[key].origin) vol = vol_zoom_type phases.append(key) vols.append(vol) t0 = time.time() # Initialize registration object reg = pirt.reg.GravityRegistration(*vols) reg.params.mass_transforms = 2 # 2nd order (Laplacian) triggers more at lines reg.params.speed_factor = 1.0 reg.params.deform_wise = 'groupwise' # groupwise! reg.params.mapping = 'backward' reg.params.deform_limit = 1.0 reg.params.final_scale = 1.0 # We might set this a wee bit lower than 1 (but slower!) reg.params.scale_sampling = 16 reg.params.final_grid_sampling = 20 reg.params.grid_sampling_factor = 0.5 # Go! reg.register(verbose=1) t1 = time.time() print('Registration completed, which took %1.2f min.' % ((t1 - t0) / 60)) # Store registration result from visvis import ssdf # Create struct s2 = vv.ssdf.new() N = len(vols) for key in dir(s): if key.startswith('meta'): s2[key] = s[key] s2.origin = s.origin s2.stenttype = s.stenttype s2.croprange = s.croprange # Obtain deform fields for i in range(N): fields = [field for field in reg.get_deform(i).as_backward()] phase = phases[i][3:] s2['deform%s' % phase] = fields s2.sampling = s2['deform%s' % phase][0].sampling # Sampling of deform is different! s2.originDeforms = s2['deform%s' % phase][0].origin # But origin is zero s2.params = reg.params # Save filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, 'deforms') ssdf.save(os.path.join(basedir, ptcode, filename), s2) print("deforms saved to disk.") #============================================================================ # Store averaged volume, where the volumes are registered #from visvis import ssdf # Create average volume from *all* volumes deformed to the "center" N = len(reg._ims) mean_vol = np.zeros(reg._ims[0].shape, 'float64') for i in range(N): vol, deform = reg._ims[i], reg.get_deform(i) mean_vol += deform.as_backward().apply_deformation(vol) mean_vol *= 1.0 / N # Create struct s_avg = ssdf.new() for key in dir(s): if key.startswith('meta'): s_avg[key] = s[key] s_avg.sampling = s.vol0.sampling # z, y, x after interpolation s_avg.origin = s.origin s_avg.stenttype = s.stenttype s_avg.croprange = s.croprange s_avg.vol = mean_vol.astype('float32') s_avg.params = s2.params fig1 = vv.figure(1) vv.clf() fig1.position = 0, 22, 1366, 706 a1 = vv.subplot(111) a1.daspect = 1, 1, -1 renderstyle = 'mip' a1b = vv.volshow(s_avg.vol, clim=(0, 2000), renderStyle=renderstyle) #a1b.isoThreshold = 600 vv.xlabel('x'), vv.ylabel('y'), vv.zlabel('z') vv.title('Average volume of %s phases (%s) (resized data)' % (len(phases), renderstyle)) # Save avg = 'avgreg' filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, avg) ssdf.save(os.path.join(basedir, ptcode, filename), s_avg) print("avgreg saved to disk.") t1 = time.time() print('Registration completed, which took %1.2f min.' % ((t1 - t0) / 60))
def _Save(self): ssdf.save(self._fname, self._s)
s = processFont(fontname) ss.append(s) # process to pack together sr, sb, si = ss[0], ss[1], ss[2] for fonttype in ['b', 'i']: s = ss[{'b':1,'i':2}[fonttype]] # cut interesting part of image in i or b [Iy,Ix] = np.where(s.data>0); y1 = Iy.max() data = s.data[0:y1+1,:] # paste that part in image of regular [Iy,Ix] = np.where(sr.data>0); y1 = Iy.max() y2 = y1 + data.shape[0] sr.data[y1:y2] = data # correct origin of chars for i in range(s.origin.shape[0]): s.origin[i,1] += y1 # copy information to struct of sr sr['charcodes_'+fonttype] = s.charcodes sr['origin_'+fonttype] = s.origin sr['size_'+fonttype] = s.size sr['width_'+fonttype] = s.width # store base[font] = sr ssdf.save(path+'fonts.ssdf', base) ssdf.save(path+'../visvisResources/fonts.ssdf', base)
def __init__(self,ptcode,ctcode,basedir, threshold=300, show=True, normalize=False, modelname='modelvessel'): import os import numpy as np import visvis as vv from visvis import ssdf from stentseg.utils import PointSet, _utils_GUI from stentseg.utils.datahandling import select_dir, loadvol, loadmodel from stentseg.stentdirect.stentgraph import create_mesh from stentseg.stentdirect import stentgraph, StentDirect, getDefaultParams from stentseg.stentdirect import AnacondaDirect, EndurantDirect, NellixDirect from stentseg.utils.visualization import show_ctvolume from stentseg.utils.picker import pick3d, label2worldcoordinates, label2volindices import scipy from scipy import ndimage import copy from stentseg.utils.get_isosurface import get_isosurface3d, isosurface_to_graph, show_surface_and_vol # Select dataset to register cropname = 'prox' #phase = 10 #what = 'phase'+str(phase) what = 'avgreg' # Load volumes s = loadvol(basedir, ptcode, ctcode, cropname, what) # sampling was not properly stored after registration for all cases: reset sampling vol_org = copy.deepcopy(s.vol) s.vol.sampling = [vol_org.sampling[1], vol_org.sampling[1], vol_org.sampling[2]] # z,y,x s.sampling = s.vol.sampling vol = s.vol # Get isosurface verts, faces, pp_vertices, mesh = get_isosurface3d(vol, threshold=threshold, showsurface=False) if show: self.label = show_surface_and_vol(vol, pp_vertices, showVol='MIP') # Convert to graph model = isosurface_to_graph(pp_vertices) # model with nodes # Store segmentation to disk p = threshold stentType = 'isosurface' # Build struct s2 = vv.ssdf.new() 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 (not also volume) s2.model = model.pack() # Save filename = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, modelname+ what) ssdf.save(os.path.join(basedir, ptcode, filename), s2) print('saved to disk as {}.'.format(filename) )