Source code for Vector

## TEMPY is a Python library designed to help the user manipulate and analyse atomic structures and density maps from 3D EM. 
## Copyright (c) 2013 Daven Vasishtan,Irene Farabella, Arun Prasad Pandurangan, Harpal Sahota, Frank Alber and Maya Topf


from math import sin, tan, cos, acos, atan2, asin, sqrt, pi
from numpy import matrix
from random import randrange, uniform
#from math import *

[docs]class Vector: """A class representing Cartesian 3-dimensonal vectors.""" def __init__(self, x,y,z): """x, y, z = Cartesian co-ordinates of vector.""" self.x = x self.y = y self.z = z def __repr__(self): return "(%.3f,%.3f,%.3f)" %(self.x, self.y, self.z) def __getitem__(self, index): l = [self.x, self.y, self.z] return l[index] def __iter__(self): l = [self.x, self.y, self.z] return l.__iter__()
[docs] def copy(self): """Return copy of Vector instance""" return Vector(self.x, self.y, self.z)
[docs] def mod(self): """Return the modulus (length) of the vector.""" return sqrt(self.x**2 + self.y**2 + self.z**2)
[docs] def reverse(self): """Return a Vector instance of the reverse of the vector (ie. Vector*-1).""" return Vector(-self.x,-self.y,-self.z)
[docs] def arg(self, vector): """Return the argument (angle) between this and another vector.""" top = self.dot(vector) bottom = self.mod()*vector.mod() #print 'top/bottom, top, bottom ', top/bottom, top, bottom if abs(top-bottom) < 0.00001: return 0.0 else: #print 'top/bottom, top, bottom ', top/bottom, top, bottom #return acos(top/bottom) return acos(min(max(top/bottom,-1.0),1.0))
[docs] def times(self, factor): """Return a Vector instance of the vector multiplied by a scalar factor.""" return Vector(factor*self.x, factor*self.y, factor*self.z)
[docs] def dot(self, vector): """Return the dot product of this and another vector.""" return vector.x * self.x + vector.y * self.y + vector.z * self.z
[docs] def cross(self, vector): """Return a Vector instance of the cross product of this and another vector.""" newX = self.y*vector.z - self.z*vector.y newY = self.z*vector.x - self.x*vector.z newZ = self.x*vector.y - self.y*vector.x return Vector(newX, newY, newZ)
def __sub__(self, vector): """Return a Vector instance of the subtraction of a vector from this one.""" newX = self.x - vector.x newY = self.y - vector.y newZ = self.z - vector.z return Vector(newX, newY, newZ)
[docs] def dist(self, vector): return (self-vector).mod()
def __add__(self, vector): """Return a Vector instance of the addition of a vector from this one.""" newX = self.x + vector.x newY = self.y + vector.y newZ = self.z + vector.z return Vector(newX, newY, newZ) def __mul__(self, prod): newX = self.x*prod newY = self.y*prod newZ = self.z*prod return Vector(newX, newY, newZ) def __div__(self, divisor): newX = self.x/float(divisor) newY = self.y/float(divisor) newZ = self.z/float(divisor) return Vector(newX, newY, newZ) def __neg__(self): return Vector(-self.x, -self.y, -self.z)
[docs] def translate(self, x, y, z): """Return Vector instance of translated vector. x, y, z = distance in Angstroms in respective Cartesian directions to translate vector.""" newX = self.x + x newY = self.y + y newZ = self.z + z return Vector(newX, newY, newZ)
[docs] def matrix_transform(self, rot_mat): """Return Vector instance transformed using a 3x3 matrix rot_mat = a 3x3 Python matrix instance.""" vec_mat = matrix([[self.x],[self.y],[self.z]]) new_pos = rot_mat*vec_mat x = float(new_pos[0]) y = float(new_pos[1]) z = float(new_pos[2]) return Vector(x,y,z)
[docs] def to_atom(self): from ProtRep import Atom template = 'ATOM 1 C NOR A 1 23.161 39.732 -25.038 1.00 10.00 C' a = Atom(template) a.x = self.x a.y = self.y a.z = self.z return a
[docs] def unit(self): """Return a Vector instance of a normalised unit vector.""" mod = self.mod() if mod==0: return Vector(0,0,0) return Vector(self.x/mod, self.y/mod, self.z/mod) #def out of the class . better have them separate as the script from the euler guy christoph goelke #http://www.lfd.uci.edu/~gohlke/ #http://www.lfd.uci.edu/~gohlke/code/transformations.py.html
[docs]def random_vector(min_v, max_v): x = uniform(min_v, max_v) y = uniform(min_v, max_v) z = uniform(min_v, max_v) return Vector(x,y,z)
[docs]def axis_angle_to_matrix(x, y, z, turn, rad=False): """Returns a matrix form of an axis angle rotation. x, y, z = axis of rotation (does not need to be normalised). turn = angle of rotation, in radians if rad=True, else in degrees.""" if not rad: turn = turn*pi/180 c_a = cos(turn) s_a = sin(turn) v = Vector(x,y,z).unit() x = v.x y = v.y z = v.z rot_mat = matrix([[x**2+(1-x**2)*c_a, x*y*(1-c_a)-z*s_a, x*z*(1-c_a)+y*s_a], [ x*y*(1-c_a)+z*s_a, y**2+(1-y**2)*c_a, y*z*(1-c_a)-x*s_a], [x*z*(1-c_a)-y*s_a, y*z*(1-c_a)+x*s_a, z**2+(1-z**2)*c_a]]) return rot_mat
[docs]def euler_to_matrix(x_turn, y_turn, z_turn, rad=False): """Returns a matrix form of a euler rotation. x_turn, y_turn, z_turn = rotation angles around respective axis, in radians if rad=True, else in degrees.""" if not rad: x_turn = x_turn*pi/180 y_turn = y_turn*pi/180 z_turn = z_turn*pi/180 x_mat = axis_angle_to_matrix(0,0,1,x_turn, rad=True) y_mat = axis_angle_to_matrix(0,1,0,y_turn, rad=True) z_mat = axis_angle_to_matrix(1,0,0,z_turn, rad=True) return x_mat*y_mat*z_mat
[docs]def axis_angle_to_euler(x,y,z, turn, rad=False): """Returns a euler form of an axis angle rotation. x, y, z = axis of rotation (does not need to be normalised). turn = angle of rotation, in radians if rad=True, else in degrees.""" if not rad: turn = turn*pi/180 z_rot = atan2(y*sin(turn)-x*z*(1-cos(turn)), 1-(y**2+z**2)*(1-cos(turn))) x_rot = asin(x*y*(1-cos(turn))+z*sin(turn)) y_rot = atan2(x*sin(turn)-y*z*(1-cos(turn)), 1-(x**2+z**2)*(1-cos(turn))) return (x_rot, y_rot, z_rot) # -- Vector methods for torsion angle geometry -- #
[docs]def torsion(a, b, c): """Find the torsion angle between planes ab and bc. a,b,c = Vector instances.""" n1 = a.cross(b) n2 = b.cross(c) return n1.arg(n2)
[docs]def altTorsion(a,b,c): """An alternate and better way to find the torsion angle between planes ab and bc. a,b,c = Vector instances.""" A = a.dot(b.cross(c))*b.mod() B = (a.cross(b)).dot(b.cross(c)) return atan2(A,B)