def basis_coordinate_transform(axes): from Matrix import invert_matrix bct = invert_matrix(((axes[0][0], axes[1][0], axes[2][0], 0), (axes[0][1], axes[1][1], axes[2][1], 0), (axes[0][2], axes[1][2], axes[2][2], 0))) return bct
def close_packing_matrices(tflist, ref_point, center, a, b, c, alpha, beta, gamma): u2r = unit_cell_to_xyz_matrix(a, b, c, alpha, beta, gamma) from Matrix import invert_matrix r2u = invert_matrix(u2r) stflist = [] from Matrix import apply_matrix, translation_matrix, multiply_matrices from numpy import array, subtract, add for tf in tflist: # shift = u2r * -map(int, r2u * (tf * center - center) + (.5,.5,.5)) ntf = array(tf) tfc = apply_matrix(ntf, ref_point) csep = subtract(tfc, center) ucsep = apply_matrix(r2u, csep) import math ushift = map(math.floor, add(ucsep, (.5,.5,.5))) shift = apply_matrix(u2r, ushift) neg_shift = map(lambda x: -x, shift) tfshift = translation_matrix(neg_shift) stf = multiply_matrices(tfshift, ntf) stflist.append(stf) return stflist
def unique_asymmetric_unit_pairs(plist, angle_tolerance, shift_tolerance): from bins import Binned_Transforms b = Binned_Transforms(angle_tolerance, shift_tolerance) from Matrix import invert_matrix, multiply_matrices uplist = [] tf1_inverse_cache = {} equiv_asu_pairs = {} for asu1, asu2 in plist: tf1_index = asu1.ncs_index if tf1_index in tf1_inverse_cache: tf1_inv = tf1_inverse_cache[tf1_index] else: tf1_inv = invert_matrix(asu1.transform) tf1_inverse_cache[tf1_index] = tf1_inv rel = multiply_matrices(tf1_inv, asu2.transform) close = b.close_transforms(rel) if close: equiv_asu_pairs[close[0]].append((asu1, asu2)) # duplicate else: b.add_transform(rel) equiv_asu_pairs[rel] = [(asu1, asu2)] uplist.append(equiv_asu_pairs[rel]) return uplist
def close_transforms(self, tf): a = rotation_angle(tf) # In range 0 to pi x,y,z = tf[0][3], tf[1][3], tf[2][3] c = (a,x,y,z) clist = self.bins.close_objects(c, self.spacing) if len(clist) == 0: return [] close = [] from Matrix import invert_matrix, multiply_matrices itf = invert_matrix(tf) for ctf in clist: dtf = multiply_matrices(ctf, itf) x,y,z = dtf[0][3], dtf[1][3], dtf[2][3] if (abs(x) < self.translation and abs(y) < self.translation and abs(z) < self.translation): a = rotation_angle(dtf) from math import pi if a < self.angle: close.append(ctf) return close
def nearby_boxes(box, crystal): from Matrix import multiply_matrices, invert_matrix act = basis_coordinate_transform(crystal.axes) isi = crystal.identity_smtry_index box2_cache = {} plist = [] for ncs1index, ncs1 in enumerate(crystal.ncs_matrices): ncs1_inv = invert_matrix(ncs1) box1 = transformed_bounding_box(box, multiply_matrices(act, ncs1)) asu1 = NCS_Asymmetric_Unit(ncs1index, isi, (0, 0, 0), ncs1) for ncs2index, ncs2 in enumerate(crystal.ncs_matrices): for symindex, sym in enumerate(crystal.smtry_matrices): identity_sym = (symindex == isi) if (ncs2index, symindex) in box2_cache: sym_ncs2, box2 = box2_cache[(ncs2index, symindex)] else: sym_ncs2 = multiply_matrices(sym, ncs2) box2_tf = multiply_matrices(act, sym_ncs2) box2 = transformed_bounding_box(box, box2_tf) box2_cache[(ncs2index, symindex)] = (sym_ncs2, box2) tlist = overlapping_translations(box1, box2, crystal.axes) for t, ucijk in tlist: if (identity_sym and ucijk == (0, 0, 0) and ncs1index >= ncs2index): continue # Include only 1 copy of pair trans_sym_ncs2 = translate_matrix(t, sym_ncs2) asu2 = NCS_Asymmetric_Unit(ncs2index, symindex, ucijk, trans_sym_ncs2) plist.append((asu1, asu2)) return plist
def nearby_boxes(box, crystal): from Matrix import multiply_matrices, invert_matrix act = basis_coordinate_transform(crystal.axes) isi = crystal.identity_smtry_index box2_cache = {} plist = [] for ncs1index, ncs1 in enumerate(crystal.ncs_matrices): ncs1_inv = invert_matrix(ncs1) box1 = transformed_bounding_box(box, multiply_matrices(act, ncs1)) asu1 = NCS_Asymmetric_Unit(ncs1index, isi, (0,0,0), ncs1) for ncs2index, ncs2 in enumerate(crystal.ncs_matrices): for symindex, sym in enumerate(crystal.smtry_matrices): identity_sym = (symindex == isi) if (ncs2index, symindex) in box2_cache: sym_ncs2, box2 = box2_cache[(ncs2index, symindex)] else: sym_ncs2 = multiply_matrices(sym, ncs2) box2_tf = multiply_matrices(act, sym_ncs2) box2 = transformed_bounding_box(box, box2_tf) box2_cache[(ncs2index, symindex)] = (sym_ncs2, box2) tlist = overlapping_translations(box1, box2, crystal.axes) for t, ucijk in tlist: if (identity_sym and ucijk == (0,0,0) and ncs1index >= ncs2index): continue # Include only 1 copy of pair trans_sym_ncs2 = translate_matrix(t, sym_ncs2) asu2 = NCS_Asymmetric_Unit(ncs2index, symindex, ucijk, trans_sym_ncs2) plist.append((asu1, asu2)) return plist
def close_packing_matrices(tflist, ref_point, center, a, b, c, alpha, beta, gamma): u2r = unit_cell_to_xyz_matrix(a, b, c, alpha, beta, gamma) from Matrix import invert_matrix r2u = invert_matrix(u2r) stflist = [] from Matrix import apply_matrix, translation_matrix, multiply_matrices from numpy import array, subtract, add for tf in tflist: # shift = u2r * -map(int, r2u * (tf * center - center) + (.5,.5,.5)) ntf = array(tf) tfc = apply_matrix(ntf, ref_point) csep = subtract(tfc, center) ucsep = apply_matrix(r2u, csep) import math ushift = map(math.floor, add(ucsep, (.5, .5, .5))) shift = apply_matrix(u2r, ushift) neg_shift = map(lambda x: -x, shift) tfshift = translation_matrix(neg_shift) stf = multiply_matrices(tfshift, ntf) stflist.append(stf) return stflist
def transform_plane(plane, transform): from Matrix import invert_matrix, transpose_matrix from Matrix import apply_matrix_without_translation, apply_matrix inv_tf = invert_matrix(transform) inv_tf_transpose = transpose_matrix(inv_tf) normal, offset = plane n = apply_matrix_without_translation(inv_tf_transpose, normal) o = offset - inner_product(normal, apply_matrix(inv_tf, (0, 0, 0))) return (n, o)
def transform_plane(plane, transform): from Matrix import invert_matrix, transpose_matrix from Matrix import apply_matrix_without_translation, apply_matrix inv_tf = invert_matrix(transform) inv_tf_transpose = transpose_matrix(inv_tf) normal, offset = plane n = apply_matrix_without_translation(inv_tf_transpose, normal) o = offset - inner_product(normal, apply_matrix(inv_tf, (0,0,0))) return (n, o)
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 box_intercepts(window_x, window_y, box_to_screen_transform, box, clip_plane_model = None): from Matrix import invert_matrix box_transform = invert_matrix(box_to_screen_transform) line = line_perpendicular_to_screen(window_x, window_y, box_transform) xyz_in, xyz_out = box_line_intercepts(line, box) if xyz_in == None or xyz_out == None: return xyz_in, xyz_out planes = clip_planes(box_transform, clip_plane_model) xyz_in, xyz_out, f1, f2 = clip_segment_with_planes(xyz_in, xyz_out, planes) return xyz_in, xyz_out
def cell_origin(grid_origin, axes, interior_point): from numpy import array, transpose, subtract, floor, add from numpy import dot as matrix_multiply from numpy.linalg import inv as invert_matrix c2rt = array(axes) c2r = transpose(c2rt) # Crystal coords to real coords r2c = invert_matrix(c2r) # Real coords to crystal coords ip_c = matrix_multiply(r2c, interior_point) # To crystal coords. ipo_c = subtract(ip_c, grid_origin) # Relative to grid origin. co_c = floor(ipo_c) # Offset to containing cell. o_c = add(grid_origin, co_c) # Origin of containing cell. co = matrix_multiply(c2r, o_c) # To real coords. return tuple(co)
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 box_intercepts(window_x, window_y, box_to_screen_transform, box, clip_plane_model=None): from Matrix import invert_matrix box_transform = invert_matrix(box_to_screen_transform) line = line_perpendicular_to_screen(window_x, window_y, box_transform) xyz_in, xyz_out = box_line_intercepts(line, box) if xyz_in == None or xyz_out == None: return xyz_in, xyz_out planes = clip_planes(box_transform, clip_plane_model) xyz_in, xyz_out, f1, f2 = clip_segment_with_planes(xyz_in, xyz_out, planes) return xyz_in, xyz_out
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 transformation_and_inverse(origin, step, axes): ox, oy, oz = origin d0, d1, d2 = step ax, ay, az = axes tf = ((d0 * ax[0], d1 * ay[0], d2 * az[0], ox), (d0 * ax[1], d1 * ay[1], d2 * az[1], oy), (d0 * ax[2], d1 * ay[2], d2 * az[2], oz)) from Matrix import invert_matrix tf_inv = invert_matrix(tf) # Replace array by tuples tf_inv = tuple(map(tuple, tf_inv)) return tf, tf_inv
def transformation_and_inverse(origin, step, axes): ox, oy, oz = origin d0, d1, d2 = step ax, ay, az = axes tf = ((d0*ax[0], d1*ay[0], d2*az[0], ox), (d0*ax[1], d1*ay[1], d2*az[1], oy), (d0*ax[2], d1*ay[2], d2*az[2], oz)) from Matrix import invert_matrix tf_inv = invert_matrix(tf) # Replace array by tuples tf_inv = tuple(map(tuple, tf_inv)) return tf, tf_inv
def space_group_matrices(space_group, a, b, c, alpha, beta, gamma): import space_groups sgtable = space_groups.space_group_symmetry_table() if not sgtable.has_key(space_group): return [] unit_cell_matrices = sgtable[space_group] r2r_symops = [] u2r = unit_cell_to_xyz_matrix(a, b, c, alpha, beta, gamma) from Matrix import invert_matrix, multiply_matrices r2u = invert_matrix(u2r) for u2u in unit_cell_matrices: r2u_sym = multiply_matrices(u2u, r2u) r2r = multiply_matrices(u2r, r2u_sym) r2r_symops.append(r2r) return r2r_symops
def map_points_and_weights(v, above_threshold, metric = 'sum product'): from chimera import Xform m, tf_inv = v.matrix_and_transform(Xform(), subregion = None, step = None) from Matrix import invert_matrix tf = invert_matrix(tf_inv) size = list(m.shape) size.reverse() from VolumeData import grid_indices from numpy import single as floatc, ravel, nonzero, take points = grid_indices(size, floatc) # i,j,k indices import _contour _contour.affine_transform_vertices(points, tf) weights = ravel(m).astype(floatc) if above_threshold: # Keep only points where density is above lowest displayed threshold threshold = min(v.surface_levels) from numpy import greater_equal, compress ge = greater_equal(weights, threshold) points = compress(ge, points, 0) weights = compress(ge, weights) if metric == 'correlation about mean': wm = weights.sum() / len(weights) weights -= wm else: # Eliminate points with zero weight. nz = nonzero(weights)[0] if len(nz) < len(weights): points = take(points, nz, axis=0) weights = take(weights, nz, axis=0) return points, weights
def close_transforms(self, tf): a = rotation_angle(tf) # In range 0 to pi x, y, z = tf[0][3], tf[1][3], tf[2][3] c = (a, x, y, z) clist = self.bins.close_objects(c, self.spacing) if len(clist) == 0: return [] close = [] from Matrix import invert_matrix, multiply_matrices itf = invert_matrix(tf) for ctf in clist: dtf = multiply_matrices(ctf, itf) x, y, z = dtf[0][3], dtf[1][3], dtf[2][3] if (abs(x) < self.translation and abs(y) < self.translation and abs(z) < self.translation): a = rotation_angle(dtf) from math import pi if a < self.angle: close.append(ctf) return close
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 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 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 eye_to_box_transform(box_transform, xform): tf = box_to_eye_transform(box_transform, xform) from Matrix import invert_matrix inv_tf = invert_matrix(tf) return inv_tf