Package Volume :: Package VisionInterface :: Module VolumeNodes
[hide private]
[frames] | no frames]

Source Code for Module Volume.VisionInterface.VolumeNodes

   1  ####################################################################### 
   2  # 
   3  # Date: March 2003 Authors: Michel Sanner, Daniel Stoffler 
   4  # 
   5  #    sanner@scripps.edu 
   6  #    stoffler@scripps.edu 
   7  # 
   8  #       The Scripps Research Institute (TSRI) 
   9  #       Molecular Graphics Lab 
  10  #       La Jolla, CA 92037, USA 
  11  # 
  12  # Copyright: Michel Sanner, Daniel Stoffler and TSRI 
  13  # 
  14  # Revision: Guillaume Vareille 
  15  # 
  16  ######################################################################## 
  17  # 
  18  # $Header: /opt/cvs/Volume/VisionInterface/VolumeNodes.py,v 1.159 2007/06/23 00:07:26 vareille Exp $ 
  19  # 
  20  # $Id: VolumeNodes.py,v 1.159 2007/06/23 00:07:26 vareille Exp $ 
  21  # 
  22   
  23   
  24  import Tkinter 
  25  import Numeric, math, types 
  26  import warnings 
  27  import re 
  28  from NetworkEditor.items import NetworkNode 
  29  from Vision import UserLibBuild 
  30   
  31  from Volume.IO.volReaders import ReadMRC, ReadCCP4, ReadCNS, ReadGRD, ReadBRIX,\ 
  32                                      ReadSPIDER, ReadRawiv, ReadEM, ReadFLDBinary 
  33  from Volume.IO.volWriters import WriteCCP4 
  34  from Volume.IO.UHBDGridReader import UHBDReaderASCII 
  35  from Volume.IO.DelphiReader import DelphiReaderBin 
  36  #from Volume.IO.rawivReader import ReadRawiv 
  37  from Volume.IO.AutoGridReader import ReadAutoGrid 
  38  from Volume.IO.gamessOrbitalsReader import ReadGamessOrbitals 
  39  from Volume.Grid3D import Grid3D, Grid3DD, Grid3DF, Grid3DI, \ 
  40       Grid3DSI, Grid3DUI, Grid3DUSI, Grid3DUC, ArrayTypeToGrid, GridTypeToArray 
  41  from mglutil.math.stats import stats 
  42  from mglutil.gui.BasicWidgets.Tk.customizedWidgets import ListChooser 
  43  from mglutil.gui.InputForm.Tk.gui import InputFormDescr, InputForm, CallBackFunction 
  44   
  45  from DejaVu.Box import Box 
  46  from DejaVu.VisionInterface.GeometryNodes import GeometryNode 
  47   
  48   
