def __getitem__(self, index: Union[int, str]) -> Optional['MultiBlock']: """Get a block by its index or name. If the name is non-unique then returns the first occurrence. """ if isinstance(index, slice): stop = index.stop if index.stop >= 0 else self.n_blocks + index.stop + 1 step = index.step if isinstance(index.step, int) else 1 multi = MultiBlock() for i in range(index.start, stop, step): multi[-1, self.get_block_name(i)] = self[i] return multi elif isinstance(index, (list, tuple, np.ndarray)): multi = MultiBlock() for i in index: name = i if isinstance(i, str) else self.get_block_name(i) multi[-1, name] = self[i] # type: ignore return multi elif isinstance(index, str): index = self.get_index_by_name(index) ############################ if index < 0: index = self.n_blocks + index if index < 0 or index >= self.n_blocks: raise IndexError(f'index ({index}) out of range for this dataset.') data = self.GetBlock(index) if data is None: return data if data is not None and not is_pyvista_dataset(data): data = wrap(data) if data not in self.refs: self.refs.append(data) return data
def extract_geometry(self): """Combines the geomertry of all blocks into a single ``PolyData`` object. Place this filter at the end of a pipeline before a polydata consumer such as a polydata mapper to extract geometry from all blocks and append them to one polydata object. """ gf = vtk.vtkCompositeDataGeometryFilter() gf.SetInputData(self) gf.Update() return wrap(gf.GetOutputDataObject(0))
def add_bounding_box(self, color=None, corner_factor=0.5, line_width=None, opacity=1.0, render_lines_as_tubes=False, lighting=None, reset_camera=None): """ Adds an unlabeled and unticked box at the boundaries of plot. Useful for when wanting to plot outer grids while still retaining all edges of the boundary. Parameters ---------- corner_factor : float, optional If ``all_edges``, this is the factor along each axis to draw the default box. Dafuault is 0.5 to show the full box. """ if lighting is None: lighting = rcParams['lighting'] self.remove_bounding_box() if color is None: color = rcParams['font']['color'] rgb_color = parse_color(color) self._bounding_box = vtk.vtkOutlineCornerSource() self._bounding_box.SetBounds(self.bounds) self._bounding_box.SetCornerFactor(corner_factor) self._bounding_box.Update() self._box_object = wrap(self._bounding_box.GetOutput()) name = 'BoundingBox({})'.format(hex(id(self._box_object))) mapper = vtk.vtkDataSetMapper() mapper.SetInputData(self._box_object) self.bounding_box_actor, prop = self.add_actor( mapper, reset_camera=reset_camera, name=name) prop.SetColor(rgb_color) prop.SetOpacity(opacity) if render_lines_as_tubes: prop.SetRenderLinesAsTubes(render_lines_as_tubes) # lighting display style if lighting is False: prop.LightingOff() # set line thickness if line_width: prop.SetLineWidth(line_width) prop.SetRepresentationToSurface() return self.bounding_box_actor
def __init__(self, dataset, plotter=None, scalars=None, preference='cell', show_bounds=False, reset_camera=True, outline=None, display_params=None, default_params=None, continuous_update=False, clean=True, **kwargs): if not scooby.in_ipython() or not IPY_AVAILABLE: logging.warning('Interactive plotting tools require IPython and the ``ipywidgets`` package.') # Check the input dataset to make sure its compatible if not is_pyvista_obj(dataset): dataset = wrap(dataset) if not is_pyvista_obj(dataset): raise RuntimeError('Object not supported for plotting in pyvista.') # Make the input/output of this tool available self.input_dataset = dataset self.output_dataset = None self.continuous_update = continuous_update if plotter is None: plotter = BackgroundPlotter(**kwargs) plotter.setWindowTitle(type(self).__name__) self._plotter = plotter self._loc = plotter.index_to_loc(plotter._active_renderer_index) # This is the actor that will be removed and re-added to the plotter self._data_to_update = None self._last_scalars = None # Intialize plotting parameters self.valid_range = self.input_dataset.get_data_range(arr=scalars, preference=preference) if display_params is None: display_params = {} if default_params is None: default_params = {} display_params.setdefault('rng', self.valid_range) display_params.setdefault('scalars', scalars) display_params.setdefault('preference', preference) display_params.setdefault('show_edges', False) # Make sure to remove the reset_camera parameter if present display_params.pop('reset_camera', None) # Make a name display_params.setdefault('name', '{}({})'.format(type(self).__name__, str(hex(id(self))))) self.display_params = display_params self.clean = clean # Set the tool status self._need_to_update = True # Add some intital plotting stuff to the scene self._initialize(show_bounds, reset_camera, outline) # Run the tool self.tool(default_params=default_params, **kwargs)
def read(self): """Read data in file. Returns ------- pyvista.DataSet PyVista Dataset. """ self._update() data = wrap(self.reader.GetOutputDataObject(0)) data._post_file_load_processing() return data
def combine(self, merge_points=False): """Appends all blocks into a single unstructured grid. Parameters ---------- merge_points : bool, optional Merge coincidental points. """ alg = vtk.vtkAppendFilter() for block in self: alg.AddInputData(block) alg.SetMergePoints(merge_points) alg.Update() return wrap(alg.GetOutputDataObject(0))
def __getitem__(self, index): """Get a block by its index or name (if the name is non-unique then returns the first occurence)""" if isinstance(index, str): index = self.get_index_by_name(index) if index < 0: index = self.n_blocks + index if index < 0 or index >= self.n_blocks: raise IndexError('index ({}) out of range for this dataset.'.format(index)) data = self.GetBlock(index) if data is None: return data if data is not None and not is_pyvista_obj(data): data = wrap(data) if data not in self.refs: self.refs.append(data) return data
def _get_output(algorithm, iport=0, iconnection=0, oport=0, active_scalars=None, active_scalars_field='point'): """Get the algorithm's output and copy input's pyvista meta info.""" ido = algorithm.GetInputDataObject(iport, iconnection) data = wrap(algorithm.GetOutputDataObject(oport)) if not isinstance(data, pyvista.MultiBlock): data.copy_meta_from(ido) if not data.field_data and ido.field_data: data.field_data.update(ido.field_data) if active_scalars is not None: data.set_active_scalars(active_scalars, preference=active_scalars_field) return data
def __setitem__(self, index: Union[Tuple[int, Optional[str]], int, str], data: DataSet): """Set a block with a VTK data object. To set the name simultaneously, pass a string name as the 2nd index. Example ------- >>> import pyvista >>> multi = pyvista.MultiBlock() >>> multi[0] = pyvista.PolyData() >>> multi[1, 'foo'] = pyvista.UnstructuredGrid() >>> multi['bar'] = pyvista.PolyData() >>> multi.n_blocks 3 """ i: int = 0 name: Optional[str] = None if isinstance( index, (np.ndarray, collections.abc.Sequence)) and not isinstance(index, str): i, name = index[0], index[1] elif isinstance(index, str): try: i = self.get_index_by_name(index) except KeyError: i = -1 name = index else: i, name = cast(int, index), None if data is not None and not is_pyvista_dataset(data): data = wrap(data) if i == -1: self.append(data) i = self.n_blocks - 1 else: self.SetBlock(i, data) if name is None: name = f'Block-{i:02}' self.set_block_name(i, name) # Note that this calls self.Modified() if data not in self.refs: self.refs.append(data)
def __setitem__(self, index, data): """Set a block with a VTK data object. To set the name simultaneously, pass a string name as the 2nd index. Example ------- >>> import pyvista >>> multi = pyvista.MultiBlock() >>> multi[0] = pyvista.PolyData() >>> multi[1, 'foo'] = pyvista.UnstructuredGrid() >>> multi['bar'] = pyvista.PolyData() >>> multi.n_blocks 3 """ if isinstance(index, collections.Iterable) and not isinstance(index, str): i, name = index[0], index[1] elif isinstance(index, str): try: i = self.get_index_by_name(index) except KeyError: i = -1 name = index else: i, name = index, None if data is not None and not is_pyvista_dataset(data): data = wrap(data) if i == -1: self.append(data) i = self.n_blocks - 1 else: self.SetBlock(i, data) if name is None: name = 'Block-{0:02}'.format(i) self.set_block_name(i, name) # Note that this calls self.Modified() if data not in self.refs: self.refs.append(data)
def add_bounding_box(self, color="grey", corner_factor=0.5, line_width=None, opacity=1.0, render_lines_as_tubes=False, lighting=None, reset_camera=None, outline=True, culling='front', loc=None): """Add an unlabeled and unticked box at the boundaries of plot. Useful for when wanting to plot outer grids while still retaining all edges of the boundary. Parameters ---------- corner_factor : float, optional If ``all_edges``, this is the factor along each axis to draw the default box. Dafuault is 0.5 to show the full box. corner_factor : float, optional This is the factor along each axis to draw the default box. Dafuault is 0.5 to show the full box. line_width : float, optional Thickness of lines. opacity : float, optional Opacity of mesh. Should be between 0 and 1. Default 1.0 outline : bool Default is ``True``. when False, a box with faces is shown with the specified culling culling : str, optional Does not render faces that are culled. Options are ``'front'`` or ``'back'``. Default is ``'front'`` for bounding box. loc : int, tuple, or list Index of the renderer to add the actor to. For example, ``loc=2`` or ``loc=(1, 1)``. If None, selects the last active Renderer. """ if lighting is None: lighting = rcParams['lighting'] self.remove_bounding_box() if color is None: color = rcParams['outline_color'] rgb_color = parse_color(color) if outline: self._bounding_box = vtk.vtkOutlineCornerSource() self._bounding_box.SetCornerFactor(corner_factor) else: self._bounding_box = vtk.vtkCubeSource() self._bounding_box.SetBounds(self.bounds) self._bounding_box.Update() self._box_object = wrap(self._bounding_box.GetOutput()) name = 'BoundingBox({})'.format(hex(id(self._box_object))) mapper = vtk.vtkDataSetMapper() mapper.SetInputData(self._box_object) self.bounding_box_actor, prop = self.add_actor( mapper, reset_camera=reset_camera, name=name, culling=culling, pickable=False) prop.SetColor(rgb_color) prop.SetOpacity(opacity) if render_lines_as_tubes: prop.SetRenderLinesAsTubes(render_lines_as_tubes) # lighting display style if lighting is False: prop.LightingOff() # set line thickness if line_width: prop.SetLineWidth(line_width) prop.SetRepresentationToSurface() return self.bounding_box_actor