Package Volume :: Package Renderers :: Package UTVolumeLibrary :: Package DejaVu :: Module UTVolRenGeom
[hide private]
[frames] | no frames]

Source Code for Module Volume.Renderers.UTVolumeLibrary.DejaVu.UTVolRenGeom

  1  ############################################################################# 
  2  # 
  3  # Author: Anna Omelchenko, Michel Sanner 
  4  # 
  5  # Copyright: M. Sanner TSRI 2003 
  6  # 
  7  ############################################################################# 
  8   
  9  # 
 10  # $Header $ 
 11  # 
 12  # $Id $ 
 13  # 
 14   
 15  import string, sys,time 
 16  from opengltk.OpenGL import GL 
 17  import Numeric 
 18  from struct import unpack 
 19  from Volume.Renderers.UTVolumeLibrary import UTVolumeLibrary 
 20  #from VolumeLibrary import VolumeLibrary 
 21  #print "UTVolumeLibrary imported from" , UTVolumeLibrary.__file__ 
 22  from DejaVu.viewerFns import checkKeywords 
 23  from Volume.Grid3D import Grid3DUC 
 24   
 25  from DejaVu.VolumeGeom import VolumeGeom, CropBox 
 26   
27 -class VolumeCrop:
28 # trying to mimic the VolumePro API 29 kDisable = 0 30 kSubVolume = 1 31 k3DCross = 2 32 k3DCrossInvert = 3 33 k3DCrossInvert = 4 34 k3DFence = 5 35 k3DFenceInvert = 6 36
37 - def __init__(self, volgeom):
38 self.volgeom = volgeom 39 self.data = None 40 self.flag = self.kSubVolume 41 self.xmin = 0 42 self.xmax = 0 43 self.ymin = 0 44 self.ymax = 0 45 self.zmin = 0 46 self.zmax = 0 47 self.size = (0,0,0)
48
49 - def updateData(self):
50 self.data = Numeric.array(self.volgeom.dataArr) 51 nx,ny,nz = self.volgeom.volumeSize 52 self.xmin = 0 53 self.xmax = nx 54 self.ymin = 0 55 self.ymax = ny 56 self.zmin = 0 57 self.zmax = nz 58 self.size = (nx,ny,nz)
59
60 - def SetXSlab(self, xmin, xmax):
61 #if self.data == None: return 62 self.xmin = xmin 63 self.xmax = xmax+1 64 if self.flag == self.kDisable: return 65 self.data[self.zmin:self.zmax, self.ymin:self.ymax, xmin:xmax+1] = self.volgeom.dataArr[self.zmin:self.zmax, self.ymin:self.ymax, xmin:xmax+1] 66 self.data[:, :, :xmin]=0 67 self.data[:, :, xmax+1: ]=0 68 nx,ny,nz=self.size 69 self.volgeom.volume.uploadColorMappedData(self.data.flat, nx,ny,nz)
70
71 - def SetYSlab(self, ymin, ymax):
72 #if self.data == None: return 73 self.ymax = ymax+1 74 self.ymin = ymin 75 if self.flag == self.kDisable: return 76 self.data[self.zmin:self.zmax, ymin:ymax+1, self.xmin:self.xmax] = self.volgeom.dataArr[self.zmin:self.zmax, ymin:ymax+1, self.xmin:self.xmax] 77 self.data[:, :ymin, :]=0 78 self.data[:, ymax+1:, :]=0 79 nx,ny,nz=self.size 80 self.volgeom.volume.uploadColorMappedData(self.data.flat, 81 nx, ny, nz)
82
83 - def SetZSlab(self, zmin, zmax):
84 #if self.data == None: return 85 self.zmax = zmax+1 86 self.zmin = zmin 87 if self.flag == self.kDisable: return 88 self.data[zmin:zmax+1, self.ymin:self.ymax, self.xmin:self.xmax] = \ 89 self.volgeom.dataArr[zmin:zmax+1, self.ymin:self.ymax, 90 self.xmin:self.xmax] 91 self.data[:zmin, :, :]=0 92 self.data[zmax+1:, :, :]=0 93 nx,ny,nz=self.size 94 self.volgeom.volume.uploadColorMappedData(self.data.flat, 95 nx, ny, nz)
96
97 - def SetSlabs(self, xmin, xmax, ymin, ymax, zmin, zmax):
98 #if self.data == None: return 99 self.data[zmin:zmax+1, ymin:ymax+1, xmin:xmax+1] = \ 100 self.volgeom.dataArr[zmin:zmax+1, ymin:ymax+1, xmin:xmax+1] 101 nx,ny,nz=self.size 102 if ymin > 0: 103 self.data[: , : ymin, :] = 0 104 if ymax < ny: 105 self.data[:, ymax+1: , :] = 0 106 if xmin > 0: 107 self.data[:xmin, :, :] = 0 108 if xmax < nx: 109 self.data[xmax+1:, :, :] = 0 110 if zmin > 0: 111 self.data[:, :, :zmin] = 0 112 if zmax < nz: 113 self.data[:, :, zmax+1:] = 0 114 self.volgeom.volume.uploadColorMappedData(self.data.flat, 115 nx, ny, nz) 116 self.xmin = xmin 117 self.xmax = xmax 118 self.ymax = ymax 119 self.ymin = ymin 120 self.zmax = zmax 121 self.zmin = zmin
122
123 - def SetFlags(self, flag):
124 self.flag = flag 125 if flag == self.kDisable: 126 nx,ny,nz=self.size 127 self.xmin = 0 128 self.xmax = nx 129 self.ymin = 0 130 self.ymax = ny 131 self.zmin = 0 132 self.zmax = nz 133 self.data[self.zmin:self.zmax+1, 134 self.ymin:self.ymax+1, 135 self.xmin:self.xmax+1] = \ 136 self.volgeom.dataArr[self.zmin:self.zmax+1, 137 self.ymin:self.ymax+1, 138 self.xmin:self.xmax+1] 139 self.volgeom.volume.uploadColorMappedData(self.data.flat, 140 nx, ny,nz)
141 142
143 -class UTVolRenGeom(VolumeGeom):
144
145 - def Draw(self):
146 """ Display the render volume""" 147 if not self.dataArr: 148 return 149 t1 = time.time() 150 UTVolumeLibrary.InitTexParameteri() 151 self.volume.renderVolume() 152 t2 = time.time()
153 #print "time tor render:",t2 -t1 154
155 - def __init__(self, name=None, **kw):
156 157 apply( VolumeGeom.__init__, (self,name,0), kw) 158 self.inheritXform=1 159 self.Set(frontPolyMode='fill', backPolyMode='fill') 160 161 #volume renderer 162 self.volume = UTVolumeLibrary.VolumeRenderer() 163 self.dataArr =None 164 self.byte_map=None 165 166 167 ## vi.cameras[0].Activate() 168 ## self.InitVolumeRenderer() 169 self.volumeSize = (0,0,0) 170 self.onaddVolume_list = [] 171 self.volrenInitialized = 0 172 self.updateBoundBox = 1 173 self.volume.GetSize = self.GetSize 174 self.crop = VolumeCrop(self) 175 self.cropBox = CropBox(self) 176 self.cropBox.crop = self.crop 177 self.masterObject = None 178 self.cropOpts = ['off','SubVolume'] 179 self.firstLoaded = 1 180 181 # rendering quality used when moving 182 self.coarseRenderingQuality = 0.5
183 184
185 - def coarseRendering(self, event=None):
186 self.volume.setQuality(self.coarseRenderingQuality)
187 188
189 - def fineRendering(self, event=None):
190 self.volume.setQuality(1.0)
191 192
193 - def InitVolumeRenderer(self):
194 """ Initialize the volume rendering""" 195 if not self.volume.initRenderer(): 196 print "Warning, there was an error initializing the volume renderer\n" 197 else: 198 self.volrenInitialized = 1
199 200
201 - def LoadVolume(self,file):
202 """ Get the data from binary file,rawiv format""" 203 204 #load colormap from file 205 myfile = open(file, "rb" ) 206 #the header 207 header=myfile.read(68) 208 # unpack header following rawiv format,big endian 209 h = unpack('>6f5I6f',header) 210 width=int(h[8]) 211 height=int(h[9]) 212 depth =int(h[10]) 213 214 # load the data 215 l = myfile.read(width*height*depth) 216 self.dataArr = Numeric.fromstring(l, Numeric.UnsignedInt8, 217 (width*height*depth)) 218 self.volumeSize = (width,height,depth) 219 #self.dataArr = Numeric.reshape(self.dataArr,(width,height,depth)) 220 myfile.close() 221 222 if self.dataArr == None: 223 print " you need to load a volume data" 224 return 225 if self.firstLoaded: 226 if self.viewer: 227 rootObject = self.viewer.rootObject 228 self.minBB=(-0.5, -0.5, -0.5) 229 self.maxBB=(0.5, 0.5, 0.5) 230 self.viewer.NormalizeCurrentObject() 231 self.firstLoaded = 0 232 status = self.volume.uploadColorMappedData(self.dataArr,width,height,depth) 233 if status !=1: 234 raise RuntimeError("uploadColorMappedData() in LoadVoulume failed. Status %d"% status) 235 #print "status uploadColorMappedData: ", status 236 self.dataArr = Numeric.reshape(self.dataArr, 237 (depth,height,width)) 238 if self.byte_map == None: 239 self.grayRamp() 240 #update crop box 241 self.crop.updateData() 242 nx,ny,nz = self.volumeSize 243 self.cropBox.setVolSize((nx,ny,nz)) 244 self.cropBox.xmin = 0 245 self.cropBox.xmax = nx 246 self.cropBox.ymin = 0 247 self.cropBox.ymax = ny 248 self.cropBox.zmin = 0 249 self.cropBox.zmax = nz 250 self.cropBox.update() 251 for c in self.onaddVolume_list: 252 c.OnAddVolumeToViewer()
253 254
255 - def AddGrid3D(self, grid):
256 assert isinstance(grid, Grid3DUC) 257 258 if not self.volrenInitialized: 259 if not self.viewer: # we need an OpenGL context before 260 print "self.viewer: ", self.viewer 261 return # we can initialize the renderer 262 self.InitVolumeRenderer() 263 for c in self.viewer.cameras: 264 c.addButtonDownCB(self.coarseRendering) 265 c.addButtonUpCB(self.fineRendering) 266 267 orig = grid.origin[:] 268 step = grid.stepSize 269 270 nx, ny, nz = grid.data.shape 271 gridSize = [nx*step[0], ny*step[1], nz*step[2]] 272 gridSize2 = [gridSize[0]*0.5, gridSize[1]*0.5, gridSize[2]*0.5] 273 maxgrid = [ orig[0]+gridSize[0], 274 orig[1]+gridSize[1], 275 orig[2]+gridSize[2]] 276 transl = [ orig[0]+gridSize2[0], 277 orig[1]+gridSize2[1], 278 orig[2]+gridSize2[2]] 279 280 # save scale and tranlation into Matrix which is not affected 281 # by reset 282 if grid.crystal: 283 # compute cartesian voxel sizes 284 x, y, z = grid.getStepSizeReal() 285 286 #build crystal object for length with padding 287 from mglutil.math.crystal import Crystal 288 if hasattr(grid, 'dataDims'): 289 # compute ratios of padding along the 3 dimensions 290 dx = grid.dimensions[0] - grid.dataDims[0] - 1 291 dy = grid.dimensions[1] - grid.dataDims[1] - 1 292 dz = grid.dimensions[2] - grid.dataDims[2] - 1 293 ry = float(dx)/dy 294 rz = float(dx)/dz 295 else: 296 ry = rz = 1.0 297 298 dims = (grid.dimensions[0]-1, (grid.dimensions[1]-1)*ry, 299 (grid.dimensions[2]-1)*rz ) 300 cryst = Crystal( (dims[0]*x, dims[1]*y, dims[2]*z), 301 grid.crystal.angles) 302 303 matrix = Numeric.identity(4, 'f') 304 matrix[:3, :3] = cryst.ftoc.astype('f') 305 matrix.shape = (16,) 306 307 # cleanup=False because rotation can contain shear which should 308 # be kept 309 self.MatrixRot, MatrixTransl, self.MatrixScale = self.Decompose4x4( 310 matrix, cleanup=False) 311 312 # set utvolgeom's Matrix components 313 self.MatrixScale = (self.MatrixScale[0], self.MatrixScale[1]/ry, 314 self.MatrixScale[2]/rz) 315 316 origin = grid.crystal.toCartesian(grid.origin) 317 self.MatrixTransl = (origin[0]+MatrixTransl[0]+dims[0]*0.5*x, 318 origin[1]+MatrixTransl[1]+dims[1]*0.5*y/ry, 319 origin[2]+MatrixTransl[2]+dims[2]*0.5*z/rz) 320 #o = grid.origin 321 #t1 = cryst.toFractional(MatrixTransl) 322 #t2 = (0.5, 0.5, 0.5) 323 #trans = ( o[0]+t1[0]+t2[0], o[1]+t1[1]+t2[1],o[2]+t1[2]+t2[2]) 324 #self.MatrixTransl = cryst.toCartesian(trans) 325 #print o 326 #print t1 327 #print t2 328 #print trans 329 #print self.MatrixTransl 330 331 #self.MatrixTransl = (0.,0.,0.) 332 #self.MatrixScale = (1.,1.,1.) 333 334 RotInv = Numeric.transpose(Numeric.reshape(self.MatrixRot, (4,4))) 335 self.MatrixRotInv = Numeric.reshape(RotInv, (16,)) 336 # 337 self.MatrixRot = self.MatrixRot.astype('f') 338 self.MatrixRotInv = self.MatrixRot.astype('f') 339 340 else: 341 self.setMatrixComponents(trans=transl) 342 self.setMatrixComponents(scale=gridSize, trans=transl) 343 344 if self.firstLoaded: 345 if self.viewer: 346 rootObject = self.viewer.rootObject 347 self.minBB = [-0.5, -0.5, -0.5] 348 self.maxBB = [ 0.5, 0.5, 0.5] 349 #print "all objects:", self.viewer.rootObject.AllObjects() 350 self.viewer.NormalizeCurrentObject() 351 self.firstLoaded = 0 352 353 # scale and translate volume 354 ##self.SetScale( gridSize) 355 ##trans = Numeric.array( gridSize2, 'f') 356 ##self.SetTranslation( trans ) 357 358 #mat = self.GetMatrix(self) 359 #self.SetMatrix(mat) 360 #self.ResetTransformation() 361 362 arr = Numeric.array( Numeric.transpose(grid.data), 363 grid.data.typecode()) 364 upload = self.volume.uploadColorMappedData 365 status = upload(arr.flat, nx, ny,nz) 366 if status !=1: 367 raise RuntimeError("uploadColorMappedData() in AddVolume failed. Status %d"% status) 368 369 self.dataArr = Numeric.reshape(arr,(nz,ny,nx)) 370 self.volumeSize = (nx,ny,nz) 371 if self.byte_map == None: 372 self.grayRamp() 373 # update cropping box 374 self.crop.updateData() 375 self.cropBox.setVolSize((nx,ny,nz)) 376 self.cropBox.xmin = 0 377 self.cropBox.xmax = nx 378 self.cropBox.ymin = 0 379 self.cropBox.ymax = ny 380 self.cropBox.zmin = 0 381 self.cropBox.zmax = nz 382 self.cropBox.update() 383 for c in self.onaddVolume_list: 384 c.OnAddVolumeToViewer()
385
386 - def AddVolume(self, arr, nx, ny, nz, datatype='numarr'):
387 if datatype == 'numarr': 388 assert len(arr.shape) == 1 389 390 if not self.volrenInitialized: 391 if not self.viewer: # we need an OpenGL context before 392 return # we can initialize the renderer 393 394 self.InitVolumeRenderer() 395 396 if self.firstLoaded: 397 if self.viewer: 398 rootObject = self.viewer.rootObject 399 self.minBB=(-0.5, -0.5, -0.5) 400 self.maxBB=(0.5, 0.5, 0.5) 401 self.viewer.NormalizeCurrentObject() 402 self.firstLoaded = 0 403 if datatype == 'numarr': 404 status = self.volume.uploadColorMappedData(arr,nx,ny,nz) 405 else: 406 status = self.volume.uploadZeroPaddedData(arr,nx,ny,nz) 407 #print "status uploadColorMappedData: ", status 408 if status !=1: 409 raise RuntimeError("uploadColorMappedData() in AddVolume failed. Status %d"% status) 410 self.dataArr = Numeric.reshape(arr,(nz,ny,nx)) 411 self.volumeSize = (nx,ny,nz) 412 if self.byte_map == None: 413 self.grayRamp() 414 # update cropping box 415 self.crop.updateData() 416 self.cropBox.setVolSize((nx,ny,nz)) 417 self.cropBox.xmin = 0 418 self.cropBox.xmax = nx 419 self.cropBox.ymin = 0 420 self.cropBox.ymax = ny 421 self.cropBox.zmin = 0 422 self.cropBox.zmax = nz 423 self.cropBox.update() 424 for c in self.onaddVolume_list: 425 c.OnAddVolumeToViewer()
426
427 - def LoadColorMap(self,file):
428 """ Get the colormap data from binaries files""" 429 430 myfile = open(file, "rb" ) 431 l = myfile.read(256*4) 432 self.byte_map =Numeric.fromstring(l,(256*4), 433 Numeric.UnsignedInt8) 434 self.byte_map = Numeric.reshape(self.byte_map,(256,4)) 435 myfile.close() 436 if self.byte_map == None: 437 print " you need to load a color map" 438 return 439 else: 440 self.volume.uploadColorMap(self.byte_map)
441 442
443 - def setVolRenColors(self, values):
444 """ update the color from the color map data""" 445 #the color editor are in 0.0 .... 1.0 range 446 #the color map are in 0 .. 255 range 447 val = values[1] *255 448 self.byte_map[values[0]:values[0]+len(val),:3] = val.astype(Numeric.UnsignedInt8) 449 self.volume.uploadColorMap(self.byte_map) 450 self.viewer.Redraw()
451
452 - def setVolRenAlpha(self, values):
453 """ update the opacity of the colormap""" 454 #val = (values[1]/4096.)*255 455 val = values[1] 456 self.byte_map[values[0]:values[0]+len(val),3] = val.astype(Numeric.UnsignedInt8) 457 self.volume.uploadColorMap(self.byte_map) 458 self.viewer.Redraw()
459
460 - def grayRamp(self):
461 self.byte_map = Numeric.transpose(Numeric.array([range(256),range(256),range(256),range(256)] )).astype(Numeric.UnsignedInt8) 462 self.volume.uploadColorMap(self.byte_map)
463
464 - def Set(self, check=1, redo=1, **kw):
465 if __debug__: 466 if check: 467 apply( checkKeywords, (self.name,self.keywords), kw) 468 apply( VolumeGeom.Set, (self,0,0), kw) 469 s = kw.get('volscale') 470 tr = kw.get('voltranslate') 471 if s: 472 self.SetScale(s) 473 if tr: 474 tr = Numeric.array(tr) 475 self.SetTranslation(tr)
476
477 - def GetSize(self):
478 return self.volumeSize
479 480 481 if __name__ == '__main__': 482 483 # create a DejaVu Viewer 484 from DejaVu import Viewer 485 vi = Viewer() 486 #Create a volumerender geoms 487 g = UTVolRenGeom('volren') 488 g.viewer = vi 489 490 vi.cameras[0].Activate() 491 g.InitVolumeRenderer() 492 493 g.LoadVolume("vh4.rawiv") 494 g.grayRamp() 495 #g.LoadColorMap("/mgl/ms3/python/dev/Volume/SimpleExample/colormap.map") 496 #g.InitData() 497 498 # add a transparent object without a dpylist 499 vi.AddObject(g) 500 501 #Color map editor 502 503 ## from mglutil.gui.BasicWidgwts.Tk.tablemaker import TableManager 504 ## t = TableManager(master=vi.master, 505 ## ymaxval = 255, 506 ## alphaCallback = g.setVolRenAlpha, 507 ## colorCallback = g.setVolRenColors) 508