def test_set_polydata_tangents(): my_polydata = PolyData() poly_point_data = my_polydata.GetPointData() npt.assert_equal(poly_point_data.GetNumberOfArrays(), 0) array = np.array([[0, 0, 0], [1, 1, 1]]) set_polydata_tangents(my_polydata, array) npt.assert_equal(poly_point_data.GetNumberOfArrays(), 1) npt.assert_equal(poly_point_data.HasArray('Tangents'), True)
def test_get_polydata_tangents(): my_polydata = PolyData() tangents = get_polydata_tangents(my_polydata) npt.assert_equal(tangents, None) array = np.array([[0, 0, 0], [1, 1, 1]]) my_polydata.GetPointData().SetTangents( numpy_support.numpy_to_vtk(array, deep=True, array_type=VTK_FLOAT)) tangents = get_polydata_tangents(my_polydata) npt.assert_array_equal(tangents, array)
def repeat_sources(centers, colors, active_scalars=1., directions=None, source=None, vertices=None, faces=None, orientation=None): """Transform a vtksource to glyph.""" if source is None and faces is None: raise IOError("A source or faces should be defined") if np.array(colors).ndim == 1: colors = np.tile(colors, (len(centers), 1)) pts = numpy_to_vtk_points(np.ascontiguousarray(centers)) cols = numpy_to_vtk_colors(255 * np.ascontiguousarray(colors)) cols.SetName('colors') if isinstance(active_scalars, (float, int)): active_scalars = np.tile(active_scalars, (len(centers), 1)) if isinstance(active_scalars, np.ndarray): ascalars = numpy_support.numpy_to_vtk(np.asarray(active_scalars), deep=True, array_type=VTK_DOUBLE) ascalars.SetName('active_scalars') if directions is not None: directions_fa = numpy_support.numpy_to_vtk(np.asarray(directions), deep=True, array_type=VTK_DOUBLE) directions_fa.SetName('directions') polydata_centers = PolyData() polydata_geom = PolyData() if faces is not None: set_polydata_vertices(polydata_geom, vertices) set_polydata_triangles(polydata_geom, faces) polydata_centers.SetPoints(pts) polydata_centers.GetPointData().AddArray(cols) if directions is not None: polydata_centers.GetPointData().AddArray(directions_fa) polydata_centers.GetPointData().SetActiveVectors('directions') if isinstance(active_scalars, np.ndarray): polydata_centers.GetPointData().AddArray(ascalars) polydata_centers.GetPointData().SetActiveScalars('active_scalars') glyph = Glyph3D() if faces is None: if orientation is not None: transform = Transform() transform.SetMatrix(numpy_to_vtk_matrix(orientation)) rtrans = TransformPolyDataFilter() rtrans.SetInputConnection(source.GetOutputPort()) rtrans.SetTransform(transform) source = rtrans glyph.SetSourceConnection(source.GetOutputPort()) else: glyph.SetSourceData(polydata_geom) glyph.SetInputData(polydata_centers) glyph.SetOrient(True) glyph.SetScaleModeToScaleByScalar() glyph.SetVectorModeToUseVector() glyph.Update() mapper = PolyDataMapper() mapper.SetInputData(glyph.GetOutput()) mapper.SetScalarModeToUsePointFieldData() mapper.SelectColorArray('colors') actor = Actor() actor.SetMapper(mapper) return actor
def lines_to_vtk_polydata(lines, colors=None): """Create a vtkPolyData with lines and colors. Parameters ---------- lines : list list of N curves represented as 2D ndarrays colors : array (N, 3), list of arrays, tuple (3,), array (K,) If None or False, a standard orientation colormap is used for every line. If one tuple of color is used. Then all streamlines will have the same colour. If an array (N, 3) is given, where N is equal to the number of lines. Then every line is coloured with a different RGB color. If a list of RGB arrays is given then every point of every line takes a different color. If an array (K, 3) is given, where K is the number of points of all lines then every point is colored with a different RGB color. If an array (K,) is given, where K is the number of points of all lines then these are considered as the values to be used by the colormap. If an array (L,) is given, where L is the number of streamlines then these are considered as the values to be used by the colormap per streamline. If an array (X, Y, Z) or (X, Y, Z, 3) is given then the values for the colormap are interpolated automatically using trilinear interpolation. Returns ------- poly_data : vtkPolyData color_is_scalar : bool, true if the color array is a single scalar Scalar array could be used with a colormap lut None if no color was used """ # Get the 3d points_array points_array = np.vstack(lines) # Set Points to vtk array format vtk_points = numpy_to_vtk_points(points_array) # Set Lines to vtk array format vtk_cell_array = numpy_to_vtk_cells(lines) # Create the poly_data poly_data = PolyData() poly_data.SetPoints(vtk_points) poly_data.SetLines(vtk_cell_array) # Get colors_array (reformat to have colors for each points) # - if/else tested and work in normal simple case nb_points = len(points_array) nb_lines = len(lines) lines_range = range(nb_lines) points_per_line = [len(lines[i]) for i in lines_range] points_per_line = np.array(points_per_line, np.intp) color_is_scalar = False if colors is None or colors is False: # set automatic rgb colors cols_arr = line_colors(lines) colors_mapper = np.repeat(lines_range, points_per_line, axis=0) vtk_colors = numpy_to_vtk_colors(255 * cols_arr[colors_mapper]) else: cols_arr = np.asarray(colors) if cols_arr.dtype == object: # colors is a list of colors vtk_colors = numpy_to_vtk_colors(255 * np.vstack(colors)) else: if len(cols_arr) == nb_points: if cols_arr.ndim == 1: # values for every point vtk_colors = numpy_support.numpy_to_vtk(cols_arr, deep=True) color_is_scalar = True elif cols_arr.ndim == 2: # map color to each point vtk_colors = numpy_to_vtk_colors(255 * cols_arr) elif cols_arr.ndim == 1: if len(cols_arr) == nb_lines: # values for every streamline cols_arrx = [] for (i, value) in enumerate(colors): cols_arrx += lines[i].shape[0] * [value] cols_arrx = np.array(cols_arrx) vtk_colors = numpy_support.numpy_to_vtk(cols_arrx, deep=True) color_is_scalar = True else: # the same colors for all points vtk_colors = numpy_to_vtk_colors( np.tile(255 * cols_arr, (nb_points, 1))) elif cols_arr.ndim == 2: # map color to each line colors_mapper = np.repeat(lines_range, points_per_line, axis=0) vtk_colors = numpy_to_vtk_colors(255 * cols_arr[colors_mapper]) else: # colormap # get colors for each vertex cols_arr = map_coordinates_3d_4d(cols_arr, points_array) vtk_colors = numpy_support.numpy_to_vtk(cols_arr, deep=True) color_is_scalar = True vtk_colors.SetName("colors") poly_data.GetPointData().SetScalars(vtk_colors) return poly_data, color_is_scalar
class ImageContainer2D(UI): """A 2D container to hold an image. Currently Supports: - png and jpg/jpeg images Attributes ---------- size: (float, float) Image size (width, height) in pixels. img : ImageData The image loaded from the specified path. """ def __init__(self, img_path, position=(0, 0), size=(100, 100)): """Init class instance. Parameters ---------- img_path : string URL or local path of the image position : (float, float), optional Absolute coordinates (x, y) of the lower-left corner of the image. size : (int, int), optional Width and height in pixels of the image. """ super(ImageContainer2D, self).__init__(position) self.img = load_image(img_path, as_vtktype=True) self.set_img(self.img) self.resize(size) def _get_size(self): lower_left_corner = self.texture_points.GetPoint(0) upper_right_corner = self.texture_points.GetPoint(2) size = np.array(upper_right_corner) - np.array(lower_left_corner) return abs(size[:2]) def _setup(self): """Setup this UI Component. Return an image as a 2D actor with a specific position. Returns ------- :class:`vtkTexturedActor2D` """ self.texture_polydata = PolyData() self.texture_points = Points() self.texture_points.SetNumberOfPoints(4) polys = CellArray() polys.InsertNextCell(4) polys.InsertCellPoint(0) polys.InsertCellPoint(1) polys.InsertCellPoint(2) polys.InsertCellPoint(3) self.texture_polydata.SetPolys(polys) tc = FloatArray() tc.SetNumberOfComponents(2) tc.SetNumberOfTuples(4) tc.InsertComponent(0, 0, 0.0) tc.InsertComponent(0, 1, 0.0) tc.InsertComponent(1, 0, 1.0) tc.InsertComponent(1, 1, 0.0) tc.InsertComponent(2, 0, 1.0) tc.InsertComponent(2, 1, 1.0) tc.InsertComponent(3, 0, 0.0) tc.InsertComponent(3, 1, 1.0) self.texture_polydata.GetPointData().SetTCoords(tc) texture_mapper = PolyDataMapper2D() texture_mapper = set_input(texture_mapper, self.texture_polydata) image = TexturedActor2D() image.SetMapper(texture_mapper) self.texture = Texture() image.SetTexture(self.texture) image_property = Property2D() image_property.SetOpacity(1.0) image.SetProperty(image_property) self.actor = image # Add default events listener to the VTK actor. self.handle_events(self.actor) def _get_actors(self): """Return the actors that compose this UI component.""" return [self.actor] def _add_to_scene(self, scene): """Add all subcomponents or VTK props that compose this UI component. Parameters ---------- scene : scene """ scene.add(self.actor) def resize(self, size): """Resize the image. Parameters ---------- size : (float, float) image size (width, height) in pixels. """ # Update actor. self.texture_points.SetPoint(0, 0, 0, 0.0) self.texture_points.SetPoint(1, size[0], 0, 0.0) self.texture_points.SetPoint(2, size[0], size[1], 0.0) self.texture_points.SetPoint(3, 0, size[1], 0.0) self.texture_polydata.SetPoints(self.texture_points) def _set_position(self, coords): """Set the lower-left corner position of this UI component. Parameters ---------- coords: (float, float) Absolute pixel coordinates (x, y). """ self.actor.SetPosition(*coords) def scale(self, factor): """Scale the image. Parameters ---------- factor : (float, float) Scaling factor (width, height) in pixels. """ self.resize(self.size * factor) def set_img(self, img): """Modify the image used by the vtkTexturedActor2D. Parameters ---------- img : imageData """ self.texture = set_input(self.texture, img)
class Button2D(UI): """A 2D overlay button and is of type vtkTexturedActor2D. Currently supports:: - Multiple icons. - Switching between icons. """ def __init__(self, icon_fnames, position=(0, 0), size=(30, 30)): """Init class instance. Parameters ---------- icon_fnames : List(string, string) ((iconname, filename), (iconname, filename), ....) position : (float, float), optional Absolute coordinates (x, y) of the lower-left corner of the button. size : (int, int), optional Width and height in pixels of the button. """ super(Button2D, self).__init__(position) self.icon_extents = dict() self.icons = self._build_icons(icon_fnames) self.icon_names = [icon[0] for icon in self.icons] self.current_icon_id = 0 self.current_icon_name = self.icon_names[self.current_icon_id] self.set_icon(self.icons[self.current_icon_id][1]) self.resize(size) def _get_size(self): lower_left_corner = self.texture_points.GetPoint(0) upper_right_corner = self.texture_points.GetPoint(2) size = np.array(upper_right_corner) - np.array(lower_left_corner) return abs(size[:2]) def _build_icons(self, icon_fnames): """Convert file names to ImageData. A pre-processing step to prevent re-read of file names during every state change. Parameters ---------- icon_fnames : List(string, string) ((iconname, filename), (iconname, filename), ....) Returns ------- icons : List A list of corresponding ImageData. """ icons = [] for icon_name, icon_fname in icon_fnames: icons.append((icon_name, load_image(icon_fname, as_vtktype=True))) return icons def _setup(self): """Set up this UI component. Creating the button actor used internally. """ # This is highly inspired by # https://github.com/Kitware/VTK/blob/c3ec2495b183e3327820e927af7f8f90d34c3474/Interaction/Widgets/vtkBalloonRepresentation.cxx#L47 self.texture_polydata = PolyData() self.texture_points = Points() self.texture_points.SetNumberOfPoints(4) polys = CellArray() polys.InsertNextCell(4) polys.InsertCellPoint(0) polys.InsertCellPoint(1) polys.InsertCellPoint(2) polys.InsertCellPoint(3) self.texture_polydata.SetPolys(polys) tc = FloatArray() tc.SetNumberOfComponents(2) tc.SetNumberOfTuples(4) tc.InsertComponent(0, 0, 0.0) tc.InsertComponent(0, 1, 0.0) tc.InsertComponent(1, 0, 1.0) tc.InsertComponent(1, 1, 0.0) tc.InsertComponent(2, 0, 1.0) tc.InsertComponent(2, 1, 1.0) tc.InsertComponent(3, 0, 0.0) tc.InsertComponent(3, 1, 1.0) self.texture_polydata.GetPointData().SetTCoords(tc) texture_mapper = PolyDataMapper2D() texture_mapper = set_input(texture_mapper, self.texture_polydata) button = TexturedActor2D() button.SetMapper(texture_mapper) self.texture = Texture() button.SetTexture(self.texture) button_property = Property2D() button_property.SetOpacity(1.0) button.SetProperty(button_property) self.actor = button # Add default events listener to the VTK actor. self.handle_events(self.actor) def _get_actors(self): """Get the actors composing this UI component.""" return [self.actor] def _add_to_scene(self, scene): """Add all subcomponents or VTK props that compose this UI component. Parameters ---------- scene : scene """ scene.add(self.actor) def resize(self, size): """Resize the button. Parameters ---------- size : (float, float) Button size (width, height) in pixels. """ # Update actor. self.texture_points.SetPoint(0, 0, 0, 0.0) self.texture_points.SetPoint(1, size[0], 0, 0.0) self.texture_points.SetPoint(2, size[0], size[1], 0.0) self.texture_points.SetPoint(3, 0, size[1], 0.0) self.texture_polydata.SetPoints(self.texture_points) def _set_position(self, coords): """Set the lower-left corner position of this UI component. Parameters ---------- coords: (float, float) Absolute pixel coordinates (x, y). """ self.actor.SetPosition(*coords) @property def color(self): """Get the button's color.""" color = self.actor.GetProperty().GetColor() return np.asarray(color) @color.setter def color(self, color): """Set the button's color. Parameters ---------- color : (float, float, float) RGB. Must take values in [0, 1]. """ self.actor.GetProperty().SetColor(*color) def scale(self, factor): """Scale the button. Parameters ---------- factor : (float, float) Scaling factor (width, height) in pixels. """ self.resize(self.size * factor) def set_icon_by_name(self, icon_name): """Set the button icon using its name. Parameters ---------- icon_name : str """ icon_id = self.icon_names.index(icon_name) self.set_icon(self.icons[icon_id][1]) def set_icon(self, icon): """Modify the icon used by the vtkTexturedActor2D. Parameters ---------- icon : imageData """ self.texture = set_input(self.texture, icon) def next_icon_id(self): """Set the next icon ID while cycling through icons.""" self.current_icon_id += 1 if self.current_icon_id == len(self.icons): self.current_icon_id = 0 self.current_icon_name = self.icon_names[self.current_icon_id] def next_icon(self): """Increment the state of the Button. Also changes the icon. """ self.next_icon_id() self.set_icon(self.icons[self.current_icon_id][1])
def __init__(self, directions, indices, values=None, affine=None, colors=None, lookup_colormap=None, linewidth=1, symmetric=True): if affine is not None: w_pos = apply_affine(affine, np.asarray(indices).T) valid_dirs = directions[indices] num_dirs = len(np.nonzero(np.abs(valid_dirs).max(axis=-1) > 0)[0]) pnts_per_line = 2 points_array = np.empty((num_dirs * pnts_per_line, 3)) centers_array = np.empty_like(points_array, dtype=int) diffs_array = np.empty_like(points_array) line_count = 0 for idx, center in enumerate(zip(indices[0], indices[1], indices[2])): if affine is None: xyz = np.asarray(center) else: xyz = w_pos[idx, :] valid_peaks = np.nonzero( np.abs(valid_dirs[idx, :, :]).max(axis=-1) > 0.)[0] for direction in valid_peaks: if values is not None: pv = values[center][direction] else: pv = 1. if symmetric: point_i = directions[center][direction] * pv + xyz point_e = -directions[center][direction] * pv + xyz else: point_i = directions[center][direction] * pv + xyz point_e = xyz diff = point_e - point_i points_array[line_count * pnts_per_line, :] = point_e points_array[line_count * pnts_per_line + 1, :] = point_i centers_array[line_count * pnts_per_line, :] = center centers_array[line_count * pnts_per_line + 1, :] = center diffs_array[line_count * pnts_per_line, :] = diff diffs_array[line_count * pnts_per_line + 1, :] = diff line_count += 1 vtk_points = numpy_to_vtk_points(points_array) vtk_cells = _points_to_vtk_cells(points_array) colors_tuple = _peaks_colors_from_points(points_array, colors=colors) vtk_colors, colors_are_scalars, self.__global_opacity = colors_tuple poly_data = PolyData() poly_data.SetPoints(vtk_points) poly_data.SetLines(vtk_cells) poly_data.GetPointData().SetScalars(vtk_colors) self.__mapper = PolyDataMapper() self.__mapper.SetInputData(poly_data) self.__mapper.ScalarVisibilityOn() self.__mapper.SetScalarModeToUsePointFieldData() self.__mapper.SelectColorArray('colors') self.__mapper.Update() self.SetMapper(self.__mapper) attribute_to_actor(self, centers_array, 'center') attribute_to_actor(self, diffs_array, 'diff') vs_dec_code = import_fury_shader('peak_dec.vert') vs_impl_code = import_fury_shader('peak_impl.vert') fs_dec_code = import_fury_shader('peak_dec.frag') fs_impl_code = import_fury_shader('peak_impl.frag') shader_to_actor(self, 'vertex', decl_code=vs_dec_code, impl_code=vs_impl_code) shader_to_actor(self, 'fragment', decl_code=fs_dec_code) shader_to_actor(self, 'fragment', impl_code=fs_impl_code, block='light') # Color scale with a lookup table if colors_are_scalars: if lookup_colormap is None: lookup_colormap = colormap_lookup_table() self.__mapper.SetLookupTable(lookup_colormap) self.__mapper.UseLookupTableScalarRangeOn() self.__mapper.Update() self.__lw = linewidth self.GetProperty().SetLineWidth(self.__lw) if self.__global_opacity >= 0: self.GetProperty().SetOpacity(self.__global_opacity) self.__min_centers = np.min(indices, axis=1) self.__max_centers = np.max(indices, axis=1) self.__is_range = True self.__low_ranges = self.__min_centers self.__high_ranges = self.__max_centers self.__cross_section = self.__high_ranges // 2 self.__mapper.AddObserver(Command.UpdateShaderEvent, self.__display_peaks_vtk_callback)
def ribbon(molecule): """Create an actor for ribbon molecular representation. Parameters ---------- molecule : Molecule The molecule to be rendered. Returns ------- molecule_actor : vtkActor Actor created to render the rubbon representation of the molecule to be visualized. References ---------- Richardson, J.S. The anatomy and taxonomy of protein structure `Advances in Protein Chemistry, 1981, 34, 167-339. <https://doi.org/10.1016/S0065-3233(08)60520-3>`_ """ coords = get_all_atomic_positions(molecule) all_atomic_numbers = get_all_atomic_numbers(molecule) num_total_atoms = molecule.total_num_atoms secondary_structures = np.ones(num_total_atoms) for i in range(num_total_atoms): secondary_structures[i] = ord('c') resi = molecule.residue_seq[i] for j, _ in enumerate(molecule.sheet): sheet = molecule.sheet[j] if molecule.chain[i] != sheet[0] or resi < sheet[1] or \ resi > sheet[3]: continue secondary_structures[i] = ord('s') for j, _ in enumerate(molecule.helix): helix = molecule.helix[j] if molecule.chain[i] != helix[0] or resi < helix[1] or \ resi > helix[3]: continue secondary_structures[i] = ord('h') output = PolyData() # for atomic numbers atomic_num_arr = nps.numpy_to_vtk(num_array=all_atomic_numbers, deep=True, array_type=VTK_ID_TYPE) # setting the array name to atom_type as vtkProteinRibbonFilter requires # the array to be named atom_type atomic_num_arr.SetName("atom_type") output.GetPointData().AddArray(atomic_num_arr) # for atom names atom_names = StringArray() # setting the array name to atom_types as vtkProteinRibbonFilter requires # the array to be named atom_types atom_names.SetName("atom_types") atom_names.SetNumberOfTuples(num_total_atoms) for i in range(num_total_atoms): atom_names.SetValue(i, molecule.atom_names[i]) output.GetPointData().AddArray(atom_names) # for residue sequences residue_seq = nps.numpy_to_vtk(num_array=molecule.residue_seq, deep=True, array_type=VTK_ID_TYPE) residue_seq.SetName("residue") output.GetPointData().AddArray(residue_seq) # for chain chain = nps.numpy_to_vtk(num_array=molecule.chain, deep=True, array_type=VTK_UNSIGNED_CHAR) chain.SetName("chain") output.GetPointData().AddArray(chain) # for secondary structures s_s = nps.numpy_to_vtk(num_array=secondary_structures, deep=True, array_type=VTK_UNSIGNED_CHAR) s_s.SetName("secondary_structures") output.GetPointData().AddArray(s_s) # for secondary structures begin newarr = np.ones(num_total_atoms) s_sb = nps.numpy_to_vtk(num_array=newarr, deep=True, array_type=VTK_UNSIGNED_CHAR) s_sb.SetName("secondary_structures_begin") output.GetPointData().AddArray(s_sb) # for secondary structures end newarr = np.ones(num_total_atoms) s_se = nps.numpy_to_vtk(num_array=newarr, deep=True, array_type=VTK_UNSIGNED_CHAR) s_se.SetName("secondary_structures_end") output.GetPointData().AddArray(s_se) # for is_hetatm is_hetatm = nps.numpy_to_vtk(num_array=molecule.is_hetatm, deep=True, array_type=VTK_UNSIGNED_CHAR) is_hetatm.SetName("ishetatm") output.GetPointData().AddArray(is_hetatm) # for model model = nps.numpy_to_vtk(num_array=molecule.model, deep=True, array_type=VTK_UNSIGNED_INT) model.SetName("model") output.GetPointData().AddArray(model) table = PTable() # for colors and radii of hetero-atoms radii = np.ones((num_total_atoms, 3)) rgb = np.ones((num_total_atoms, 3)) for i in range(num_total_atoms): radii[i] = np.repeat(table.atomic_radius(all_atomic_numbers[i], 'VDW'), 3) rgb[i] = table.atom_color(all_atomic_numbers[i]) Rgb = nps.numpy_to_vtk(num_array=rgb, deep=True, array_type=VTK_UNSIGNED_CHAR) Rgb.SetName("rgb_colors") output.GetPointData().SetScalars(Rgb) Radii = nps.numpy_to_vtk(num_array=radii, deep=True, array_type=VTK_FLOAT) Radii.SetName("radius") output.GetPointData().SetVectors(Radii) # setting the coordinates points = numpy_to_vtk_points(coords) output.SetPoints(points) ribbonFilter = ProteinRibbonFilter() ribbonFilter.SetInputData(output) ribbonFilter.SetCoilWidth(0.2) ribbonFilter.SetDrawSmallMoleculesAsSpheres(0) mapper = PolyDataMapper() mapper.SetInputConnection(ribbonFilter.GetOutputPort()) molecule_actor = Actor() molecule_actor.SetMapper(mapper) return molecule_actor