49 -def importMolKitLib(net):
50 try: 51 from MolKit.VisionInterface.MolKitNodes import molkitlib 52 net.editor.addLibraryInstance( 53 molkitlib, 'MolKit.VisionInterface.MolKitNodes', 'molkitlib') 54 except: 55 warnings.warn( 56 'Warning! Could not import molkitlib from MolKit.VisionInterface')
57
58 -def importVizLib(net):
59 try: 60 from DejaVu.VisionInterface.DejaVuNodes import vizlib 61 net.editor.addLibraryInstance( 62 vizlib, 'DejaVu.VisionInterface.DejaVuNodes', 'vizlib') 63 except: 64 warnings.warn( 65 'Warning! Could not import vizlib from DejaVu/VisionInterface')
66 67 68 69
70 -class TestVolume(NetworkNode):
71 """Outputs a 3D volume of user specified dimensions where each 72 voxel contains the distance to 'point' 73 74 Input Ports 75 dim: number of grid points along a size of the volume 76 point: point from wich distance is computed. Defaults to (0,0,0) 77 78 Output Ports 79 data: the 3D volume 80 """ 81
82 - def dist(self, x , y, z):
83 return math.sqrt((x-self.xo)**2+(y-self.yo)**2++(z-self.zo)**2)
84 85
86 - def __init__(self, name='Test Volume', **kw):
87 kw['name'] = name 88 apply( NetworkNode.__init__, (self,), kw) 89 self.xo = self.yo = self.zo = 0.0 90 91 self.widgetDescr['dim'] = { 92 'class':'NEDial', 'master':'node', 'initialValue':10, 93 'labelCfg':{'text':'dim:'}, 'size':50, 'type':'int' } 94 self.inputPortsDescr.append(datatype='int', name='dim') 95 self.inputPortsDescr.append(datatype='None', required=False, 96 name='point') 97 98 self.outputPortsDescr.append(datatype='Grid3DF', name='grid') 99 100 code = """def doit(self, dim, point): 101 if point is None: 102 point = (0.,0,0) 103 self.xo, self.yo, self.zo = point 104 #m = Numeric.fromfunction( self.dist, ( dim, dim, dim)) 105 m = Numeric.indices( (dim,dim,dim), 'f' )[0] 106 h = {'title':'testgrid'} 107 g = Grid3DF( m.astype('f'), [0.,0.,0.], [1.0, 1.0, 1.0], h ) 108 if g: 109 self.outputData(grid=g) 110 """ 111 112 if code: self.setFunction(code)
113 114
115 -class GridPoints(NetworkNode):
116 """Outputs a nx3 array of 3D coordinates of the centers of voxels in a grid 117 118 Input Ports 119 dim: number of grid points along a size of the volume 120 121 Output Ports 122 data: coordinates of the voxel centers 123 """ 124
125 - def __init__(self, name='GridPoints', **kw):
126 kw['name'] = name 127 apply( NetworkNode.__init__, (self,), kw) 128 129 self.widgetDescr['dim'] = { 130 'class':'NEDial', 'master':'node', 'initialValue':10, 131 'labelCfg':{'text':'dim:'}, 'size':50, 'type':'int', 132 'oneTurn':10} 133 self.inputPortsDescr.append(datatype='int', name='dim') 134 self.outputPortsDescr.append(datatype='NumericArray', name='data') 135 136 code = """def doit(self, dim): 137 import Numeric 138 coords= Numeric.zeros( (dim*dim*dim, 3), 'f') 139 dim2 = dim*dim 140 for i in xrange(dim): 141 for j in xrange(dim): 142 for k in xrange(dim): 143 coords[i*dim2+j*dim+k] = (i, j, k) 144 self.outputData(data=coords) 145 """ 146 147 if code: self.setFunction(code)
148 149
150 -class Grid3DNode(NetworkNode):
151 """Create a Grid3D object 152 153 Input Ports 154 dimx: number of grid points along a size of the volume 155 dimy: number of grid points along a size of the volume 156 dimz: number of grid points along a size of the volume 157 dtype: data type 158 origin: 3-float tuple 159 stepsize: 3-float tuple or single float 160 161 Output Ports 162 grid: Grid3D object 163 """ 164
165 - def __init__(self, name='GridPoints', **kw):
166 kw['name'] = name 167 apply( NetworkNode.__init__, (self,), kw) 168 169 ip = self.inputPortsDescr 170 ip.append(datatype='int', name='dimx') 171 ip.append(datatype='int', name='dimy') 172 ip.append(datatype='int', name='dimz') 173 ip.append(datatype='string', name='dtype') 174 ip.append(datatype='list', name='origin') 175 ip.append(datatype='list', name='stepsize') 176 177 self.widgetDescr['dimx'] = { 178 'class':'NEThumbWheel', 'width':60, 'height':20, 'type':'int', 179 'showLabel':1, 'oneTurn':5, 'min':1, 'lockMin':True, 180 'master':'node', 'labelCfg':{'text':'dimx:'}, 181 'initialValue':32} 182 self.widgetDescr['dimy'] = { 183 'class':'NEThumbWheel', 'width':60, 'height':20, 'type':'int', 184 'showLabel':1, 'oneTurn':5, 'min':1, 'lockMin':True, 185 'master':'node', 'labelCfg':{'text':'dimy:'}, 186 'initialValue':32} 187 self.widgetDescr['dimz'] = { 188 'class':'NEThumbWheel', 'width':60, 'height':20, 'type':'int', 189 'showLabel':1, 'oneTurn':5, 'min':1, 'lockMin':True, 190 'master':'node', 'labelCfg':{'text':'dimz:'}, 191 'initialValue':32} 192 self.widgetDescr['dtype'] = { 193 'initialValue': 'Grid3DF', 'fixedChoices': 1, 'autoList': False, 194 'choices': ('Grid3DD', 'Grid3DF', 'Grid3DF', 'Grid3DI', 195 'Grid3DSI', 'Grid3DUC'), 'master': 'node', 196 'labelCfg': {'text': 'data type'}, 197 'entryfield_entry_width':8, 198 'class': 'NEComboBox'} 199 self.widgetDescr['origin'] = {'class':'NEEntry', 200 'labelGridCfg':{'sticky':'we'}, 'master':'node', 201 'labelCfg':{'text':'origin ox,oy,oz:'}, 202 'initialValue': '0,0,0' 203 } 204 self.widgetDescr['stepsize'] = {'class':'NEEntry', 205 'labelGridCfg':{'sticky':'we'}, 'master':'node', 206 'labelCfg':{'text':'stepsize:'}, 207 'initialValue': '1,1,1' 208 } 209 210 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 211 212 code = """def doit(self, dimx, dimy, dimz, dtype, origin, stepsize): 213 214 import Numeric 215 dt = GridTypeToArray[dtype] 216 array= Numeric.zeros( (dimx,dimy,dimz), dt) 217 gtype = ArrayTypeToGrid[dt] 218 import types 219 stepsize = eval(stepsize) 220 if type(stepsize)==types.FloatType: 221 stepsize=[stepsize]*3 222 elif type(stepsize)==types.IntType: 223 stepsize=[float(stepsize)]*3 224 225 origin = eval(origin) 226 grid = gtype(array, origin, stepsize, {}, None) 227 self.outputPorts[0].setDataType(gtype) 228 self.outputData(grid=grid) 229 """ 230 231 if code: self.setFunction(code)
232 233
234 -class SetValuesAtPositions(NetworkNode):
235 """Set values in grid as position indicated by real coordinates 236 237 Input Ports 238 positions: list of (x,y,z) positions 239 values: list of values 240 241 Output Ports 242 grid: Grid3D object 243 """ 244
245 - def __init__(self, name='GridPoints', **kw):
246 kw['name'] = name 247 apply( NetworkNode.__init__, (self,), kw) 248 249 ip = self.inputPortsDescr 250 ip.append(datatype='Grid3D', name='grid') 251 ip.append(datatype='list', name='positions') 252 ip.append(datatype='list', name='values') 253 254 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 255 256 code = """def doit(self, grid, positions, values): 257 258 assert len(positions)==len(values) 259 ox, oy, oz = grid.origin 260 sx, sy, sz = grid.stepSize 261 dx, dy, dz = grid.dimensions 262 data = grid.data 263 for p,v in zip(positions, values): 264 i = int((p[0]-ox)/sx) 265 j = int((p[1]-oy)/sy) 266 k = int((p[2]-oz)/sz) 267 data[i,j,k] = v 268 269 self.outputPorts[0].setDataType(grid) 270 self.outputData(grid=grid) 271 """ 272 273 if code: self.setFunction(code)
274 275
276 -class ToGrid3D(NetworkNode):
277 """Takes 3D scale data and turns it into a Grid3D object 278 279 Input Ports 280 array: data that will be turned into a 3D Numeric array 281 282 Output Ports 283 grid: Grid3D Volume object 284 """ 285
286 - def __init__(self, name='NumericToGrid', **kw):
287 kw['name'] = name 288 apply( NetworkNode.__init__, (self,), kw) 289 290 self.inputPortsDescr.append(datatype='NumericArray', name='array') 291 self.inputPortsDescr.append(datatype='Grid3D', name='headerGrid', 292 required=False) 293 294 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 295 296 code = """def doit(self, array, headerGrid=None): 297 if not isinstance(array, Numeric.ArrayType): 298 castok = False 299 tp = [Numeric.UInt8, Numeric.Int16, Numeric.Int32, Numeric.Float8, 300 Numeric.Float32, Numeric.Float64] 301 for tp in typelist: 302 try: 303 ar = Numeric.array( array, tp ) 304 except: 305 pass 306 break 307 array = ar 308 309 gtype = ArrayTypeToGrid[array.typecode()] 310 311 if headerGrid is not None: 312 # we should make sure headerGrid.dimensions matches array.shape 313 origin = headerGrid.origin[:] 314 stepSize = headerGrid.stepSize[:] 315 header = headerGrid.header.copy() 316 crystal = headerGrid.crystal 317 else: 318 origin = [0.,0.,0.] 319 stepSize = [1.,1.,1.] 320 header = {'title':'from Numeric array'} 321 crystal = None 322 323 grid = gtype(array, origin, stepSize, header, crystal) 324 self.outputPorts[0].setDataType(gtype) 325 self.outputData(grid=grid) 326 """ 327 if code: self.setFunction(code)
328 329 330
331 -class Sample(NetworkNode):
332 """Subsamples a grid, creating a new volume object of the same type 333 Simply implements the Numeric ::step to get values from the original volume 334 335 Input Ports 336 grid: Grid3D Volume object to be sampled 337 338 Output Ports 339 grid: new Grid3D Volume object 340 """ 341
342 - def __init__(self, name='SampleGrid', **kw):
343 kw['name'] = name 344 apply( NetworkNode.__init__, (self,), kw) 345 346 self.inputPortsDescr.append(datatype='Grid3D', name='grid') 347 self.inputPortsDescr.append(datatype='int', name='step') 348 self.widgetDescr['step'] = { 349 'class':'NEThumbWheel', 'width':60, 'height':20, 'type':'int', 350 'showLabel':1, 'oneTurn':5, 'min':1, 'lockMin':True, 351 'master':'node', 352 'labelCfg':{'text':'step:'}, 353 } 354 355 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 356 357 code = """def doit(self, grid, step): 358 359 if step==1: 360 self.outputData(grid=grid) 361 else: 362 smallarray = Numeric.array(grid.data[::step, ::step, ::step]) 363 # recompute spacing 364 d = grid.dimensions 365 s = grid.stepSize 366 dims = smallarray.shape 367 sx = s[0]*step 368 sy = s[1]*step 369 sz = s[2]*step 370 gtype = ArrayTypeToGrid[smallarray.typecode()] 371 crystal = None 372 if grid.crystal: 373 from mglutil.math.crystal import Crystal 374 crystal = Crystal( grid.crystal.length, grid.crystal.angles) 375 ngrid = gtype(smallarray, grid.origin, (sx,sy,sz), 376 grid.header.copy(), crystal) 377 ngrid.normalize() 378 self.outputPorts[0].setDataType(gtype) 379 self.outputData(grid=ngrid) 380 """ 381 if code: self.setFunction(code)
382 383
384 -class ArrayArrayOp(NetworkNode):
385 """Add, subtract, multiply or divide the data of 2 Grid3d objects. 386 It is assumed the grids are of same shape. 387 388 Input Ports 389 grid1: first Grid3D Volume object 390 grid2: second Grid3D Volume object 391 operation: string in 'add', 'sub', 'mult', div' 392 copy: boolean indicating of a new grid object shoudl be crated. When 393 False grid1.data is modified 394 395 Output Ports 396 grid: Grid3D with modified values 397 """
398 - def __init__(self, name='ArrayOp', **kw):
399 kw['name'] = name 400 apply( NetworkNode.__init__, (self,), kw) 401 ip = self.inputPortsDescr 402 ip.append({'datatype': 'Grid3D', 'name': 'grid1'}) 403 ip.append({'datatype': 'Grid3D', 'name': 'grid2'}) 404 ip.append({'datatype': 'string', 'name': 'operator'}) 405 ip.append({'datatype': 'boolean', 'name': 'copy'}) 406 407 self.widgetDescr['operator'] = { 408 'initialValue': '', 'fixedChoices': 1, 'autoList': False, 409 'choices': ('add','sub','mul','div'), 'master': 'node', 410 'widgetGridCfg': {'column': 1, 'labelSide': 'left', 'row': 0}, 411 'labelCfg': {'text': 'operator'}, 412 'entryfield_entry_width':8, 413 'class': 'NEComboBox'} 414 415 self.widgetDescr['copy'] = {'class':'NECheckButton', 'master':'node', 416 'initialValue':True, 417 'labelGridCfg':{'sticky':'we'}, 418 'labelCfg':{'text':'create new grid:'}, 419 } 420 421 op = self.outputPortsDescr 422 op.append({'datatype': 'Grid3DF', 'name': 'grid'}) 423 424 code = """def doit(self, grid1, grid2, operation, copy): 425 import operator 426 op = getattr(operator, operation) 427 if copy is False: 428 grid1.data = apply(op, (grid1.data, grid2.data)).astype(grid1.data.typecode()) 429 newgrid = grid1 430 else: 431 newdata = apply(op, (grid1.data, grid2.data)).astype(grid1.data.typecode()) 432 newgrid = grid1.__class__( newdata, grid1.origin, grid1.stepSize[::-1], 433 grid1.header) 434 self.outputData(grid=newgrid) 435 """ 436 self.configure(function=code)
437 438
439 -class ArrayScalarOp(NetworkNode):
440 """Add, subtract, multiply or divide the data of 2 a Grid3d object by a 441 scalar value. It is assumed the grids are of same shape. 442 443 Input Ports 444 grid: Grid3D Volume object 445 value: scalar value 446 operation: string in 'add', 'sub', 'mult', div' 447 copy: boolean indicating of a new grid object should be crated. 448 449 Output Ports 450 grid: Grid3DF with modified values if a new grid is created or grid1 with 451 modified values 452 """
453 - def __init__(self, name='ArrayOp', **kw):
454 kw['name'] = name 455 apply( NetworkNode.__init__, (self,), kw) 456 ip = self.inputPortsDescr 457 ip.append({'datatype': 'Grid3D', 'name': 'grid'}) 458 ip.append({'datatype': 'float', 'name': 'value'}) 459 ip.append({'datatype': 'string', 'name': 'operator'}) 460 ip.append({'datatype': 'boolean', 'name': 'copy'}) 461 462 self.widgetDescr['operator'] = { 463 'initialValue': '', 'fixedChoices': 1, 'autoList': False, 464 'choices': ('add','sub','mul','div'), 'master': 'node', 465 'widgetGridCfg': {'column': 1, 'labelSide': 'left', 'row': 0}, 466 'labelCfg': {'text': 'operator'}, 467 'entryfield_entry_width':8, 468 'class': 'NEComboBox'} 469 470 self.widgetDescr['copy'] = {'class':'NECheckButton', 'master':'node', 471 'initialValue':True, 472 'labelGridCfg':{'sticky':'we'}, 473 'labelCfg':{'text':'create new grid:'}, 474 } 475 476 op = self.outputPortsDescr 477 op.append({'datatype': 'Grid3DF', 'name': 'grid'}) 478 479 code = """def doit(self, grid, value, operation, copy): 480 import operator 481 op = getattr(operator, operation) 482 if copy is False: 483 grid.data = (apply(op, (grid.data, value))).astype(grid.data.typecode()) 484 newgrid = grid 485 else: 486 newdata = apply(op, (grid.data, value)).astype('f') 487 newgrid = Grid3DF( newdata, grid.origin, grid.stepSize, grid.header) 488 self.outputData(grid=newgrid) 489 """ 490 self.configure(function=code)
491 492 493 try: 494 from DejaVu.VisionInterface.GeometryNodes import GeometryNode 495 foundGeometryNode = True 496 except ImportError: 497 foundGeometryNode = False 498 GeometryNode = NetworkNode # so we can define OrthoSlice, but it won;t be added 499 500 from DejaVu.bitPatterns import patternList 501
502 -class OrthoSlice(GeometryNode):
503 """Create a texture mapped quad displ;aying a 2D slices orthogonal 504 to the volume axes. 505 506 Input Ports 507 grid: Grid3D object 508 axis: 'x', 'y' or 'z' 509 sliceNumber: position along the axis 510 colorMap: colormap object used to build 2D texture 511 transparency: 'alpha' or 'pat1', 'pat2', ..., 'pat8'. Patx are screen 512 door transparency patterns. 1 and 2 are 50% of pixels and mutually 513 transparent, 3,4,5 and 6 are 25% of pixels and mutually transparent, 514 pat7 is 25% but adjacent pixels so it looks striped 515 pat8 12.5% faint staggered stripe 516 517 Output Ports 518 geom: geom object textured2DArray 519 """
520 - def __init__(self, name='OrthoSlice', **kw):
521 kw['name'] = name 522 apply( GeometryNode.__init__, (self, 'OrthoSlice'), kw ) 523 524 ip = self.inputPortsDescr 525 ip.append({'datatype': 'Grid3D', 'name': 'grid'}) 526 ip.append({'datatype': 'string', 'name': 'axis'}) 527 ip.append({'datatype': 'int', 'name': 'sliceNumber'}) 528 ip.append({'datatype': 'ColorMapType', 'name': 'colorMap'}) 529 ip.append({'datatype': 'string', 'name': 'transparency'}) 530 531 self.widgetDescr['sliceNumber'] = { 532 'class':'NEThumbWheel', 'width':60, 'height':20, 'type':'int', 533 'min':0, 'showLabel':1, 'oneTurn':10, 'master':'node', 534 'labelCfg':{'text':'sliceNumber:'}, 535 } 536 537 self.widgetDescr['axis'] = { 538 'initialValue': 'z', 'fixedChoices': 1, 'autoList': False, 539 'choices': ('x','y','z'), 'master':'ParamPanel', 540 'widgetGridCfg': {'column': 1, 'labelSide': 'left', 'row': 0}, 541 'labelCfg': {'text': 'axis'}, 542 'entryfield_entry_width':4, 543 'class': 'NEComboBox'} 544 545 self.widgetDescr['colorMap'] = { 546 'class':'NEColorMap', #'mini':0.0, 'maxi':255.0, 547 'labelCfg':{'text':'colorMap'}, 'master':'ParamPanel'} 548 549 self.widgetDescr['transparency'] = { 550 'initialValue': 'alpha', 'fixedChoices': 1, 'autoList': False, 551 'lockedOnPort':True, 'master':'ParamPanel', 552 'choices': ('alpha','pat1','pat2', 'pat3', 'pat4', 'pat5', 'pat6', 'pat7', 'pat8'), 553 'widgetGridCfg': {'labelSide': 'left'}, 554 'labelCfg': {'text': 'transp.'}, 555 'entryfield_entry_width':4, 556 'class': 'NEComboBox'} 557 558 self.rearrangePorts() 559 560 code = """def doit(self, grid, axis, sliceNumber, colorMap, transparency, 561 name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 562 563 GeometryNode.doit(self, name, geoms, instanceMatrices, geomOptions, parent) 564 565 if self.selectedGeomIndex is not None: 566 g = self.geom() 567 if transparency=='alpha': 568 g.Set(stipplePolygons=0) 569 570 else: 571 ind = int(transparency[-1])-1 572 g.polygonstipple.Set(pattern=patternList[ind]) 573 g.Set(stipplePolygons=1, inheritStipplePolygons=False, opacity=1.0) 574 575 if colorMap != g.colormap: 576 g.Set(colormap=colorMap) 577 578 if self.inputPortByName['grid'].hasNewData(): 579 mini = min(grid.data.flat) 580 maxi = max(grid.data.flat) 581 g.Set(min=mini, max=maxi) 582 583 p = self.inputPortByName['axis'] 584 w = self.inputPortByName['sliceNumber'].widget 585 if p.hasNewData() and w: 586 axisInd = ['x', 'y', 'z'].index(axis) 587 w.configure(max=grid.dimensions[axisInd]-1) 588 589 data, vertices = grid.get2DOrthoSlice(axis, sliceNumber) 590 g.Set(vertices=vertices, array=data, colormap=colorMap) 591 self.outputData(OrthoSlice=g, allGeometries=self.geoms) 592 else: 593 self.outputData(OrthoSlice=None, allGeometries=self.geoms) 594 """ 595 self.configure(function=code)
596 597
598 - def beforeAddingToNetwork(self, net):
599 # loading library vizlib 600 importVizLib(net)
601 602
603 - def appendGeometry(self, name):
604 from DejaVu.Textured2DArray import textured2DArray 605 self.geoms.append(textured2DArray(name)) 606 return 1 # num of appended geoms
607 608 609 ## 610 ## MS attempt to make a node with 3 slicing planes 611 ## 612 ## class OrthoSlices(GeometryNode): 613 ## """Create a texture mapped quad displ;aying a 2D slices orthogonal 614 ## to the volume axes. 615 616 ## Input Ports 617 ## grid: Grid3D object 618 ## axis: 'x', 'y' or 'z' 619 ## sliceNumber: position along the axis 620 ## colorMap: colormap object used to build 2D texture 621 622 ## Output Ports 623 ## geom: geom object textured2DArray 624 ## """ 625 ## def __init__(self, name='OrthoSlices', **kw): 626 ## kw['name'] = name 627 ## apply( GeometryNode.__init__, (self, 'indexedPolygons'), kw ) 628 629 ## from DejaVu.Textured2DArray import textured2DArray 630 ## self.xsliceGeom = textured2DArray('xslice') 631 ## self.geoms.append(self.xsliceGeom) 632 ## self.ysliceGeom = textured2DArray('yslice') 633 ## self.geoms.append(self.ysliceGeom) 634 ## self.zsliceGeom = textured2DArray('zslice') 635 ## self.geoms.append(self.zsliceGeom) 636 637 ## ip = self.inputPortsDescr 638 ## ip.append({'datatype': 'Grid3D', 'name': 'grid'}) 639 ## ip.append({'datatype': 'string', 'name': 'xaxis'}) 640 ## ip.append({'datatype': 'string', 'name': 'yaxis'}) 641 ## ip.append({'datatype': 'string', 'name': 'zaxis'}) 642 ## ip.append({'datatype': 'int', 'name': 'slicex'}) 643 ## ip.append({'datatype': 'int', 'name': 'slicey'}) 644 ## ip.append({'datatype': 'int', 'name': 'slicez'}) 645 ## ip.append({'datatype': 'ColorMapType', 'name': 'colorMap'}) 646 647 ## self.widgetDescr['xaxis'] = { 648 ## 'class': 'NECheckButton', 'initialValue': 0, 649 ## 'master': 'node', 650 ## 'widgetGridCfg': {'column': 0, 'labelSide': 'top', 'row': 0}, 651 ## 'labelCfg': {'text': 'axis'}, 652 ## } 653 654 ## self.widgetDescr['slicex'] = { 655 ## 'class':'NEThumbWheel', 'width':60, 'height':30, 'type':'int', 656 ## 'min':0, 'showLabel':1, 'oneTurn':10, 'master': 'node', 657 ## 'widgetGridCfg': {'column': 1, 'labelSide': 'top', 'row': 0}, 658 ## 'labelCfg':{'text':'sliceNumber:'}, 659 ## } 660 661 ## self.widgetDescr['yaxis'] = { 662 ## 'class': 'NECheckButton', 'initialValue': 0, 663 ## 'master': 'node', 664 ## 'widgetGridCfg': {'column': 0, 'row': 1}, 665 ## } 666 667 ## self.widgetDescr['slicey'] = { 668 ## 'class':'NEThumbWheel', 'width':60, 'height':30, 'type':'int', 669 ## 'min':0, 'showLabel':1, 'oneTurn':10, 'master': 'node', 670 ## 'widgetGridCfg': {'column': 1, 'row': 1}, 671 ## } 672 673 ## self.widgetDescr['zaxis'] = { 674 ## 'class': 'NECheckButton', 'initialValue': 1, 675 ## 'master': 'node', 676 ## 'widgetGridCfg': {'column': 0, 'row': 2}, 677 ## } 678 679 ## self.widgetDescr['slicez'] = { 680 ## 'class':'NEThumbWheel', 'width':60, 'height':30, 'type':'int', 681 ## 'min':0, 'showLabel':1, 'oneTurn':10, 'master': 'node', 682 ## 'widgetGridCfg': {'column': 1, 'row': 2}, 683 ## } 684 685 ## ## self.widgetDescr['sliceNumber'] = { 686 ## ## 'class':'NEThumbWheel', 'width':60, 'height':20, 'type':'int', 687 ## ## 'min':0, 'showLabel':1, 'oneTurn':10, 'master': 'node', 688 ## ## 'labelCfg':{'text':'sliceNumber:'}, 689 ## ## } 690 691 ## ## self.widgetDescr['axis'] = { 692 ## ## 'initialValue': 'z', 'fixedChoices': 1, 'autoList': False, 693 ## ## 'choices': ('x','y','z'), 'master': 'node', 694 ## ## 'widgetGridCfg': {'column': 1, 'labelSide': 'left', 'row': 0}, 695 ## ## 'labelCfg': {'text': 'axis'}, 696 ## ## 'entryfield_entry_width':4, 697 ## ## 'class': 'NEComboBox'} 698 699 ## self.widgetDescr['colorMap'] = { 700 ## 'class':'NEColorMap', 'mini':0.0, 'maxi':255.0, 701 ## 'labelCfg':{'text':''}, } 702 703 ## self.widgetDescr['name']['choices'] = ['slice'] 704 ## self.widgetDescr['name']['initialValue'] = 'slice' 705 706 ## self.rearrangePorts() 707 708 ## code = """def doit(self, grid, xaxis, yaxis, zaxis, slicex, slicey, slicez, colorMap, name=None, instanceMatrices=None, geomOptions=None, parent=None): 709 710 ## GeometryNode.doit(self, name, instanceMatrices, geomOptions, parent) 711 712 ## p = self.getInputPortByName('grid') 713 ## if p.hasNewData(): 714 ## dims = grid.dimensions[0] 715 ## w = self.getInputPortByName('slicex').widget 716 ## if w: w.configure(max=dims[0]-1) 717 ## w = self.getInputPortByName('slicey').widget 718 ## if w: w.configure(max=dims[1]-1) 719 ## w = self.getInputPortByName('slicez').widget 720 ## if w: w.configure(max=dims[1]-1) 721 722 ## if xaxis: 723 ## data, vertices = grid.get2DOrthoSlice('x', slicex) 724 ## g = self.xsliceGeom 725 ## g.Set(visible=True, vertices=vertices, array=data, colormap=colorMap) 726 727 ## if yaxis: 728 ## data, vertices = grid.get2DOrthoSlice('y', slicey) 729 ## g = self.xsliceGeom 730 ## g.Set(visible=True, vertices=vertices, array=data, colormap=colorMap) 731 732 ## if zaxis: 733 ## data, vertices = grid.get2DOrthoSlice('z', slicez) 734 ## g = self.zsliceGeom 735 ## g.Set(visible=True, vertices=vertices, array=data, colormap=colorMap) 736 737 ## if self.xlisceGeom.viewer is None: 738 ## self.outputData(orthoslices=self.geoms, allGeometries=self.geoms) 739 ## """ 740 ## self.configure(function=code) 741 742 ## def appendGeometry(self, name): 743 ## return 1 # num of appended geoms 744 745
746 -class Grid3DTo2D(NetworkNode):
747 """Project the grid data along one of the axis. 748 749 Input Ports 750 grid: Grid3D Volume object 751 axis: string in ['x', 'y', 'z'] 752 753 Output Ports 754 projection: 2D array of values 755 """
756 - def __init__(self, name='ArrayOp', **kw):
757 kw['name'] = name 758 apply( NetworkNode.__init__, (self,), kw) 759 ip = self.inputPortsDescr 760 ip.append({'datatype': 'Grid3D', 'name': 'grid'}) 761 ip.append({'datatype': 'string', 'name': 'axis'}) 762 763 self.widgetDescr['axis'] = { 764 'initialValue': 'z', 'fixedChoices': 1, 'autoList': False, 765 'choices': ('x','y','z'), 'master': 'node', 766 'widgetGridCfg': {'column': 1, 'labelSide': 'left', 'row': 0}, 767 'labelCfg': {'text': 'axis'}, 768 'entryfield_entry_width':4, 769 'class': 'NEComboBox'} 770 771 op = self.outputPortsDescr 772 op.append({'datatype': '2Darray', 'name': 'projection'}) 773 774 code = """def doit(self, grid, axis): 775 import Numeric 776 777 axisInt = ['x', 'y', 'z'].index(axis) 778 proj = data = Numeric.sum(grid.data, axisInt) 779 self.outputData(projection=proj) 780 """ 781 self.configure(function=code)
782 783 784
785 -class SetOrigin(NetworkNode):
786 """Set the grid's origin attribute to a sequence of 3 floats. These 787 number are given in fractional coordinates 788 789 Input Ports 790 grid: Grid3D Volume object to be sampled 791 origin: sequence of 3 floating point values in fractional coord. 792 793 Output Ports 794 grid: Grid3D with new origin 795 """ 796
797 - def __init__(self, name='SetOrigin', **kw):
798 kw['name'] = name 799 apply( NetworkNode.__init__, (self,), kw) 800 801 self.inputPortsDescr.append(datatype='Grid3D', name='grid') 802 self.inputPortsDescr.append(datatype='None', name='origin') 803 804 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 805 806 code = """def doit(self, grid, origin): 807 assert len(origin)==3 808 assert type(origin[0])==types.FloatType 809 assert type(origin[1])==types.FloatType 810 assert type(origin[2])==types.FloatType 811 grid.origin = origin 812 self.outputData(grid=grid) 813 """ 814 if code: self.setFunction(code)
815 816
817 -class SetStepSize(NetworkNode):
818 """Scales the stepSize 819 820 Input Ports 821 grid: Grid3D Volume object to be sampled 822 stepSize: sequence of 3 floating point values providing the length of a 823 voxel in the 3 x,y and z in angstroms 824 825 Output Ports 826 grid: Grid3D Volume with scaled stepSize 827 """ 828
829 - def __init__(self, name='StepSize', **kw):
830 kw['name'] = name 831 apply( NetworkNode.__init__, (self,), kw) 832 833 self.inputPortsDescr.append(datatype='Grid3D', name='grid') 834 self.inputPortsDescr.append(datatype='None', name='stepSize') 835 836 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 837 838 code = """def doit(self, grid, stepSize): 839 assert len(stepSize)==3 840 assert type(stepSize[0])==types.FloatType 841 assert type(stepSize[1])==types.FloatType 842 assert type(stepSize[2])==types.FloatType 843 grid.stepSize = stepSize 844 self.outputData(grid=grid) 845 """ 846 if code: self.setFunction(code)
847 848
849 -class Center(NetworkNode):
850 """Center a grid ona user specified point 851 852 Input Ports 853 grid: Grid3D Volume object to be centered 854 center: 3-D point 855 856 Output Ports 857 grid: same grid as incomming on bu with origin modified such that the 858 Grid3D's center is on the user specified point 859 """ 860
861 - def __init__(self, name='ScaleGrid', **kw):
862 kw['name'] = name 863 apply( NetworkNode.__init__, (self,), kw) 864 865 self.inputPortsDescr.append(datatype='Grid3D', name='grid') 866 self.inputPortsDescr.append(datatype='None', name='center') 867 self.widgetDescr['center'] = { 868 'class':'NEVectEntry', 869 'initialValue':[0.,0.,0.], 870 'widgetGridCfg':{'labelSide':'top'}, 871 'labelCfg':{'text':'center point'}, 872 'master':'node' 873 } 874 875 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 876 877 code = """def doit(self, grid, center): 878 ocenter = grid.centerPoint() 879 grid.origin[0] += center[0]-ocenter[0] 880 grid.origin[1] += center[1]-ocenter[1] 881 grid.origin[2] += center[2]-ocenter[2] 882 self.outputData(grid=grid) 883 """ 884 if code: self.setFunction(code)
885 886
887 -class VolumeStats(NetworkNode):
888 """Compute simple statistics over volumetric data. 889 Computes the min, max, mean and standard deviation 890 891 Input Ports 892 grid: Grid3D object to be sampled 893 894 Output Ports 895 mini: minimum value 896 maxi: maximum value 897 mean: mean value 898 stdDev: standard deviation value 899 """ 900
901 - def __init__(self, name='VolumeStats', **kw):
902 kw['name'] = name 903 apply( NetworkNode.__init__, (self,), kw) 904 905 self.inputPortsDescr.append(datatype='Grid3D', name='grid') 906 self.outputPortsDescr.append(datatype='float', name='mini') 907 self.outputPortsDescr.append(datatype='float', name='maxi') 908 self.outputPortsDescr.append(datatype='float', name='mean') 909 self.outputPortsDescr.append(datatype='float', name='stdDev') 910 code = """def doit(self, grid): 911 myData=Numeric.array(grid.data.flat) 912 mymin, mymax, mymean, mystdev = stats(myData) 913 self.outputData(mini=mymin,maxi=mymax,mean=mymean,stdDev=mystdev) 914 print "\\nSTATS:" 915 print "minimum: ",mymin 916 print "maximum: ",mymax 917 print "mean: ",mymean 918 print "standard deviation: ",mystdev 919 """ 920 if code: self.setFunction(code)
921 922
923 -class TransposeGrid3D(NetworkNode):
924 """takes the Volume object and transposes the data array 925 [[1 2 3] -> [[1 4 7] 926 [4 5 6] -> [2 5 6] 927 [7 8 9]] -> [3 6 9]] 928 929 Input Ports 930 grid: Grid3D Volume object to be transposed 931 copy: (optional) 932 When True, a new Volume will be produced for the transposed 933 data, else the data is transposed within the original Volume. 934 935 Output Ports 936 grid: Grid3D object 937 """ 938
939 - def __init__(self, name='NumericToGrid', **kw):
940 kw['name'] = name 941 apply( NetworkNode.__init__, (self,), kw) 942 943 self.widgetDescr['copy'] = {'class':'NECheckButton', 'master':'node', 944 'initialValue':0, 945 'labelGridCfg':{'sticky':'we'}, 946 'labelCfg':{'text':'create new grid:'}, 947 } 948 949 self.inputPortsDescr.append(datatype='Grid3D', name='grid') 950 self.inputPortsDescr.append(datatype='boolean', name='copy') 951 952 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 953 954 code = """def doit(self, grid, copy): 955 art = Numeric.array(Numeric.transpose(grid.data), grid.data.typecode()) 956 if copy is False: 957 grid.data = art 958 grid.dimensions = art.shape 959 grid.stepSize = grid.stepSize[::-1] 960 newgrid = grid 961 else: 962 newgrid = grid.__class__( art, grid.origin, grid.stepSize[::-1], 963 grid.header) 964 965 self.outputPorts[0].setDataType(grid) 966 self.outputData(grid=newgrid) 967 """ 968 if code: self.setFunction(code)
969 970
971 -class Orthogonalize(NetworkNode):
972 """Create an orthogonal grid for non-orthogonal volumetric data 973 974 Input Ports 975 grid: Grid3D Volume object 976 977 Output Ports 978 grid: orthogonal Grid3D Volume object 979 """ 980
981 - def __init__(self, name='Orthog', **kw):
982 kw['name'] = name 983 apply( NetworkNode.__init__, (self,), kw) 984 985 self.inputPortsDescr.append(datatype='Grid3D', name='grid') 986 987 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 988 989 code = """def doit(self, grid): 990 if grid.crystal is None: 991 self.outputPorts[0].setDataType(grid) 992 self.outputData(grid=grid) 993 else: 994 # find grid dimensions in real space 995 pt1 = grid.origin 996 dims = grid.data.shape 997 pt2 = [pt1[0]+(grid.stepSize[0]*(dims[0]-1)), 998 pt1[1]+(grid.stepSize[1]*(dims[1]-1)), 999 pt1[2]+(grid.stepSize[2]*(dims[2]-1))] 1000 coords = (pt1, pt2) 1001 1002 ptList=((pt2[0],pt2[1],pt1[2]), 1003 (pt1[0],pt2[1],pt1[2]), 1004 (pt1[0],pt1[1],pt1[2]), 1005 (pt2[0],pt1[1],pt1[2]), 1006 (pt2[0],pt2[1],pt2[2]), 1007 (pt1[0],pt2[1],pt2[2]), 1008 (pt1[0],pt1[1],pt2[2]), 1009 (pt2[0],pt1[1],pt2[2])) 1010 coords = grid.crystal.toCartesian(ptList) 1011 mini = coords[0].copy() 1012 maxi = coords[0].copy() 1013 for i in range(1,8): 1014 for j in (0,1,2): 1015 if coords[i][j]<mini[j]: 1016 mini[j] = coords[i][j] 1017 if coords[i][j]>maxi[j]: 1018 maxi[j] = coords[i][j] 1019 1020 realdims = [0,0,0] 1021 fracdims = [0,0,0] 1022 stepsize = grid.getStepSizeReal() 1023 origin = grid.getOriginReal() 1024 for i in (0,1,2): 1025 realdims[i] = maxi[i]-mini[i] 1026 fracdims[i] = int(realdims[i]/stepsize[i])+2 1027 1028 data = Numeric.zeros( fracdims, grid.data.typecode() ) 1029 tocart = grid.crystal.toCartesian 1030 # 1/2 step size real 1031 sx2,sy2,sz2 = stepsize[0]*.5, stepsize[1]*.5, stepsize[2]*.5 1032 # real step size 1033 sxr,syr,szr = 1./stepsize[0],1./stepsize[1],1./stepsize[2] 1034 # fractioanl step size 1035 sxf,syf,szf = grid.stepSize 1036 # offset is new_origin - old_origin + 1/2 voxel 1037 offx,offy,offz = [ mini[0]-origin[0]+sx2, mini[1]-origin[1]+sy2, 1038 mini[2]-origin[2]+sz2] 1039 source = grid.data 1040 for i in range(grid.dimensions[0]): 1041 for j in range(grid.dimensions[1]): 1042 for k in range(grid.dimensions[2]): 1043 # real coordinate of point inside box 1044 rx,ry,rz = tocart((i*sxf,j*syf,k*szf)) 1045 # add origin offset and divide by real step size 1046 ix = int( ( offx + rx) * sxr ) 1047 iy = int( ( offy + ry) * syr ) 1048 iz = int( ( offz + rz) * szr ) 1049 #print ix, iy, iz 1050 data[ix][iy][iz] = source[i][j][k] 1051 1052 h={} 1053 ngrid = grid.__class__( data, mini, stepsize, h, None) 1054 1055 self.outputPorts[0].setDataType(grid) 1056 self.outputData(grid=ngrid) 1057 """ 1058 if code: self.setFunction(code)
1059 1060 1061
1062 -class BoundingBox(GeometryNode):
1063 """Create an Indexed Polygon geometry box depicting the edges 1064 of the Volume data 1065 1066 Input Ports 1067 grid: Grid3D Volume object 1068 1069 Output Ports 1070 grid: 3D Box displaying the boundaries of the Volume 1071 """ 1072
1073 - def __init__(self, name='Grid3DBB', **kw):
1074 1075 kw['name'] = name 1076 apply( GeometryNode.__init__, (self, 'Grid3DBB'), kw ) 1077 1078 ip = self.inputPortsDescr 1079 ip.append(datatype='Grid3D', name='grid') 1080 1081 # for backward compatibility 1082 # this make sure that the first ports in the node are the ones 1083 # that use to be there before we introduced the GeometryNode class 1084 # (old network were saved with port indices instead of port names) 1085 self.rearrangePorts() 1086 1087 code = """def doit(self, grid, 1088 name=None, geoms=None, instanceMatrices=None, geomOptions=None, parent=None): 1089 #print "doit", self.name 1090 #apply( GeometryNode.doit, (self,)+args ) 1091 GeometryNode.doit(self, name, geoms, instanceMatrices, geomOptions, parent) 1092 1093 if self.selectedGeomIndex is not None: 1094 g = self.geom() 1095 1096 pt1 = grid.origin 1097 dims = grid.data.shape 1098 pt2 = [pt1[0]+(grid.stepSize[0]*(dims[0]-1)), 1099 pt1[1]+(grid.stepSize[1]*(dims[1]-1)), 1100 pt1[2]+(grid.stepSize[2]*(dims[2]-1))] 1101 if grid.crystal: 1102 ptList=((pt2[0],pt2[1],pt1[2]), 1103 (pt1[0],pt2[1],pt1[2]), 1104 (pt1[0],pt1[1],pt1[2]), 1105 (pt2[0],pt1[1],pt1[2]), 1106 (pt2[0],pt2[1],pt2[2]), 1107 (pt1[0],pt2[1],pt2[2]), 1108 (pt1[0],pt1[1],pt2[2]), 1109 (pt2[0],pt1[1],pt2[2])) 1110 coords = grid.crystal.toCartesian(ptList) 1111 g.Set(vertices=coords) 1112 else: 1113 coords = (pt1, pt2) 1114 g.Set(cornerPoints=coords) 1115 1116 self.outputData(Grid3DBB=g, allGeometries=self.geoms) 1117 else: 1118 self.outputData(Grid3DBB=None, allGeometries=self.geoms) 1119 """ 1120 if code: self.setFunction(code)
1121 1122
1123 - def appendGeometry(self, name):
1124 from DejaVu.Box import Box 1125 self.geoms.append(Box(name=name, maxCube=[.5,.5,.5], 1126 minCube=[-.5,-.5,-.5],frontPolyMode='line')) 1127 return 1 # num of geoms appended
1128 1129
1130 - def beforeAddingToNetwork(self, net):
1131 # import vizlib 1132 importVizLib(net)
1133 1134 1135
1136 -class RegionBox(NetworkNode):
1137 """Situates a 3D box within the grid boundaries of a volume, 1138 for quick bounding of octants or halves. 1139 Quadrant numbering ascribes to the traditional numbering system 1140 used in describing graphs. 1141 1142 Inputs Ports 1143 grid: Grid3D Volume object 1144 1145 Output Ports 1146 geom: 3D box placed in the desired position 1147 """
1148 - def beforeAddingToNetwork(self, net):
1149 # import vizlib 1150 importVizLib(net)
1151
1152 - def __init__(self, name='Place Box', **kw):
1153 kw['name'] = name 1154 apply( NetworkNode.__init__, (self,), kw) 1155 1156 ip = self.inputPortsDescr 1157 ip.append(datatype='string', name='placement') 1158 ip.append(datatype='Grid3D', name='grid') 1159 1160 self.widgetDescr['placement'] = { 1161 'class': 'NEComboBox', 'master':'node', 1162 'choices':['No Box','FrontI', 'FrontII', 'FrontIII', 'FrontIV', 1163 'BackI','BackII','BackIII','BackIV', 1164 'Front Half','Back Half','Right Half','Left Half'], 1165 'initialValue':'FrontI', 1166 'entryfield_entry_width':10, 1167 'labelGridCfg':{'sticky':'we'}, 1168 'labelCfg':{'text':'placement:'}, 1169 } 1170 1171 1172 self.outputPortsDescr.append(datatype='geom', name='geom') 1173 self.bb = Box('regionBox', maxCube=[.5,.5,.5], minCube=[-.5,-.5,-.5]) 1174 1175 code = """def doit(self, placement, grid): 1176 ori = grid.origin 1177 dims = grid.data.shape 1178 if placement=='No Box': pt1=ori 1179 1180 elif placement=='BackIII' or placement=='Back Half' or placement=='Left Half': 1181 pt1 = ori 1182 1183 elif placement=='BackIV' or placement=='Right Half': 1184 pt1 = [ori[0]+(0.5*grid.stepSize[0]*(dims[0]-1)), 1185 ori[1], 1186 ori[2]] 1187 1188 elif placement=='BackII': 1189 pt1 = [ori[0], 1190 ori[1]+(0.5*grid.stepSize[1]*(dims[1]-1)), 1191 ori[2]] 1192 1193 elif placement=='FrontIII' or placement == 'Front Half': 1194 pt1 = [ori[0], 1195 ori[1], 1196 ori[2]+(0.5*grid.stepSize[2]*(dims[2]-1))] 1197 1198 elif placement=='FrontII': 1199 pt1 = [ori[0], 1200 ori[1]+(0.5*grid.stepSize[1]*(dims[1]-1)), 1201 ori[2]+(0.5*grid.stepSize[2]*(dims[2]-1))] 1202 1203 elif placement=='BackI': 1204 pt1 = [ori[0]+(0.5*grid.stepSize[0]*(dims[0]-1)), 1205 ori[1]+(0.5*grid.stepSize[1]*(dims[1]-1)), 1206 ori[2]] 1207 1208 elif placement=='FrontIV': 1209 pt1 = [ori[0]+(0.5*grid.stepSize[0]*(dims[0]-1)), 1210 ori[1], 1211 ori[2]+(0.5*grid.stepSize[2]*(dims[2]-1))] 1212 1213 elif placement=='FrontI': 1214 pt1 = [ori[0]+(0.5*grid.stepSize[0]*(dims[0]-1)), 1215 ori[1]+(0.5*grid.stepSize[1]*(dims[1]-1)), 1216 ori[2]+(0.5*grid.stepSize[2]*(dims[2]-1))] 1217 1218 1219 if placement=='No Box': pt2=ori 1220 elif placement=='Front Half' or placement=='Back Half': 1221 pt2 = [pt1[0]+(grid.stepSize[0]*(dims[0]-1)), 1222 pt1[1]+(grid.stepSize[1]*(dims[1]-1)), 1223 pt1[2]+(0.5*grid.stepSize[2]*(dims[2]-1))] 1224 1225 elif placement=='Right Half' or placement=='Left Half': 1226 pt2 = [pt1[0]+(0.5*grid.stepSize[0]*(dims[0]-1)), 1227 pt1[1]+(grid.stepSize[1]*(dims[1]-1)), 1228 pt1[2]+(grid.stepSize[2]*(dims[2]-1))] 1229 1230 else: 1231 pt2 = [pt1[0]+(0.5*grid.stepSize[0]*(dims[0]-1)), 1232 pt1[1]+(0.5*grid.stepSize[1]*(dims[1]-1)), 1233 pt1[2]+(0.5*grid.stepSize[2]*(dims[2]-1))] 1234 1235 coords = (pt1, pt2) 1236 if grid.crystal: 1237 ptList=((pt2[0],pt2[1],pt1[2]), 1238 (pt1[0],pt2[1],pt1[2]), 1239 (pt1[0],pt1[1],pt1[2]), 1240 (pt2[0],pt1[1],pt1[2]), 1241 (pt2[0],pt2[1],pt2[2]), 1242 (pt1[0],pt2[1],pt2[2]), 1243 (pt1[0],pt1[1],pt2[2]), 1244 (pt2[0],pt1[1],pt2[2])) 1245 coords = grid.crystal.toCartesian(ptList) 1246 self.bb.Set(vertices=coords) 1247 else: 1248 self.bb.Set(cornerPoints=coords) 1249 self.outputData(geom=self.bb) 1250 """ 1251 if code: self.setFunction(code)
1252
1253 -class ReadAnyMap(NetworkNode):
1254
1255 - def __init__(self, constrkw={}, name='ReadAnyMap', **kw):
1256 kw['name']=name 1257 apply( NetworkNode.__init__, (self,), kw ) 1258 fileTypes = [('All supported files', '*.map *.fld *.ccp4 *.dx *.grd '+ 1259 '*.omap *.brix* *.dsn6* *.cns *.xplo*r* *.d*e*l*phi *.mrc *.rawiv *.spi *.uhbd'), 1260 ('AutoGrid', '*.map'), 1261 ('AVS/FLD Binary', '*.fld'), 1262 ('BRIX/DSN6', '*.omap *.brix* *.dsn6*'), 1263 ('CCP4', '*.ccp4'), 1264 ('CNS/XPLOR', '*.cns *.xplo*r*'), 1265 ('Data Explorer(DX)', '*.dx'), 1266 ('Delphi', '*.d*e*l*phi'), 1267 ('GRD', '*.grd'), 1268 ('MRC', '*.mrc'), 1269 ('Rawiv', '*.rawiv'), 1270 ('SPIDER', '*.spi'), 1271 ('UHBD/GRID', '*.uhbd'), 1272 ('all', '*')] 1273 wd = self.widgetDescr 1274 wd['filename'] = {'class':'NEEntryWithFileBrowser', 1275 'master':'node', 1276 'filetypes':fileTypes, 1277 'title':'browse files', 1278 'labelCfg':{'text':'file:'}, 1279 'width':20 1280 } 1281 1282 ip = self.inputPortsDescr 1283 ip.append(datatype='string', name='filename') 1284 1285 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 1286 1287 global ifd 1288 ifd=InputFormDescr(title='Map Types') 1289 mapItems = [('AutoGrid',None), 1290 ('BRIX/DSN6',None), 1291 ('CCP4',None), 1292 ('CNS/XPLOR',None), 1293 ('Data Explorer(DX)',None), 1294 ('Delphi',None), 1295 ('GRD',None), 1296 ('MRC',None), 1297 ('Rawiv',None), 1298 ('SPIDER',None), 1299 ('UHBD/GRID',None), 1300 ('AVS/FLD Binary',None), 1301 ] 1302 1303 ifd.append({'name':'listchooser', 1304 'widgetType':ListChooser, 1305 'wcfg':{'title':'Select a Map Type:', 1306 'entries':mapItems, 1307 'lbwcfg':{'width':20,'height':12}, 1308 'mode':'single', 1309 }, 1310 'gridcfg':{'sticky':'w','row':-1} 1311 }) 1312 1313 1314 code = """def doit(self, filename, normalize=True): 1315 global ifd 1316 if not filename: return 1317 else: 1318 if(re.search('\.mrc$',filename,re.I)): 1319 self.reader = ReadMRC() 1320 elif(re.search('\.ccp4*$',filename,re.I)): 1321 self.reader = ReadCCP4() 1322 elif(re.search('\.cns$|\.xplo*r*$',filename,re.I)): 1323 self.reader = ReadCNS() 1324 elif(re.search('\.grd$',filename,re.I)): 1325 self.reader = ReadGRD() 1326 elif(re.search('\.fld$',filename,re.I)): 1327 self.reader = ReadFLDBinary() 1328 elif(re.search('\.map$',filename,re.I)): 1329 self.reader = ReadAutoGrid() 1330 elif(re.search('\.omap$|\.brix$|\.dsn6$|\.dn6$',filename,re.I)): 1331 self.reader = ReadBRIX() 1332 elif(re.search('\.rawiv$',filename,re.I)): 1333 self.reader = ReadRawiv() 1334 elif(re.search('\.d*e*l*phi$',filename,re.I)): 1335 self.reader = DelphiReaderBin() 1336 elif(re.search('\.uhbd$',filename,re.I)): 1337 self.reader = UHBDReaderASCII() 1338 elif(re.search('\.dx$',filename,re.I)): 1339 self.reader = ReadDX() 1340 elif(re.search('\.spi$',filename,re.I)): 1341 self.reader = ReadSPIDER() 1342 else: 1343 f = InputForm(master=Tkinter._default_root, 1344 root=Tkinter.Toplevel(), 1345 descr=ifd, blocking=1, modal=1) 1346 maptype=f.go() 1347 choice=maptype['listchooser'][0] 1348 if choice=='AutoGrid': self.reader=ReadAutoGrid() 1349 elif choice=='BRIX/DSN6': self.reader=ReadBRIX() 1350 elif choice=='CCP4': self.reader=ReadCCP4() 1351 elif choice=='CNS/XPLOR': self.reader=ReadCNS() 1352 elif choice=='Data Explorer(DX)': self.reader=ReadDX() 1353 elif choice=='Delphi': self.reader=DelphiReaderBin() 1354 elif choice=='GRD':self.reader=ReadGRD() 1355 elif choice=='MRC':self.reader=ReadMRC() 1356 elif choice=='Rawiv':self.reader=ReadRawiv() 1357 elif choice=='SPIDER':self.reader=ReadSPIDER() 1358 elif choice=='UHBD/GRID':self.reader=UHBDReaderASCII() 1359 elif choice=='AVS/FLD Binary':self.reader=ReadFLDBinary() 1360 else: print "error in choosing a map" 1361 grid = self.reader.read(filename, normalize=normalize) 1362 if grid: self.outputData(grid=grid) 1363 """ 1364 1365 if code: self.setFunction(code)
1366 1367
1368 -class ReadBinary(NetworkNode):
1369 """Parse a binary volume data file 1370 1371 Input Ports 1372 filename: filename of the file to parse 1373 dims: 3-tuples (nx,ny,nz) 1374 dtype: datatype ('int', float') 1375 swap: True of False to swap or not the bytes 1376 1377 Output Ports 1378 grid: Grid3D Volume object 1379 """ 1380
1381 - def __init__(self, name='Read Binary 3D file', **kw):
1382 kw['name'] = name 1383 apply( NetworkNode.__init__, (self,), kw) 1384 1385 self.widgetDescr['dims'] = {'class':'NEEntry', 1386 'labelGridCfg':{'sticky':'we'}, 'master':'node', 1387 'labelCfg':{'text':'dims (nx,ny,nz):'}, 1388 } 1389 1390 self.widgetDescr['filename'] = {'class':'NEEntryWithFileBrowser', 1391 'title':'browse files', 'master':'node', 1392 'filetypes':[('all', '*')], 1393 'labelCfg':{'text':'file:'}, 1394 'width':10 1395 } 1396 1397 self.widgetDescr['dtype'] = { 1398 'class': 'NEComboBox', 'master':'node', 1399 'choices':['double', 'float', 'int', 'uint', 'short', 'ushort', 1400 'uchar'], 1401 'initialValue':'float', 1402 'entryfield_entry_width':16, 1403 'labelGridCfg':{'sticky':'we'}, 1404 'labelCfg':{'text':'datatype:'}, 1405 } 1406 1407 self.widgetDescr['byteorder'] = { 1408 'class': 'NEComboBox', 'master':'node', 1409 'choices':['None', 'native =', 'native @', 'little-endian', 1410 'big-endian', 'network'], 1411 'initialValue':'None', 1412 'entryfield_entry_width':16, 1413 'labelGridCfg':{'sticky':'we'}, 1414 'labelCfg':{'text':'byteorder:'}, 1415 } 1416 1417 self.inputPortsDescr.append(datatype='string', name='filename') 1418 self.inputPortsDescr.append(datatype='None', name='dims') 1419 self.inputPortsDescr.append(datatype='string', name='dtype') 1420 self.inputPortsDescr.append(datatype='string', name='byteorder') 1421 1422 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 1423 self.reader = DelphiReaderBin() 1424 1425 code = """def doit(self, filename, dims, dtype, byteorder): 1426 if not filename: 1427 return 1428 1429 if dims=='': 1430 return 1431 1432 import types 1433 if type(dims)==types.StringType: 1434 dims = eval(dims) 1435 assert len(dims)==3 1436 size = dims[0]*dims[1]*dims[2] 1437 1438 # read file 1439 f = open(filename, 'rb') 1440 data = f.read() 1441 f.close() 1442 1443 if byteorder=='native @': swapc = '@' 1444 elif byteorder=='native =': swapc = '=' 1445 elif byteorder=='little-endian': swapc = '>' 1446 elif byteorder=='big-endian': swapc = '<' 1447 elif byteorder=='network': swapc = '!' 1448 else: swapc = '' 1449 1450 import Numeric 1451 if dtype=='double': 1452 dtypec='d' 1453 ntype=Numeric.Float64 1454 elif dtype=='float': 1455 dtypec='f' 1456 ntype=Numeric.Float32 1457 elif dtype=='int': 1458 dtypec='i' 1459 ntype=Numeric.Int32 1460 elif dtype=='uint': 1461 dtypec='I' 1462 ntype=Numeric.Int32 1463 elif dtype=='short': 1464 dtypec='h' 1465 ntype=Numeric.Int16 1466 elif dtype=='ushort': 1467 dtypec='H' 1468 ntype=Numeric.Int16 1469 elif dtype=='uchar': 1470 dtypec='' 1471 ntype=Numeric.UInt8 1472 1473 import struct 1474 values = struct.unpack('%1s%d%1s'%(swapc,size,dtypec), data) 1475 1476 values = Numeric.array(values, ntype) 1477 values.shape = dims 1478 1479 gtype = ArrayTypeToGrid[values.typecode()] 1480 grid = gtype(values, [0.,0.,0.], [1.,1.,1.], {'title':'from %s'%filename}) 1481 self.outputPorts[0].setDataType(gtype) 1482 self.outputData(grid=grid) 1483 """ 1484 1485 if code: self.setFunction(code)
1486 1487 1488
1489 -class ReadDelphiBin(NetworkNode):
1490 """Parse a binary Delphi file 1491 1492 Input Ports 1493 filename: filename of the file to parse 1494 1495 Output Ports 1496 grid: Grid3DF object 1497 """ 1498
1499 - def __init__(self, name='Read Delphi bin', **kw):
1500 kw['name'] = name 1501 apply( NetworkNode.__init__, (self,), kw) 1502 1503 self.widgetDescr['filename'] = {'class':'NEEntryWithFileBrowser', 1504 'master':'node', 'title':'browse files', 1505 'filetypes':[('phi','*.phi'), ('all', '*')], 1506 'labelCfg':{'text':'file:'}, 'width':10 } 1507 self.inputPortsDescr.append(datatype='string', name='filename') 1508 1509 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 1510 self.reader = DelphiReaderBin() 1511 1512 code = """def doit(self, filename, normalize=True): 1513 if not filename: 1514 return 1515 grid = self.reader.read(filename) 1516 if grid: 1517 self.outputData(grid=grid) 1518 """ 1519 1520 if code: self.setFunction(code)
1521 1522
1523 -class ReadUHBDAscii(NetworkNode):
1524 """Parse a UHBD file in ASCII format 1525 1526 Input Ports 1527 filename: filename of the file to parse 1528 1529 Output Ports 1530 grid: Grid3DF object 1531 """ 1532
1533 - def __init__(self, name='Read UHBD ASCII', **kw):
1534 kw['name'] = name 1535 apply( NetworkNode.__init__, (self,), kw) 1536 1537 self.widgetDescr['filename'] = {'class':'NEEntryWithFileBrowser', 1538 'master':'node', 'title':'browse files', 1539 'filetypes':[('UHBD ASCII files','*.uhbd'), ('all', '*')], 1540 'labelCfg':{'text':'file:'}, 'width':10 } 1541 self.inputPortsDescr.append(datatype='string', name='filename') 1542 1543 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 1544 self.reader = UHBDReaderASCII() 1545 1546 code = """def doit(self, filename, normalize=True): 1547 if not filename: 1548 return 1549 grid = self.reader.read(filename) 1550 if grid: 1551 self.outputData(grid=grid) 1552 """ 1553 1554 if code: self.setFunction(code)
1555 1556 1557
1558 -class ReadMRCfile(NetworkNode):
1559 """Parse an MRC file. 1560 1561 Input Ports 1562 filename: filename of the file to parse 1563 1564 Output Ports 1565 grid: Grid3D Volume object 1566 """ 1567
1568 - def __init__(self, name='Read MRC', **kw):
1569 kw['name'] = name 1570 apply( NetworkNode.__init__, (self,), kw) 1571 1572 self.widgetDescr['filename'] = {'class':'NEEntryWithFileBrowser', 1573 'master':'node', 'title':'browse files', 1574 'filetypes':[('MRC files','*.mrc'), ('all', '*')], 1575 'labelCfg':{'text':'file:'}, 'width':10 } 1576 self.inputPortsDescr.append(datatype='string', name='filename') 1577 1578 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 1579 self.reader = ReadMRC() 1580 1581 code = """def doit(self, filename, normalize=True): 1582 if not filename: 1583 return 1584 grid = self.reader.read(filename) 1585 if grid: 1586 self.outputData(grid=grid) 1587 """ 1588 1589 if code: self.setFunction(code)
1590 1591
1592 -class ReadCCP4file(NetworkNode):
1593 """Parse a CCP4 file. 1594 1595 Input Ports 1596 filename: filename of the file to parse 1597 normalize: boolean, check to normalize the data 1598 1599 Output Ports 1600 data: the resulting 3D table 1601 header: the complete header as a dictionary 1602 origin: the lower left corner of the data (3-tuple) 1603 step: the grid step size (3-tuple) 1604 """ 1605
1606 - def __init__(self, name='Read CCP4', **kw):
1607 kw['name'] = name 1608 apply( NetworkNode.__init__, (self,), kw) 1609 1610 self.widgetDescr['filename'] = {'class':'NEEntryWithFileBrowser', 1611 'master':'node', 'title':'browse files', 1612 'filetypes':[('CCP4 files','*.map'),('CCP4 files','*.ccp4'), ('all', '*')], 1613 'labelCfg':{'text':'file:'}, 'width':10 } 1614 self.widgetDescr['normalize'] = { 1615 'class':'NECheckButton', 'master':'ParamPanel', 1616 'initialValue':1, 'labelGridCfg':{'sticky':'we'}, 1617 'labelCfg':{'text':'normalize:'}, 1618 } 1619 1620 self.inputPortsDescr.append(datatype='string', name='filename') 1621 self.inputPortsDescr.append(datatype='boolean', required=False, name='normalize') 1622 1623 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 1624 self.reader = ReadCCP4() 1625 1626 code = """def doit(self, filename, normalize=True): 1627 if not filename: 1628 return 1629 grid = self.reader.read(filename, normalize=normalize) 1630 if grid: 1631 self.outputData(grid=grid) 1632 """ 1633 1634 if code: self.setFunction(code)
1635 1636
1637 -class ReadSPIDERfile(NetworkNode):
1638 """Parse a SPIDER file. 1639 1640 Input Ports 1641 filename: filename of the file to parse 1642 normalize: boolean, check to normalize the data 1643 1644 Output Ports 1645 data: the resulting 3D table 1646 header: the complete header as a dictionary 1647 origin: the lower left corner of the data (3-tuple) 1648 step: the grid step size (3-tuple) 1649 """ 1650
1651 - def __init__(self, name='Read SPIDER', **kw):
1652 kw['name'] = name 1653 apply( NetworkNode.__init__, (self,), kw) 1654 1655 self.widgetDescr['filename'] = {'class':'NEEntryWithFileBrowser', 1656 'master':'node', 'title':'browse files', 1657 'filetypes':[('SPIDER files','*.spi'), ('all', '*')], 1658 'labelCfg':{'text':'file:'}, 'width':10 } 1659 self.widgetDescr['normalize'] = { 1660 'class':'NECheckButton', 'master':'ParamPanel', 1661 'initialValue':1, 'labelGridCfg':{'sticky':'we'}, 1662 'labelCfg':{'text':'normalize:'}, 1663 } 1664 1665 self.inputPortsDescr.append(datatype='string', name='filename') 1666 self.inputPortsDescr.append(datatype='boolean', required=False, name='normalize') 1667 1668 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 1669 self.reader = ReadSPIDER() 1670 1671 code = """def doit(self, filename, normalize=True): 1672 if not filename: 1673 return 1674 grid = self.reader.read(filename, normalize=normalize) 1675 if grid: 1676 self.outputData(grid=grid) 1677 """ 1678 1679 if code: self.setFunction(code)
1680 1681
1682 -class ReadCNSfile(NetworkNode):
1683 """Parse a CNS/XPLOR formatted file. 1684 1685 Input Ports 1686 filename: filename of the file to parse 1687 normalize: boolean, check to normalize the data 1688 1689 Output Ports 1690 data: the resulting 3D table 1691 header: the complete header as a dictionary 1692 origin: the lower left corner of the data (3-tuple) 1693 step: the grid step size (3-tuple) 1694 """ 1695
1696 - def __init__(self, name='Read CNS/XPLOR', **kw):
1697 kw['name'] = name 1698 apply( NetworkNode.__init__, (self,), kw) 1699 1700 self.widgetDescr['filename'] = {'class':'NEEntryWithFileBrowser', 1701 'master':'node', 'title':'browse files', 1702 'filetypes':[('CNS files','*.cns'), 1703 ('XPLOR files','*.xplor'), 1704 ('all', '*')], 1705 'labelCfg':{'text':'file:'}, 'width':10 } 1706 self.widgetDescr['normalize'] = { 1707 'class':'NECheckButton', 'master':'ParamPanel', 1708 'initialValue':1, 'labelGridCfg':{'sticky':'we'}, 1709 'labelCfg':{'text':'normalize:'}, 1710 } 1711 1712 self.inputPortsDescr.append(datatype='string', name='filename') 1713 self.inputPortsDescr.append(datatype='boolean', required=False, name='normalize') 1714 1715 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 1716 self.reader = ReadCNS() 1717 1718 code = """def doit(self, filename, normalize=True): 1719 if not filename: 1720 return 1721 grid = self.reader.read(filename, normalize=normalize) 1722 if grid: 1723 self.outputData(grid=grid) 1724 """ 1725 1726 if code: self.setFunction(code)
1727
1728 -class ReadGRDfile(NetworkNode):
1729 """Parse a GRD formatted file. 1730 1731 Input Ports 1732 filename: filename of the file to parse 1733 normalize: boolean, check to normalize the data 1734 1735 Output Ports 1736 data: the resulting 3D table 1737 header: the complete header as a dictionary 1738 origin: the lower left corner of the data (3-tuple) 1739 step: the grid step size (3-tuple) 1740 """ 1741
1742 - def __init__(self, name='Read GRD', **kw):
1743 kw['name'] = name 1744 apply( NetworkNode.__init__, (self,), kw) 1745 1746 self.widgetDescr['filename'] = {'class':'NEEntryWithFileBrowser', 1747 'master':'node', 'title':'browse files', 1748 'filetypes':[('GRD files','*.grd'), ('all', '*')], 1749 'labelCfg':{'text':'file:'}, 'width':10 } 1750 self.widgetDescr['normalize'] = { 1751 'class':'NECheckButton', 'master':'ParamPanel', 1752 'initialValue':1, 'labelGridCfg':{'sticky':'we'}, 1753 'labelCfg':{'text':'normalize:'}, 1754 } 1755 1756 self.inputPortsDescr.append(datatype='string', name='filename') 1757 self.inputPortsDescr.append(datatype='boolean', required=False, name='normalize') 1758 1759 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 1760 self.reader = ReadGRD() 1761 1762 code = """def doit(self, filename, normalize=True): 1763 if not filename: 1764 return 1765 grid = self.reader.read(filename, normalize=normalize) 1766 if grid: 1767 self.outputData(grid=grid) 1768 """ 1769 1770 if code: self.setFunction(code)
1771 1772
1773 -class ReadEMfile(NetworkNode):
1774 """Parse an EM formatted file. 1775 (This format is used at the MPI for Biochemistry, Munich, for electron 1776 microscopy 3-D reconstructions) 1777 1778 Input Ports 1779 filename: filename of the file to parse 1780 normalize: boolean, check to normalize the data 1781 1782 Output Ports 1783 data: the resulting 3D table 1784 header: the complete header as a dictionary 1785 origin: the lower left corner of the data (3-tuple) 1786 step: the grid step size (3-tuple) 1787 """ 1788
1789 - def __init__(self, name='Read EM', **kw):
1790 kw['name'] = name 1791 apply( NetworkNode.__init__, (self,), kw) 1792 1793 self.widgetDescr['filename'] = {'class':'NEEntryWithFileBrowser', 1794 'master':'node', 'title':'browse files', 1795 'filetypes':[('EM files','*'), ('all', '*')], 1796 'labelCfg':{'text':'file:'}, 'width':10 } 1797 1798 self.inputPortsDescr.append(datatype='string', name='filename') 1799 1800 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 1801 self.reader = ReadEM() 1802 1803 code = """def doit(self, filename): 1804 if not filename: 1805 return 1806 grid = self.reader.read(filename) 1807 if grid: 1808 self.outputData(grid=grid) 1809 """ 1810 1811 if code: self.setFunction(code)
1812 1813
1814 -class ReadBRIXfile(NetworkNode):
1815 """Parse a BRIX file. 1816 1817 Input Ports 1818 filename: filename of the file to parse 1819 normalize: boolean, check to normalize the data 1820 1821 Output Ports 1822 data: the resulting 3D table 1823 header: the complete header as a dictionary 1824 origin: the lower left corner of the data (3-tuple) 1825 step: the grid step size (3-tuple) 1826 """ 1827
1828 - def __init__(self, name='Read BRIX', **kw):
1829 kw['name'] = name 1830 apply( NetworkNode.__init__, (self,), kw) 1831 1832 self.widgetDescr['filename'] = {'class':'NEEntryWithFileBrowser', 1833 'master':'node', 'title':'browse files', 1834 'filetypes':[('BRIX files','*.brix'), 1835 ('DSN6 files','*.dsn6'), 1836 ('all', '*')], 1837 'labelCfg':{'text':'file:'}, 'width':10 } 1838 self.widgetDescr['normalize'] = { 1839 'class':'NECheckButton', 'master':'ParamPanel', 1840 'initialValue':1, 'labelGridCfg':{'sticky':'we'}, 1841 'labelCfg':{'text':'normalize:'}, 1842 } 1843 1844 self.inputPortsDescr.append(datatype='string', name='filename') 1845 self.inputPortsDescr.append(datatype='boolean', required=False, name='normalize') 1846 1847 self.outputPortsDescr.append(datatype='Grid3D', name='grid') 1848 self.reader = ReadBRIX() 1849 1850 code = """def doit(self, filename, normalize=True): 1851 if not filename: 1852 return 1853 grid = self.reader.read(filename, normalize=normalize) 1854 if grid: 1855 self.outputData(grid=grid) 1856 """ 1857 1858 if code: self.setFunction(code)
1859 1860 from Volume.IO.dxReader import ReadDX 1861
1862 -class ReadDXfile(NetworkNode):
1863 """Parse an DX (data explorer) volume data file. 1864 1865 Input Ports 1866 filename: filename of the file to parse 1867 1868 Output Ports 1869 grid: the resulting Grid3DF object 1870 """ 1871
1872 - def __init__(self, name='Read MRC', **kw):
1873 kw['name'] = name 1874 apply( NetworkNode.