Source code for paraview.web.dataset_builder

from vtk.web import camera
from paraview.web import data_writer
from paraview.web import data_converter

from vtk.web.query_data_model import *
from paraview.web.camera import *

from paraview import simple
from paraview import servermanager
from vtk import *

import json, os, math, gzip, shutil, hashlib

# Global helper variables
encode_codes = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
arrayTypesMapping = '  bBhHiIlLfd'
jsMapping = {
    'b': 'Int8Array',
    'B': 'Uint8Array',
    'h': 'Int16Array',
    'H': 'Int16Array',
    'i': 'Int32Array',
    'I': 'Uint32Array',
    'l': 'Int32Array',
    'L': 'Uint32Array',
    'f': 'Float32Array',
    'd': 'Float64Array'
}

# -----------------------------------------------------------------------------
# Basic Dataset Builder
# -----------------------------------------------------------------------------

[docs]class DataSetBuilder(object): def __init__(self, location, camera_data, metadata={}, sections={}): self.dataHandler = DataHandler(location) self.cameraDescription = camera_data self.camera = None for key, value in metadata.iteritems(): self.dataHandler.addMetaData(key, value) for key, value in sections.iteritems(): self.dataHandler.addSection(key, value) # Update the can_write flag for MPI self.dataHandler.can_write = (servermanager.vtkProcessModule.GetProcessModule().GetPartitionId() == 0)
[docs] def getDataHandler(self): return self.dataHandler
[docs] def getCamera(self): return self.camera
[docs] def updateCamera(self, camera): update_camera(self.view, camera)
[docs] def start(self, view=None): if view: # Keep track of the view self.view = view # Handle camera if any if self.cameraDescription: if self.cameraDescription['type'] == 'spherical': self.camera = camera.SphericalCamera(self.dataHandler, view.CenterOfRotation, view.CameraPosition, view.CameraViewUp, self.cameraDescription['phi'], self.cameraDescription['theta']) elif self.cameraDescription['type'] == 'cylindrical': self.camera = camera.CylindricalCamera(self.dataHandler, view.CenterOfRotation, view.CameraPosition, view.CameraViewUp, self.cameraDescription['phi'], self.cameraDescription['translation']) # Update background color bgColor = view.Background bgColorString = 'rgb(%d, %d, %d)' % tuple(int(bgColor[i]*255) for i in range(3)) if view.UseGradientBackground: bgColor2 = view.Background2 bgColor2String = 'rgb(%d, %d, %d)' % tuple(int(bgColor2[i]*255) for i in range(3)) self.dataHandler.addMetaData('backgroundColor', 'linear-gradient(%s,%s)' % (bgColor2String, bgColorString)) else: self.dataHandler.addMetaData('backgroundColor', bgColorString) # Update file patterns self.dataHandler.updateBasePattern()
[docs] def stop(self): self.dataHandler.writeDataDescriptor()
# ----------------------------------------------------------------------------- # Image Dataset Builder # -----------------------------------------------------------------------------
[docs]class ImageDataSetBuilder(DataSetBuilder): def __init__(self, location, imageMimeType, cameraInfo, metadata={}): DataSetBuilder.__init__(self, location, cameraInfo, metadata) imageExtenstion = '.' + imageMimeType.split('/')[1] self.dataHandler.registerData(name='image', type='blob', mimeType=imageMimeType, fileName=imageExtenstion)
[docs] def writeImages(self): for cam in self.camera: update_camera(self.view, cam) simple.WriteImage(self.dataHandler.getDataAbsoluteFilePath('image'))
# ----------------------------------------------------------------------------- # Data Prober Dataset Builder # -----------------------------------------------------------------------------
[docs]class DataProberDataSetBuilder(DataSetBuilder): def __init__(self, input, location, sampling_dimesions, fields_to_keep, custom_probing_bounds = None, metadata={}): DataSetBuilder.__init__(self, location, None, metadata) self.fieldsToWrite = fields_to_keep self.resamplerFilter = simple.ResampleToImage(Input=input) self.resamplerFilter.SamplingDimensions = sampling_dimesions if custom_probing_bounds: self.resamplerFilter.UseInputBounds = 0 self.resamplerFilter.SamplingBounds = custom_probing_bounds else: self.resamplerFilter.UseInputBounds = 1 # Register all fields self.dataHandler.addTypes('data-prober', 'binary') self.DataProber = { 'types': {}, 'dimensions': sampling_dimesions, 'ranges': {}, 'spacing': [1,1,1] } for field in self.fieldsToWrite: self.dataHandler.registerData(name=field, type='array', rootFile=True, fileName='%s.array' % field)
[docs] def writeData(self, time=0): if not self.dataHandler.can_write: return self.resamplerFilter.UpdatePipeline(time) imageData = self.resamplerFilter.GetClientSideObject().GetOutput() self.DataProber['spacing'] = imageData.GetSpacing() arrays = imageData.GetPointData() maskArray = arrays.GetArray(vtk.vtkDataSetAttributes.GhostArrayName()) for field in self.fieldsToWrite: array = arrays.GetArray(field) if array: if array.GetNumberOfComponents() == 1: # Push NaN when no value are present instead of 0 for idx in range(maskArray.GetNumberOfTuples()): if maskArray.GetValue(idx) == 2: # Hidden point array.SetValue(idx, float('NaN')) with open(self.dataHandler.getDataAbsoluteFilePath(field), 'wb') as f: f.write(buffer(array)) self.expandRange(array) else: magarray = array.NewInstance() magarray.SetNumberOfTuples(array.GetNumberOfTuples()) magarray.SetName(field) for idx in range(magarray.GetNumberOfTuples()): if maskArray.GetValue(idx) == 2: # Hidden point # Push NaN when no value are present magarray.SetValue(idx, float('NaN')) else: entry = array.GetTuple(idx) mag = self.magnitude(entry) magarray.SetValue(idx,mag) with open(self.dataHandler.getDataAbsoluteFilePath(field), 'wb') as f: f.write(buffer(magarray)) self.expandRange(magarray) else: print ('No array for', field) print (self.resamplerFilter.GetOutput())
[docs] def magnitude(self, tuple): value = 0 for item in tuple: value += item * item value = value**0.5 return value
[docs] def expandRange(self, array): field = array.GetName() self.DataProber['types'][field] = jsMapping[arrayTypesMapping[array.GetDataType()]] if field in self.DataProber['ranges']: dataRange = array.GetRange() if dataRange[0] < self.DataProber['ranges'][field][0]: self.DataProber['ranges'][field][0] = dataRange[0] if dataRange[1] > self.DataProber['ranges'][field][1]: self.DataProber['ranges'][field][1] = dataRange[1] else: self.DataProber['ranges'][field] = [array.GetRange()[0], array.GetRange()[1]]
[docs] def stop(self, compress=True): # Rescale spacing to have the smaller value to be 1.0 smallerValue = min(self.DataProber['spacing']) if smallerValue < 1.0: self.DataProber['spacing'] = tuple( i / smallerValue for i in self.DataProber['spacing']) # Push metadata self.dataHandler.addSection('DataProber', self.DataProber) # Write metadata DataSetBuilder.stop(self) if compress: for root, dirs, files in os.walk(self.dataHandler.getBasePath()): print ('Compress', root) for name in files: if '.array' in name and '.gz' not in name: with open(os.path.join(root, name), 'rb') as f_in: with gzip.open(os.path.join(root, name + '.gz'), 'wb') as f_out: shutil.copyfileobj(f_in, f_out) os.remove(os.path.join(root, name))
# ----------------------------------------------------------------------------- # Float Image with Layer Dataset Builder # -----------------------------------------------------------------------------
[docs]class LayerDataSetBuilder(DataSetBuilder): def __init__(self, input, location, cameraInfo, imageSize=[500,500], metadata={}): DataSetBuilder.__init__(self, location, cameraInfo, metadata) self.dataRenderer = data_writer.ScalarRenderer(isWriter=self.dataHandler.can_write) self.view = self.dataRenderer.getView() self.view.ViewSize = imageSize self.floatImage = {'dimensions': imageSize, 'layers': [], 'ranges': {}} self.layerMap = {} self.input = input self.activeLayer = None self.activeField = None self.layerChanged = False self.lastTime = -1 # Update data type self.dataHandler.addTypes('float-image')
[docs] def getView(self): return self.view
[docs] def setActiveLayer(self, layer, field, hasMesh=False, activeSource=None): if activeSource: self.activeSource = activeSource else: self.activeSource = self.input needDataRegistration = False if layer not in self.layerMap: layerObj = { 'name': layer, 'array': field, 'arrays': [ field ], 'active': True, 'type': 'Float32Array', 'hasMesh': hasMesh } self.layerMap[layer] = layerObj self.floatImage['layers'].append(layerObj) needDataRegistration = True # Register layer lighting self.dataHandler.registerData(name='%s__light' % layer, type='array', rootFile=True, fileName='%s__light.array' % layer, categories=[ '%s__light' % layer ]) # Register layer mesh if hasMesh: self.dataHandler.registerData(name='%s__mesh' % layer, type='array', rootFile=True, fileName='%s__mesh.array' % layer, categories=[ '%s__mesh' % layer ]) elif field not in self.layerMap[layer]['arrays']: self.layerMap[layer]['arrays'].append(field) needDataRegistration = True # Keep track of the active data if self.activeLayer != layer: self.layerChanged = True self.activeLayer = layer self.activeField = field if needDataRegistration: self.dataHandler.registerData(name='%s_%s' % (layer, field), type='array', rootFile=True, fileName='%s_%s.array' % (layer, field), categories=[ '%s_%s' % (layer, field) ])
[docs] def writeLayerData(self, time=0): dataRange = [0, 1] self.activeSource.UpdatePipeline(time) if self.activeField and self.activeLayer: if self.layerChanged or self.lastTime != time: self.layerChanged = False self.lastTime = time # Capture lighting information for camPos in self.getCamera(): self.view.CameraFocalPoint = camPos['focalPoint'] self.view.CameraPosition = camPos['position'] self.view.CameraViewUp = camPos['viewUp'] self.dataRenderer.writeLightArray(self.dataHandler.getDataAbsoluteFilePath('%s__light'%self.activeLayer), self.activeSource) # Capture mesh information if self.layerMap[self.activeLayer]['hasMesh']: for camPos in self.getCamera(): self.view.CameraFocalPoint = camPos['focalPoint'] self.view.CameraPosition = camPos['position'] self.view.CameraViewUp = camPos['viewUp'] self.dataRenderer.writeMeshArray(self.dataHandler.getDataAbsoluteFilePath('%s__mesh'%self.activeLayer), self.activeSource) for camPos in self.getCamera(): self.view.CameraFocalPoint = camPos['focalPoint'] self.view.CameraPosition = camPos['position'] self.view.CameraViewUp = camPos['viewUp'] dataName = ('%s_%s' % (self.activeLayer, self.activeField)) dataRange = self.dataRenderer.writeArray(self.dataHandler.getDataAbsoluteFilePath(dataName), self.activeSource, self.activeField) if self.activeField not in self.floatImage['ranges']: self.floatImage['ranges'][self.activeField] = [ dataRange[0], dataRange[1] ] else: # Expand the ranges if dataRange[0] < self.floatImage['ranges'][self.activeField][0]: self.floatImage['ranges'][self.activeField][0] = dataRange[0] if dataRange[1] > self.floatImage['ranges'][self.activeField][1]: self.floatImage['ranges'][self.activeField][1] = dataRange[1]
[docs] def start(self): DataSetBuilder.start(self, self.view)
[docs] def stop(self, compress=True): if not self.dataHandler.can_write: return # Push metadata self.dataHandler.addSection('FloatImage', self.floatImage) # Write metadata DataSetBuilder.stop(self) if compress: for root, dirs, files in os.walk(self.dataHandler.getBasePath()): print ('Compress', root) for name in files: if '.array' in name and '.gz' not in name: with open(os.path.join(root, name), 'rb') as f_in: with gzip.open(os.path.join(root, name + '.gz'), 'wb') as f_out: shutil.copyfileobj(f_in, f_out) os.remove(os.path.join(root, name))
# ----------------------------------------------------------------------------- # Composite Dataset Builder # -----------------------------------------------------------------------------
[docs]class CompositeDataSetBuilder(DataSetBuilder): def __init__(self, location, sceneConfig, cameraInfo, metadata={}, sections={}): DataSetBuilder.__init__(self, location, cameraInfo, metadata, sections) self.view = simple.CreateView('RenderView') self.view.ViewSize = sceneConfig['size'] self.view.CenterAxesVisibility = 0 self.view.OrientationAxesVisibility = 0 self.view.UpdatePropertyInformation() if 'camera' in sceneConfig and 'CameraFocalPoint' in sceneConfig['camera']: self.view.CenterOfRotation = sceneConfig['camera']['CameraFocalPoint'] # Initialize camera for key, value in sceneConfig['camera'].iteritems(): self.view.GetProperty(key).SetData(value) # Create a representation for all scene sources self.config = sceneConfig self.representations = [] for data in self.config['scene']: rep = simple.Show(data['source'], self.view) self.representations.append(rep) if 'representation' in data: for key in data['representation']: rep.GetProperty(key).SetData(data['representation'][key]) # Add directory path self.dataHandler.registerData(name='directory', rootFile=True, fileName='file.txt', categories=['trash'])
[docs] def start(self): DataSetBuilder.start(self, self.view)
[docs] def stop(self, compress=True, clean=True): DataSetBuilder.stop(self) if not self.dataHandler.can_write: return # Make the config serializable for item in self.config['scene']: del item['source'] # Write the scene to disk with open(os.path.join(self.dataHandler.getBasePath(), "config.json"), 'w') as f: f.write(json.dumps(self.config)) dataConverter = data_converter.ConvertCompositeDataToSortedStack(self.dataHandler.getBasePath()) dataConverter.convert() # Remove tmp files os.remove(os.path.join(self.dataHandler.getBasePath(), "index.json")) os.remove(os.path.join(self.dataHandler.getBasePath(), "config.json")) # Composite pipeline meta description compositePipeline = { 'default_pipeline': '', 'layers': [], 'fields': {}, 'layer_fields': {}, 'pipeline': [] } rootItems = {} fieldNameMapping = {} # Clean scene in config and gather ranges dataRanges = {} layerIdx = 0 for layer in self.config['scene']: # Create group node if any if 'parent' in layer and layer['parent'] not in rootItems: rootItems[layer['parent']] = { 'name': layer['parent'], 'ids': [], 'children': [] } compositePipeline['pipeline'].append(rootItems[layer['parent']]) # Create layer entry layerCode = encode_codes[layerIdx] layerItem = { 'name': layer['name'], 'ids': [ layerCode ]} compositePipeline['layers'].append(layerCode) compositePipeline['layer_fields'][layerCode] = [] compositePipeline['default_pipeline'] += layerCode # Register layer entry in pipeline if 'parent' in layer: rootItems[layer['parent']]['children'].append(layerItem) rootItems[layer['parent']]['ids'].append(layerCode) else: compositePipeline['pipeline'].append(layerItem) # Handle color / field colorByList = [] for color in layer['colors']: # Find color code if color not in fieldNameMapping: colorCode = encode_codes[len(fieldNameMapping)] fieldNameMapping[color] = colorCode compositePipeline['fields'][colorCode] = color else: colorCode = fieldNameMapping[color] # Register color code compositePipeline['layer_fields'][layerCode].append(colorCode) if len(colorByList) == 0: compositePipeline['default_pipeline'] += colorCode values = None if 'constant' in layer['colors'][color]: value = layer['colors'][color]['constant'] values = [ value, value ] colorByList.append({'name': color, 'type': 'const', 'value': value}) elif 'range' in layer['colors'][color]: values = layer['colors'][color]['range'] colorByList.append({'name': color, 'type': 'field'}) if values: if color not in dataRanges: dataRanges[color] = values else: dataRanges[color][0] = min(dataRanges[color][0], values[0], values[1]) dataRanges[color][1] = max(dataRanges[color][1], values[0], values[1]) layer['colorBy'] = colorByList del layer['colors'] layerIdx += 1 sortedCompositeSection = { 'dimensions': self.config['size'], 'pipeline': self.config['scene'], 'ranges': dataRanges, 'layers': len(self.config['scene']), 'light': self.config['light'] } self.dataHandler.addSection('SortedComposite', sortedCompositeSection) self.dataHandler.addSection('CompositePipeline', compositePipeline) self.dataHandler.addTypes('sorted-composite', 'multi-color-by') self.dataHandler.removeData('directory') for dataToRegister in dataConverter.listData(): self.dataHandler.registerData(**dataToRegister) self.dataHandler.writeDataDescriptor() if clean: for root, dirs, files in os.walk(self.dataHandler.getBasePath()): print ('Clean', root) for name in files: if name in ['camera.json']: os.remove(os.path.join(root, name)) if compress: for root, dirs, files in os.walk(self.dataHandler.getBasePath()): print ('Compress', root) for name in files: if ('.float32' in name or '.uint8' in name) and '.gz' not in name: with open(os.path.join(root, name), 'rb') as f_in: with gzip.open(os.path.join(root, name + '.gz'), 'wb') as f_out: shutil.copyfileobj(f_in, f_out) os.remove(os.path.join(root, name))
[docs] def writeData(self): composite_size = len(self.representations) self.view.UpdatePropertyInformation() self.view.Background = [0,0,0] imageSize = self.view.ViewSize[0] * self.view.ViewSize[1] # Generate the heavy data for camPos in self.getCamera(): self.view.CameraFocalPoint = camPos['focalPoint'] self.view.CameraPosition = camPos['position'] self.view.CameraViewUp = camPos['viewUp'] # Show all representations for compositeIdx in range(composite_size): rep = self.representations[compositeIdx] rep.Visibility = 1 # Fix camera bounds self.view.LockBounds = 0 simple.Render(self.view) self.view.LockBounds = 1 # Update destination directory dest_path = os.path.dirname(self.dataHandler.getDataAbsoluteFilePath('directory')) # Write camera informations if self.dataHandler.can_write: with open(os.path.join(dest_path, "camera.json"), 'w') as f: f.write(json.dumps(camPos)) # Hide all representations for compositeIdx in range(composite_size): rep = self.representations[compositeIdx] rep.Visibility = 0 # Show only active Representation # Extract images for each fields for compositeIdx in range(composite_size): rep = self.representations[compositeIdx] if compositeIdx > 0: self.representations[compositeIdx - 1].Visibility = 0 rep.Visibility = 1 # capture Z simple.Render() zBuffer = self.view.CaptureDepthBuffer() with open(os.path.join(dest_path, 'depth_%d.float32' % compositeIdx), 'wb') as f: f.write(buffer(zBuffer)) # Prevent color interference rep.DiffuseColor = [1,1,1] # Handle light for lightType in self.config['light']: if lightType == 'intensity': rep.AmbientColor = [1,1,1] rep.SpecularColor = [1,1,1] self.view.StartCaptureLuminance() image = self.view.CaptureWindow(1) imagescalars = image.GetPointData().GetScalars() self.view.StopCaptureLuminance() # Extract specular information specularOffset = 1 # [diffuse, specular, ?] imageSize = imagescalars.GetNumberOfTuples() specularComponent = vtkUnsignedCharArray() specularComponent.SetNumberOfComponents(1) specularComponent.SetNumberOfTuples(imageSize) for idx in range(imageSize): specularComponent.SetValue(idx, imagescalars.GetValue(idx * 3 + specularOffset)) with open(os.path.join(dest_path, 'intensity_%d.uint8' % compositeIdx), 'wb') as f: f.write(buffer(specularComponent)) # Free memory image.UnRegister(None) if lightType == 'normal': if rep.Representation == 'Point Gaussian' or rep.Representation == 'Points': uniqNormal = [(camPos['position'][i] - camPos['focalPoint'][i]) for i in range(3)] tmpNormalArray = vtkFloatArray() tmpNormalArray.SetNumberOfComponents(1) tmpNormalArray.SetNumberOfTuples(imageSize) for comp in range(3): tmpNormalArray.FillComponent(0, uniqNormal[comp]) with open(os.path.join(dest_path, 'normal_%d_%d.float32' % (compositeIdx, comp)), 'wb') as f: f.write(buffer(tmpNormalArray)) else: for comp in range(3): # Configure view to handle POINT_DATA / CELL_DATA self.view.DrawCells = 0 self.view.ArrayNameToDraw = 'Normals' self.view.ArrayComponentToDraw = comp self.view.ScalarRange = [-1.0, 1.0] self.view.StartCaptureValues() image = self.view.CaptureWindow(1) imagescalars = image.GetPointData().GetScalars() self.view.StopCaptureValues() # Convert RGB => Float => Write floatArray = data_converter.convertRGBArrayToFloatArray(imagescalars, [-1.0, 1.0]) with open(os.path.join(dest_path, 'normal_%d_%d.float32' % (compositeIdx, comp)), 'wb') as f: f.write(buffer(floatArray)) # Free memory image.UnRegister(None) # Handle color by for fieldName, fieldConfig in self.config['scene'][compositeIdx]['colors'].iteritems(): if 'constant' in fieldConfig: # Skip nothing to render continue # Configure view to handle POINT_DATA / CELL_DATA if fieldConfig['location'] == 'POINT_DATA': self.view.DrawCells = 0 else: self.view.DrawCells = 1 self.view.ArrayNameToDraw = fieldName self.view.ArrayComponentToDraw = 0 self.view.ScalarRange = fieldConfig['range'] self.view.StartCaptureValues() image = self.view.CaptureWindow(1) imagescalars = image.GetPointData().GetScalars() self.view.StopCaptureValues() floatArray = data_converter.convertRGBArrayToFloatArray(imagescalars, fieldConfig['range']) with open(os.path.join(dest_path, '%d_%s.float32' % (compositeIdx, fieldName)), 'wb') as f: f.write(buffer(floatArray)) self.dataHandler.registerData(name='%d_%s' % (compositeIdx, fieldName), fileName='/%d_%s.float32' % (compositeIdx, fieldName), type='array', categories=['%d_%s' % (compositeIdx, fieldName)]) # Free memory image.UnRegister(None)
# ----------------------------------------------------------------------------- # GeometryDataSetBuilder Dataset Builder # -----------------------------------------------------------------------------
[docs]class GeometryDataSetBuilder(DataSetBuilder): def __init__(self, location, sceneConfig, metadata={}, sections={}): DataSetBuilder.__init__(self, location, None, metadata, sections) # Update data type self.dataHandler.addTypes('geometry'); # Create a representation for all scene sources self.config = sceneConfig # Processing pipeline self.surfaceExtract = None # Add directory path self.dataHandler.registerData(priority=0, name='scene', rootFile=True, fileName='scene.json', type='json') # Create directory containers pointsPath = os.path.join(location, 'points') polyPath = os.path.join(location, 'index') colorPath = os.path.join(location, 'fields') for p in [pointsPath, polyPath, colorPath]: if not os.path.exists(p): os.makedirs(p) # Create metadata structure colorToCodeMap = {} parentNodes = {} pipelineMeta = { 'layers': [], 'pipeline': [], 'layer_fields': {}, 'fields': {} } geometryMeta = { 'ranges': {}, 'layer_map': {}, 'object_size': {} } self.objSize = geometryMeta['object_size'] for item in sceneConfig['scene']: # Handle layer layerCode = encode_codes[len(pipelineMeta['layers'])] pipelineMeta['layers'].append(layerCode) geometryMeta['layer_map'][layerCode] = item['name'] geometryMeta['object_size'][item['name']] = { 'points': 0, 'index': 0 } # Handle colors pipelineMeta['layer_fields'][layerCode] = [] for fieldName in item['colors']: colorCode = None if fieldName in colorToCodeMap: colorCode = colorToCodeMap[fieldName] else: colorCode = encode_codes[len(colorToCodeMap)] colorToCodeMap[fieldName] = colorCode geometryMeta['ranges'][fieldName] = [0, 1] # FIXME we don't know the range pipelineMeta['layer_fields'][layerCode].append(colorCode) pipelineMeta['fields'][colorCode] = fieldName # Handle pipeline if 'parent' in item: # Need to handle hierarchy if item['parent'] in parentNodes: # Fill children rootNode = parentNodes[item['parent']] rootNode['ids'].append(layerCode) rootNode['children'].append({ 'name': item['name'], 'ids': [layerCode] }) else: # Create root + register rootNode = { 'name': item['parent'], 'ids': [ layerCode ], 'children': [ { 'name': item['name'], 'ids': [ layerCode ] } ] } parentNodes[item['parent']] = rootNode pipelineMeta['pipeline'].append(rootNode) else: # Add item info as a new pipeline node pipelineMeta['pipeline'].append({ 'name': item['name'], 'ids': [layerCode] }) # Register metadata to be written in index.json self.dataHandler.addSection('Geometry', geometryMeta) self.dataHandler.addSection('CompositePipeline', pipelineMeta)
[docs] def writeData(self, time=0): if not self.dataHandler.can_write: return currentScene = []; for data in self.config['scene']: currentData = { 'name': data['name'], 'fields': {} } currentScene.append(currentData) if self.surfaceExtract: self.merge.Input = data['source'] else: self.merge = simple.MergeBlocks(Input=data['source'], MergePoints=0) self.surfaceExtract = simple.ExtractSurface(Input=self.merge) # Extract surface self.surfaceExtract.UpdatePipeline(time) ds = self.surfaceExtract.SMProxy.GetClientSideObject().GetOutputDataObject(0) originalDS = data['source'].SMProxy.GetClientSideObject().GetOutputDataObject(0) originalPoints = ds.GetPoints() # Points points = vtkFloatArray() nbPoints = originalPoints.GetNumberOfPoints() points.SetNumberOfComponents(3) points.SetNumberOfTuples(nbPoints) for idx in range(nbPoints): coord = originalPoints.GetPoint(idx) points.SetTuple3(idx, coord[0], coord[1], coord[2]) pBuffer = buffer(points) pMd5 = hashlib.md5(pBuffer).hexdigest() pPath = os.path.join(self.dataHandler.getBasePath(), 'points',"%s.Float32Array" % pMd5) currentData['points'] = 'points/%s.Float32Array' % pMd5 with open(pPath, 'wb') as f: f.write(pBuffer) # Polys poly = ds.GetPolys() nbCells = poly.GetNumberOfCells() cellLocation = 0 idList = vtkIdList() topo = vtkTypeUInt32Array() topo.Allocate(poly.GetData().GetNumberOfTuples()) for cellIdx in range(nbCells): poly.GetCell(cellLocation, idList) cellSize = idList.GetNumberOfIds() cellLocation += cellSize + 1 if cellSize == 3: topo.InsertNextValue(idList.GetId(0)) topo.InsertNextValue(idList.GetId(1)) topo.InsertNextValue(idList.GetId(2)) elif cellSize == 4: topo.InsertNextValue(idList.GetId(0)) topo.InsertNextValue(idList.GetId(1)) topo.InsertNextValue(idList.GetId(3)) topo.InsertNextValue(idList.GetId(1)) topo.InsertNextValue(idList.GetId(2)) topo.InsertNextValue(idList.GetId(3)) else: print ("Cell size of", cellSize, "not supported") iBuffer = buffer(topo) iMd5 = hashlib.md5(iBuffer).hexdigest() iPath = os.path.join(self.dataHandler.getBasePath(), 'index',"%s.Uint32Array" % iMd5) currentData['index'] = 'index/%s.Uint32Array' % iMd5 with open(iPath, 'wb') as f: f.write(iBuffer) # Grow object side self.objSize[data['name']]['points'] = max(self.objSize[data['name']]['points'], nbPoints) self.objSize[data['name']]['index'] = max(self.objSize[data['name']]['index'], topo.GetNumberOfTuples()) # Colors / FIXME for fieldName, fieldInfo in data['colors'].iteritems(): array = ds.GetPointData().GetArray(fieldName) tupleSize = array.GetNumberOfComponents() arraySize = array.GetNumberOfTuples() outputField = vtkFloatArray() outputField.SetNumberOfTuples(arraySize) if tupleSize == 1: for i in range(arraySize): outputField.SetValue(i, array.GetValue(i)) else: # compute magnitude tupleIdxs = range(tupleSize) for i in range(arraySize): magnitude = 0 for j in tupleIdxs: magnitude += math.pow(array.GetValue(i * tupleSize + j), 2) outputField.SetValue(i, math.sqrt(magnitude)) fBuffer = buffer(outputField) fMd5 = hashlib.md5(fBuffer).hexdigest() fPath = os.path.join(self.dataHandler.getBasePath(), 'fields',"%s_%s.Float32Array" % (fieldName, fMd5)) with open(fPath, 'wb') as f: f.write(fBuffer) currentData['fields'][fieldName] = 'fields/%s_%s.Float32Array' % (fieldName, fMd5) # Write scene with open(self.dataHandler.getDataAbsoluteFilePath('scene'), 'w') as f: f.write(json.dumps(currentScene, indent=4))
[docs] def stop(self, compress=True, clean=True): if not self.dataHandler.can_write: return DataSetBuilder.stop(self) if compress: for dirName in ['fields', 'index', 'points']: for root, dirs, files in os.walk(os.path.join(self.dataHandler.getBasePath(), dirName)): print ('Compress', root) for name in files: if 'Array' in name and '.gz' not in name: with open(os.path.join(root, name), 'rb') as f_in: with gzip.open(os.path.join(root, name + '.gz'), 'wb') as f_out: shutil.copyfileobj(f_in, f_out) os.remove(os.path.join(root, name))