def report_correlations_with_rotation(v1, v2, aboveThreshold, axis, center, angleRange, plot): from chimera import Vector, Point, replyobj # Convert axis and center to v1 local coordinates so transformation # is still valid if user rotates entire scene. xf = v1.openState.xform.inverse() axis = xf.apply(Vector(*axis)).data() center = xf.apply(Point(*center)).data() import FitMap, Matrix replyobj.info('Correlation between %s and %s\n' % (v1.name, v2.name) + 'Rotation\tCorrelation\n') a0, a1, astep = angleRange angle = a0 clist = [] from Matrix import multiply_matrices, xform_matrix, rotation_transform, chimera_xform while angle < a1: tf = multiply_matrices(xform_matrix(v1.openState.xform), rotation_transform(axis, angle, center), xform_matrix(v1.openState.xform.inverse())) xf = chimera_xform(tf) olap, cor = FitMap.map_overlap_and_correlation(v1, v2, aboveThreshold, xf) replyobj.status('angle = %.4g, correlation = %.4g\n' % (angle, cor)) replyobj.info('%.4g\t%.4g\n' % (angle, cor)) clist.append((angle,cor)) angle += astep if plot: angles = [a for a,c in clist] corr = [c for a,c in clist] plot_correlation(angles, corr, v1, v2, axis, center)
def report_correlations_with_rotation(v1, v2, aboveThreshold, axis, center, angleRange, plot): from chimera import Vector, Point, replyobj # Convert axis and center to v1 local coordinates so transformation # is still valid if user rotates entire scene. xf = v1.openState.xform.inverse() axis = xf.apply(Vector(*axis)).data() center = xf.apply(Point(*center)).data() import FitMap, Matrix replyobj.info('Correlation between %s and %s\n' % (v1.name, v2.name) + 'Rotation\tCorrelation\n') a0, a1, astep = angleRange angle = a0 clist = [] from Matrix import multiply_matrices, xform_matrix, rotation_transform, chimera_xform while angle < a1: tf = multiply_matrices(xform_matrix(v1.openState.xform), rotation_transform(axis, angle, center), xform_matrix(v1.openState.xform.inverse())) xf = chimera_xform(tf) olap, cor = FitMap.map_overlap_and_correlation(v1, v2, aboveThreshold, xf) replyobj.status('angle = %.4g, correlation = %.4g\n' % (angle, cor)) replyobj.info('%.4g\t%.4g\n' % (angle, cor)) clist.append((angle, cor)) angle += astep if plot: angles = [a for a, c in clist] corr = [c for a, c in clist] plot_correlation(angles, corr, v1, v2, axis, center)
def bond_points(bonds, xform, bond_point_spacing): if bond_point_spacing == None and use_bond_zone(): bond_point_spacing = bond_zone_point_spacing() if bond_point_spacing == None: return [] xyz_list = [] for b in bonds: c = bond_point_count(b, bond_point_spacing) if c > 0: xyz1, xyz2 = map(lambda a: a.xformCoord().data(), b.atoms) for k in range(c): fb = float(k+1) / (c+1) fa = 1-fb xyz = map(lambda a,b: fa*a + fb*b, xyz1, xyz2) xyz_list.append(xyz) from numpy import array, single as floatc, zeros if len(xyz_list) > 0: points = array(xyz_list, floatc) from Matrix import xform_matrix import _contour _contour.affine_transform_vertices(points, xform_matrix(xform)) else: points = zeros((0,3), floatc) return points
def bounding_xray_map_symmetry(atoms, pad, volume): # Get atom positions. from _multiscale import get_atom_coordinates xyz = get_atom_coordinates(atoms, transformed = True) # Transform atom coordinates to volume ijk indices. from Matrix import multiply_matrices, xform_matrix tf = multiply_matrices(volume.data.xyz_to_ijk_transform, xform_matrix(volume.model_transform().inverse())) from _contour import affine_transform_vertices affine_transform_vertices(xyz, tf) ijk = xyz # Find integer bounds. from math import floor, ceil ijk_min = [int(floor(i-pad)) for i in ijk.min(axis=0)] ijk_max = [int(ceil(i+pad)) for i in ijk.max(axis=0)] #gather information about unit cell and symmetry ijk_cell_size = getattr(volume.data, 'unit_cell_size', volume.data.size) syms = volume.data.symmetries step = volume.data.step from VolumeFilter import cover cg = cover.map_covering_box(volume, ijk_min, ijk_max, ijk_cell_size, syms, step) from VolumeViewer import volume_from_grid_data v = volume_from_grid_data(cg, show_data = False) v.copy_settings_from(volume, copy_region = False) return v
def bond_points(bonds, xform, bond_point_spacing): if bond_point_spacing == None and use_bond_zone(): bond_point_spacing = bond_zone_point_spacing() if bond_point_spacing == None: return [] xyz_list = [] for b in bonds: c = bond_point_count(b, bond_point_spacing) if c > 0: xyz1, xyz2 = map(lambda a: a.xformCoord().data(), b.atoms) for k in range(c): fb = float(k + 1) / (c + 1) fa = 1 - fb xyz = map(lambda a, b: fa * a + fb * b, xyz1, xyz2) xyz_list.append(xyz) from numpy import array, single as floatc, zeros if len(xyz_list) > 0: points = array(xyz_list, floatc) from Matrix import xform_matrix import _contour _contour.affine_transform_vertices(points, xform_matrix(xform)) else: points = zeros((0, 3), floatc) return points
def align_molecule(): # TODO: Not ported. from chimera import selection atoms = selection.currentAtoms(ordered=True) mols = set([a.molecule for a in atoms]) if len(mols) != 1: return mol = mols.pop() molxf = mol.openState.xform from Molecule import atom_positions axyz = atom_positions(atoms, molxf) from numpy import roll, float32, float64 from Matrix import xform_matrix, xform_points from chimera.match import matchPositions xflist = [] for mset in cage_marker_sets(): for p in polygons(mset): if p.n == len(atoms): c = p.center() vxyz = [p.vertex_xyz(m) for m in p.vertices] exyz = (0.5 * (vxyz + roll(vxyz, 1, axis=0))).astype(float32) xform_points(exyz, mset.transform(), molxf) xf, rms = matchPositions(exyz.astype(float64), axyz.astype(float64)) xflist.append(xf) molxf.multiply(xflist[0]) mol.openState.xform = molxf import MultiScale mm = MultiScale.multiscale_manager() tflist = [xform_matrix(xf) for xf in xflist] mm.molecule_multimer(mol, tflist)
def clicked_mask_region(segmentation, pointer_x, pointer_y): s = segmentation if not s.display: return None if s.mask is None: print 'mouse down: no current segmentation mask' return None mk, mj, mi = s.mask.shape box = ((0, 0, 0), (mi, mj, mk)) from Matrix import xform_matrix, multiply_matrices ijk_to_eye = multiply_matrices(xform_matrix(s.openState.xform), s.point_transform()) from VolumeViewer.slice import box_intercepts, array_slice_values ijk_in, ijk_out = box_intercepts(pointer_x, pointer_y, ijk_to_eye, box, s) if ijk_in is None or ijk_out is None: print 'mouse down: no intercept with mask' return None rnums = array_slice_values(s.mask, ijk_in, ijk_out, method='nearest')[:, 1] r = first_shown_region(s, rnums) if r is None: r = clicked_volume_region(segmentation, pointer_x, pointer_y) if r is None: print 'mouse down: no intercept with region' return None return r
def chain_center(chain): xyz = chain.lan_chain.source_atom_xyz() sc = center(xyz) from Matrix import apply_matrix, xform_matrix c = apply_matrix(xform_matrix(chain.xform), sc) return c
def chain_transform(cp): sm = cp.surface_model() xf = sm.openState.xform xf.multiply(cp.xform) from Matrix import xform_matrix t = xform_matrix(xf) return t
def transform_vertices_and_normals(v, n, xform): from Matrix import xform_matrix, zero_translation tf = xform_matrix(xform) rot = zero_translation(tf) from _contour import affine_transform_vertices affine_transform_vertices(v, tf) affine_transform_vertices(n, rot)
def atom_coordinates(atoms, xform): from _multiscale import get_atom_coordinates xyz = get_atom_coordinates(atoms, transformed = True) from Matrix import xform_matrix tf = xform_matrix(xform.inverse()) from _contour import affine_transform_vertices affine_transform_vertices(xyz, tf) return xyz
def move_objects(self, xf): from Matrix import xform_matrix tf = xform_matrix(xf) from _contour import affine_transform_vertices for p in self.pieces: varray, tarray = p.geometry affine_transform_vertices(varray, tf) p.geometry = varray, tarray
def atom_positions(atoms, xform = None): import _multiscale xyz = _multiscale.get_atom_coordinates(atoms, transformed = True) if xform: from Matrix import xform_matrix tf = xform_matrix(xform.inverse()) from _contour import affine_transform_vertices affine_transform_vertices(xyz, tf) return xyz
def get_atom_coordinates(atoms, xform): from _multiscale import get_atom_coordinates xyz = get_atom_coordinates(atoms, transformed=True) from _contour import affine_transform_vertices from Matrix import xform_matrix affine_transform_vertices(xyz, xform_matrix(xform)) return xyz
def get_atom_coordinates(atoms, xform): from _multiscale import get_atom_coordinates xyz = get_atom_coordinates(atoms, transformed = True) from _contour import affine_transform_vertices from Matrix import xform_matrix affine_transform_vertices(xyz, xform_matrix(xform)) return xyz
def data_region_xyz_to_ijk_transform(data_region): xf = data_region.model_transform() xf.invert() from Matrix import xform_matrix, translation_matrix, multiply_matrices xyz_to_data_xyz = xform_matrix(xf) data_xyz_to_ijk = data_region.data.xyz_to_ijk_transform ijk_min = data_region.region[0] ijk_origin_shift = translation_matrix(map(lambda a: -a, ijk_min)) xyz_to_ijk_transform = multiply_matrices( ijk_origin_shift, data_xyz_to_ijk, xyz_to_data_xyz) return xyz_to_ijk_transform
def molecule_atom_set(ma): m, atoms = ma from _multiscale import get_atom_coordinates xyz = get_atom_coordinates(atoms) from Matrix import xform_matrix transform = xform_matrix(m.openState.xform) aset = Atom_Set(xyz, transform, atoms) return aset
def chain_atom_subset(ca): cp, atoms = ca from _multiscale import get_atom_coordinates xyz = get_atom_coordinates(atoms) # transform = chain_transform(cp) from Matrix import xform_matrix transform = xform_matrix(cp.surface_model().openState.xform) aset = Atom_Set(xyz, transform, atoms, cp) return aset
def chain_radial_size(chain): xyz = chain.lan_chain.source_atom_xyz() from numpy import array, multiply, sum xyzc = array(xyz) from Matrix import xform_matrix import _contour _contour.affine_transform_vertices(xyzc, xform_matrix(chain.xform)) multiply(xyzc, xyzc, xyzc) r2 = sum(xyzc, axis=1) r2max = max(r2) import math r = math.sqrt(r2max) return r
def volume_plane_intercept(window_x, window_y, volume, k): from Matrix import multiply_matrices, xform_matrix, invert_matrix ijk_to_screen = multiply_matrices(xform_matrix(volume.model_transform()), volume.data.ijk_to_xyz_transform) screen_to_ijk = invert_matrix(ijk_to_screen) line = line_perpendicular_to_screen(window_x, window_y, screen_to_ijk) p, d = line if d[2] == 0: return None t = (k - p[2]) / d[2] ijk = (p[0] + t * d[0], p[1] + t * d[1], k) xyz = volume.data.ijk_to_xyz(ijk) return xyz
def volume_plane_intercept(window_x, window_y, volume, k): from Matrix import multiply_matrices, xform_matrix, invert_matrix ijk_to_screen = multiply_matrices(xform_matrix(volume.model_transform()), volume.data.ijk_to_xyz_transform) screen_to_ijk = invert_matrix(ijk_to_screen) line = line_perpendicular_to_screen(window_x, window_y, screen_to_ijk) p,d = line if d[2] == 0: return None t = (k - p[2]) / d[2] ijk = (p[0]+t*d[0], p[1]+t*d[1], k) xyz = volume.data.ijk_to_xyz(ijk) return xyz
def mask_volume_using_selected_surfaces(axis = (0,1,0), pad = None): from VolumeViewer import active_volume v = active_volume() if v is None: return from Surface import selected_surface_pieces plist = selected_surface_pieces() from Matrix import xform_matrix, invert_matrix tf = invert_matrix(xform_matrix(v.model_transform())) surfaces = surface_geometry(plist, tf, pad) if surfaces: masked_volume(v, surfaces, axis)
def mask_volume_using_selected_surfaces(axis=(0, 1, 0), pad=None): from VolumeViewer import active_volume v = active_volume() if v is None: return from Surface import selected_surface_pieces plist = selected_surface_pieces() from Matrix import xform_matrix, invert_matrix tf = invert_matrix(xform_matrix(v.model_transform())) surfaces = surface_geometry(plist, tf, pad) if surfaces: masked_volume(v, surfaces, axis)
def copy_groups(from_seg, to_seg): # Find transform from to_seg mask indices to from_seg mask indices. from Matrix import multiply_matrices, invert_matrix, xform_matrix tf = multiply_matrices( invert_matrix(from_seg.point_transform()), invert_matrix(xform_matrix(from_seg.openState.xform)), xform_matrix(to_seg.openState.xform), to_seg.point_transform()) # Find from_seg regions containing to_seg region maximum points. fmask = from_seg.mask rlist = list(to_seg.regions) ijk = [r.max_point for r in rlist] from _interpolate import interpolate_volume_data rnums, outside = interpolate_volume_data(ijk, tf, fmask, 'nearest') # Find to_seg regions that have max_point in same from_seg region. fr2tr = {} id2r = from_seg.id_to_region for tr, frnum in zip(rlist, rnums): if frnum > 0: fr = id2r[frnum].top_parent() if fr in fr2tr: fr2tr[fr].append(tr) else: fr2tr[fr] = [tr] groups = [g for g in fr2tr.values() if len(g) > 1] # Form groups. for g in groups: r = to_seg.join_regions(g) for gr in g: gr.set_color(r.color) print 'Made %d groups for %s matching %s' % (len(groups), to_seg.name, from_seg.name)
def face_normal(self, axis, side): xform = self.xform() if xform == None: return None from Matrix import invert_matrix, xform_matrix from Matrix import apply_matrix_without_translation, normalize_vector inv_s = invert_matrix(self.box_transform) n = inv_s[axis, :3] if side == 0: n = -n model_transform = xform_matrix(xform) ne = apply_matrix_without_translation(model_transform, n) ne = normalize_vector(ne) return ne
def molecule_grid_data(atoms, resolution, step, pad, cutoff_range, sigma_factor): from _multiscale import get_atom_coordinates, bounding_box xyz = get_atom_coordinates(atoms, transformed=True) # Transform coordinates to local coordinates of the molecule containing # the first atom. This handles multiple unaligned molecules. from Matrix import xform_matrix m0 = atoms[0].molecule tf = xform_matrix(m0.openState.xform.inverse()) from _contour import affine_transform_vertices affine_transform_vertices(xyz, tf) xyz_min, xyz_max = bounding_box(xyz) origin = [x - pad for x in xyz_min] ijk = (xyz - origin) / step anum = [a.element.number for a in atoms] sdev = sigma_factor * resolution / step from numpy import zeros, float32 sdevs = zeros((len(atoms), 3), float32) sdevs[:] = sdev from math import pow, pi, ceil normalization = pow(2 * pi, -1.5) * pow(sdev * step, -3) shape = [ int(ceil((xyz_max[a] - xyz_min[a] + 2 * pad) / step)) for a in (2, 1, 0) ] matrix = zeros(shape, float32) from _gaussian import sum_of_gaussians sum_of_gaussians(ijk, anum, sdevs, cutoff_range, matrix) matrix *= normalization molecules = set([a.molecule for a in atoms]) if len(molecules) > 1: name = 'molmap res %.3g' % (resolution, ) else: name = 'molmap %s res %.3g' % (m0.name, resolution) from VolumeData import Array_Grid_Data grid = Array_Grid_Data(matrix, origin, (step, step, step), name=name) return grid, molecules
def report_distance(xyz1, xyz2, from_name, to_name, surf, color): i1, i2, d = closest_approach(xyz1, xyz2) msg = 'minimum distance from %s to %s = %.5g' % (from_name, to_name, d) from chimera import replyobj replyobj.status(msg) replyobj.info(msg + '\n') if surf: from Matrix import apply_matrix, xform_matrix tf = xform_matrix(surf.openState.xform.inverse()) v = apply_matrix(tf, (xyz1[i1], xyz2[i2])) t = [(0, 1, 0)] p = surf.addPiece(v, t, color) p.displayStyle = p.Mesh p.useLighting = False p.lineThickness = 3
def report_transformation_matrix(self, model, map): m = model mname = '%s (%s)' % (m.name, m.oslIdent()) mxf = m.openState.xform f = map fname = '%s (%s)' % (f.name, f.oslIdent()) fxf = f.openState.xform mxf.premultiply(fxf.inverse()) from Matrix import xform_matrix mtf = xform_matrix(mxf) message = ('Position of %s relative to %s coordinates:\n' % (mname, fname)) message += transformation_description(mtf) from chimera import replyobj replyobj.info(message)
def contacting_transforms(mol, csys, tflist, cdist): from _multiscale import get_atom_coordinates points = get_atom_coordinates(mol.atoms) pxf = mol.openState.xform pxf.premultiply(csys.openState.xform.inverse()) from Matrix import xform_matrix, identity_matrix from numpy import array, float32 point_tf = xform_matrix(pxf) from _contour import affine_transform_vertices affine_transform_vertices(points, point_tf) # points in reference coords ident = array(identity_matrix(),float32) from _closepoints import find_close_points_sets, BOXES_METHOD ctflist = [tf for tf in tflist if len(find_close_points_sets(BOXES_METHOD, [(points, ident)], [(points, array(tf,float32))], cdist)[0][0]) > 0] return ctflist
def molecule_grid_data(atoms, resolution, step, pad, cutoff_range, sigma_factor): from _multiscale import get_atom_coordinates, bounding_box xyz = get_atom_coordinates(atoms, transformed = True) # Transform coordinates to local coordinates of the molecule containing # the first atom. This handles multiple unaligned molecules. from Matrix import xform_matrix m0 = atoms[0].molecule tf = xform_matrix(m0.openState.xform.inverse()) from _contour import affine_transform_vertices affine_transform_vertices(xyz, tf) xyz_min, xyz_max = bounding_box(xyz) origin = [x-pad for x in xyz_min] ijk = (xyz - origin) / step anum = [a.element.number for a in atoms] sdev = sigma_factor * resolution / step from numpy import zeros, float32 sdevs = zeros((len(atoms),3), float32) sdevs[:] = sdev from math import pow, pi, ceil normalization = pow(2*pi,-1.5)*pow(sdev*step,-3) shape = [int(ceil((xyz_max[a] - xyz_min[a] + 2*pad) / step)) for a in (2,1,0)] matrix = zeros(shape, float32) from _gaussian import sum_of_gaussians sum_of_gaussians(ijk, anum, sdevs, cutoff_range, matrix) matrix *= normalization molecules = set([a.molecule for a in atoms]) if len(molecules) > 1: name = 'molmap res %.3g' % (resolution,) else: name = 'molmap %s res %.3g' % (m0.name, resolution) from VolumeData import Array_Grid_Data grid = Array_Grid_Data(matrix, origin, (step,step,step), name = name) return grid, molecules
def contacting_transforms(mol, csys, tflist, cdist): from _multiscale import get_atom_coordinates points = get_atom_coordinates(mol.atoms) pxf = mol.openState.xform pxf.premultiply(csys.openState.xform.inverse()) from Matrix import xform_matrix, identity_matrix from numpy import array, float32 point_tf = xform_matrix(pxf) from _contour import affine_transform_vertices affine_transform_vertices(points, point_tf) # points in reference coords ident = array(identity_matrix(), float32) from _closepoints import find_close_points_sets, BOXES_METHOD ctflist = [ tf for tf in tflist if len( find_close_points_sets(BOXES_METHOD, [(points, ident)], [( points, array(tf, float32))], cdist)[0][0]) > 0 ] return ctflist
def transform_schematic(xform, center, from_rgba, to_rgba): corners = transform_square(xform, center) if corners is None: return None # No rotation. import _surface sm = _surface.SurfaceModel() varray = corners tarray = ((0, 1, 2), (0, 2, 3), (0, 1, 5), (0, 5, 4), (1, 2, 6), (1, 6, 5), (2, 3, 7), (2, 7, 6), (3, 0, 4), (3, 4, 7), (4, 5, 6), (4, 6, 7)) g1 = sm.addPiece(varray, tarray, from_rgba) from Matrix import xform_matrix, apply_matrix tf = xform_matrix(xform) corners2 = [apply_matrix(tf, p) for p in corners] varray2 = corners2 g2 = sm.addPiece(varray2, tarray, to_rgba) return sm
def per_model_clip_planes(clip_plane_model): if clip_plane_model == None or not clip_plane_model.useClipPlane: return [] p = clip_plane_model.clipPlane plane = (p.normal.data(), -p.offset()) planes = [plane] # Handle slab clipping mode. if clip_plane_model.useClipThickness: normal = map(lambda x: -x, p.normal.data()) offset = p.offset() - clip_plane_model.clipThickness plane = (normal, offset) planes.append(plane) from Matrix import xform_matrix model_to_screen = xform_matrix(clip_plane_model.openState.xform) tplanes = map(lambda p: transform_plane(p, model_to_screen), planes) return tplanes
def clicked_volume_region(segmentation, pointer_x, pointer_y): r = None s = segmentation m = s.mask v = s.volume_data() if v and v.shown() and v.single_plane() and not m is None: box = v.region[:2] from Matrix import xform_matrix, multiply_matrices ijk_to_eye = multiply_matrices(xform_matrix(s.openState.xform), s.point_transform()) from VolumeViewer.slice import box_intercepts ijk_in, ijk_out = box_intercepts(pointer_x, pointer_y, ijk_to_eye, box, v) if not ijk_in is None: i, j, k = [int(round(h)) for h in ijk_in] ksz, jsz, isz = m.shape if i >= 0 and i < isz and j >= 0 and j < jsz and k >= 0 and k < ksz: rid = s.mask[k, j, i] r = s.id_to_region.get(rid, None) return r
def transform_schematic(xform, center, from_rgba, to_rgba): corners = transform_square(xform, center) if corners is None: return None # No rotation. import _surface sm = _surface.SurfaceModel() varray = corners tarray = ((0,1,2),(0,2,3),(0,1,5),(0,5,4),(1,2,6),(1,6,5), (2,3,7),(2,7,6),(3,0,4),(3,4,7),(4,5,6),(4,6,7)) g1 = sm.addPiece(varray, tarray, from_rgba) from Matrix import xform_matrix, apply_matrix tf = xform_matrix(xform) corners2 = [apply_matrix(tf, p) for p in corners] varray2 = corners2 g2 = sm.addPiece(varray2, tarray, to_rgba) return sm
def subregion_grid(self, voxel_size, xform, name): bm = self.box_model if bm is None or bm.box is None or bm.model() is None: return None # Deterime array size. Use half voxel padding on all sides. elength = bm.edge_lengths() from math import ceil size = [ max(1, int(ceil((elength[a] - voxel_size[a]) / voxel_size[a]))) for a in (0, 1, 2) ] # Allocate array. from VolumeData import allocate_array array = allocate_array(size, zero_fill=True) # Determine origin, rotation, and cell angles. b2vxf = bm.xform() b2vxf.premultiply(xform.inverse()) from Matrix import xform_matrix, apply_matrix, apply_matrix_without_translation, cell_angles_and_rotation b2v = xform_matrix(b2vxf) origin = apply_matrix(b2v, bm.origin()) vaxes = [apply_matrix_without_translation(b2v, v) for v in bm.axes()] cell_angles, rotation = cell_angles_and_rotation(vaxes) # Create grid. from VolumeData import Array_Grid_Data g = Array_Grid_Data(array, origin, voxel_size, cell_angles, rotation, name=name) # Add half voxel padding. g.set_origin(g.ijk_to_xyz((0.5, 0.5, 0.5))) return g
def surface_geometry(plist, tf, pad): surfaces = [] for p in plist: surfs = [] va, ta = p.maskedGeometry(p.Solid) na = p.normals if isinstance(pad, (float, int)) and pad != 0: varray, tarray = offset_surface(va, ta, na, pad) elif isinstance(pad, (list, tuple)) and len(pad) == 2: varray, tarray = slab_surface(va, ta, na, pad) else: varray, tarray = va, ta if not tf is None: from Matrix import xform_matrix, multiply_matrices, is_identity_matrix vtf = multiply_matrices(tf, xform_matrix(p.model.openState.xform)) if not is_identity_matrix(vtf): apply_transform(vtf, varray) surfaces.append((varray, tarray)) return surfaces
def surface_geometry(plist, tf, pad): surfaces = [] for p in plist: surfs = [] va, ta = p.maskedGeometry(p.Solid) na = p.normals if isinstance(pad, (float,int)) and pad != 0: varray, tarray = offset_surface(va, ta, na, pad) elif isinstance(pad, (list,tuple)) and len(pad) == 2: varray, tarray = slab_surface(va, ta, na, pad) else: varray, tarray = va, ta if not tf is None: from Matrix import xform_matrix, multiply_matrices, is_identity_matrix vtf = multiply_matrices(tf, xform_matrix(p.model.openState.xform)) if not is_identity_matrix(vtf): apply_transform(vtf, varray) surfaces.append((varray, tarray)) return surfaces
def mask(volumes, surfaces, axis = None, fullMap = False, pad = 0., slab = None, sandwich = True, invertMask = False): from Commands import CommandError, filter_volumes, parse_floats vlist = filter_volumes(volumes) from Surface import selected_surface_pieces glist = selected_surface_pieces(surfaces, include_outline_boxes = False) if len(glist) == 0: raise CommandError, 'No surfaces specified' axis = parse_floats(axis, 'axis', 3, (0,1,0)) if not isinstance(fullMap, (bool,int)): raise CommandError, 'fullMap option value must be true or false' if not isinstance(invertMask, (bool,int)): raise CommandError, 'invertMask option value must be true or false' if not isinstance(pad, (float,int)): raise CommandError, 'pad option value must be a number' if isinstance(slab, (float,int)): pad = (-0.5*slab, 0.5*slab) elif not slab is None: pad = parse_floats(slab, 'slab', 2) if not isinstance(sandwich, bool): raise CommandError, 'sandwich option value must be true or false' from depthmask import surface_geometry, masked_volume from Matrix import xform_matrix, invert_matrix for v in vlist: tf = invert_matrix(xform_matrix(v.model_transform())) surfs = surface_geometry(glist, tf, pad) masked_volume(v, surfs, axis, fullMap, sandwich, invertMask)
def computeVolume(self, atoms, startFrame=None, endFrame=None, bound=None, volumeName=None, step=1, spacing=0.5): # load and process frames if startFrame is None: startFrame = self.startFrame if endFrame is None: endFrame = self.endFrame if bound is not None: from _closepoints import find_close_points, BOXES_METHOD from Matrix import xform_matrix if self.holdingSteady: steadyAtoms, steadySel, steadyCS, inverse = \ self.holdingSteady # all the above used later... inverse = xform_matrix(inverse) gridData = {} from math import floor from numpy import array, float32 from _contour import affine_transform_vertices for fn in range(startFrame, endFrame+1, step): cs = self.findCoordSet(fn) if not cs: self.status("Loading frame %d" % fn) self._LoadFrame(fn, makeCurrent=False) cs = self.findCoordSet(fn) self.status("Processing frame %d" % fn) pts = array([a.coord(cs) for a in atoms], float32) if self.holdingSteady: if bound is not None: steadyPoints = array([a.coord(cs) for a in steadyAtoms], float32) closeIndices = find_close_points( BOXES_METHOD, steadyPoints, #otherPoints, bound)[1] pts, bound)[1] pts = pts[closeIndices] try: xf, inv = self.transforms[fn] except KeyError: xf, inv = self.steadyXform(cs=cs) self.transforms[fn] = (xf, inv) xf = xform_matrix(xf) affine_transform_vertices(pts, xf) affine_transform_vertices(pts, inverse) # add a half-voxel since volume positions are # considered to be at the center of their voxel from numpy import floor, zeros pts = floor(pts/spacing + 0.5).astype(int) for pt in pts: center = tuple(pt) gridData[center] = gridData.get(center, 0) + 1 # generate volume self.status("Generating volume") axisData = zip(*tuple(gridData.keys())) minXyz = [min(ad) for ad in axisData] maxXyz = [max(ad) for ad in axisData] # allow for zero-padding on both ends dims = [maxXyz[axis] - minXyz[axis] + 3 for axis in range(3)] from numpy import zeros, transpose volume = zeros(dims, int) for index, val in gridData.items(): adjIndex = tuple([index[i] - minXyz[i] + 1 for i in range(3)]) volume[adjIndex] = val from VolumeData import Array_Grid_Data gd = Array_Grid_Data(volume.transpose(), # the "cushion of zeros" means d-1... [(d-1) * spacing for d in minXyz], [spacing] * 3) if volumeName is None: volumeName = self.ensemble.name gd.name = volumeName # show volume self.status("Showing volume") import VolumeViewer dataRegion = VolumeViewer.volume_from_grid_data(gd) vd = VolumeViewer.volumedialog.volume_dialog(create=True) vd.message("Volume can be saved from File menu") self.status("Volume shown")
def computeVolume(self, atoms, frame_ids, volumeName=None, spacing=0.5, radiiTreatment="ignored"): #function taken from Movie/gui.py and tweaked to compute volume based on an array of frame_ids from Matrix import xform_matrix gridData = {} from math import floor from numpy import array, float32, concatenate from _contour import affine_transform_vertices insideDeltas = {} include = {} sp2 = spacing * spacing for fn in frame_ids: cs = self.movie.findCoordSet(fn) if not cs: self.movie.status("Loading frame %d" % fn) self.movie._LoadFrame(int(fn), makeCurrent=False) cs = self.movie.findCoordSet(fn) self.movie.status("Processing frame %d" % fn) pts = array([a.coord(cs) for a in atoms], float32) if self.movie.holdingSteady: if bound is not None: steadyPoints = array([a.coord(cs) for a in steadyAtoms], float32) closeIndices = find_close_points( BOXES_METHOD, steadyPoints, #otherPoints, bound)[1] pts, bound)[1] pts = pts[closeIndices] try: xf, inv = self.movie.transforms[fn] except KeyError: xf, inv = self.movie.steadyXform(cs=cs) self.movie.transforms[fn] = (xf, inv) xf = xform_matrix(xf) affine_transform_vertices(pts, xf) affine_transform_vertices(pts, inverse) if radiiTreatment != "ignored": ptArrays = [pts] for pt, radius in zip(pts, [a.radius for a in atoms]): if radius not in insideDeltas: mul = 1 deltas = [] rad2 = radius * radius while mul * spacing <= radius: for dx in range(-mul, mul+1): for dy in range(-mul, mul+1): for dz in range(-mul, mul+1): if radiiTreatment == "uniform" \ and min(dx, dy, dz) > -mul and max(dx, dy, dz) < mul: continue key = tuple(sorted([abs(dx), abs(dy), abs(dz)])) if key not in include.setdefault(radius, {}): include[radius][key] = (dx*dx + dy*dy + dz*dz ) * sp2 <= rad2 if include[radius][key]: deltas.append([d*spacing for d in (dx,dy,dz)]) mul += 1 insideDeltas[radius] = array(deltas) if len(deltas) < 10: print deltas if insideDeltas[radius].size > 0: ptArrays.append(pt + insideDeltas[radius]) pts = concatenate(ptArrays) # add a half-voxel since volume positions are # considered to be at the center of their voxel from numpy import floor, zeros pts = floor(pts/spacing + 0.5).astype(int) for pt in pts: center = tuple(pt) gridData[center] = gridData.get(center, 0) + 1 # generate volume self.movie.status("Generating volume") axisData = zip(*tuple(gridData.keys())) minXyz = [min(ad) for ad in axisData] maxXyz = [max(ad) for ad in axisData] # allow for zero-padding on both ends dims = [maxXyz[axis] - minXyz[axis] + 3 for axis in range(3)] from numpy import zeros, transpose volume = zeros(dims, int) for index, val in gridData.items(): adjIndex = tuple([index[i] - minXyz[i] + 1 for i in range(3)]) volume[adjIndex] = val from VolumeData import Array_Grid_Data gd = Array_Grid_Data(volume.transpose(), # the "cushion of zeros" means d-1... [(d-1) * spacing for d in minXyz], [spacing] * 3) if volumeName is None: volumeName = self.movie.ensemble.name gd.name = volumeName # show volume self.movie.status("Showing volume") import VolumeViewer dataRegion = VolumeViewer.volume_from_grid_data(gd) vd = VolumeViewer.volumedialog.volume_dialog(create=True) vd.message("Volume can be saved from File menu") self.movie.status("Volume shown")
def update_force_field(self): pd = self.phantom_device if pd == None: return dr = self.data_region() if dr == None: self.remove_gradient_force() return data = dr.matrix(read_matrix = False) if data is None: self.remove_gradient_force() return xform = dr.model_transform() if xform == None: self.remove_gradient_force() return ijk_min, ijk_max = dr.ijk_bounds() bbox = chimera.BBox() bbox.llf = chimera.Point(*ijk_min) bbox.urb = chimera.Point(*ijk_max) cm = self.cursor_model cm.crosshair_bounding_box = bbox from Matrix import multiply_matrices, xform_matrix, invert_matrix btf = multiply_matrices(xform_matrix(xform), dr.data.ijk_to_xyz_transform) btf_inv = invert_matrix(btf) cm.crosshair_box_transform = (btf, btf_inv) # # TODO: These parameters are not adequate to determine whether volume # has changed. # volume_parameters = data.shape gf = self.gradient_force if gf and gf.volume_parameters != volume_parameters: self.remove_gradient_force() gf = None newtons_per_pound = 4.45 max_force_lbs = float_variable_value(self.maximum_force) max_force = newtons_per_pound * max_force_lbs force_constant = self.force_constant.value(default = 0) if self.auto_adjust_force_constant.get(): force_constant = self.adjust_force_constant(force_constant, max_force) ijk_to_vxyz = dr.matrix_indices_to_xyz_transform() from Matrix import multiply_matrices, xform_matrix, invert_matrix ijk_to_xyz = multiply_matrices(xform_matrix(xform), ijk_to_vxyz) xyz_to_ijk = invert_matrix(ijk_to_xyz) if gf == None: import _phantomcursor gf = _phantomcursor.Gradient_Force_Field(data, xyz_to_ijk, force_constant, max_force) gf.volume_parameters = volume_parameters self.gradient_force = gf pd.force_active = 0 pd.phantom_force_field = gf else: gf.maximum_force = max_force gf.force_constant = force_constant gf.xyz_to_grid_index = xyz_to_ijk force_on = (self.force_field.get() and (self.mode == 'cursor' or self.mode == 'move marker')) pd.force_active = force_on
def box_to_eye_transform(box_transform, xform): from Matrix import xform_matrix, multiply_matrices model_transform = xform_matrix(xform) # chimera.Xform -> 3x4 matrix transform = multiply_matrices(model_transform, box_transform) return transform