def add_data_to_dataset(self, dataset, data): """Add point and cell data to the dataset.""" dm = DatasetManager(dataset=dataset) for key, val in six.iteritems(data): if val.mode == 'vertex': aux = self._reshape(val.data, self.dim) dm.add_array(aux, key, 'point') elif val.mode == 'cell': aux = self._reshape(val.data, self.dim) dm.add_array(aux, key, 'cell')
def _find_stiff_elements(self): if (self._first_time_stiff_elements): self._first_time_stiff_elements = False self._surface_grid = type(self.inputs[0].outputs[0])() self._surface_grid.copy_structure(self.inputs[0].outputs[0]) if (self._surface_grid.points.data_type == 'double'): # tvtk.DataSetSurfaceFilter produces surface points as float # so we need to convert input points from doubles to floats # if necessary float_points = array(self._surface_grid.points, 'float32') self._surface_grid.points = float_points self._dataset_manager = DatasetManager(dataset=self._surface_grid) surface_points = self._get_surface_points() self._add_stiff_elements(surface_points)
def get_mat_id(self, mat_id_name='mat_id'): """ Get material ID numbers of the underlying mesh elements. """ if self.source is not None: dm = DatasetManager(dataset=self.source.outputs[0]) mat_id = dm.cell_scalars[mat_id_name] return mat_id
def update_pipeline(self): if len(self.inputs) == 0 or len(self.inputs[0].outputs) == 0: return # Call cell_picked() when a cell is clicked. self.scene.picker.cellpicker.add_observer("EndPickEvent", self.cell_picked) self.scene.picker.pick_type = 'cell_picker' self.scene.picker.tolerance = 0.0 self.scene.picker.show_gui = False self._input_grid.deep_copy(self.inputs[0].outputs[0]) self._current_grid = self._input_grid self._dataset_manager = DatasetManager(dataset=self._input_grid) self._set_outputs([self._current_grid]) # Filter for masking. self._extract_cells_filter.set_input(self._input_grid)
def create_source(self): """ Create a VTK source from data in a SfePy-supported file. Notes ----- All data need to be set here, otherwise time stepping will not work properly - data added by user later will be thrown away on time step change. """ if self.io is None: self.read_common(self.filename) dataset = self.create_dataset() try: out = self.io.read_data(self.step) except ValueError: out = None if out is not None: self.add_data_to_dataset(dataset, out) if self.mat_id_name is not None: mat_id = self.mesh.cmesh.cell_groups if self.single_color: rm = mat_id.min(), mat_id.max() mat_id[mat_id > rm[0]] = rm[1] dm = DatasetManager(dataset=dataset) dm.add_array(mat_id, self.mat_id_name, 'cell') src = VTKDataSource(data=dataset) # src.print_traits() # debug() return src
def add_subdomains_surface(obj, position, mat_id_name='mat_id', threshold_limits=(None, None), **kwargs): dm = DatasetManager(dataset=obj.outputs[0]) mat_id = dm.cell_scalars[mat_id_name] rm = mat_id.min(), mat_id.max() active = mlab.pipeline.set_active_attribute(obj) active.cell_scalars_name = mat_id_name aa = mlab.pipeline.set_active_attribute(obj) aa.cell_scalars_name = mat_id_name threshold = mlab.pipeline.threshold(aa) threshold.threshold_filter.progress = 1.0 if threshold_limits[0] is not None: threshold.lower_threshold = threshold_limits[0] + 0.1 if threshold_limits[1] is not None: threshold.upper_threshold = threshold_limits[1] - 0.1 threshold.auto_reset_lower = False threshold.auto_reset_upper = False surface = mlab.pipeline.surface(threshold, opacity=0.3) surface.actor.actor.position = position module_manager = surface.parent lm = module_manager.scalar_lut_manager lm.lut_mode = 'Blues' if (rm[1] - rm[0]) == 1: lm.reverse_lut = True surface2 = mlab.pipeline.surface(active, opacity=0.2) surface2.actor.actor.position = position module_manager = surface2.parent module_manager.scalar_lut_manager.lut_mode = 'Blues' return surface, surface2
def add_data_to_dataset(self, dataset, data): """Add point and cell data to the dataset.""" dim = self.dim sym = (dim + 1) * dim // 2 dm = DatasetManager(dataset=dataset) for key, val in six.iteritems(data): vd = val.data ## print vd.shape if val.mode == 'vertex': if vd.shape[1] == 1: aux = vd.reshape((vd.shape[0], )) elif vd.shape[1] == 2: zz = nm.zeros((vd.shape[0], 1), dtype=vd.dtype) aux = nm.c_[vd, zz] elif vd.shape[1] == 3: aux = vd else: raise ValueError('unknown vertex data format! (%s)'\ % vd.shape) dm.add_array(aux, key, 'point') elif val.mode == 'cell': ne, aux, nr, nc = vd.shape if (nr == 1) and (nc == 1): aux = vd.reshape((ne, )) elif (nr == dim) and (nc == 1): if dim == 3: aux = vd.reshape((ne, dim)) else: zz = nm.zeros((vd.shape[0], 1), dtype=vd.dtype) aux = nm.c_[vd.squeeze(), zz] elif (((nr == sym) or (nr == (dim * dim))) and (nc == 1)) \ or ((nr == dim) and (nc == dim)): vd = vd.squeeze() if dim == 3: if nr == sym: aux = vd[:, [0, 3, 4, 3, 1, 5, 4, 5, 2]] elif nr == (dim * dim): aux = vd[:, [0, 3, 4, 6, 1, 5, 7, 8, 2]] else: aux = vd.reshape((vd.shape[0], dim * dim)) else: zz = nm.zeros((vd.shape[0], 1), dtype=vd.dtype) if nr == sym: aux = nm.c_[vd[:, [0, 2]], zz, vd[:, [2, 1]], zz, zz, zz, zz] elif nr == (dim * dim): aux = nm.c_[vd[:, [0, 2]], zz, vd[:, [3, 1]], zz, zz, zz, zz] else: aux = nm.c_[vd[:, 0, [0, 1]], zz, vd[:, 1, [0, 1]], zz, zz, zz, zz] dm.add_array(aux, key, 'cell')
class BoundaryMarkerEditor(Filter): """ Edit the boundary marker of a Triangle surface mesh. To use: select the label to assign, hover your cursor over the cell you wish to edit, and press 'p'. """ # The version of this class. Used for persistence. __version__ = 0 _current_grid = Instance(tvtk.UnstructuredGrid, allow_none=False) _input_grid = Instance(tvtk.UnstructuredGrid, args=(), allow_none=False) _extract_cells_filter = Instance(tvtk.ExtractCells, args=(), allow_none=False) _dataset_manager = Instance(DatasetManager, allow_none=False) _cell_mappings = List label_to_apply = Range(0,255) select_coplanar_cells = Bool epsilon = Range(0.0, 1.0, 0.0001) mask_labels = Bool labels_to_mask = List(label_to_apply) # Saving file output_file = File save = Button ###################################################################### # The view. ###################################################################### traits_view = \ View( Group( Item(name='label_to_apply'), Item(name='select_coplanar_cells'), Item(name='epsilon', enabled_when='select_coplanar_cells', label='Tolerance'), Item(name='mask_labels'), Group( Item(name='labels_to_mask', style='custom', editor=ListEditor(rows=3)), show_labels=False, show_border=True, label='Labels to mask', enabled_when='mask_labels==True' ), Group( Item(name='output_file'), Item(name='save', label='Save'), show_labels=False, show_border=True, label='Save changes to file (give only a basename, without the file extension)' ) ), height=500, width=600 ) ###################################################################### # `Filter` interface. ###################################################################### def update_pipeline(self): if len(self.inputs) == 0 or len(self.inputs[0].outputs) == 0: return # Call cell_picked() when a cell is clicked. self.scene.picker.cellpicker.add_observer("EndPickEvent", self.cell_picked) self.scene.picker.pick_type = 'cell_picker' self.scene.picker.tolerance = 0.0 self.scene.picker.show_gui = False self._input_grid.deep_copy(self.inputs[0].outputs[0]) self._current_grid = self._input_grid self._dataset_manager = DatasetManager(dataset=self._input_grid) self._set_outputs([self._current_grid]) # Filter for masking. self._extract_cells_filter.set_input(self._input_grid) def update_data(self): self.data_changed = True ###################################################################### # Non-public interface. ###################################################################### def cell_picked(self, object, event): cell_id = self.scene.picker.cellpicker.cell_id self.modify_cell(cell_id, self.label_to_apply) if (self.select_coplanar_cells): self.modify_neighbouring_cells(cell_id) if (self.mask_labels): self.perform_mask() self._dataset_manager.activate(self._input_grid.cell_data.scalars.name, 'cell') self._dataset_manager.update() self.pipeline_changed = True def get_all_cell_neigbours(self, cell_id, cell): neighbour_cell_ids = array([], dtype=int) for i in range(cell.number_of_edges): # Get points belonging to ith edge edge_point_ids = cell.get_edge(i).point_ids # Find neigbours which share the edge current_neighbour_cell_ids = tvtk.IdList() self._current_grid.get_cell_neighbors(cell_id, edge_point_ids, current_neighbour_cell_ids) neighbour_cell_ids = append(neighbour_cell_ids, array(current_neighbour_cell_ids)) return neighbour_cell_ids.tolist() def modify_neighbouring_cells(self, cell_id): cell = self._current_grid.get_cell(cell_id) cell_normal = [0,0,0] cell.compute_normal(cell.points[0], cell.points[1], cell.points[2], cell_normal) cells_pending = self.get_all_cell_neigbours(cell_id, cell) cells_visited = [cell_id] while (len(cells_pending) > 0): current_cell_id = cells_pending.pop() if (current_cell_id not in cells_visited): cells_visited.append(current_cell_id) current_cell = self._current_grid.get_cell(current_cell_id) current_cell_normal = [0,0,0] current_cell.compute_normal(current_cell.points[0], current_cell.points[1], current_cell.points[2], current_cell_normal) if (dot(cell_normal, current_cell_normal) > (1-self.epsilon)): self.modify_cell(current_cell_id, self.label_to_apply) cells_pending.extend(self.get_all_cell_neigbours(current_cell_id, current_cell)) def _mask_labels_changed(self): if (self.mask_labels): self.perform_mask() self._current_grid = self._extract_cells_filter.output else: self._current_grid = self._input_grid self._set_outputs([self._current_grid]) self.pipeline_changed = True def _labels_to_mask_changed(self): self.perform_mask() def _labels_to_mask_items_changed(self): self.perform_mask() def perform_mask(self): labels_array = self._input_grid.cell_data.get_array(self._input_grid.cell_data.scalars.name) in_masked = map(lambda x: x in self.labels_to_mask, labels_array) unmasked_cells_list = tvtk.IdList() cell_ids = range(self._input_grid.number_of_cells) # _cell_mappings is indexed by cell_id of the original input grid, and each value # is the new cell_id of the corresponding cell in the masked grid self._cell_mappings = map(lambda masked,cell_id: None if masked else unmasked_cells_list.insert_next_id(cell_id), in_masked, cell_ids) self._extract_cells_filter.set_cell_list(unmasked_cells_list) self._extract_cells_filter.update() self.pipeline_changed = True def modify_cell(self, cell_id, value): if (self.mask_labels): cell_id = self._cell_mappings.index(cell_id) # Adjust cell_id if masked self._input_grid.cell_data.get_array(self._input_grid.cell_data.scalars.name)[cell_id] = value def _save_fired(self): from mayavi_amcg.triangle_writer import TriangleWriter if (self.output_file): writer = TriangleWriter(self._input_grid, self.output_file) writer.write() print "#### Saved ####"
def add_data_to_dataset(self, dataset, data): """Add point and cell data to the dataset.""" dim = self.dim sym = (dim + 1) * dim / 2 dm = DatasetManager(dataset=dataset) for key, val in data.iteritems(): vd = val.data ## print vd.shape if val.mode == 'vertex': if vd.shape[1] == 1: aux = vd.reshape((vd.shape[0],)) elif vd.shape[1] == 2: zz = nm.zeros((vd.shape[0], 1), dtype=vd.dtype) aux = nm.c_[vd, zz] elif vd.shape[1] == 3: aux = vd else: raise ValueError('unknown vertex data format! (%s)'\ % vd.shape) dm.add_array(aux, key, 'point') elif val.mode == 'cell': ne, aux, nr, nc = vd.shape if (nr == 1) and (nc == 1): aux = vd.reshape((ne,)) elif (nr == dim) and (nc == 1): if dim == 3: aux = vd.reshape((ne, dim)) else: zz = nm.zeros((vd.shape[0], 1), dtype=vd.dtype); aux = nm.c_[vd.squeeze(), zz] elif (((nr == sym) or (nr == (dim * dim))) and (nc == 1)) \ or ((nr == dim) and (nc == dim)): vd = vd.squeeze() if dim == 3: if nr == sym: aux = vd[:,[0,3,4,3,1,5,4,5,2]] elif nr == (dim * dim): aux = vd[:,[0,3,4,6,1,5,7,8,2]] else: aux = vd.reshape((vd.shape[0], dim*dim)) else: zz = nm.zeros((vd.shape[0], 1), dtype=vd.dtype); if nr == sym: aux = nm.c_[vd[:,[0,2]], zz, vd[:,[2,1]], zz, zz, zz, zz] elif nr == (dim * dim): aux = nm.c_[vd[:,[0,2]], zz, vd[:,[3,1]], zz, zz, zz, zz] else: aux = nm.c_[vd[:,0,[0,1]], zz, vd[:,1,[0,1]], zz, zz, zz, zz] dm.add_array(aux, key, 'cell')
class BoundaryMarkerEditor(Filter): """ Edit the boundary marker of a Triangle surface mesh. To use: select the label to assign, hover your cursor over the cell you wish to edit, and press 'p'. """ # The version of this class. Used for persistence. __version__ = 0 _current_grid = Instance(tvtk.UnstructuredGrid, allow_none=False) _input_grid = Instance(tvtk.UnstructuredGrid, args=(), allow_none=False) _extract_cells_filter = Instance(tvtk.ExtractCells, args=(), allow_none=False) _dataset_manager = Instance(DatasetManager, allow_none=False) _cell_mappings = List label_to_apply = Range(0, 255) select_coplanar_cells = Bool epsilon = Range(0.0, 1.0, 0.0001) mask_labels = Bool labels_to_mask = List(label_to_apply) # Saving file output_file = File save = Button ###################################################################### # The view. ###################################################################### traits_view = \ View( Group( Item(name='label_to_apply'), Item(name='select_coplanar_cells'), Item(name='epsilon', enabled_when='select_coplanar_cells', label='Tolerance'), Item(name='mask_labels'), Group( Item(name='labels_to_mask', style='custom', editor=ListEditor(rows=3)), show_labels=False, show_border=True, label='Labels to mask', enabled_when='mask_labels==True' ), Group( Item(name='output_file'), Item(name='save', label='Save'), show_labels=False, show_border=True, label='Save changes to file (give only a basename, without the file extension)' ) ), height=500, width=600 ) ###################################################################### # `Filter` interface. ###################################################################### def update_pipeline(self): if len(self.inputs) == 0 or len(self.inputs[0].outputs) == 0: return # Call cell_picked() when a cell is clicked. self.scene.picker.cellpicker.add_observer("EndPickEvent", self.cell_picked) self.scene.picker.pick_type = 'cell_picker' self.scene.picker.tolerance = 0.0 self.scene.picker.show_gui = False self._input_grid.deep_copy(self.inputs[0].outputs[0]) self._current_grid = self._input_grid self._dataset_manager = DatasetManager(dataset=self._input_grid) self._set_outputs([self._current_grid]) # Filter for masking. self._extract_cells_filter.set_input(self._input_grid) def update_data(self): self.data_changed = True ###################################################################### # Non-public interface. ###################################################################### def cell_picked(self, object, event): cell_id = self.scene.picker.cellpicker.cell_id self.modify_cell(cell_id, self.label_to_apply) if (self.select_coplanar_cells): self.modify_neighbouring_cells(cell_id) if (self.mask_labels): self.perform_mask() self._dataset_manager.activate(self._input_grid.cell_data.scalars.name, 'cell') self._dataset_manager.update() self.pipeline_changed = True def get_all_cell_neigbours(self, cell_id, cell): neighbour_cell_ids = array([], dtype=int) for i in range(cell.number_of_edges): # Get points belonging to ith edge edge_point_ids = cell.get_edge(i).point_ids # Find neigbours which share the edge current_neighbour_cell_ids = tvtk.IdList() self._current_grid.get_cell_neighbors(cell_id, edge_point_ids, current_neighbour_cell_ids) neighbour_cell_ids = append(neighbour_cell_ids, array(current_neighbour_cell_ids)) return neighbour_cell_ids.tolist() def modify_neighbouring_cells(self, cell_id): cell = self._current_grid.get_cell(cell_id) cell_normal = [0, 0, 0] cell.compute_normal(cell.points[0], cell.points[1], cell.points[2], cell_normal) cells_pending = self.get_all_cell_neigbours(cell_id, cell) cells_visited = [cell_id] while (len(cells_pending) > 0): current_cell_id = cells_pending.pop() if (current_cell_id not in cells_visited): cells_visited.append(current_cell_id) current_cell = self._current_grid.get_cell(current_cell_id) current_cell_normal = [0, 0, 0] current_cell.compute_normal(current_cell.points[0], current_cell.points[1], current_cell.points[2], current_cell_normal) if (dot(cell_normal, current_cell_normal) > (1 - self.epsilon)): self.modify_cell(current_cell_id, self.label_to_apply) cells_pending.extend( self.get_all_cell_neigbours(current_cell_id, current_cell)) def _mask_labels_changed(self): if (self.mask_labels): self.perform_mask() self._current_grid = self._extract_cells_filter.output else: self._current_grid = self._input_grid self._set_outputs([self._current_grid]) self.pipeline_changed = True def _labels_to_mask_changed(self): self.perform_mask() def _labels_to_mask_items_changed(self): self.perform_mask() def perform_mask(self): labels_array = self._input_grid.cell_data.get_array( self._input_grid.cell_data.scalars.name) in_masked = map(lambda x: x in self.labels_to_mask, labels_array) unmasked_cells_list = tvtk.IdList() cell_ids = range(self._input_grid.number_of_cells) # _cell_mappings is indexed by cell_id of the original input grid, and each value # is the new cell_id of the corresponding cell in the masked grid self._cell_mappings = map( lambda masked, cell_id: None if masked else unmasked_cells_list.insert_next_id(cell_id), in_masked, cell_ids) self._extract_cells_filter.set_cell_list(unmasked_cells_list) self._extract_cells_filter.update() self.pipeline_changed = True def modify_cell(self, cell_id, value): if (self.mask_labels): cell_id = self._cell_mappings.index( cell_id) # Adjust cell_id if masked self._input_grid.cell_data.get_array( self._input_grid.cell_data.scalars.name)[cell_id] = value def _save_fired(self): from mayavi_amcg.triangle_writer import TriangleWriter if (self.output_file): writer = TriangleWriter(self._input_grid, self.output_file) writer.write() print "#### Saved ####"
class MeshDiagnostics(Filter): """ Identifies stiff elements of a solid mesh. Also includes diagnostics from vtkMeshQuality: <http://www.vtk.org/doc/release/5.0/html/a01739.html> """ # The version of this class. Used for persistence. __version__ = 0 _dataset_manager = Instance(DatasetManager, allow_none=False) _surface_grid = Instance(tvtk.PointSet, allow_none=False) stiff_elements = Bool _first_time_stiff_elements = Bool(True) _mesh_quality_filter = Instance(tvtk.MeshQuality, args=(), allow_none=False) tet_quality_measure = Enum('Edge ratio', 'Aspect ratio', 'Radius ratio', 'Min angle', 'Frobenius norm', 'Volume') triangle_quality_measure = Enum('Edge ratio', 'Aspect ratio', 'Radius ratio', 'Min angle', 'Frobenius norm') quad_quality_measure = Enum('Edge ratio', 'Aspect ratio', 'Radius ratio', 'Min angle', 'Med Frobenius norm', 'Max Frobenius norm') hex_quality_measure = Enum('Edge ratio') tet_stats = triangle_stats = quad_stats = hex_stats = Tuple(Float,Float,Float,Float,Float) ###################################################################### # The view. ###################################################################### stats_editor = TupleEditor(labels=['Minimum','Average','Maximum','Variance','Number of cells']) traits_view = \ View( Item(name='stiff_elements'), Group( Group( Item(name='tet_quality_measure'), Item(name='tet_stats', style='custom', editor=stats_editor), label='Tetrahedron quality measure', show_labels=False, show_border=True, ), Group( Item(name='triangle_quality_measure'), Item(name='triangle_stats', style='custom', editor=stats_editor), label='Triangle quality measure', show_labels=False, show_border=True, ), Group( Item(name='quad_quality_measure'), Item(name='quad_stats', style='custom', editor=stats_editor), label='Quadrilateral quality measure', show_labels=False, show_border=True, ), Group( Item(name='hex_quality_measure'), Item(name='hex_stats', style='custom', editor=stats_editor), label='Hexahedron quality measure', show_labels=False, show_border=True, ), enabled_when='stiff_elements==False', show_border=False ), width=300 ) """ Hexahedron quality measure - EdgeRatio Quadrilateral quality measure - EdgeRatio - AspectRatio - RadiusRatio - MinAngle - MedFrobeniusNorm - MaxFrobeniusNorm Tetrahedron quality measure - EdgeRatio - AspectRatio - RadiusRatio - MinAngle - FrobeniusNorm - Volume (compatibility mode on/off) Triangle quality measure - EdgeRatio - AspectRatio - RadiusRatio - MinAngle - FrobeniusNorm """ ###################################################################### # `Filter` interface. ###################################################################### def update_pipeline(self): if len(self.inputs) == 0 or len(self.inputs[0].outputs) == 0: return self._mesh_quality_filter.set_input(self.inputs[0].outputs[0]) for type in ['tet','triangle','quad','hex']: self._change_quality_measure(type, 'Edge ratio') self._mesh_quality_filter.update() self._set_outputs([self._mesh_quality_filter.output]) def update_data(self): self.data_changed = True ###################################################################### # Non-public interface. ###################################################################### def _stiff_elements_changed(self, value): if (value): self._find_stiff_elements() self._set_outputs([self._surface_grid]) else: self._set_outputs([self._mesh_quality_filter.output]) def _tet_quality_measure_changed(self, value): self._change_quality_measure('tet', value) def _change_quality_measure(self, cell_type, quality_measure): if (quality_measure == 'Volume'): self._mesh_quality_filter.compatibility_mode = True self._mesh_quality_filter.volume = True else: self._mesh_quality_filter.compatibility_mode = False self._mesh_quality_filter.volume = False quality_measure_names = {'Edge ratio':'edge_ratio', 'Aspect ratio':'aspect_ratio', 'Radius ratio':'radius_ratio', 'Min angle':'min_angle', 'Frobenius norm':'frobenius_norm', 'Max Frobenius norm':'max_frobenius_norm', 'Med Frobenius norm':'med_frobenius_norm'} setattr(self._mesh_quality_filter, '%s_quality_measure' %cell_type, quality_measure_names.get(quality_measure)) self._mesh_quality_filter.update() self._set_outputs([self._mesh_quality_filter.output]) cell_type_fullnames = {'tet':'Tetrahedron', 'triangle':'Triangle', 'quad':'Quadrilateral', 'hex':'Hexahedron'} stats = self._mesh_quality_filter.output.field_data.get_array('Mesh %s Quality' %cell_type_fullnames.get(cell_type))[0] setattr(self, '%s_stats' %cell_type, stats) def _find_stiff_elements(self): if (self._first_time_stiff_elements): self._first_time_stiff_elements = False self._surface_grid = type(self.inputs[0].outputs[0])() self._surface_grid.copy_structure(self.inputs[0].outputs[0]) if (self._surface_grid.points.data_type == 'double'): # tvtk.DataSetSurfaceFilter produces surface points as float # so we need to convert input points from doubles to floats # if necessary float_points = array(self._surface_grid.points, 'float32') self._surface_grid.points = float_points self._dataset_manager = DatasetManager(dataset=self._surface_grid) surface_points = self._get_surface_points() self._add_stiff_elements(surface_points) def _get_surface_points(self): surface_filter = tvtk.DataSetSurfaceFilter() surface_filter.set_input(self._surface_grid) surface_filter.update() return surface_filter.output.points def _add_stiff_elements(self, surface_points): stiff_elements = [] surface_points = Set(surface_points) for i in range(self._surface_grid.number_of_cells): cell = self._surface_grid.get_cell(i) points = Set(cell.points) val = int(points.issubset(surface_points)) stiff_elements.append(val) array_name = 'Stiff Elements' self._dataset_manager.add_array(array(stiff_elements), array_name, 'cell') self._dataset_manager.activate(array_name, 'cell')
class MeshDiagnostics(Filter): """ Identifies stiff elements of a solid mesh. Also includes diagnostics from vtkMeshQuality: <http://www.vtk.org/doc/release/5.0/html/a01739.html> """ # The version of this class. Used for persistence. __version__ = 0 _dataset_manager = Instance(DatasetManager, allow_none=False) _surface_grid = Instance(tvtk.PointSet, allow_none=False) stiff_elements = Bool _first_time_stiff_elements = Bool(True) _mesh_quality_filter = Instance(tvtk.MeshQuality, args=(), allow_none=False) tet_quality_measure = Enum('Edge ratio', 'Aspect ratio', 'Radius ratio', 'Min angle', 'Frobenius norm', 'Volume') triangle_quality_measure = Enum('Edge ratio', 'Aspect ratio', 'Radius ratio', 'Min angle', 'Frobenius norm') quad_quality_measure = Enum('Edge ratio', 'Aspect ratio', 'Radius ratio', 'Min angle', 'Med Frobenius norm', 'Max Frobenius norm') hex_quality_measure = Enum('Edge ratio') tet_stats = triangle_stats = quad_stats = hex_stats = Tuple( Float, Float, Float, Float, Float) ###################################################################### # The view. ###################################################################### stats_editor = TupleEditor(labels=[ 'Minimum', 'Average', 'Maximum', 'Variance', 'Number of cells' ]) traits_view = \ View( Item(name='stiff_elements'), Group( Group( Item(name='tet_quality_measure'), Item(name='tet_stats', style='custom', editor=stats_editor), label='Tetrahedron quality measure', show_labels=False, show_border=True, ), Group( Item(name='triangle_quality_measure'), Item(name='triangle_stats', style='custom', editor=stats_editor), label='Triangle quality measure', show_labels=False, show_border=True, ), Group( Item(name='quad_quality_measure'), Item(name='quad_stats', style='custom', editor=stats_editor), label='Quadrilateral quality measure', show_labels=False, show_border=True, ), Group( Item(name='hex_quality_measure'), Item(name='hex_stats', style='custom', editor=stats_editor), label='Hexahedron quality measure', show_labels=False, show_border=True, ), enabled_when='stiff_elements==False', show_border=False ), width=300 ) """ Hexahedron quality measure - EdgeRatio Quadrilateral quality measure - EdgeRatio - AspectRatio - RadiusRatio - MinAngle - MedFrobeniusNorm - MaxFrobeniusNorm Tetrahedron quality measure - EdgeRatio - AspectRatio - RadiusRatio - MinAngle - FrobeniusNorm - Volume (compatibility mode on/off) Triangle quality measure - EdgeRatio - AspectRatio - RadiusRatio - MinAngle - FrobeniusNorm """ ###################################################################### # `Filter` interface. ###################################################################### def update_pipeline(self): if len(self.inputs) == 0 or len(self.inputs[0].outputs) == 0: return self._mesh_quality_filter.set_input(self.inputs[0].outputs[0]) for type in ['tet', 'triangle', 'quad', 'hex']: self._change_quality_measure(type, 'Edge ratio') self._mesh_quality_filter.update() self._set_outputs([self._mesh_quality_filter.output]) def update_data(self): self.data_changed = True ###################################################################### # Non-public interface. ###################################################################### def _stiff_elements_changed(self, value): if (value): self._find_stiff_elements() self._set_outputs([self._surface_grid]) else: self._set_outputs([self._mesh_quality_filter.output]) def _tet_quality_measure_changed(self, value): self._change_quality_measure('tet', value) def _change_quality_measure(self, cell_type, quality_measure): if (quality_measure == 'Volume'): self._mesh_quality_filter.compatibility_mode = True self._mesh_quality_filter.volume = True else: self._mesh_quality_filter.compatibility_mode = False self._mesh_quality_filter.volume = False quality_measure_names = { 'Edge ratio': 'edge_ratio', 'Aspect ratio': 'aspect_ratio', 'Radius ratio': 'radius_ratio', 'Min angle': 'min_angle', 'Frobenius norm': 'frobenius_norm', 'Max Frobenius norm': 'max_frobenius_norm', 'Med Frobenius norm': 'med_frobenius_norm' } setattr(self._mesh_quality_filter, '%s_quality_measure' % cell_type, quality_measure_names.get(quality_measure)) self._mesh_quality_filter.update() self._set_outputs([self._mesh_quality_filter.output]) cell_type_fullnames = { 'tet': 'Tetrahedron', 'triangle': 'Triangle', 'quad': 'Quadrilateral', 'hex': 'Hexahedron' } stats = self._mesh_quality_filter.output.field_data.get_array( 'Mesh %s Quality' % cell_type_fullnames.get(cell_type))[0] setattr(self, '%s_stats' % cell_type, stats) def _find_stiff_elements(self): if (self._first_time_stiff_elements): self._first_time_stiff_elements = False self._surface_grid = type(self.inputs[0].outputs[0])() self._surface_grid.copy_structure(self.inputs[0].outputs[0]) if (self._surface_grid.points.data_type == 'double'): # tvtk.DataSetSurfaceFilter produces surface points as float # so we need to convert input points from doubles to floats # if necessary float_points = array(self._surface_grid.points, 'float32') self._surface_grid.points = float_points self._dataset_manager = DatasetManager(dataset=self._surface_grid) surface_points = self._get_surface_points() self._add_stiff_elements(surface_points) def _get_surface_points(self): surface_filter = tvtk.DataSetSurfaceFilter() surface_filter.set_input(self._surface_grid) surface_filter.update() return surface_filter.output.points def _add_stiff_elements(self, surface_points): stiff_elements = [] surface_points = Set(surface_points) for i in range(self._surface_grid.number_of_cells): cell = self._surface_grid.get_cell(i) points = Set(cell.points) val = int(points.issubset(surface_points)) stiff_elements.append(val) array_name = 'Stiff Elements' self._dataset_manager.add_array(array(stiff_elements), array_name, 'cell') self._dataset_manager.activate(array_name, 'cell')
def setUp(self): self.data = make_data() self.dm = DatasetManager(dataset=self.data) return