def loadvol(basedir, ptcode=None, ctcode=None, cropname=None, what='phases', fname=None): """ Load volume data. An ssdf struct is returned. The volumes are made into Aarray's with their sampling and origin set. """ if fname is None: fname = '%s_%s_%s_%s.ssdf' % (ptcode, ctcode, cropname, what) try: s = ssdf.load(os.path.join(basedir, ptcode, fname)) except FileNotFoundError: s = ssdf.load(os.path.join(basedir, fname)) for key in dir(s): if key.startswith('vol'): s[key] = vv.Aarray(s[key], s.sampling, s.origin) elif key.startswith('deform'): fields = s[key] s[key] = [ vv.Aarray(field, s.sampling, s.origin) for field in fields ] # origin of volume is added as meta-data #[vv.Aarray(field, s.sampling, [0,0,0]) for field in fields] would use wrong deform-data when deforming return s
def plot(image): # ax = vv.gca() # ms = vv.Mesh(ax) logging.warning([image.shape, image.spacing]) vol = image[:, :, :, 0] logging.warning([vol.min(), vol.max()]) vol = util.normalize(vol, 'ADCm') logging.warning([vol.min(), vol.max()]) vol = vv.Aarray(vol, image.spacing) cmap = None # cmap = vv.CM_VIRIDIS render_style = 'mip' # render_style = 'iso' # render_style = 'ray' # render_style = 'edgeray' # render_style = 'litray' vv.figure() vv.xlabel('x axis') vv.ylabel('y axis') vv.zlabel('z axis') a1 = vv.subplot(111) t1 = vv.volshow(vol, cm=cmap, renderStyle=render_style) t1.isoThreshold = 0.7 vv.title(render_style) # a1.camera = a2.camera = a3.camera vv.ColormapEditor(a1)
def resample_vol(vol, xsampling=0.5, ysampling=0.5, zsampling=0.5): """ input: vol with vol.sampling output: vol with new sampling """ currentSampling = vol.sampling # vol in z,y,x zscale = vol.sampling[0] / zsampling # z / znew yscale = vol.sampling[1] / ysampling # y / ynew xscale = vol.sampling[2] / xsampling # x / xnew vol_sampled = scipy.ndimage.interpolation.zoom(vol, [zscale, yscale, xscale], 'float32') newSampling = (zsampling, ysampling, xsampling) # adjust vol with sampling and origin vol_sampled_type = vv.Aarray(vol_sampled, newSampling, vol.origin) vol = vol_sampled_type
def visvis_plot(vp): """ This function accepts a volume rendering object, which it then tosses into visvis for plotting. """ vp.partition_grids() gs = vp.bricks mi = min((g.my_data[0].min() for g in gs)) ma = max((g.my_data[0].max() for g in gs)) texes = [] ax = vv.gca() for g in gs: ss = ((g.RightEdge - g.LeftEdge) / (np.array(g.my_data[0].shape) - 1)).tolist() origin = g.LeftEdge.astype("float32").tolist() dd = (g.my_data[0].astype("float32") - mi) / (ma - mi) dd = np.clip(dd, 0.0, 1.0) print(ss) texes.append(vv.Aarray(dd, origin=origin, sampling=ss)) mtex = MultipleTexture(ax, texes, global_size=vp.ds.domain_dimensions) ax.daspectAuto = False ax.SetLimits() ax.bgcolor = (0, 0, 0) # set camera ax.cameraType = '3d' # done ax.Draw() return mtex, ax
# calculate B field at given points B = sol.CalculateB(points=points) Babs = np.linalg.norm(B, axis=1) # draw results # prepare axes a = vv.gca() a.cameraType = '3d' a.daspectAuto = False vol = Babs.reshape(grid.shape[1:]).T vol = np.clip(vol, 0.002, 0.01) vol = vv.Aarray(vol, sampling=(resolution, resolution, resolution), origin=(volume_corner1[2], volume_corner1[1], volume_corner1[0])) # set labels vv.xlabel('x axis') vv.ylabel('y axis') vv.zlabel('z axis') sol.vv_PlotWires() t = vv.volshow2(vol, renderStyle='mip', cm=vv.CM_JET) vv.colorbar() app = vv.use() app.Run()
""" Example demonstrating the stent segmentation algorithm on the stent CT volume that comes with visvis. """ import numpy as np import visvis as vv from visvis import ssdf from stentseg.stentdirect import StentDirect, StentDirect_old, getDefaultParams, stentgraph from stentseg.stentdirect.stentgraph import create_mesh # Load volume data, use Aarray class for anisotropic volumes vol = vv.volread('stent') vol = vv.Aarray(vol,(1,1,1)) #stentvol = vv.ssdf.load(r'C:\Users\Maaike\Dropbox\UT MA3\Research Aortic Stent Grafts\Data_nonECG-gated\lspeas\lspeas_003.ssdf') #vol = vv.Aarray(stentvol.vol,stentvol.sampling) #stentvol = vv.ssdf.load('/home/almar/data/lspeas/LSPEAS_002/LSPEAS_002_1month_ring_avg3090.ssdf') #vol = vv.Aarray(stentvol.vol,stentvol.sampling) # Get parameters. Different scanners/protocols/stent material might need # different parameters. p = getDefaultParams() p.graph_weakThreshold = 10 # step 3, stentgraph.prune_very_weak: p.mcp_maxCoverageFronts = 0.03 # step 2, create MCP object p.graph_expectedNumberOfEdges = 2 # 2 for zig-zag, 4 for diamond shaped # # step 3, in stentgraph.prune_weak #p.graph_trimLength = # step 3, stentgraph.prune_tails #p.graph_strongThreshold # step 3, stentgraph.prune_weak and stentgraph.prune_redundant p.seed_threshold = 800 # step 1 #p.graph_minimumClusterSize # step 3, stentgraph.prune_clusters
# 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) # get slice 2d if slice: vol = vol_zoom_type[slice,:,:] # z y x elif slicey: vol = vol_zoom_type[:,slicey,:] # z y x else: # use mid slice z vol = vol_zoom_type[int(0.5*volOr.shape[0]),:,:] phases.append(key) vols.append(vol) t0 = time.time() # Initialize registration object
B2Dabsgrid = B2Dabs.reshape(grid2D.shape[1:-1]).T # draw results # prepare axes a = vv.gca() a.cameraType = '3d' a.daspectAuto = False #Bgrid = B.reshape(grid3D.shape).T Babsgrid = Babs.reshape(grid3D.shape[1:]).T # clipping is not automatic! Babsgrid = np.clip(Babsgrid, 0, 0.005) Babsgrid = vv.Aarray(Babsgrid, sampling=(resolution, resolution, resolution), origin=(volume_corner1[2], volume_corner1[1], volume_corner1[0])) # set labels vv.xlabel('x axis') vv.ylabel('y axis') vv.zlabel('z axis') bs.vv_PlotWires() t = vv.volshow2(Babsgrid, renderStyle='mip', cm=vv.CM_JET) vv.colorbar() app = vv.use() app.Run() # matplotlib plot
ls = l.split('[') lsc = ls[1].split(',') z = int(lsc[0]) y = int(lsc[1]) x = int(lsc[2]) print('point indices z,y,x: {},{},{}.'.format(z, y, x)) return [x, y, z] def get_picked_seed(data, label): """ Picked point (SHIFT+r-click) is converted to world coordinates as in Step1 Input: volume data, label """ from stentseg.utils import PointSet coord = label2volindices(label) # [x,y,z] p = PointSet(coord, dtype=np.float32) # Correct for anisotropy and offset if hasattr(data, 'sampling'): p *= PointSet(list(reversed(data.sampling))) if hasattr(data, 'origin'): p += PointSet(list(reversed(data.origin))) return list(p.flat) if __name__ == '__main__': vol = vv.Aarray(vv.volread('stent'), (0.5, 0.5, 0.5), (100, 40, 10)) a = vv.gca() t = vv.volshow(vol) pick3d(a, vol)
# set clim if isinstance(clim,list): clim = tuple(clim) if isinstance(clim, tuple): t.SetClim(clim) # set colormap if cm is not None: t.colormap = cm # set axes if axesAdjust: if axes.daspectAuto is None: axes.daspectAuto = False axes.cameraType = '2d' da = axes.daspect axes.daspect = da[0], -abs(da[1]), da[2] axes.SetLimits() # return axes.Draw() return t if __name__ == '__main__': im = vv.imread('astronaut.png') im = vv.Aarray(im[:,::4,:], (1,4,1)) # Keep every 4th pixel and make them wide # imshow knows about anisotropic arrays! t = vv.imshow(im)
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))
# 'Dressed' part gives errors due to extreme negative intensities (-2000) --> # clip intensities below -1000 for registration, --> set to -200 (HU between fat-lung) if True: volOr[volOr < -1000] = -200 volTr[volTr < -1000] = -200 # Get the sampling of DataDressed and DataDressedInterpolated sampling2_x = mat['DressedVars']['width_pixel_y'][0][0][0][ 0] # y in matlab = x in python (left-right) sampling2_y = mat['DressedVars']['width_pixel_x'][0][0][0][ 0] # x in matlab = y in python (ant-post) sampling2_z = mat['DressedVars']['width_pixel_z'][0][0][0][0] sampling2 = tuple([sampling2_z, sampling2_y, sampling2_x]) # zyx # create Aarray volume volOr = vv.Aarray(volOr, sampling2, origin2) volTr = vv.Aarray(volTr, sampling2, origin2) vols = [volOr, volTr] if reg2d: # Get a slice for registration not the volume imOr = volOr[int(0.5 * volOr.shape[0]), :, :] # pick a z slice in mid volume imTr = volTr[int(0.5 * volOr.shape[0]), :, :] sampling2 = sampling2[1:] # keep y,x origin2 = origin2[1:] vols = [imOr, imTr] if visualize: f = vv.figure(1) vv.clf() f.position = 0.00, 22.00, 1914.00, 1018.00
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))
img_nm = "pat_dash%.5d.png" % lp_arr[i] print("nm= %s" % img_nm) img_lst.append(vv.imread(img_nm)) #sys.exit(1) #img = img[:-1,:-1] # make not-power-of-two (to test if video driver is capable) #print(img.shape) y0i = int(y0) y1i = int(y1)+1 x1i = int(x1)+1 vv.figure() a1 = vv.subplot(121) #im = vv.Aarray(im) im = vv.Aarray((y1i+y0i, use_len*x1i, 4)) # Cut in four pieces, but also change resolution using different step sizes #im1 = im[:300,:300] #im2 = im # Create new camera and attach #cam = vv.cameras.TwoDCamera() #a1.camera = cam for i in range(0, use_len): j = uval[i][1] im[:y1i+y0i,i*x1i:(i+1)*x1i] = img_lst[j][:y1i+y0i,:x1i] #x, y = (0, 288-fsz) #text = "Display "+bmarkf+" sub-benchmark for interval, BW" #txt = ("GIPS: %.3f bill instr/sec" % uval[i][0]) #w, h = font.getsize(text)