def doit(self,mobAtoms): """ mobAtoms: AtomSet that is being frozen. Assuming the AtomSet are from same molecule """ # fixme: need checking for mat (matrix) and mobAtoms geomContainer = mobAtoms[0].top.geomContainer mGeom = geomContainer.masterGeom mat = mGeom.rotation mat = Numeric.reshape(mat, (4,4)) # update coords mobAtoms = mobAtoms.findType(Atom) coords = mobAtoms.coords hCoords = Numeric.concatenate((coords,Numeric.ones((len(coords),1),\ 'd')), 1) tCoords = Numeric.dot(hCoords, mat)[:,:3] tCoords = tCoords.tolist() mobAtoms.updateCoords(tCoords, 0) # overwritten the original coords # reset the rotation matrix of masterGeom identity = Numeric.identity(4,'f').ravel() mGeom.SetRotation(Numeric.identity(4,'f').ravel() ) event = EditAtomsEvent('coords', mobAtoms) self.vf.dispatchEvent(event) mGeom.viewer.Redraw() return
def getMatrices(self, mol=None, keyword='MTRIX'): if mol is None: return matrices = [] next = 0 lines = mol.data[0].parser.allLines arr = Numeric.identity(4).astype('f') for l in lines: spl = string.split(l) if spl[0][:-1] != keyword: continue index = int(spl[0][-1:])-1 arr[index][0] = float(spl[2]) arr[index][1] = float(spl[3]) arr[index][2] = float(spl[4]) if index == 2: matrices.append(arr) arr = Numeric.identity(4).astype('f') return matrices
def inverse4X4(matrix): """ returns the inverse of the given 4x4 transformation matrix t_1: the negetive of Translation vector r_1: the inverse of rotation matrix inversed transformation is 1) t_1 applied first 2) then r_1 is applied to validate the result, N.dot(matrix, mat_inverse)==N.identity(4,'f') """ # check the shape if matrix.shape != (4, 4) and matrix.shape != (16, ): raise ValueError("Argument must Numeric array of shape (4,4) or (16,)") return None if matrix.shape == (16, ): matrix = N.array(matrix, 'f') matrix = N.reshape(matrix, (4, 4)) # force the matrix to be (4,4) t_1 = N.identity(4, 'f') t_1[:2, 3] = -matrix[:2, 3] r_1 = N.identity(4, 'f') r_1[:3, :3] = N.transpose(matrix[:3, :3]) mat_inverse = N.dot(r_1, t_1) #asert N.dot(matrix, mat_inverse) is N.identity(4,'f') return mat_inverse
def inverse4X4(matrix): """ returns the inverse of the given 4x4 transformation matrix t_1: the negetive of Translation vector r_1: the inverse of rotation matrix inversed transformation is 1) t_1 applied first 2) then r_1 is applied to validate the result, N.dot(matrix, mat_inverse)==N.identity(4,'f') """ # check the shape if matrix.shape !=(4,4) and matrix.shape !=(16,) : raise ValueError("Argument must Numeric array of shape (4,4) or (16,)") return None if matrix.shape ==(16,): matrix=N.array(matrix,'f') matrix=N.reshape(matrix,(4,4)) # force the matrix to be (4,4) t_1=N.identity(4,'f') t_1[:2,3]= - matrix[:2, 3] r_1=N.identity(4,'f') r_1[:3,:3] = N.transpose(matrix[:3,:3]) mat_inverse=N.dot(r_1, t_1) #asert N.dot(matrix, mat_inverse) is N.identity(4,'f') return mat_inverse
def doit(self, mobAtoms): """ mobAtoms: AtomSet that is being frozen. Assuming the AtomSet are from same molecule """ # fixme: need checking for mat (matrix) and mobAtoms geomContainer = mobAtoms[0].top.geomContainer mGeom = geomContainer.masterGeom mat = mGeom.rotation mat = Numeric.reshape(mat, (4, 4)) # update coords mobAtoms = mobAtoms.findType(Atom) coords = mobAtoms.coords hCoords = Numeric.concatenate((coords,Numeric.ones((len(coords),1),\ 'd')), 1) tCoords = Numeric.dot(hCoords, mat)[:, :3] tCoords = tCoords.tolist() mobAtoms.updateCoords(tCoords, 0) # overwritten the original coords # reset the rotation matrix of masterGeom identity = Numeric.identity(4, 'f').ravel() mGeom.SetRotation(Numeric.identity(4, 'f').ravel()) event = EditAtomsEvent('coords', mobAtoms) self.vf.dispatchEvent(event) mGeom.viewer.Redraw() return
def getMatrices(self): m=[] mat=Numeric.identity(4).astype('f') if self.length is None or self.length == 0: m.append( Numeric.identity(4).astype('f') ) return m if self.identity == 1: m.append( Numeric.identity(4).astype('f') ) mat[:3, 3] = (self.vector*self.length).astype('f') m.append(mat) return m
def test_0031(self ): # example we test glMultMatrixf import Tkinter root = Tkinter.Tk() vi = OGLTkWidget(root) id = Numeric.array([1.,0.,0.,0., 0.,1.,0.,0., 0.,0.,1.,0., 0.,0.,0.,1.], "d") from opengltk.extent import _gllib as gllib #GL.glMultMatrixf(id) try: gllib.cvar.checkArgumentsInCWrapper = 0 GL.glMultMatrixf(id) # calling with bad argument gllib.cvar.checkArgumentsInCWrapper = 1 #import numpy.oldnumeric as Numeric id = Numeric.identity(4).astype('d') try: GL.glMultMatrixf(id) raise RuntimeError('failed to catch type error in wrapper') except TypeError: print 'Type Error caught succefully in wrapper' except ImportError: pass root.after(1000, root.quit ) root.mainloop() root.destroy()
def doit(self, geom, matrix): # gets called from NodeRepr() blender = [] # if self.usePROTO is set to 1: don't convert instance matrices # geoms into geoms, but use the vrml2 USE if self.usePROTOFlag: # create all the necessary data to be put in the PROTO which goes # in the header of the vrml2 file if geom.VRML2CreatedPROTOForThisGeom == 0: name = self.getGeomName(geom) blender.append("PROTO " + name + " [ ] {\n") identityMatrix = Numeric.identity(4).astype('f') blender.extend(self.doitReally(geom, identityMatrix)) blender.append("}\n") # now insert this into the header of self.output for i in range(len(vrml2)): self.output.insert(i + 1, blender[i]) geom.VRML2CreatedPROTOForThisGeom = 1 # don't add this geom # to the header next time # this PROTO flag will be deleted when we leave the recursive # and add it as USE to the body blender = [] # clear the list because this data has been added blender.extend(self.doitUsePROTO(geom, matrix)) return blender else: # here we save all the data for all geoms return self.doitReally(geom, matrix)
def rotz(angle): ret = numerix.identity(4).astype(numerix.Float) ret[0, 0] = ret[1, 1] = numerix.cos(angle) sn = numerix.sin(angle) ret[0, 1] = -sn ret[1, 0] = sn return ret
def _checkOrth(self, T, TT, eps=0.0001, output=False): """check if the basis is orthogonal on a set of points x: TT == T*transpose(T) == c*Identity INPUT: T: matrix of values of polynomials calculated at common reference points (x) TT = T * transpose(T) eps: max numeric error """ TTd0 = (-1. * Numeric.identity(Numeric.shape(TT)[0]) + 1) * TT # TTd0 = TT with 0s on the main diagonal s = Numeric.sum(Numeric.sum(Numeric.absolute(TTd0))) minT = MLab.min(MLab.min(T)) maxT = MLab.max(MLab.max(T)) minTTd0 = MLab.min(MLab.min(TTd0)) maxTTd0 = MLab.max(MLab.max(TTd0)) if not s < eps: out = "NOT ORTHOG, min(T), max(T):\t%f\t%f\n" % (minT, maxT) out += " min(TTd0), max(TTd0), sum-abs-el(TTd0):\t%f\t%f\t%f" % ( minTTd0, maxTTd0, s) if output: print out return False else: raise out elif output: out = "ORTHOGONAL, min(T), max(T):\t%f\t%f\n" % (minT, maxT) out += " min(TTd0), max(TTd0), sum-abs-el(TTd0):\t%f\t%f\t%f" % ( minTTd0, maxTTd0, s) print out return True
def rotz(angle): ret = numerix.identity(4).astype(numerix.Float) ret[0,0] = ret[1,1] = numerix.cos(angle) sn = numerix.sin(angle) ret[0,1] = -sn ret[1,0] = sn return ret
def GetMatrix(self, root=None, instance=None, scale=True, transpose=True): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Returns the matrix by which this object is transformed scale = False: returns the rotation and translation. no scaling info included Used to save the transformed geom --> coords --> new pdb file instance is a list of integer instance indices for all parents """ if root is None: root = self.viewer.rootObject if instance is None: instance = [0] p = self.parent while p: instance.append(0) p = p.parent GL.glPushMatrix() GL.glLoadIdentity() #print 'GetMatrix', instance self.BuildMat(self, root, scale, instance) #GL.glMultMatrixf(self.instanceMatricesFortran[instanceList[0]]]) m = Numeric.array(GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)).astype('f') GL.glPopMatrix() if Numeric.alltrue(m==Numeric.zeros(16).astype('f')): # this happens when Pmv has no GUI m = Numeric.identity(4) if transpose: return Numeric.transpose(Numeric.reshape(m, (4,4))) else: return Numeric.reshape(m, (4,4))
def doit(self, geom, matrix): # gets called from NodeRepr() blender = [] # if self.usePROTO is set to 1: don't convert instance matrices # geoms into geoms, but use the vrml2 USE if self.usePROTOFlag: # create all the necessary data to be put in the PROTO which goes # in the header of the vrml2 file if geom.VRML2CreatedPROTOForThisGeom == 0: name = self.getGeomName(geom) blender.append("PROTO "+name+" [ ] {\n") identityMatrix = Numeric.identity(4).astype('f') blender.extend( self.doitReally(geom, identityMatrix) ) blender.append("}\n") # now insert this into the header of self.output for i in range(len(vrml2)): self.output.insert(i+1,blender[i]) geom.VRML2CreatedPROTOForThisGeom = 1 # don't add this geom # to the header next time # this PROTO flag will be deleted when we leave the recursive # and add it as USE to the body blender = [] # clear the list because this data has been added blender.extend( self.doitUsePROTO(geom, matrix) ) return blender else: # here we save all the data for all geoms return self.doitReally(geom, matrix)
def _checkOrth(self, T, TT, eps=0.0001, output=False): """check if the basis is orthogonal on a set of points x: TT == T*transpose(T) == c*Identity INPUT: T: matrix of values of polynomials calculated at common reference points (x) TT = T * transpose(T) eps: max numeric error """ TTd0 = (-1.*Numeric.identity(Numeric.shape(TT)[0])+1) * TT # TTd0 = TT with 0s on the main diagonal s = Numeric.sum(Numeric.sum(Numeric.absolute(TTd0))) minT = MLab.min(MLab.min(T)) maxT = MLab.max(MLab.max(T)) minTTd0 = MLab.min(MLab.min(TTd0)) maxTTd0 = MLab.max(MLab.max(TTd0)) if not s < eps: out = "NOT ORTHOG, min(T), max(T):\t%f\t%f\n" % (minT, maxT) out += " min(TTd0), max(TTd0), sum-abs-el(TTd0):\t%f\t%f\t%f" % (minTTd0, maxTTd0, s) if output: print out return False else: raise out elif output: out = "ORTHOGONAL, min(T), max(T):\t%f\t%f\n" % (minT, maxT) out += " min(TTd0), max(TTd0), sum-abs-el(TTd0):\t%f\t%f\t%f" % (minTTd0, maxTTd0, s) print out return True
def getMatrices(self): angle=360.0/self.symmetry m=[] t=Numeric.array(self.point)*-1 if self.identity == 1: mat = Numeric.identity(4).astype('f') m.append(mat) T = Transformation(trans=t) T1 = T.inverse() for i in range(self.symmetry-1): newList=[] newList.extend(list(self.vector)) newList.append(angle) R = Transformation(quaternion=newList) mt = T1 * R * T #newmat = mt.getMatrix() newmat = mt.getDejaVuMatrix() m.append(newmat) angle=angle+360.0/self.symmetry return m
def scale(sxyz): ret = numerix.identity(4).astype(numerix.Float) s = numerix.ones(3, numerix.Float) s[0:len(sxyz)] = sxyz ret[0, 0] = s[0] ret[1, 1] = s[1] ret[2, 2] = s[2] return ret
def set(self, coords=None, matrices=None): if coords is None: return else: self.coords = Numeric.array(coords).astype('f') if matrices is None: self.matrices = [Numeric.identity(4).astype('f')] else: #assert matrices.shape[-2] == 4 and matrices.shape[-1] == 4 self.matrices = matrices
def scale(sxyz): ret = numerix.identity(4).astype(numerix.Float) s = numerix.ones(3, numerix.Float) s[0:len(sxyz)] = sxyz ret[0,0] = s[0] ret[1,1] = s[1] ret[2,2] = s[2] return ret
def __call__(self, inMatrices, applyIndex=None): """outMatrices <- SymMerge(inMatrices, applyIndex=None) inMatrices: list of 4x4 matrices outMatrices: list of 4x4 matrices """ if not inMatrices: inMatrices = [Numeric.identity(4).astype('f')] return inMatrices
def __init__(self, name='Common2d3dObject', check=1, **kw): """Constructor """ #self.newList = GL.glGenLists(1) self.name = name self.viewer = None self.immediateRendering = False self.needsRedoDpyListOnResize = False self.protected = False # False == not protected against deletion self.replace = True # this is used to store in a geometry the # desired behavior when adding the geom to the Viewer. # in AddObject, if replace is not specified, geom.replace will be # used self.isExpandedInObjectList = 1 # set to 1 when children of that geom # are visible in ViewerGUI object list self.parent = None # parent object self.fullName = name # object's name including parent's name self.children = [] # list of children self.listed = True # When true the name of this object appears # in the GUI's object self.pickable = True # when set the object can be picked self.pickNum = 0 self.dpyList = None # display list for drawing self.pickDpyList = None # display list for picking # FIXME: quick hack. Flag set by SetCurrentXxxx. When set object's # transformation and material are saved in log file self.hasBeenCurrent = False self.depthMask = 1 # 0: zbuffer is readOnly for transparent objects # 1: zbuffer is read write for transparent objects self.srcBlendFunc = GL.GL_SRC_ALPHA #self.dstBlendFunc = GL.GL_ONE #GL.GL_ONE_MINUS_SRC_COLOR # ONE_MINUS_SRC_ALPHA works for colorMapEditor self.dstBlendFunc = GL.GL_ONE_MINUS_SRC_ALPHA self.transparent = False #viewerConst.NO self.visible = True m = Numeric.reshape( Numeric.identity(4), (1,16) ) self.instanceMatricesFortran = m.astype('f') self.ownGui = None self.animatable = True apply( self.Set, (check, 0), kw) self._modified = False # used to decide if we should save state
def __call__(self, inMatrices, applyIndex=None): """outMatrices <- SymSplit(inMatrices, applyIndex=None) inMatrices: list of 4x4 matrices outMatrices: list of 4x4 matrices """ if not inMatrices: outMatrices = [Numeric.identity(4).astype('f')] else: outMatrices = self.getMatrices() return outMatrices
def __init__(self, name='Common2d3dObject', check=1, **kw): """Constructor """ #self.newList = GL.glGenLists(1) self.name = name self.viewer = None self.immediateRendering = False self.needsRedoDpyListOnResize = False self.protected = False # False == not protected against deletion self.replace = True # this is used to store in a geometry the # desired behavior when adding the geom to the Viewer. # in AddObject, if replace is not specified, geom.replace will be # used self.isExpandedInObjectList = 1 # set to 1 when children of that geom # are visible in ViewerGUI object list self.parent = None # parent object self.fullName = name # object's name including parent's name self.children = [] # list of children self.listed = True # When true the name of this object appears # in the GUI's object self.pickable = True # when set the object can be picked self.pickNum = 0 self.dpyList = None # display list for drawing self.pickDpyList = None # display list for picking # FIXME: quick hack. Flag set by SetCurrentXxxx. When set object's # transformation and material are saved in log file self.hasBeenCurrent = False self.depthMask = 1 # 0: zbuffer is readOnly for transparent objects # 1: zbuffer is read write for transparent objects self.srcBlendFunc = GL.GL_SRC_ALPHA #self.dstBlendFunc = GL.GL_ONE #GL.GL_ONE_MINUS_SRC_COLOR # ONE_MINUS_SRC_ALPHA works for colorMapEditor self.dstBlendFunc = GL.GL_ONE_MINUS_SRC_ALPHA self.transparent = False #viewerConst.NO self.visible = True m = Numeric.reshape(Numeric.identity(4), (1, 16)) self.instanceMatricesFortran = m.astype('f') self.ownGui = None self.animatable = True apply(self.Set, (check, 0), kw) self._modified = False # used to decide if we should save state
def interpolate3DTransform(matrixList, indexList, percent): """ This function gets input of two list and a percent value. Return value is a 4x4 matrix corresponding to percent% of the transformation. matrixList: a list of 4x4 transformation matrix indexList : a list of sorted index (positive float number) percent : a positive float number. if only one matrix in the matrix list: percent = 0.0 means no transformation (identity) 1.0 means 100% of the transformation (returns mat) 0.58 means 58% of translation and rotatetion 58% of rotation angle along the same rotation axis percent can go above 1.0 If matrixList has more than one matrix: matrixList=[M1, M2, M3] #Attention: All M uses the same reference frame indexList =[0.2, 0.5, 1.0] #Attention: assume the list sorted ascendingly p = 0.5 means apply M2 p = 0.8 means apply M3 p = 0.9 means apply M2 first, then apply 50% of M'. M' is the transformation from M2 to M3. 50% = (0.9-0.8) / (1.0-0.8) M2 x M' = M3 --> M2.inverse x M2 x M'= M2.inverse x M3 --> M'= M2.inverse x M """ listLen = len(matrixList) if listLen != len(indexList): raise ValueError("matrix list should have same length of index list") if listLen == 0: raise ValueError("no matrix found in the matrix list") offset = -1 for i in range(listLen): if indexList[i] >= percent: offset = i break prevMat = nextMat = N.identity(4, 'f') if offset == -1: prevMat = matrixList[-1] p = percent / indexList[-1] return _interpolateMat(matrixList[-1], p) elif offset == 0: nextMat = matrixList[0] p = percent / indexList[0] return _interpolateMat(N.array(matrixList[0]), p) else: prevMat = matrixList[offset - 1] nextMat = matrixList[offset] p = (percent - indexList[offset - 1]) / (indexList[offset] - indexList[offset - 1]) from numpy.oldnumeric.linear_algebra import inverse M = N.dot(inverse(prevMat), nextMat) Mat = _interpolateMat(M, p) return N.dot(prevMat, Mat)
def interpolate3DTransform(matrixList, indexList, percent): """ This function gets input of two list and a percent value. Return value is a 4x4 matrix corresponding to percent% of the transformation. matrixList: a list of 4x4 transformation matrix indexList : a list of sorted index (positive float number) percent : a positive float number. if only one matrix in the matrix list: percent = 0.0 means no transformation (identity) 1.0 means 100% of the transformation (returns mat) 0.58 means 58% of translation and rotatetion 58% of rotation angle along the same rotation axis percent can go above 1.0 If matrixList has more than one matrix: matrixList=[M1, M2, M3] #Attention: All M uses the same reference frame indexList =[0.2, 0.5, 1.0] #Attention: assume the list sorted ascendingly p = 0.5 means apply M2 p = 0.8 means apply M3 p = 0.9 means apply M2 first, then apply 50% of M'. M' is the transformation from M2 to M3. 50% = (0.9-0.8) / (1.0-0.8) M2 x M' = M3 --> M2.inverse x M2 x M'= M2.inverse x M3 --> M'= M2.inverse x M """ listLen = len(matrixList) if listLen != len(indexList): raise ValueError("matrix list should have same length of index list") if listLen == 0: raise ValueError("no matrix found in the matrix list") offset = -1 for i in range(listLen): if indexList[i] >= percent: offset = i break prevMat = nextMat = N.identity(4,'f') if offset == -1: prevMat = matrixList[-1] p = percent/indexList[-1] return _interpolateMat(matrixList[-1], p) elif offset == 0: nextMat = matrixList[0] p = percent/indexList[0] return _interpolateMat(N.array(matrixList[0]), p) else: prevMat = matrixList[offset-1] nextMat = matrixList[offset] p = (percent-indexList[offset-1])/( indexList[offset]-indexList[offset-1]) from numpy.oldnumeric.linear_algebra import inverse M = N.dot(inverse(prevMat), nextMat) Mat = _interpolateMat(M, p) return N.dot(prevMat, Mat)
def transformIsIdentity(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """return true if this object has the identity matrix as transformation""" mat = self.GetMatrix() diff = Numeric.sum( (mat-Numeric.identity(4)).ravel() ) if math.fabs(diff) < 0.00001: return True else: return False
def mat_to_axis_angle(matrix): """ NOTE: This function is added by Yong 2/01/04: given a 4x4 transformation matrix of hinge motion, now returns the rotation angle and axis (defined by vector and a point) Please be noticed that if the motion is not hinge, the function will complain and return none """ if matrix.shape != (16, ) and matrix.shape != (4, 4): raise ValueError("matrix should be of shape (4,4) or (16,)") return None if matrix.shape == (16, ): matrix = N.reshape(matrix, (4, 4)) from math import sin, cos, pi, sqrt, fabs, acos degtorad = pi / 180. transf = matrix from mglutil.math.rotax import mat_to_quat rotMat = N.identity(4, 'f') rotMat[:3, :3] = transf[:3, :3] qB = mat_to_quat(matrix=N.array(rotMat).ravel()) angle = qB[3] sa = sin(angle * degtorad / 2.0) if (fabs(angle) < 0.0005): sa = 1 if angle > 180.: vector = [-qB[0] / sa, -qB[1] / sa, -qB[2] / sa] else: vector = [qB[0] / sa, qB[1] / sa, qB[2] / sa] tranMat = transf[3, :3] # check if the transformation is a hinge motion a = vector b = tranMat c = [a[0] - b[0], a[1] - b[1], a[2] - b[2]] a2 = a[0] * a[0] + a[1] * a[1] + a[2] * a[2] b2 = b[0] * b[0] + b[1] * b[1] + b[2] * b[2] c2 = c[0] * c[0] + c[1] * c[1] + c[2] * c[2] theta = acos((c2 - a2 - b2) / (2 * sqrt(a2 * b2))) / pi * 180 if fabs(theta - 90) > 1e-4: raise ValueError("The given transformation is not a hinge motion") return None, None, None ratio = sqrt(1. / (2. * (1. - cos(degtorad * angle)))) p = [tranMat[0] * ratio, tranMat[1] * ratio, tranMat[2] * ratio] ang = 90. - angle / 2.0 rot = rotax([0., 0., 0.], vector, ang * degtorad, transpose=1) rot = rot[:3, :3] point = N.dot(p, rot) return vector, point, angle
def mat_to_axis_angle( matrix ): """ NOTE: This function is added by Yong 2/01/04: given a 4x4 transformation matrix of hinge motion, now returns the rotation angle and axis (defined by vector and a point) Please be noticed that if the motion is not hinge, the function will complain and return none """ if matrix.shape != (16,) and matrix.shape != (4,4): raise ValueError("matrix should be of shape (4,4) or (16,)") return None if matrix.shape == (16,): matrix = N.reshape(matrix, (4,4)) from math import sin, cos, pi, sqrt, fabs, acos degtorad = pi/180. transf = matrix from mglutil.math.rotax import mat_to_quat rotMat = N.identity(4, 'f') rotMat[:3,:3] = transf[:3,:3] qB = mat_to_quat(matrix=N.array(rotMat).ravel()) angle = qB[3] sa=sin(angle*degtorad/2.0) if(fabs(angle) < 0.0005): sa = 1 if angle > 180.: vector=[-qB[0]/sa, -qB[1]/sa, -qB[2]/sa] else: vector=[qB[0]/sa, qB[1]/sa, qB[2]/sa] tranMat = transf[3,:3] # check if the transformation is a hinge motion a=vector b=tranMat c =[a[0]-b[0], a[1]-b[1], a[2]-b[2]] a2= a[0]*a[0] + a[1]*a[1] + a[2]*a[2] b2= b[0]*b[0] + b[1]*b[1] + b[2]*b[2] c2= c[0]*c[0] + c[1]*c[1] + c[2]*c[2] theta = acos((c2-a2-b2)/(2* sqrt(a2*b2))) / pi * 180 if fabs(theta -90) > 1e-4: raise ValueError("The given transformation is not a hinge motion") return None, None, None ratio = sqrt( 1. / (2. * (1.- cos(degtorad * angle )))) p = [tranMat[0]*ratio, tranMat[1]*ratio, tranMat[2]*ratio] ang = 90. - angle/2.0 rot = rotax([0.,0.,0.], vector, ang*degtorad, transpose=1) rot = rot[:3,:3] point = N.dot(p, rot) return vector, point, angle
def set(self, inA=None, inB=None): if inA is None and inB is not None: matInA = matInB = inB elif inA is not None and inB is None: matInA = matInB = inA elif inA is not None and inB is not None: matInA = inA matInB = inB elif inA is None and inB is None: matInA = matInB = Numeric.identity(4).astype('f') return matInA, matInB
def ResetTransformation(self, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Reset the tranformations (Rotation, translation, pivot, scale)""" self.rotation = Numeric.identity(4).astype('f') self.rotation.shape = (16, ) self.translation = Numeric.zeros( (3,), 'f') self.pivot = Numeric.zeros( (3,), 'f') self.scale = Numeric.ones( (3,), 'f') if self.viewer: if self.viewer.currentObject != self.viewer.rootObject \ and redo: self.viewer.deleteOpenglList()
def __init__(self, viewer=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Constructor""" self.inheritXform = 1 # set to 0 not to inherit self.redirectXform = None # object to which transf. # should be redirected self.propagateRedirection = 1 self.copyXform = [] # list of objects to be # transf. along with me # Object's original transf. # in OpenGL form (shape (16,)) self.Matrix = Numeric.identity(4).astype('f') self.Matrix.shape = (16, ) self.MatrixRot = self.Matrix self.MatrixRotInv = self.Matrix self.MatrixScale = Numeric.ones((3,), 'f') self.MatrixTransl = Numeric.zeros( (3,), 'f') self.viewer = viewer self.ResetTransformation(redo=0) # init object's transf. self.R = Numeric.identity(4).astype('f') # Object's frame rotation self.R.shape = (16, ) self.Ri = Numeric.identity(4) .astype('f') # Inverse of R self.Ri.shape = (16, ) self.Si = Numeric.ones( (3, ) ).astype('f') # Inverse of frame's scale self.isScalable = 1 self.immediateRendering = False #self.hasChildWithImmediateRendering = False # set to True if a child is not using dpyList self.needsRedoDpyListOnResize = False
def _uinv(self, mat): """Inverts a transformation matrix used to go from cartesian to cell coordinates""" dmat = Numeric.identity(3).astype('d') imat = Numeric.identity(3).astype('d') dmat[0][0]=mat[1][1]*mat[2][2]-mat[2][1]*mat[1][2] dmat[1][0]=mat[1][2]*mat[2][0]-mat[1][0]*mat[2][2] dmat[2][0]=mat[1][0]*mat[2][1]-mat[1][1]*mat[2][0] dmat[0][1]=mat[0][2]*mat[2][1]-mat[0][1]*mat[2][2] dmat[1][1]=mat[0][0]*mat[2][2]-mat[0][2]*mat[2][0] dmat[2][1]=mat[0][1]*mat[2][0]-mat[0][0]*mat[2][1] dmat[0][2]=mat[0][1]*mat[1][2]-mat[0][2]*mat[1][1] dmat[1][2]=mat[0][2]*mat[1][0]-mat[0][0]*mat[1][2] dmat[2][2]=mat[0][0]*mat[1][1]-mat[0][1]*mat[1][0] det = mat[0][0]*mat[1][1]*mat[2][2]+mat[1][0]*mat[2][1]*mat[0][2]+ \ mat[2][0]*mat[0][1]*mat[1][2]-mat[2][2]*mat[0][1]*mat[1][0]- \ mat[0][0]*mat[2][1]*mat[1][2]-mat[2][0]*mat[1][1]*mat[0][2] for i in (0,1,2): for j in (0,1,2): imat[j][i]=dmat[j][i]/det return Numeric.transpose(imat)
def _interpolateMat(mat, percent): """ called only by interpolate3DTransform() """ if mat.shape != (16, ) and mat.shape != (4, 4): raise ValueError("matrix should be of shape (4,4) or (16,)") return None if mat.shape == (16, ): mat = N.reshape(mat, (4, 4)) # if percent <0.0: # raise ValueError('The parameter percent should be a positive float"') # return p = percent transf = mat[:, :] rotMat = N.identity(4, 'f') rotMat[:3, :3] = transf.astype(N.Float32)[:3, :3] from mglutil.math.rotax import mat_to_quat quat = mat_to_quat(matrix=N.array(rotMat).ravel()) angle = quat[3] * p newRotMat = rotax([0., 0., 0.], quat[:3], angle * degtorad, transpose=1) newTranMat = N.identity(4, 'f') newTranMat[3][0] = transf[3][0] * p newTranMat[3][1] = transf[3][1] * p newTranMat[3][2] = transf[3][2] * p transform = newRotMat transform[3][0] = newTranMat[3][0] transform[3][1] = newTranMat[3][1] transform[3][2] = newTranMat[3][2] # That's it.. the self.transform is now updated. return transform
def _interpolateMat(mat, percent): """ called only by interpolate3DTransform() """ if mat.shape != (16,) and mat.shape != (4,4): raise ValueError("matrix should be of shape (4,4) or (16,)") return None if mat.shape == (16,): mat = N.reshape(mat, (4,4)) # if percent <0.0: # raise ValueError('The parameter percent should be a positive float"') # return p = percent transf = mat[:,:] rotMat = N.identity(4, 'f') rotMat[:3,:3]=transf.astype(N.Float32)[:3,:3] from mglutil.math.rotax import mat_to_quat quat = mat_to_quat(matrix=N.array(rotMat).ravel()) angle = quat[3] * p newRotMat = rotax([0.,0.,0.], quat[:3], angle*degtorad, transpose = 1) newTranMat = N.identity(4, 'f') newTranMat[3][0] = transf[3][0]*p newTranMat[3][1] = transf[3][1]*p newTranMat[3][2] = transf[3][2]*p transform = newRotMat transform[3][0] = newTranMat[3][0] transform[3][1] = newTranMat[3][1] transform[3][2] = newTranMat[3][2] # That's it.. the self.transform is now updated. return transform
def doit(self, refAtoms, mobAtoms, updateGeom=True, showRMSD=True): """ The SuperImposeAtomsCommand takes two set of Atoms of the same length compute the rotation and translation matrices to superimpose the mobAtoms onto the refAtoms using rigidFit module and then transform the corresponding geometry. updateGeom = True : transform the masterGeom of mobAtoms. showRMSD = True : print and return RMSD """ if refAtoms is None or mobAtoms is None: return assert isinstance(refAtoms, TreeNodeSet) assert isinstance(mobAtoms, TreeNodeSet) refAtoms = refAtoms.findType(Atom) mobAtoms = mobAtoms.findType(Atom) # validate the inputs if len(refAtoms) != len(mobAtoms): print "The two atomSet are not of equal length" return if len(refAtoms) < 3: print "At least three atoms are needed for superimposition" return refCoords = refAtoms.coords mobCoords = mobAtoms.coords rigidfitAligner = RigidfitBodyAligner() rigidfitAligner.setRefCoords(refCoords) rigidfitAligner.rigidFit(mobCoords) if updateGeom: rotMat = Numeric.identity(4).astype('d') rotMat[:3, :3] = rigidfitAligner.rotationMatrix transMat = Numeric.array(rigidfitAligner.translationMatrix) rotMat[3, :3] = transMat #print rotMat # the matrix mGeom = mobAtoms[0].top.geomContainer.masterGeom mGeom.SetRotation(Numeric.reshape(rotMat, (16, )).astype('f')) mGeom.viewer.Redraw() if showRMSD: rmsd = rigidfitAligner.rmsdAfterSuperimposition(mobCoords) print "RMSD = ", rmsd return rmsd else: return
def doit(self, refAtoms, mobAtoms, updateGeom=True, showRMSD=True): """ The SuperImposeAtomsCommand takes two set of Atoms of the same length compute the rotation and translation matrices to superimpose the mobAtoms onto the refAtoms using rigidFit module and then transform the corresponding geometry. updateGeom = True : transform the masterGeom of mobAtoms. showRMSD = True : print and return RMSD """ if refAtoms is None or mobAtoms is None: return assert isinstance(refAtoms, TreeNodeSet) assert isinstance(mobAtoms, TreeNodeSet) refAtoms = refAtoms.findType(Atom) mobAtoms = mobAtoms.findType(Atom) # validate the inputs if len(refAtoms) !=len(mobAtoms): print "The two atomSet are not of equal length" return if len(refAtoms) < 3 : print "At least three atoms are needed for superimposition" return refCoords = refAtoms.coords mobCoords = mobAtoms.coords rigidfitAligner = RigidfitBodyAligner() rigidfitAligner.setRefCoords(refCoords) rigidfitAligner.rigidFit(mobCoords) if updateGeom: rotMat = Numeric.identity(4).astype('d') rotMat[:3,:3] = rigidfitAligner.rotationMatrix transMat = Numeric.array(rigidfitAligner.translationMatrix) rotMat[3,:3] = transMat #print rotMat # the matrix mGeom = mobAtoms[0].top.geomContainer.masterGeom mGeom.SetRotation(Numeric.reshape(rotMat, (16,)).astype('f')) mGeom.viewer.Redraw() if showRMSD: rmsd=rigidfitAligner.rmsdAfterSuperimposition(mobCoords) print "RMSD = ", rmsd return rmsd else: return
def __call__(self, inMatrices, applyIndex=None): """outMatrices <- SymOrient(inMatrices, applyIndex=None) inMatrices: list of 4x4 matrices outMatrices: list of 4x4 matrices """ if not inMatrices: inMatrices = [Numeric.identity(4).astype('f')] matrices = Numeric.array(inMatrices) assert len(matrices.shape)==3 assert matrices.shape[-2] == 4 and matrices.shape[-1] == 4 ownmat = self.getMatrices() out = [] for m in ownmat: # loop over this node's own transformation matrices for im in matrices: #loop over node's incoming matrices out.append( Numeric.dot(m, im) ) return out
def __call__(self, inMatrices=None, applyIndex=None): """outMatrices <- SymTranspose(inMatrices, applyIndex=None) inMatrices: list of 4x4 matrices outMatrices: list of 4x4 matrices """ if not inMatrices: inMatrices = [Numeric.identity(4).astype('f')] matrices = Numeric.array(inMatrices) assert matrices.shape[-2] == 4 and matrices.shape[-1] == 4 out = [] for im in matrices: #loop over node's incoming matrices out.append( Numeric.transpose(im) ) return out
def __call__(self, inMatrices=None, applyIndex=None): """outMatrices <- SymInverse(inMatrices, applyIndex=None) inMatrices: list of 4x4 matrices outMatrices: list of 4x4 matrices """ import numpy.oldnumeric.linear_algebra as LinearAlgebra if not inMatrices: inMatrices = [Numeric.identity(4).astype('f')] matrices = Numeric.array(inMatrices) assert matrices.shape[-2] == 4 and matrices.shape[-1] == 4 out = [] for im in matrices: #loop over node's incoming matrices out.append( LinearAlgebra.inverse(im) ) return out
def __call__(self, inMatrices, scaleFactor, applyIndex=None, selection=[True,True,True]): """outMatrices <- SymScale(inMatrices, applyIndex=None, selection=[1,1,1]) inMatrices: list of 4x4 matrices outMatrices: list of 4x4 matrices (selection: scale x,y, and/or z) can be 1,True or 0,False) """ if not inMatrices: inMatrices = [Numeric.identity(4).astype('f')] matrices = Numeric.array(inMatrices) assert len(matrices.shape)==3 assert matrices.shape[-2] == 4 and matrices.shape[-1] == 4 ownmat = self.getMatrices(scaleFactor, selection) out = [] for im in matrices: #loop over node's incoming matrices out.append( Numeric.dot(im, ownmat) ) return out
def __call__(self, inMatrices, applyIndex=None): """outMatrices <- SymNFold(inMatrices, applyIndex=None) inMatrices: list of 4x4 matrices outMatrices: list of 4x4 matrices if applyIndex is given it should be a list of 0-based indices of matrices to which this operator's transformation will be applied. """ if not inMatrices: inMatrices = [Numeric.identity(4).astype('f')] matrices = Numeric.array(inMatrices) assert len(matrices.shape)==3 assert matrices.shape[-2] == 4 and matrices.shape[-1] == 4 ownmat = self.getMatrices() out = [] for m in ownmat: # loop over this node's own transformation matrices for im in matrices: #loop over node's incoming matrices out.append( Numeric.dot(m, im) ) return out
def getMatrices(self): m=[] newList=[] mat = Numeric.identity(4).astype('f') if self.identity == 1: m.append(mat) newList.extend(list(self.vector)) newList.append(self.angle) t=Numeric.array(self.center)*-1 T = Transformation(trans=t) R = Transformation(quaternion=newList) mt = T.inverse() * R * T newmat = mt.getMatrix() m.append(newmat) return m
def EulerAnglesToMat( angles ): """Builds a rotation matrix from Euler angles given in degrees""" from math import pi, cos, sin t1 = angles[0]* (pi/180.0) t2 = angles[1]* (pi/180.0) t3 = angles[2]* (pi/180.0) # from Lattman, Meth. Enzymology V. 115 p. 63 rot = Numeric.identity(3).astype('d') rot[0][0]= -sin(t1)*cos(t2)*sin(t3) + cos(t1)*cos(t3) rot[0][1]= cos(t1)*cos(t2)*sin(t3) + sin(t1)*cos(t3) rot[0][2]= sin(t2)*sin(t3) rot[1][0]= -sin(t1)*cos(t2)*cos(t3) - cos(t1)*sin(t3) rot[1][1]= cos(t1)*cos(t2)*cos(t3) - sin(t1)*sin(t3) rot[1][2]= sin(t2)*cos(t3) rot[2][0]= sin(t1)*sin(t2) rot[2][1]= -cos(t1)*sin(t2) rot[2][2]= cos(t2) return rot
def __init__(self, name='Set Instances', **kw): kw['name'] = name apply(NetworkNode.__init__, (self, ), kw) self.inputPortsDescr.append(datatype='Molecule', name='molecule') self.inputPortsDescr.append(datatype='instancemat(0)', name='matrices', required=False, defaultValue=[Numeric.identity(4, 'f')]) code = """def doit(self, molecule, matrices): if molecule: assert hasattr(molecule, 'geomContainer') geom = molecule.geomContainer.geoms['master'] geom.Set(instanceMatrices=matrices) geom.viewer.Redraw()\n""" self.setFunction(code)
def rotxyz(angles): ret = numerix.identity(4).astype(numerix.Float) ret[1, 1] = ret[2, 2] = numerix.cos(angles[0]) sn = numerix.sin(angles[0]) ret[1, 2] = -sn ret[2, 1] = sn cs = numerix.cos(angles[1]) ret[0, 0] = cs ret[2, 2] += cs sn = numerix.sin(angles[1]) ret[0, 2] = sn ret[2, 0] = -sn cs = numerix.cos(angles[2]) ret[0, 0] += cs ret[1, 1] += cs sn = numerix.sin(angles[2]) ret[0, 1] = -sn ret[1, 0] = sn return ret
def transformCoords(self, setCoords): """ The transformCoords method applies the transformation matrices computed by rigidFit method to the given list of coordinates. """ # This can only be done if the transformation matrices have been computed # by the rigidFit method. if not self.superimposed: return # 1- apply the rotation and the translation matrix to the given set of coords. transfoMatrix = Numeric.identity(4, 'd') transfoMatrix[:3, :3] = self.rotationMatrix transfoMatrix[3][0] = self.translationMatrix[0] transfoMatrix[3][1] = self.translationMatrix[1] transfoMatrix[3][2] = self.translationMatrix[2] # 2- now apply the transformation to the list of given coordinates list: # make homogeneous coords homoCoords = Numeric.concatenate( (setCoords, Numeric.ones((len(setCoords), 1), 'd')), 1) # 3- apply the transformation matrix to the homogeneous coords. transformedCoords = Numeric.dot(homoCoords, transfoMatrix) return transformedCoords
def Decompose4x4(self, matrix, cleanup=True): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """ takes a matrix in shape (16,) in OpenGL form (sequential values go down columns) and decomposes it into its rotation (shape (16,)), translation (shape (3,)), and scale (shape (3,)) """ m = matrix transl = Numeric.array((m[12], m[13], m[14]), 'f') scale0 = Numeric.sqrt(m[0]*m[0]+m[4]*m[4]+m[8]*m[8]) scale1 = Numeric.sqrt(m[1]*m[1]+m[5]*m[5]+m[9]*m[9]) scale2 = Numeric.sqrt(m[2]*m[2]+m[6]*m[6]+m[10]*m[10]) scale = Numeric.array((scale0,scale1,scale2)).astype('f') mat = Numeric.reshape(m, (4,4)) rot = Numeric.identity(4).astype('f') rot[:3,:3] = mat[:3,:3].astype('f') rot[:,0] = (rot[:,0]/scale0).astype('f') rot[:,1] = (rot[:,1]/scale1).astype('f') rot[:,2] = (rot[:,2]/scale2).astype('f') if cleanup: rot = glCleanRotMat(rot.ravel()) rot.shape = (16,) #rot1 = rot.astype('f') return rot, transl, scale
def doit(self, refAtoms, mobAtoms): """ The SuperImposeAtomsCommand takes two set of Atoms of the same length compute the rotation and translation matrices to superimpose the mobAtoms onto the refAtoms using rigidFit module and then transform the corresponding geometry. """ refCoords = refAtoms.coords mobCoords = mobAtoms.coords self.rigidfitAligner.setRefCoords(refCoords) # Nothing can be done if the two sets of coords are not of the same # size if not len(refCoords) == len(mobCoords): print " ERROR: Cannot perform the superimposition because the 2 \ mv.lsets of Atoms are not of the same length" return # Get the rotation and the translation ysing mglutil.math.rigidFit self.rigidfitAligner.rigidFit(mobCoords) #rotation, translation= rigidFit.rigid_fit( refCoords, inCoords) rotMat = Numeric.identity(4).astype('f') rotMat[:3,:3] = self.rigidfitAligner.rotationMatrix rotMat = Numeric.reshape(rotMat, (16,)) transMat = Numeric.array(self.rigidfitAligner.translationMatrix) # transform the geometry representing the atoms only if a gui has been # created: #if not self.vf.hasGui: # return # Transform the mob geometry mobMol = mobAtoms.top.uniq()[0] mob = mobMol.geomContainer.masterGeom self.vf.transformObject('rotation', mob.fullName, matrix=tuple(rotMat)) self.vf.transformObject('translation', mob.fullName, matrix=tuple(transMat))
def sartran(self, rho, x, force=0, precis=DELTA): n = len(x) listflag = 0 if type(x) == list: x = Numeric.array(x, Numeric.Float) listflag = 1 sarx = Numeric.zeros(n, Numeric.Float) if n > WT_SMALL or force: sarx = x wx = self.splag(x) * rho sarx += wx while max(wx) > precis: wx = self.splag(wx) * rho sarx += wx else: # small weights full matrix inverse w = self.wt2mat() w *= -rho w += Numeric.identity(n) wx = LinearAlgebra.inverse(w) sarx = Numeric.matrixmultiply(wx, x) if listflag: return sarx.tolist() else: return sarx
def translate(txyz): ret = numerix.identity(4).astype(numerix.Float) ret[0:len(txyz), 3] = txyz return ret
def AddGrid3D(self, grid): assert isinstance(grid, Grid3DUC) if not self.volrenInitialized: if not self.viewer: # we need an OpenGL context before print "self.viewer: ", self.viewer return # we can initialize the renderer self.InitVolumeRenderer() for c in self.viewer.cameras: c.addButtonDownCB(self.coarseRendering) c.addButtonUpCB(self.fineRendering) orig = grid.origin[:] step = grid.stepSize nx, ny, nz = grid.data.shape gridSize = [nx * step[0], ny * step[1], nz * step[2]] gridSize2 = [gridSize[0] * 0.5, gridSize[1] * 0.5, gridSize[2] * 0.5] maxgrid = [ orig[0] + gridSize[0], orig[1] + gridSize[1], orig[2] + gridSize[2] ] transl = [ orig[0] + gridSize2[0], orig[1] + gridSize2[1], orig[2] + gridSize2[2] ] # save scale and tranlation into Matrix which is not affected # by reset if grid.crystal: # compute cartesian voxel sizes x, y, z = grid.getStepSizeReal() #build crystal object for length with padding from mglutil.math.crystal import Crystal if hasattr(grid, 'dataDims'): # compute ratios of padding along the 3 dimensions dx = grid.dimensions[0] - grid.dataDims[0] - 1 dy = grid.dimensions[1] - grid.dataDims[1] - 1 dz = grid.dimensions[2] - grid.dataDims[2] - 1 ry = float(dx) / dy rz = float(dx) / dz else: ry = rz = 1.0 dims = (grid.dimensions[0] - 1, (grid.dimensions[1] - 1) * ry, (grid.dimensions[2] - 1) * rz) cryst = Crystal((dims[0] * x, dims[1] * y, dims[2] * z), grid.crystal.angles) matrix = Numeric.identity(4, 'f') matrix[:3, :3] = cryst.ftoc.astype('f') matrix.shape = (16, ) # cleanup=False because rotation can contain shear which should # be kept self.MatrixRot, MatrixTransl, self.MatrixScale = self.Decompose4x4( matrix, cleanup=False) # set utvolgeom's Matrix components self.MatrixScale = (self.MatrixScale[0], self.MatrixScale[1] / ry, self.MatrixScale[2] / rz) origin = grid.crystal.toCartesian(grid.origin) self.MatrixTransl = (origin[0] + MatrixTransl[0] + dims[0] * 0.5 * x, origin[1] + MatrixTransl[1] + dims[1] * 0.5 * y / ry, origin[2] + MatrixTransl[2] + dims[2] * 0.5 * z / rz) #o = grid.origin #t1 = cryst.toFractional(MatrixTransl) #t2 = (0.5, 0.5, 0.5) #trans = ( o[0]+t1[0]+t2[0], o[1]+t1[1]+t2[1],o[2]+t1[2]+t2[2]) #self.MatrixTransl = cryst.toCartesian(trans) #print o #print t1 #print t2 #print trans #print self.MatrixTransl #self.MatrixTransl = (0.,0.,0.) #self.MatrixScale = (1.,1.,1.) RotInv = Numeric.transpose(Numeric.reshape(self.MatrixRot, (4, 4))) self.MatrixRotInv = Numeric.reshape(RotInv, (16, )) # self.MatrixRot = self.MatrixRot.astype('f') self.MatrixRotInv = self.MatrixRot.astype('f') else: self.setMatrixComponents(trans=transl) self.setMatrixComponents(scale=gridSize, trans=transl) if self.firstLoaded: if self.viewer: rootObject = self.viewer.rootObject self.minBB = [-0.5, -0.5, -0.5] self.maxBB = [0.5, 0.5, 0.5] #print "all objects:", self.viewer.rootObject.AllObjects() self.viewer.NormalizeCurrentObject() self.firstLoaded = 0 # scale and translate volume ##self.SetScale( gridSize) ##trans = Numeric.array( gridSize2, 'f') ##self.SetTranslation( trans ) #mat = self.GetMatrix(self) #self.SetMatrix(mat) #self.ResetTransformation() arr = Numeric.ascontiguousarray(Numeric.transpose(grid.data), grid.data.dtype.char) upload = self.volume.uploadColorMappedData status = upload(arr.ravel(), nx, ny, nz) if status != 1: raise RuntimeError( "uploadColorMappedData() in AddVolume failed. Status %d" % status) self.dataArr = Numeric.reshape(arr, (nz, ny, nx)) self.volumeSize = (nx, ny, nz) if self.byte_map == None: self.grayRamp() # update cropping box self.crop.updateData() self.cropBox.setVolSize((nx, ny, nz)) self.cropBox.xmin = 0 self.cropBox.xmax = nx self.cropBox.ymin = 0 self.cropBox.ymax = ny self.cropBox.zmin = 0 self.cropBox.zmax = nz self.cropBox.update() for c in self.onaddVolume_list: c.OnAddVolumeToViewer()
def doit(self, refAtoms, mobAtoms): """ The SuperImposeAtomsCommand takes two set of Atoms of the same length compute the rotation and translation matrices to superimpose the mobAtoms onto the refAtoms using rigidFit module and then transform the corresponding geometry. """ refCoords = refAtoms.coords mobCoords = mobAtoms.coords self.rigidfitAligner.setRefCoords(refCoords) # Nothing can be done if the two sets of coords are not of the same # size if not len(refCoords) == len(mobCoords): print " ERROR: Cannot perform the superimposition because the 2 \ mv.lsets of Atoms are not of the same length" return # Get the rotation and the translation ysing mglutil.math.rigidFit self.rigidfitAligner.rigidFit(mobCoords) #rotation, translation= rigidFit.rigid_fit( refCoords, inCoords) rotMat = Numeric.identity(4).astype('d') rotMat[:3, :3] = self.rigidfitAligner.rotationMatrix transMat = Numeric.array(self.rigidfitAligner.translationMatrix) # transform the geometry representing the atoms only if a gui has been # created: #if not self.vf.hasGui: # return # build the geometry name: mobMol = mobAtoms.top.uniq()[0] mob = mobMol.geomContainer.masterGeom #gName = 'root|'+ mobMol[0].name if not self.vf.hasGui: vi = self.vf.GUI.VIEWER oldCurrent = vi.currentObject vi.SetCurrentObject(mob) # transform only the given geometry. if vi.redirectTransformToRoot == 1: old = vi.redirectTransformToRoot vi.TransformRootOnly(0) else: old = 0 # apply the rotation to the masterGeom of the inMol mob.SetRotation(Numeric.reshape(rotMat, (16, ))) # apply the translation to the masterGeom of the inMol mob.SetTranslation(transMat) ## refMol = refAtoms.top.uniq()[0] ## refmg = refMol.geomContainer.masterGeom ## refmg = refAtoms.top.uniq()[0].geomContainer.masterGeom ## mat = refmg.GetMatrix(refmg) ## tmat = Numeric.transpose(mat) ## rot, trans, scale = refmg.Decompose4x4(Numeric.reshape(tmat, (16,))) ## rot_1 = refmg.rotation ## trans_1 = refmg.translation ## print 'rot',rot ## print 'trans',trans ## print 'rot_1',rot_1 ## print 'trans_1',trans_1 ## mobPivot = list(mob.pivot) ## mobPivot.append(1.) ## transfo = Numeric.identity(4).astype('d') ## transfo[:3,:3] = rotMat[:3,:3] ## transfo[3, :3] = transMat ## hc = Numeric.array(mobPivot) ## tPivot = Numeric.dot(hc, transfo) ## print tPivot[:3] ## mob.SetPivot(tPivot[:3]) #self.vf.centerOnNodes(refMol) #mob.ConcatRotationRelative(Numeric.reshape(rot, (16,))) #mob.ConcatTranslation(trans_1) if not self.vf.hasGui: if old == 1: vi.TransformRootOnly(1) vi.SetCurrentObject(oldCurrent)
def Set(self, **kw): """Set various clipping plane parameters""" self.hasBeenCurrent = True # remember the light has been changed tagModified = True val = getkw(kw, 'tagModified') if val is not None: tagModified = val assert tagModified in [True, False] self._modified = tagModified val = getkw(kw, 'enabled') if not val is None: if val is True: self._Enable(1) elif val is False: self._Disable() else: raise AttributeError('enable can only be True or False') self.enabled = val val = getkw(kw, 'name') if not val is None: self.name = val val = getkw(kw, 'visible') if not val is None: if val in [False, True]: self.visible = val else: raise AttributeError('visible can only be 0 or 1') val = getkw(kw, 'color') if not val is None: col = OneColor(val) if col: self.color = col val = getkw(kw, 'lineWidth') if not val is None: try: int(val) except: raise ValueError('lineWidth must be a positive int') if val >= 1: self.lineWidth = int(val) else: raise ValueError('lineWidth must be a positive int') # val = getkw(kw, 'antialiased') # if not val is None: # if val in (True, False) : # self.antialiased = val # else: raise ValueError ('antialiased can only be YES or NO') val = getkw(kw, 'rotation') if not val is None: self.rotation = Numeric.identity(4, 'f').ravel() mat = Numeric.reshape(Numeric.array(val), (16, )).astype('f') self.ConcatRotation(mat) val = getkw(kw, 'translation') if not val is None: self.translation = Numeric.zeros((3, ), 'f') mat = Numeric.reshape(Numeric.array(val), (3, )).astype('f') self.ConcatTranslation(mat) val = getkw(kw, 'scale') if not val is None: self.SetScale(val) val = getkw(kw, 'pivot') if not val is None: self.SetPivot(val) if len(kw): print 'WARNING1: Keyword(s) %s not used' % kw.keys() if self.object.viewer: self.object.viewer.objectsNeedingRedo[self.object] = None self.object.viewer.Redraw()
def _orthog(self, length, angles): """ let u be a 3x3 transformation matrix which relates a new cell with orthogonal axes of unit dimensions to the original unit cell (crystal system). Aug 5, 1991 changed to XPLOR convention was: ut[0][0]=as; ut[0][1]=0.; ut[0][2]=0.; ut[1][0]=bs*cosgas; ut[1][1]=1./b; ut[1][2]= -(1./tan(al))/b; ut[2][0]=cs*cosbes; ut[2][1]=0.; ut[2][2]=1./(c*sin(al)); June 1, 1996: Corrected LFT The correct orthogonalization matrix for the default PDB convention (Cartesion x along A, y in A-B plane, and z along c*) is 1/a -cos(ga)/(a sin(ga)) as cosbes 0 1/(b sin(ga)) bs cosals 0 0 cs and the deorthogonalization matrix is a b cos(ga) c cos(be) 0 b sin(ga) -c sin(be) cosals 0 0 1/cs usage: xf = x * ut[0][0] + y * ut[0][1] + z * ut[0][2] yf = x * ut[1][0] + y * ut[1][1] + z * ut[1][2] zf = x * ut[2][0] + y * ut[2][1] + z * ut[2][2] """ from math import pi, cos, sin, sqrt degtor=pi/180. al=angles[0]*degtor be=angles[1]*degtor ga=angles[2]*degtor vol= length[0]* length[1]* length[2] *sqrt(1.-cos(al)*cos(al)-cos(be)*cos(be) -cos(ga)*cos(ga)+2.*(cos(al)*cos(be)*cos(ga))) lAs=(length[1]* length[2]*sin(al))/vol bs=(length[0]* length[2]*sin(be))/vol cs=(length[0]* length[1]*sin(ga))/vol cosals=(cos(be)*cos(ga)-cos(al))/(sin(be)*sin(ga)) cosbes=(cos(ga)*cos(al)-cos(be))/(sin(ga)*sin(al)) cosgas=(cos(al)*cos(be)-cos(ga))/(sin(al)*sin(be)) ut = Numeric.identity(3).astype('f') # sabgs1 = sqrt(1.0-cos(al)*cos(al)) ut[0][0]=1./length[0] ut[0][1]= -(cos(ga))/(sin(ga)*length[0]) # ut[0][2]= -(cos(ga)*sin(be)*cosals + cos(be)*sin(ga))/ */ # (sin(be)*sabgs1*sin(ga)*a) */ ut[0][2]= lAs * cosbes ut[1][0]=0.0 ut[1][1]=1./(sin(ga)*length[1]) # ut[1][2]=cosals/(sabgs1*sin(ga)*b) ut[1][2]= bs * cosals ut[2][0]=0.0 ut[2][1]=0.0 # ut[2][2]=1.0/(sin(be)*sabgs1*c) ut[2][2]= cs return Numeric.transpose(ut)
def rigidFit(self, mobileCoords): """ the rigidFit method computes the necessary transformation matrices to superimpose the list of mobileCoords onto the list of referenceCoords, and stores the resulting matrices (rot, trans) <- rigidFit(mobileCoords) Rigid body fit. Finds transformation (rot,trans) such that r.m.s dist(x,rot*y+trans) --> min ! mobileCoords: cartesian coordinates of mobile structure (3,n) (input) rot : rotation matrix (3,3) (output) trans : translation vector (3) (output) status: 0 if OK, 1 if singular problem (n<3 ...) Method: W.Kabsch, Acta Cryst. (1976). A32,922-923 W.Kabsch, Acta Cryst. (1978). A34,827-828 """ if self.refCoords is None: raise RuntimeError(" no reference coordinates specified") refCoords = self.refCoords if len(refCoords) != len(mobileCoords): raise RuntimeError("input vector length mismatch") refCoords = Numeric.array(refCoords) mobileCoords = Numeric.array(mobileCoords) # # 1. Compute centroids: refCentroid = Numeric.sum(refCoords) / len(refCoords) mobileCentroid = Numeric.sum(mobileCoords) / len(mobileCoords) # # 2. Wolfgang Kabsch's method for rotation matrix rot: rot = Numeric.identity(3).astype('f') # LOOK how to modify that code. for i in xrange(3): for j in xrange(3): rot[j][i] = Numeric.sum( (refCoords[:, i] - refCentroid[i]) * (mobileCoords[:, j] - mobileCentroid[j])) rotTransposed = Numeric.transpose(rot) e = Numeric.dot(rot, rotTransposed) evals, evecs = LinearAlgebra.eigenvectors(e) ev = Numeric.identity(3).astype('d') # set ev[0] to be the evec or the largest eigenvalue # and ev[1] to be the evec or the second largest eigenvalue eigenValues = list(evals) discard = eigenValues.index(min(eigenValues)) i = j = 0 while i < 3: if i == discard: i = i + 1 continue ev[j] = evecs[i] j = j + 1 i = i + 1 evecs = ev evecs[2][0] = evecs[0][1] * evecs[1][2] - evecs[0][2] * evecs[1][1] evecs[2][1] = evecs[0][2] * evecs[1][0] - evecs[0][0] * evecs[1][2] evecs[2][2] = evecs[0][0] * evecs[1][1] - evecs[0][1] * evecs[1][0] b = Numeric.dot(evecs, rot) norm = math.sqrt(b[0][0] * b[0][0] + b[0][1] * b[0][1] + b[0][2] * b[0][2]) if math.fabs(norm) < 1.0e-20: return -1, -1 b[0] = b[0] / norm norm = math.sqrt(b[1][0] * b[1][0] + b[1][1] * b[1][1] + b[1][2] * b[1][2]) if math.fabs(norm) < 1.0e-20: return -1, -1 b[1] = b[1] / norm # vvmult(b[0],b[1],b[2]) b[2][0] = b[0][1] * b[1][2] - b[0][2] * b[1][1] b[2][1] = b[0][2] * b[1][0] - b[0][0] * b[1][2] b[2][2] = b[0][0] * b[1][1] - b[0][1] * b[1][0] # mtrans3(e) e = evecs tempo = e[0][1] e[0][1] = e[1][0] e[1][0] = tempo tempo = e[0][2] e[0][2] = e[2][0] e[2][0] = tempo tempo = e[1][2] e[1][2] = e[2][1] e[2][1] = tempo # mmmult3(b,e,rot) rot[0][0] = b[0][0] * e[0][0] + b[1][0] * e[0][1] + b[2][0] * e[0][2] rot[0][1] = b[0][1] * e[0][0] + b[1][1] * e[0][1] + b[2][1] * e[0][2] rot[0][2] = b[0][2] * e[0][0] + b[1][2] * e[0][1] + b[2][2] * e[0][2] rot[1][0] = b[0][0] * e[1][0] + b[1][0] * e[1][1] + b[2][0] * e[1][2] rot[1][1] = b[0][1] * e[1][0] + b[1][1] * e[1][1] + b[2][1] * e[1][2] rot[1][2] = b[0][2] * e[1][0] + b[1][2] * e[1][1] + b[2][2] * e[1][2] rot[2][0] = b[0][0] * e[2][0] + b[1][0] * e[2][1] + b[2][0] * e[2][2] rot[2][1] = b[0][1] * e[2][0] + b[1][1] * e[2][1] + b[2][1] * e[2][2] rot[2][2] = b[0][2] * e[2][0] + b[1][2] * e[2][1] + b[2][2] * e[2][2] # # Compute translation vector trans: # mvmult3(rot,cy,cy); trans3 = [0, 0, 0] for i in range(3): trans3[i] = mobileCentroid[0]*rot[0][i] + mobileCentroid[1]*rot[1][i] + \ mobileCentroid[2]*rot[2][i] #bcopy(t3,cy,sizeof(t3)); #vvdiff(cx,cy,trans); trans = (refCentroid[0] - trans3[0], refCentroid[1] - trans3[1], refCentroid[2] - trans3[2]) # # That's it... self.rotationMatrix = rot self.translationMatrix = trans self.superimposed = 1