def unit_cell_box_drawing(unit_cell_corners, corner_radius=1.0, origin_radius=2.0, cylinder_radius=0.2): from chimerax.graphics import Drawing md = Drawing('Unit cell box') cd = Drawing('Corners') ed = Drawing('Edges') md.add_drawing(cd) md.add_drawing(ed) from chimerax.surface.shapes import sphere_geometry2, cylinder_geometry cd.set_geometry(*sphere_geometry2(80)) ed.set_geometry(*cylinder_geometry()) from chimerax.geometry import Places, cylinder_rotations import numpy shift_and_scale = numpy.empty((8, 4), numpy.float32) shift_and_scale[:, :3] = unit_cell_corners shift_and_scale[1:, 3] = corner_radius shift_and_scale[0, 3] = origin_radius cd.positions = Places(shift_and_scale=shift_and_scale) edges = [[0, 1], [0, 2], [0, 4], [1, 3], [1, 5], [2, 3], [2, 6], [3, 7], [4, 5], [4, 6], [5, 7], [6, 7]] xyz = [[], []] for e in edges: for i in range(2): xyz[i].append(unit_cell_corners[e[i]]) xyz0, xyz1 = [numpy.array(x) for x in xyz] rot44 = numpy.empty((12, 4, 4), numpy.float32) cylinder_rotations(xyz0, xyz1, numpy.ones(12, numpy.float32) * cylinder_radius, rot44) rot44[:, 3, :3] = 0.5 * (xyz0 + xyz1) ed.positions = Places(opengl_array=rot44) return md
def _annotation_transforms(self): n = len(self) f = c_function(self._C_FUNCTION_PREFIX + '_annotation_transform', args=(ctypes.c_void_p, ctypes.c_size_t, ctypes.c_void_p, ctypes.c_void_p)) tf1 = numpy.empty((n, 4, 4), float32) tf2 = numpy.empty((n, 4, 4), float32) f(self._c_pointers, n, pointer(tf1), pointer(tf2)) from chimerax.geometry import Places return (Places(opengl_array=tf1), Places(opengl_array=tf2))
def _chain_operators(self, chain_id): cops = [] for chain_ids, operator_expr, ops in self.chain_ops: if chain_id in chain_ids: cops.extend(ops) from chimerax.geometry import Places return Places(cops)
def set_state_from_snapshot(self, session, data): self.name = data['name'] self.id = data['id'] p = data['parent'] if p: p.add([self]) pa = data['positions'] from numpy import float32, float64 if pa.dtype == float32: # Fix old sessions that saved array as float32 pa = pa.astype(float64) from chimerax.geometry import Places self.positions = Places(place_array=pa) self.display_positions = data['display_positions'] for d in self.all_drawings(): for attr in [ 'allow_depth_cue', 'accept_shadow', 'accept_multishadow' ]: if attr in data: setattr(d, attr, data[attr]) if 'clip_cap' in data: self.clip_cap = data['clip_cap'] if 'drawing state' in data: from chimerax.graphics.gsession import DrawingState DrawingState.set_state_from_snapshot(self, session, data['drawing state']) self.SESSION_SAVE_DRAWING = True
def parse_map_symmetry_file(filename): import numpy from collections import defaultdict ncs_map = defaultdict(list) with open(filename, 'rt') as infile: data = infile.read().split('\n') ncs_group_id = -1 i = 0 print(len(data)) while i < len(data): line = data[i] if line.startswith('new_ncs_group'): ncs_group_id += 1 i += 1 continue if line.startswith('new_operator'): op, incr = _parse_operator(data[i + 1:]) ncs_map[ncs_group_id].append(op) i += (incr + 1) continue else: i += 1 continue from chimerax.geometry import Places ret = {} for gid, ncslist in ncs_map.items(): ret[gid] = Places(place_array=numpy.array(ncslist)) return ret
def add_gaussians(grid, xyz, weights, sdev, cutoff_range, transforms=None, normalize=True): from numpy import zeros, float32, empty sdevs = zeros((len(xyz), 3), float32) for a in (0, 1, 2): sdevs[:, a] = sdev / grid.step[a] if transforms is None: from chimerax.geometry import Places transforms = Places() from ._map import sum_of_gaussians ijk = empty(xyz.shape, float32) matrix = grid.matrix() for tf in transforms: ijk[:] = xyz (grid.xyz_to_ijk_transform * tf).transform_points(ijk, in_place=True) sum_of_gaussians(ijk, weights, sdevs, cutoff_range, matrix) if normalize: from math import pow, pi normalization = pow(2 * pi, -1.5) * pow(sdev, -3) matrix *= normalization
def update_graphics(self, *_): from chimerax.core.triggerset import DEREGISTER ramas = self._visible_ramas od = self._omega_drawing rd = self._rama_drawing if not len(ramas): od.display = False rd.display = False return DEREGISTER mgr = self._mgr #mgr.color_cas_by_rama_score(ramas, self.hide_favored) coords, colors, selecteds = mgr._ca_positions_colors_and_selecteds(ramas, self.hide_favored) n = len(coords) if n > 0: xyzr = numpy.empty((n, 4), numpy.float32) xyzr[:,:3] = coords xyzr[:,3] = self.ca_radius from chimerax.geometry import Places rd.positions = Places(shift_and_scale = xyzr) rd.colors = colors rd.highlighted_positions = selecteds rd.display = True else: rd.display = False v, n, t, c = mgr._draw_cis_and_twisted_omegas(ramas) if len(v): od.set_geometry(v, n, t) od.vertex_colors = c od.display = True else: od.display = False return DEREGISTER
def sym_axis_drawing_screw(fold_symmetry, screw_component, axyz0, axyz1, base_radius=0.3): ''' Just draw as a dashed cylinder for now. ''' import numpy from chimerax.surface.shapes import dashed_cylinder_geometry from chimerax.geometry import Places, cylinder_rotations, rotation n = len(axyz0) radius = base_radius * (1 + 0.1 * fold_symmetry) radii = numpy.ones(n, numpy.float32) * radius rot44 = numpy.empty([n, 4, 4], numpy.float32) cylinder_rotations(axyz0, axyz1, radii, rot44) rot44[:, 3, :3] = 0.5 * (axyz0 + axyz1) from chimerax.graphics import Drawing d = Drawing('{}-fold screw axis'.format(fold_symmetry)) d.set_geometry(*dashed_cylinder_geometry(segments=15)) d.color = _symmetry_colors[fold_symmetry][1] d.positions = Places(opengl_array=rot44) return d
def set_instance_positions_and_colors(drawings): from chimerax.geometry import Places for d in drawings: if hasattr(d, 'position_list') and hasattr(d, 'color_list'): clist = d.color_list from numpy import array, uint8 d.colors = array(clist, uint8).reshape((len(clist), 4)) d.positions = Places(d.position_list)
def sym_clear(session, structures=None): ''' Remove copies of structures that were made with sym command. Parameters ---------- structures : list of AtomicStructure List of structures to for which to remove copies. ''' if structures is None: from chimerax.atomic import all_structures structures = all_structures(session) for m in structures: from chimerax.geometry import Places m.positions = Places([m.position]) # Keep only first position. for s in m.surfaces(): s.positions = Places([s.position])
def find_symmetries(self, group): va = group._v_attrs if 'symmetries' in va: from chimerax.geometry import Places sym = Places(place_array = va.symmetries) else: sym = None return sym
def _target_transforms(self): from chimerax.geometry import Places f = c_function('distance_restraint_target_transform', args=(ctypes.c_void_p, ctypes.c_size_t, ctypes.POINTER(ctypes.c_float))) n = len(self) transforms = empty((n, 4, 4), float32) f(self._c_pointers, n, pointer(transforms)) return Places(opengl_array=transforms)
def ijk_symmetry_matrices(data, symmetries): if symmetries is None or len(symmetries) == 0: from chimerax.geometry import Places return Places() isyms = symmetries.transform_coordinates(data.ijk_to_xyz_transform) return isyms
def find_symmetries(self, group): va = group._v_attrs if 'symmetries' in va: from chimerax.geometry import Places from numpy import array, float64 sym = Places(place_array=array(va.symmetries, float64)) else: sym = None return sym
def biological_unit_matrices(molecule): if hasattr(molecule, 'metadata') and 'REMARK' in molecule.metadata: s = pdb_biomt_matrices(molecule.metadata) # elif hasattr(molecule, 'mmCIFHeaders'): # s = PDBmatrices.mmcif_biounit_matrices(molecule.mmCIFHeaders) else: from chimerax.geometry import Places s = Places([]) return s
def _bond_cylinder_transforms(self): '''Transforms mapping a unit cylinder onto the restraint bonds. Read only.''' from chimerax.geometry import Places f = c_function('distance_restraint_bond_transform', args=(ctypes.c_void_p, ctypes.c_size_t, ctypes.POINTER(ctypes.c_float))) n = len(self) transforms = empty((n, 4, 4), float32) f(self._c_pointers, n, pointer(transforms)) return Places(opengl_array=transforms)
def update_graphics(self, *_, scale_by_scores = True): from chimerax.core.triggerset import DEREGISTER if not self.visible: return DEREGISTER rots, scales, colors = self._mgr.validate_scale_and_color_rotamers( self._selected_rotamers, max_scale=self._MAX_SCALE, non_favored_only = self._hide_favored) d = self._drawing if not len(rots): d.display = False return DEREGISTER d.display = True bonds = rots.ca_cb_bonds transforms = bond_cylinder_placements(bonds) if scale_by_scores: transforms = Places(place_array=scale_transforms(scales, transforms.array())) d.positions = transforms d.colors = colors return DEREGISTER
def make_closest_placement_identity(tflist, center): d = tflist.array()[:, :, 3] - center d2 = (d * d).sum(axis=1) i = d2.argmin() tfinv = tflist[i].inverse() rtflist = [tf * tfinv for tf in tflist] from chimerax.geometry import Place, Places rtflist[i] = Place() return Places(rtflist)
def parse_symmetry(session, group, center=None, axis=None, molecule=None): # Handle products of symmetry groups. groups = group.split('*') from chimerax.geometry import Places ops = Places() for g in groups: ops = ops * group_symmetries(session, g, molecule) # Apply center and axis transformation. if center is not None or axis is not None: from chimerax.geometry import Place, vector_rotation, translation tf = Place() if center is not None and tuple(center) != (0, 0, 0): tf = translation([-c for c in center]) if axis is not None and tuple(axis) != (0, 0, 1): tf = vector_rotation(axis, (0, 0, 1)) * tf if not tf.is_identity(): ops = ops.transform_coordinates(tf) return ops
def placements(n, marker_set, each_edge=False): plist = polygons(marker_set) from chimerax.geometry import Places tflist = Places([polygon_coordinate_frame(p) for p in plist if p.n == n]) if each_edge: from chimerax import geometry tflist = tflist * geometry.cyclic_symmetry_matrices(n) return tflist
def __init__(self, name, hkls, vals, dim_scale=2.0, highlight_negatives=True): super().__init__(name) from chimerax.surface.shapes import sphere_geometry2 self.set_geometry(*sphere_geometry2(80)) import numpy from chimerax.geometry import Places, Place, identity id_axes = identity().axes() abs_vals = numpy.abs(vals) import numpy place_array = numpy.zeros((len(hkls), 3, 4)) place_array[:, :, 3] = hkls * dim_scale place_array[:, :, :3] = id_axes for i in range(3): # Volume scales with value, so radius scales with cube root of value place_array[:, i, i] *= abs_vals**(1 / 3) # positions =[Place(origin=hkl*dim_scale, axes=id_axes*max(rval, 0)) # for (hkl, rval) in zip(hkls, vals) # ] if highlight_negatives: import numpy negatives = numpy.argwhere(vals < 0).flatten() place_array[negatives, :, :3] = id_axes # for ni in negatives: # positions[ni] = Place(origin=positions[ni].origin(), axes=id_axes) positions = Places(place_array=place_array) self.set_positions(Places(positions)) from chimerax.core.colors import BuiltinColormaps cmap = BuiltinColormaps['rdylbu'].linear_range(-1, 1) colors = cmap.interpolated_rgba8(vals) if highlight_negatives: colors[vals < 0] = [255, 0, 0, 255] self.set_colors(colors)
def add_balls(grid, xyz, radii, sdev, cutoff_range, transforms=None): if transforms is None or len(transforms) == 0: from chimerax.geometry import Places transforms = Places() from numpy import empty, float32 ijk = empty(xyz.shape, float32) r = (radii - sdev) / grid.step[0] matrix = grid.matrix() from ._map import sum_of_balls for tf in transforms: ijk[:] = xyz (grid.xyz_to_ijk_transform * tf).transform_points(ijk, in_place=True) sum_of_balls(ijk, r, sdev, cutoff_range, matrix)
def _close_center_transforms(structures, transforms, distance): from numpy import concatenate points = concatenate([s.atoms.scene_coords for s in structures]) from chimerax.geometry import point_bounds, distance as point_distance, Places box = point_bounds(points) if box is None: return [] center = box.center() tfnear = Places([ tf for tf in transforms if point_distance(center, tf * center) <= distance ]) return tfnear
def _contacting_transforms(structures, transforms, distance): from numpy import concatenate, float32 points = concatenate([s.atoms.scene_coords for s in structures]).astype(float32) from chimerax.geometry import identity, find_close_points_sets, Places ident = identity().matrix.astype(float32) orig_points = [(points, ident)] tfnear = Places([ tf for tf in transforms if len( find_close_points_sets(orig_points, [( points, tf.matrix.astype(float32))], distance)[0][0]) > 0 ]) return tfnear
def _start_spotlight_mode(self): zm = self._zone_mgr zm.radius = zm.pad = self.spotlight_radius zm.allow_remask_on_coord_updates() # zm.coords = [self.spotlight_center] self.triggers.activate_trigger('spotlight changed', (self.spotlight_center, self.spotlight_radius) ) if self._box_update_handler is None: self._box_update_handler = self.crystal_mgr.triggers.add_handler( 'spotlight moved', self.update_spotlight) self.update_spotlight(None, self.spotlight_center) from chimerax.geometry import Places self.positions = Places()
def pdb_mtrix_matrices(pdb_headers, add_identity=True, given=False): h = pdb_headers have_matrix = ('MTRIX1' in h and 'MTRIX2' in h and 'MTRIX3' in h) if not have_matrix: if add_identity: from chimerax.geometry import identity return [identity()] else: return [] row1_list = h['MTRIX1'] row2_list = h['MTRIX2'] row3_list = h['MTRIX3'] if len(row1_list) != len(row2_list) or len(row2_list) != len(row3_list): if add_identity: from chimerax.geometry import identity return [identity()] else: return [] row_triples = zip(row1_list, row2_list, row3_list) mlist = [] from chimerax.geometry import Place for row_triple in row_triples: matrix = [] for line in row_triple: try: mrow = [ float(f) for f in (line[10:20], line[20:30], line[30:40], line[45:55]) ] except ValueError: break mgiven = (len(line) >= 60 and line[59] == '1') if (mgiven and given) or (not mgiven and not given): matrix.append(mrow) if len(matrix) == 3: mlist.append(Place(matrix)) if add_identity: if len([m for m in mlist if m.is_identity()]) == 0: # Often there is no MTRIX identity entry from chimerax.geometry import identity mlist.append(identity()) return Places(mlist)
def bond_cylinder_placements(bonds): '''From chimerax.core.structure._bond_cylinder_placements.''' n = len(bonds) from numpy import empty, float32 p = empty((n, 4, 4), float32) radii = numpy.ones(len(bonds)) from chimerax.geometry import cylinder_rotations, Places axyz0, axyz1 = [a.coords for a in bonds.atoms] cylinder_rotations(axyz0, axyz1, radii, p) p[:, 3, :3] = 0.5 * (axyz0 + axyz1) pl = Places(opengl_array=p) return pl
def read_positions(session, stream, name, models=None, match_names=False, child_models=False): """ Read position matrices and set positions of specified models. """ from chimerax.core.errors import UserError if models is None or len(models) == 0: raise UserError('Must specify models when opening positions file %s.' % stream.name) if not child_models: models = _exclude_child_models(models) lines = stream.readlines() places = _parse_places(lines) if len(places) == 0: raise UserError('No positions specified in positions file %s.' % stream.name) if match_names: n2p = dict(places) mpos = [(m, n2p[m.name]) for m in models if m.name in n2p] for m, position in mpos: m.position = position msg = (('Set position of model %s' % m.name) if len(mpos) == 1 else ('Set %d positions' % len(mpos))) elif len(models) == 1: m = models[0] from chimerax.geometry import Places m.positions = Places(p for name, p in places) msg = (('Set position of model %s' % m.name) if len(places) == 1 else ('Set %d position for model %s' % (len(places), m.name))) elif len(places) != len(models): raise UserError( 'Number of models (%d) does not equal number of positions (%d) in position file %s' % (len(models), len(places), stream.name)) else: for m, (name, position) in zip(models, places): m.position = position msg = 'Set %d positions' % len(places) return [], msg
def _bond_transforms(self): ''' Transforms mapping a tripartite bond onto the restraint vectors. Read only. ''' from chimerax.geometry import Places f = c_function('adaptive_distance_restraint_bond_transforms', args=( ctypes.c_void_p, ctypes.c_size_t, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), )) n = len(self) tf_ends = empty((n * 2, 4, 4), float32) tf_m = empty((n, 4, 4), float32) f(self._c_pointers, n, pointer(tf_ends), pointer(tf_m)) return tuple(Places(opengl_array=tf) for tf in (tf_ends, tf_m))
def make_unit_cell(model, xmap, draw = True): from chimerax.geometry import Place, Places cell = xmap.cell() atoms = model.atoms clipper_atoms = atom_list_from_sel(atoms) coord = model.bounds().center() from .clipper_python import Coord_orth coord_orth = Coord_orth(coord) coord_frac = coord_orth.coord_frac(cell) sg = xmap.spacegroup() unit_cell_frac_symops = xmap.unit_cell_symops(coord_frac, clipper_atoms) if draw: uc_places = [] for op in unit_cell_frac_symops.symops(): op_orth = op.rtop_orth(cell) uc_places.append(Place(matrix=op_orth.matrix()[0:3,:])) ucp = Places(uc_places) model.positions = ucp return unit_cell_frac_symops