def test_save_and_load_polydata(): l_ext = ["vtk", "fib", "ply", "xml"] fname = "temp-io" for ext in l_ext: with InTemporaryDirectory() as odir: data = np.random.randint(0, 255, size=(50, 3)) pd = vtk.vtkPolyData() pd.SetPoints(numpy_to_vtk_points(data)) fname_path = pjoin(odir, "{0}.{1}".format(fname, ext)) save_polydata(pd, fname_path) npt.assert_equal(os.path.isfile(fname_path), True) assert_greater(os.stat(fname_path).st_size, 0) out_pd = load_polydata(fname_path) out_data = numpy_support.vtk_to_numpy(out_pd.GetPoints().GetData()) npt.assert_array_equal(data, out_data) npt.assert_raises(IOError, save_polydata, vtk.vtkPolyData(), "test.vti") npt.assert_raises(IOError, save_polydata, vtk.vtkPolyData(), "test.obj") npt.assert_raises(IOError, load_polydata, "test.vti")
def bounding_box(molecule, colors=(1, 1, 1), linewidth=0.3): """Create a bounding box for a molecule. Parameters ---------- molecule : Molecule The molecule around which the bounding box is to be created. colors : tuple (3,) or ndarray of shape (3,), optional Color of the bounding box. Default: (1, 1, 1) linewidth: float, optional Thickness of tubes used to compose bounding box. Default: 0.3 Returns ------- bbox_actor : vtkActor Actor created to serve as a bounding box for a given molecule. """ pts = numpy_to_vtk_points(get_all_atomic_positions(molecule)) min_x, max_x, min_y, max_y, min_z, max_z = pts.GetBounds() lines = np.array([[[min_x, min_y, min_z], [min_x, min_y, max_z]], [[min_x, max_y, min_z], [min_x, max_y, max_z]], [[max_x, min_y, min_z], [max_x, min_y, max_z]], [[max_x, max_y, min_z], [max_x, max_y, max_z]], [[min_x, min_y, min_z], [max_x, min_y, min_z]], [[min_x, max_y, min_z], [max_x, max_y, min_z]], [[min_x, max_y, max_z], [max_x, max_y, max_z]], [[min_x, min_y, max_z], [max_x, min_y, max_z]], [[min_x, min_y, min_z], [min_x, max_y, min_z]], [[max_x, min_y, min_z], [max_x, max_y, min_z]], [[min_x, min_y, max_z], [min_x, max_y, max_z]], [[max_x, min_y, max_z], [max_x, max_y, max_z]]]) return streamtube(lines, colors=colors, linewidth=linewidth)
def glyph_dot(centers, colors, radius=100): if np.array(colors).ndim == 1: colors = np.tile(colors, (len(centers), 1)) vtk_pnt = numpy_to_vtk_points(centers) pnt_polydata = vtk.vtkPolyData() pnt_polydata.SetPoints(vtk_pnt) vertex_filter = vtk.vtkVertexGlyphFilter() vertex_filter.SetInputData(pnt_polydata) vertex_filter.Update() polydata = vtk.vtkPolyData() polydata.ShallowCopy(vertex_filter.GetOutput()) mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(polydata) mapper.SetScalarModeToUsePointFieldData() pnt_actor = vtk.vtkActor() pnt_actor.SetMapper(mapper) pnt_actor.GetProperty().SetPointSize(radius) cols = numpy_to_vtk_colors(255 * np.ascontiguousarray(colors)) cols.SetName('colors') polydata.GetPointData().AddArray(cols) mapper.SelectColorArray('colors') return pnt_actor
def disk(): np.random.seed(42) n_points = 1 centers = np.random.rand(n_points, 3) colors = 255 * np.random.rand(n_points, 3) vtk_points = numpy_to_vtk_points(centers) points_polydata = vtk.vtkPolyData() points_polydata.SetPoints(vtk_points) vertex_filter = vtk.vtkVertexGlyphFilter() vertex_filter.SetInputData(points_polydata) vertex_filter.Update() polydata = vtk.vtkPolyData() polydata.ShallowCopy(vertex_filter.GetOutput()) mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(polydata) points_actor = vtk.vtkActor() points_actor.SetMapper(mapper) points_actor.GetProperty().SetPointSize(1000) points_actor.GetProperty().SetRenderPointsAsSpheres(True) return points_actor
def test_save_and_load_options(): l_ext = ["ply", "vtk"] l_options = [{ 'color_array_name': 'horizon', }, { 'binary': True, }] fname = "temp-io" for ext, option in zip(l_ext, l_options): with InTemporaryDirectory() as odir: data = np.random.randint(0, 255, size=(50, 3)) pd = vtk.vtkPolyData() pd.SetPoints(numpy_to_vtk_points(data)) fname_path = pjoin(odir, "{0}.{1}".format(fname, ext)) save_polydata(pd, fname_path, **option) npt.assert_equal(os.path.isfile(fname_path), True) assert_greater(os.stat(fname_path).st_size, 0) out_pd = load_polydata(fname_path) out_data = numpy_support.vtk_to_numpy(out_pd.GetPoints().GetData()) npt.assert_array_equal(data, out_data) l_ext = ["stl", "obj"] l_options = [{}, { 'is_mni_obj': True, }] for ext, option in zip(l_ext, l_options): with InTemporaryDirectory() as odir: data = np.random.randint(0, 255, size=(50, 3)) pd = vtk.vtkPolyData() pd.SetPoints(numpy_to_vtk_points(data)) fname_path = pjoin(odir, "{0}.{1}".format(fname, ext)) save_polydata(pd, fname_path, **option) npt.assert_equal(os.path.isfile(fname_path), True) assert_greater(os.stat(fname_path).st_size, 0)
def __init__(self, directions, indices, values=None, affine=None, colors=None, lookup_colormap=None, linewidth=1): 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. point_i = directions[center][direction] * pv + xyz point_e = -directions[center][direction] * pv + 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 = vtk.vtkPolyData() poly_data.SetPoints(vtk_points) poly_data.SetLines(vtk_cells) poly_data.GetPointData().SetScalars(vtk_colors) self.__mapper = vtk.vtkPolyDataMapper() 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 = load('peak_dec.vert') vs_impl_code = load('peak_impl.vert') fs_dec_code = load('peak_dec.frag') fs_impl_code = load('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(vtk.vtkCommand.UpdateShaderEvent, self.__display_peaks_vtk_callback)
def sphere(centers, colors, radii=1., theta=16, phi=16, vertices=None, faces=None): """Visualize one or many spheres with different colors and radii Parameters ---------- centers : ndarray, shape (N, 3) colors : ndarray (N,3) or (N, 4) or tuple (3,) or tuple (4,) RGB or RGBA (for opacity) R, G, B and A should be at the range [0, 1] radii : float or ndarray, shape (N,) theta : int phi : int vertices : ndarray, shape (N, 3) faces : ndarray, shape (M, 3) If faces is None then a sphere is created based on theta and phi angles If not then a sphere is created with the provided vertices and faces. Returns ------- vtkActor Examples -------- >>> from fury import window, actor >>> scene = window.Scene() >>> centers = np.random.rand(5, 3) >>> sphere_actor = actor.sphere(centers, window.colors.coral) >>> scene.add(sphere_actor) >>> # window.show(scene) """ if np.array(colors).ndim == 1: colors = np.tile(colors, (len(centers), 1)) if isinstance(radii, (float, int)): radii = radii * np.ones(len(centers), dtype='f8') pts = numpy_to_vtk_points(np.ascontiguousarray(centers)) cols = numpy_to_vtk_colors(255 * np.ascontiguousarray(colors)) cols.SetName('colors') radii_fa = numpy_support.numpy_to_vtk(np.ascontiguousarray( radii.astype('f8')), deep=0) radii_fa.SetName('rad') polydata_centers = vtk.vtkPolyData() polydata_sphere = vtk.vtkPolyData() if faces is None: src = vtk.vtkSphereSource() src.SetRadius(1) src.SetThetaResolution(theta) src.SetPhiResolution(phi) else: set_polydata_vertices(polydata_sphere, vertices) set_polydata_triangles(polydata_sphere, faces) polydata_centers.SetPoints(pts) polydata_centers.GetPointData().AddArray(radii_fa) polydata_centers.GetPointData().SetActiveScalars('rad') polydata_centers.GetPointData().AddArray(cols) glyph = vtk.vtkGlyph3D() if faces is None: glyph.SetSourceConnection(src.GetOutputPort()) else: glyph.SetSourceData(polydata_sphere) glyph.SetInputData(polydata_centers) glyph.Update() mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(glyph.GetOutput()) mapper.SetScalarModeToUsePointFieldData() mapper.SelectColorArray('colors') actor = vtk.vtkActor() actor.SetMapper(mapper) return actor
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
def __init__(self, atomic_numbers=None, coords=None, atom_names=None, model=None, residue_seq=None, chain=None, sheet=None, helix=None, is_hetatm=None): """Send the atomic data to the molecule. Parameters ---------- atomic_numbers : ndarray of integers, optional The shape of the array must be (N, ) where N is the total number of atoms present in the molecule. Array having atomic number corresponding to each atom of the molecule. coords : ndarray of floats, optional The shape of the array must be (N, 3) where N is the total number of atoms present in the molecule. Array having coordinates corresponding to each atom of the molecule. atom_names : ndarray of strings, optional The shape of the array must be (N, ) where N is the total number of atoms present in the molecule. Array having the names of atoms. model : ndarray of integers, optional The shape of the array must be (N, ) where N is the total number of atoms present in the molecule. Array having the model number corresponding to each atom. residue_seq : ndarray of integers, optional The shape of the array must be (N, ) where N is the total number of atoms present in the molecule. Array having the residue sequence number corresponding to each atom of the molecule. chain : ndarray of integers, optional The shape of the array must be (N, ) where N is the total number of atoms present in the molecule. Array having the chain number corresponding to each atom. sheet : ndarray of integers, optional The shape of the array must be (S, 4) where S is the total number of sheets present in the molecule. Array containing information about sheets present in the molecule. helix : ndarray of integers, optional The shape of the array must be (H, 4) where H is the total number of helices present in the molecule. Array containing information about helices present in the molecule. is_hetatm : ndarray of bools, optional The shape of the array must be (N, ) where N is the total number of atoms present in the molecule. Array containing a bool value to indicate if an atom is a heteroatom. """ if atomic_numbers is None and coords is None: self.Initialize() elif not isinstance(atomic_numbers, np.ndarray) \ or \ not isinstance(coords, np.ndarray): raise ValueError('atom_types and coords must be numpy arrays.') elif len(atomic_numbers) == len(coords): self.atom_names = atom_names self.model = model self.residue_seq = residue_seq self.chain = chain self.sheet = sheet self.helix = helix self.is_hetatm = is_hetatm coords = numpy_to_vtk_points(coords) atom_nums = nps.numpy_to_vtk(atomic_numbers, array_type=VTK_UNSIGNED_SHORT) atom_nums.SetName("Atomic Numbers") fieldData = DataSetAttributes() fieldData.AddArray(atom_nums) self.Initialize(coords, fieldData) else: n1 = len(coords) n2 = len(atomic_numbers) raise ValueError('Mismatch in length of atomic_numbers({0}) and ' 'length of atomic_coords({1}).'.format(n1, n2))
def rectangle2(centers, colors, use_vertices=False, size=(2, 2)): """Visualize one or many spheres with different colors and radii Parameters ---------- centers : ndarray, shape (N, 3) colors : ndarray (N,3) or (N, 4) or tuple (3,) or tuple (4,) RGB or RGBA (for opacity) R, G, B and A should be at the range [0, 1] """ 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') polydata_centers = vtk.vtkPolyData() polydata_centers.SetPoints(pts) polydata_centers.GetPointData().AddArray(cols) print("NB pts: ", polydata_centers.GetNumberOfPoints()) print("NB arrays: ", polydata_centers.GetPointData().GetNumberOfArrays()) for i in range(polydata_centers.GetPointData().GetNumberOfArrays()): print("Array {0}: {1}".format( i, polydata_centers.GetPointData().GetArrayName(i))) for i in range(polydata_centers.GetCellData().GetNumberOfArrays()): print("Cell {0}: {1}".format( i, polydata_centers.GetCellData().GetArrayName(i))) print("Array pts: {}".format( polydata_centers.GetPoints().GetData().GetName())) glyph = vtk.vtkGlyph3D() if use_vertices: scale = 1 my_polydata = vtk.vtkPolyData() my_vertices = np.array([[0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [1.0, 1.0, 0.0], [1.0, 0.0, 0.0]]) my_vertices -= np.array([0.5, 0.5, 0]) my_vertices = scale * my_vertices my_triangles = np.array([[0, 1, 2], [2, 3, 0]], dtype='i8') set_polydata_vertices(my_polydata, my_vertices) set_polydata_triangles(my_polydata, my_triangles) glyph.SetSourceData(my_polydata) else: src = vtk.vtkPlaneSource() src.SetXResolution(size[0]) src.SetYResolution(size[1]) glyph.SetSourceConnection(src.GetOutputPort()) glyph.SetInputData(polydata_centers) glyph.Update() mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(glyph.GetOutput()) mapper.SetScalarModeToUsePointFieldData() mapper.SelectColorArray('colors') actor = vtk.vtkActor() actor.SetMapper(mapper) return actor