Esempio n. 1
0
    def findCoilPoints(self, s0, s1, s2, displacement_s2_m2, 
                                         displacement_m2_m1, 
                                         displacement_m1_m0, 
                                         alpha_s0_s1_s2_m2, 
                                         beta_s1_s2_m2, 
                                         alpha_s1_s2_m2_m1, 
                                         beta_s2_m2_m1, 
                                         alpha_s2_m2_m1_m0,
                                         beta_m2_m1_m0):
        
        # function identifies the positions of the ends of a free coil in terms of the
        # end point it is connecting to and certain bond information. 
        # Our objective is to define m2, m1 and m0 in terms of this information.
        # the names s0, s1, s2 and m2, m1, m0 are defined in the building block function
        # for connecting two blocks together.
        
        # m2 atom in terms of s0, s1 and s2
        TNB1 = coords.constructTNBFrame(s0, s1, s2)
        m2 = s2 + displacement_s2_m2 * coords.generateTNBVecXYZ(TNB1, beta_s1_s2_m2, alpha_s0_s1_s2_m2)

        # m1 atom in terms of s1, s2 and m2
        TNB2 = coords.constructTNBFrame(s1, s2, m2)
        m1 = m2 +  displacement_m2_m1 * coords.generateTNBVecXYZ(TNB2, beta_s2_m2_m1, alpha_s1_s2_m2_m1)

        # m0 atom in terms of s2, m2 and m1
        TNB3 = coords.constructTNBFrame(s2, m2, m1)
        m0 = m1 +  displacement_m1_m0 * coords.generateTNBVecXYZ(TNB3, beta_m2_m1_m0, alpha_s2_m2_m1_m0)
        
        return [m0, m1, m2]
Esempio n. 2
0
    def residueToAtoms(self, S0, S1, S2, S3, alpha0, b1, beta1, b2, beta2, b3, beta3):
        # Positioning M0 correctly in the S0, S1, S2 TNB frame
        # allows for alpha0, b1 and beta1 to be set correctly.
        TNB_S0_S1_S2 = coords.constructTNBFrame(S0, S1, S2)
        M0 = S2 + b1 * coords.generateTNBVecXYZ(TNB_S0_S1_S2, beta1, alpha0)

        TNB_S1_S2_M0 = coords.constructTNBFrame(S1, S2, M0)        
        # Can position M1 such that b2, and beta2 are correct, but that leaves b3 and beta3 and only one
        # parameter - alpha2 - which is dihedral about s2 to m0 axis. So find the alpha which
        # minimises the difference between b3 and linalg.norm(M1 - S3).
        results = minimize(coords.computeDistBetweenM1AndS3, [-60 *np.pi/180], (TNB_S1_S2_M0, beta2, S3, b3))
        alpha2 = results['x']

        # compute position of M1 with b2, beta2 and alpha2. We don't care what the last angle is. 
        M1 = M0 + b2 * coords.generateTNBVecXYZ(TNB_S1_S2_M0, beta2, alpha2)
        
        return M0, M1
Esempio n. 3
0
    def constructLoop(self, BB1, BB2, loopGen, pointsToAvoid):

        connectorA = BB1.getConnectionAtoms(
            1)  # 1 is the C terminus of interest
        connectorB = BB2.getConnectionAtoms(
            0)  # 0 is the N terminus of interest

        # generate TNB frames at either connector
        TNBA = coords.constructTNBFrame(connectorA[0], connectorA[1],
                                        connectorA[2])
        TNBB = coords.constructTNBFrame(connectorB[0], connectorB[1],
                                        connectorB[2])

        # C terminus is CCN triad (new atom will be an N).
        betaA = self.angleC
        alphaA = self.phi
        # N Terminus is CNC triad. (new atom will be a C).
        betaB = self.angleN
        alphaB = self.psi

        # compute the coil start and end points
        pointA = connectorA[2] + self.CNbondLength * coords.generateTNBVecXYZ(
            TNBA, betaA, alphaA)
        pointB = connectorB[2] + self.CNbondLength * coords.generateTNBVecXYZ(
            TNBB, betaB, alphaB)

        if self.dumpInterimFiles:
            fIO.saveXYZList([pointA, connectorA[2], pointB, connectorB[2]],
                            ['Ca', 'S', 'O', 'S'], 'connectionDetails.xyz')
            fIO.saveXYZ(pointsToAvoid, 'K', 'pointsToAvoid.xyz')

        numCrankMoves = 0
        if self.parallel:
            iSphereR = 0.4 * self.strandLength * 3.5
        else:
            iSphereR = 0.9 * self.betaStrandSeparation / 2.0

        # create the loop building Blockss
        return loopGen.generateBuildingBlock(
            self.numLoopResidues,
            pointA,
            pointB,
            self.minDist,
            numCrankMoves,
            pointsToAvoid=pointsToAvoid,
            envelopeList=["innersphere " + str(iSphereR)])
Esempio n. 4
0
    def generateResidue(self, prevRes):

        # given a list of 3 xyz positions for the previous residue
        # construct the next set of three positions with appropriate bond angles
        # and dihedral angles.

        # construct the first TNB from the previous residue
        TNB1 = coords.constructTNBFrame(prevRes[0], prevRes[1], prevRes[2])
        NPos = prevRes[2] + self.CNbondLength * coords.generateTNBVecXYZ(
            TNB1, self.angleC, self.phi)

        TNB2 = coords.constructTNBFrame(prevRes[-2], prevRes[-1], NPos)
        CAPos = NPos + self.CNbondLength * coords.generateTNBVecXYZ(
            TNB2, self.angleN, self.omega)

        TNB3 = coords.constructTNBFrame(prevRes[-1], NPos, CAPos)
        CPos = CAPos + self.CCbondLength * coords.generateTNBVecXYZ(
            TNB3, self.angleCA, self.psi)

        return [NPos, CAPos, CPos]
Esempio n. 5
0
    def findLastTwoPointsFit(self, startPoints, endPoints, distanceBetweenPoints):
        # This function figures out the coordinates of the last 
        # one or two points in a polymer chain such that they are 
        # bondLength distance apart. It stops worrying about bond angles. 
        
        # This is a many dimensional problem and there
        # are many ways to solve it. varies all four angles simultaneously
        # and calculates the resulting distance
        # between the particles. THe function minimises this distance - bondLength.

        # construct TNB frames
        TNBA = coords.constructTNBFrame(startPoints[-3],
                                        startPoints[-2],
                                        startPoints[-1])
        TNBB = coords.constructTNBFrame(endPoints[-3],
                                        endPoints[-2],
                                        endPoints[-1])
        
        # pick bond angles at random from the acceptable range
        betaA = rnd.uniform(self.beta1, self.beta2)
        betaB = rnd.uniform(self.beta1, self.beta2)
        alphaA = rnd.uniform(self.alpha1, self.alpha2)
        alphaB = rnd.uniform(self.alpha1, self.alpha2)

        # optimise the angles for the given function.
        finalAngles = minimize(coords.computeDistBetweenPoints, 
                               [alphaA, alphaB], 
                               args=(startPoints[-1], endPoints[-1], TNBA, TNBB, betaA, betaB, self.bondLength, distanceBetweenPoints))
        
        pointA = startPoints[-1] + self.bondLength * coords.generateTNBVecXYZ(TNBA, betaA, finalAngles['x'][0])
        pointB = endPoints[-1] + self.bondLength * coords.generateTNBVecXYZ(TNBB, betaB, finalAngles['x'][1])

        # true if the optimisation exited successfully (it gave a result!)
        listsAreGood = finalAngles['success']
        
        return pointA, pointB, listsAreGood
Esempio n. 6
0
    def startResidue(self):
        # generates the first residue of the backbone

        # set first NPos to be at origin.
        NPos = np.array([0.0, 0.0, 0.0])

        # Assume CAPos is along director axis from NPos - bad assumption - we'll correct it later
        CAPos = NPos + self.CNbondLength * self.directorHat

        # generate a third dummy vector
        DummyPos = NPos + np.array([1.0, 0.0, 0.0])

        # compute the final CPos for the initial residue
        TNB3 = coords.constructTNBFrame(DummyPos, NPos, CAPos)
        CPos = CAPos + self.CCbondLength * coords.generateTNBVecXYZ(
            TNB3, self.angleCA, self.psi)

        return [NPos, CAPos, CPos]
Esempio n. 7
0
    def generateSpaceCurve(self):
        # generates a space curve with a specified bond angle, dihedrals and bondlength

        b = self.bondLength
        n = self.numPoints

        # generate 3 points a distance b apart one of which is pointA
        s2 = self.pointA - b * self.blockDirectorHat
        s1Dir = np.array([
            rnd.uniform(0.0, 1.0),
            rnd.uniform(0.0, 1.0),
            rnd.uniform(0.0, 1.0)
        ])
        s1 = s2 - b * s1Dir / np.linalg.norm(s1Dir)
        spaceCurve = [s1, s2, self.pointA]

        # have first point so add a further n-1 points
        for _ in range(n - 1):
            # construct TNB frame from last three points of the space curve
            tnb = coords.constructTNBFrame(spaceCurve[-3], spaceCurve[-2],
                                           spaceCurve[-1])

            if self.angularRange[0] == 'None':
                # compute a new direction based on beta and alpha
                alpha = self.alpha
                beta = self.beta
            else:
                # if the angular range is set then pick a random direction. (hope it's not too madly self intersecting. Got a bit chill about that later on.
                # careful narrow choices of ranges can give good results without checking for intersections.
                alpha = rnd.uniform(self.angularRange[0], self.angularRange[1])
                beta = rnd.uniform(self.angularRange[2], self.angularRange[3])
            dirn = coords.generateTNBVecXYZ(tnb, beta, alpha)

            # construct next space curve point
            spaceCurve.append(spaceCurve[-1] + b * dirn / np.linalg.norm(dirn))

        currentAxis = coords.axisFromHelix(spaceCurve[2:])
        currentRefPoint = self.pointA

        spaceCurve = coords.transformFromBlockFrameToLabFrame(
            self.blockDirectorHat, self.pointA, 0.0, currentAxis,
            currentRefPoint, spaceCurve[2:])

        return spaceCurve
Esempio n. 8
0
    def generateSpaceCurve(self):
        # generates a space curve with specified bondLength but with bond angles and dihedrals
        # chosen from a range

        b = self.bondLength
        n = self.numPoints

        # generate 3 points a distance b apart one of which is pointA
        s2 = self.pointA - b * self.blockDirectorHat
        s1Dir = np.array([
            rnd.uniform(0.0, 1.0),
            rnd.uniform(0.0, 1.0),
            rnd.uniform(0.0, 1.0)
        ])
        s1 = s2 - b * s1Dir / np.linalg.norm(s1Dir)
        spaceCurve = [s1, s2, self.pointA]

        # have first point so add a further n-1 points
        for _ in range(n - 1):
            # construct TNB frame from last three points of the space curve
            tnb = coords.constructTNBFrame(spaceCurve[-3], spaceCurve[-2],
                                           spaceCurve[-1])

            beta = rnd.uniform(self.beta1, self.beta2)
            alpha = rnd.uniform(self.alpha1, self.alpha2)

            # compute a new direction based on beta and alpha
            dirn = coords.generateTNBVecXYZ(tnb, beta, alpha)

            # construct next space curve point
            spaceCurve.append(spaceCurve[-1] + b * dirn / np.linalg.norm(dirn))

        # chop the starting points off
        spaceCurve = spaceCurve[2:]

        if self.SpaceCurveTransform == True:
            currentAxis = coords.axisFromHelix(spaceCurve)
            currentRefPoint = self.pointA
            spaceCurve = coords.transformFromBlockFrameToLabFrame(
                self.blockDirectorHat, self.pointA, 0.0, currentAxis,
                currentRefPoint, spaceCurve)

        return spaceCurve
Esempio n. 9
0
    def generateGPQUnit(self, prevGPQ):

        # given a list of 6 xyz positions for the previous G-PQ Unit
        # construct the next G-PQ unit with appropriate bond angles
        # and dihedral angles.

        # construct the first G Unit from the previous G-PQ unit
        TNB1 = coords.constructTNBFrame(prevGPQ[2], prevGPQ[3], prevGPQ[5])
        NPosG = prevGPQ[5] + self.CNbondLength * coords.generateTNBVecXYZ(
            TNB1, self.angleC, self.PGPsi)

        TNB2 = coords.constructTNBFrame(prevGPQ[3], prevGPQ[5], NPosG)
        dirHat = coords.generateTNBVecXYZ(TNB2, self.angleN, self.PGPhi)
        if self.species == 'SP1':
            FPosG = NPosG + self.GG1bondLength / 2.0 * dirHat
            CPosG = FPosG + self.GG1bondLength / 2.0 * dirHat
        else:
            FPosG = NPosG + self.GG2bondLength / 2.0 * dirHat
            CPosG = FPosG + self.GG2bondLength / 2.0 * dirHat

        TNB3 = coords.constructTNBFrame(prevGPQ[5], NPosG, CPosG)

        # now construct the P or Q unit
        if self.species == 'SP1':
            dirHat = coords.generateTNBVecXYZ(TNB3, self.angleN, self.GPPsi)
            NPosP = CPosG + self.CNbondLength * dirHat
            TNB4 = coords.constructTNBFrame(NPosG, CPosG, NPosP)
            dirHat = coords.generateTNBVecXYZ(TNB4, self.angleN, self.GPPhi)
            FPosP = NPosP + self.PPbondLength / 2.0 * dirHat
            CPosP = FPosP + self.PPbondLength / 2.0 * dirHat
            G_PQUnit = [NPosG, FPosG, CPosG, NPosP, FPosP, CPosP]
        else:
            dirHat = coords.generateTNBVecXYZ(TNB3, self.angleC, self.GQPsi)
            NPosQ = CPosG + self.CNbondLength * dirHat
            TNB4 = coords.constructTNBFrame(NPosG, CPosG, NPosQ)
            dirHat = coords.generateTNBVecXYZ(TNB4, self.angleN, self.GQPhi)
            FPosQ = NPosQ + self.QQbondLength / 2.0 * dirHat
            CPosQ = FPosQ + self.QQbondLength / 2.0 * dirHat
            G_PQUnit = [NPosG, FPosG, CPosG, NPosQ, FPosQ, CPosQ]
        return G_PQUnit
Esempio n. 10
0
def connectBackboneSegments(backboneSet, connectorDictList):    
    ''' connects together a set of polymer building block objects according to the
    connection information in the connectorDictList. The order of the segments is defined by the order 
    they appear in the backboneSet list. 
    If there are N segments there must be N-1 connector objects with the link information.
    The connector information contains the angle between polymer directors, and the azimuthal rotation between
    the directors of each segment, as well as the distance from the last monomer of the first polymer
    and the first monomer of the second polymer, in the direction of the first polymer's 
    labdirector. The first two segments are always contained in the zx plane, and the first polymer is
    always aligned with the z axis. Setting all the azimuthal rotations to zero thus keeps all subsequent 
    segments in the zx plane which is useful for 2D figures, and for defining a zero plane
    to put side brushes in later on.'''
    
    # intialise the first labdirector, TNB frame and start point
    labDirector = np.array([0.0, 0.0, 1.0])
    labBidirector  = np.array([1.0, 0.0, 0.0])  # initial bi-director along the x axis.
    labNormDirector = np.cross(labDirector, labBidirector)
    zeroPoint = np.array([0.0, 0.0, 0.0])
    
    # initialise the output arrays with data from the first segment. 
    backboneXYZ = backboneSet[0].blockXYZVals
    backboneNames = backboneSet[0].blockAtomNames
    backboneIndexList = [len(backboneXYZ)]
    backboneTNBList = [ (cp.copy(labDirector), cp.copy(labNormDirector), cp.copy(labBidirector) ) ]  
    
    # find the principal axis of the first segment
    blockDirector = coords.axisFromHelix(backboneXYZ)
    
    # rotate the xyz vals to the z-axis lab director and translate the first point to the zeroPoint as defined
    backboneXYZ = coords.transformFromBlockFrameToLabFrame(labDirector, zeroPoint, 0.0, blockDirector, backboneXYZ[0], backboneXYZ)     
     
    # loop through the connectors and remaining segments orienting them according to the instructions in the connector list
    for connector, newBackboneSegmentBB in zip(connectorDictList, backboneSet[1:]):
        
        # generate unit TNB frame for the last segment 
        TNB = [labDirector, labNormDirector, labBidirector] 
        
        # compute the lab director for the new block and connector information, which is defined relative to end of last polymer.
        newLabDirector = coords.generateTNBVecXYZ(TNB, connector['beta']*np.pi/180.0, connector['alpha']*np.pi/180.0)

        # compute the zero point for the new block to attach to the end of the polymer backbone as it is just now
        zeroPoint = backboneXYZ[-1] + connector['displacement'] * newLabDirector 

        # find the current principal axis of the new segment
        blockDirector = coords.axisFromHelix(newBackboneSegmentBB.blockXYZVals)
               
        # rotate the xyz vals to the z-axis lab director and translate the first point to the zeroPoint as defined
        newBackboneXYZ = coords.transformFromBlockFrameToLabFrame(newLabDirector, 
                                                                  zeroPoint, 
                                                                  0.0, 
                                                                  blockDirector, 
                                                                  newBackboneSegmentBB.blockXYZVals[0], 
                                                                  newBackboneSegmentBB.blockXYZVals)     
        # generate new TNB frame for the next segment
        labNormDirector = np.cross(labDirector, newLabDirector)
        labBidirector = np.cross(labNormDirector, newLabDirector)
        labDirector = newLabDirector

        # add the output information to the output arrays
        backboneXYZ = np.concatenate((backboneXYZ, newBackboneXYZ), 0)
        backboneNames = np.concatenate((backboneNames, newBackboneSegmentBB.blockAtomNames), 0)
        backboneIndexList.append(len(newBackboneXYZ))
        backboneTNBList.append((cp.copy(newLabDirector), cp.copy(labNormDirector), cp.copy(labBidirector)))
        
    # return all the information that describes the backbone necessary for decorating it with side chains        
    return (backboneXYZ, backboneNames, backboneIndexList, backboneTNBList)
Esempio n. 11
0
    def startGPQUnit(self):
        # generates the first G-PQ unit of the spidroin Backbone

        # A G or PQ unit has three nodes: the NPos, the FPos and the CPos.
        # The NPos is the N terminal of the unit, The FPos is the force centre and the CPos is the C terminal.
        # Together these three things define an ellipsoid and a central repulsive/attractive field.

        if self.species == 'SP2':
            # First Unit in SP2 is a P-Unit
            # set up a dummy pos to sort out first dihedral
            DPos = np.array([1.0, 0.0, 0.0])

            # set first NPos to be at origin.
            NPosP1 = np.array([0.0, 0.0, 0.0])

            # Assume FPos is along director axis from NPos - bad assumption - we'll correct it later
            FPosP1 = NPosP1 + self.PPbondLength / 2.0 * self.directorHat

            # Make the CPos at the end of the GUnit
            CPosP1 = NPosP1 + self.PPbondLength / 2.0 * self.directorHat

            # set up the TNB frame to define the alpha and betas for the first part of the P to G Unit
            TNB1 = coords.constructTNBFrame(DPos, NPosP1, CPosP1)
            NPosG = CPosP1 + self.CNbondLength * coords.generateTNBVecXYZ(
                TNB1, self.angleC, self.PGPsi)

            # set up the TNB frame to define the alpha and betas for the second part of the P to G Unit
            TNB2 = coords.constructTNBFrame(NPosP1, CPosP1, NPosG)

            # set up FPosG and CPosG
            dirHat = coords.generateTNBVecXYZ(TNB2, self.angleN, self.PGPhi)
            FPosG = NPosG + self.GG2bondLength / 2.0 * dirHat
            CPosG = FPosG + self.GG2bondLength / 2.0 * dirHat

            # now generate NPosP2, FPosP2, CPosP2
            # set up the TNB frame to define the alpha and betas for the first part of the G to P Unit
            TNB3 = coords.constructTNBFrame(CPosP1, NPosG, CPosG)
            NPosP2 = CPosG + self.CNbondLength * coords.generateTNBVecXYZ(
                TNB3, self.angleC, self.GPPsi)

            # set up the TNB frame to define the alpha and betas for the second part of the G to P Unit
            TNB2 = coords.constructTNBFrame(NPosG, CPosG, NPosP2)
            dirHat = coords.generateTNBVecXYZ(TNB3, self.angleN, self.GPPhi)

            # Assume FPos is along director axis from NPos - bad assumption - we'll correct it later
            FPosP2 = NPosP2 + self.PPbondLength / 2.0 * dirHat

            # Make the CPos at the end of the GUnit
            CPosP2 = NPosP1 + self.PPbondLength / 2.0 * dirHat

            GPQUnit = [
                NPosP1, FPosP1, CPosP1, NPosG, FPosG, CPosG, NPosP2, FPosP2,
                CPosP2
            ]

        # In SP1 we start with a G-Q, in SP2 we start with a P-G-P
        if self.species == 'SP1':
            # First unit in SP1 is a G-Q unit.

            # set up a dummy pos to sort out first dihedral
            DPos = np.array([1.0, 0.0, 0.0])

            # set first NPos to be at origin.
            NPosG = np.array([0.0, 0.0, 0.0])

            # Assume FPos is along director axis from NPos - bad assumption - we'll correct it later
            FPosG = NPosG + self.GG1bondLength / 2.0 * self.directorHat

            # Make the CPos at the end of the GUnit
            CPosG = FPosG + self.GG1bondLength / 2.0 * self.directorHat

            # set up the TNB frame to define the alpha and betas for the first part of the G to P Unit
            TNB1 = coords.constructTNBFrame(DPos, NPosG, CPosG)
            NPosQ = CPosG + self.CNbondLength * coords.generateTNBVecXYZ(
                TNB1, self.angleC, self.GQPsi)

            # set up the TNB frame to define the alpha and betas for the second part of the G to Q Unit
            TNB2 = coords.constructTNBFrame(NPosG, CPosG, NPosQ)

            # set up FPosPQ and CPosPQ
            dirHat = coords.generateTNBVecXYZ(TNB2, self.angleN, self.GQPhi)
            FPosQ = NPosQ + self.QQbondLength / 2.0 * dirHat
            CPosQ = FPosQ + self.QQbondLength / 2.0 * dirHat

            GPQUnit = [NPosG, FPosG, CPosG, NPosQ, FPosQ, CPosQ]

        return GPQUnit
Esempio n. 12
0
    def makeConnection(self, selfConnector, newBB, newBBConnector, displacement, alpha1, beta1, alpha2, beta2, alpha3):
        # Returns a copy of the newBB that is correctly positioned relative to self, as defined
        # by the six parameters provided. Six degrees of freedom are necessary to specify the global
        # position and orientation of the mobile block. These are specified in terms of the dihedral and bond angles
        # formed by the juxtaposition of the two connectors used to connect the blocks. Input angles are in Radians. 
        # 
        # Six atoms are used to connect the blocks which are specified using 2 arrays of 3 indices that refer to the atoms in 
        # both of the building blocks. There are three atoms from each block: called 0s, 1s, 2s and 0m, 1m, 2m where m stands for 
        # mobile and s for static.
        # 
        # It is envisaged that 2m and 2s are the two atoms that form the connecting "bond" between the blocks so 2 is 
        # at the surface of a structure and 1, and 0 are increasingly deeper into the structures with m and s specifying which 
        # block they come from.
        # 
        # The algorithm never moves the static block and proceeds by first establishing the correct position for 2m in the 
        # mobile block, then 1m and then 0m. This is performed by a translation and three rotations.
        
        # Alpha1 is the dihedral angle formed by the atoms referenced by connector indices 0s 1s 2s 2m
        # beta1 is the bond angle formed by the atoms 1s, 2s and 2m.
        # displacement is the distance between 2s and 2m which form the connector points.
        # Together displacement, alpha1 and beta1 define where atom 2m goes in the static TNB frame formed 
        # from 0s, 1s and 2s, when this frame is positioned at 2s.
        #  
        # Thus the first translation places the mobile block so that atom 2m is at the location specified.
        #
        # Alpha2, beta2 and alpha3 then define the re-orientation of the entire second block.
        #
        # Beta2 is set first and is the the bond angle that should exist between the 2s 2m and 1m atoms.
        # This angle is set by first measuring the existing bond angle so formed after the translation.  
        # The second block is then rotated by the necessary angle about an axis through 2m which is Normal 
        # to the plane formed by 2s, 2m and 1m. (this is the N vector of the TNBframe define by the points 
        # 2s, 2m, 1m). 
        #
        # Alpha2 is set next and is the dihedral angle formed by the point 1s 2s 2m 1m. 
        # The existing angle is measured and the mobile block is then
        # rotated by the appropriate angle about a vector through 2m which is parallel to 2m - 2s. 
        #
        # point 1m is now positioned correctly.
        #  
        # THe final dihedral that must be set is the one defined by 2s, 2m, 1m and 0m, which is a rotation about the 2m to 1m axis.
        # The dihedral is measured and adjusted accordingly. 
        # Only moves point 0m and that means that the second block is now correctly positioned. 
        
        # first create a copy of the new BB so as not to modify the original building block.
        # mBB = mobile Building Block
        mBB = cp.copy(newBB)
        
        # extract the connection points for the two building blocks (self and mobile).  
        selfConnectXYZ = self.getConnectionAtoms(selfConnector)
        mobileConnectXYZ = mBB.getConnectionAtoms(newBBConnector)

        # construct a TNB frame from 0s, 1s and 2s. 
        TNB1 = coord.constructTNBFrame(selfConnectXYZ[0], selfConnectXYZ[1], selfConnectXYZ[2])
        
        # Compute the displacement of the mobileBlock so that the mobile BB's connection point 2m  
        # is at the right place in the TNB frame of the first connector when it is position with it's origin on the 
        # third point. The vector in this frame is defined by displacement, alpha1 and beta1.
        displacementVec = selfConnectXYZ[2] + displacement * coord.generateTNBVecXYZ(TNB1, beta1, alpha1) - mobileConnectXYZ[2]     
    
        # translate the mobile block so it's in the right place
        mBB.translateBB(displacementVec)
        
        
        ##### Rot 1: Set alpha 2 - dihedral about 2s to 2m axis ######
        # get the new repositioned mobile connector block
        mobileConnectXYZ = mBB.getConnectionAtoms(newBBConnector)
        
        # measure the dihedral between s1, s2, m2 and m1, keep order the same to maintain signs.
        alpha2Meas = coord.Dihedral(selfConnectXYZ[1], selfConnectXYZ[2], mobileConnectXYZ[2], mobileConnectXYZ[1])
        if alpha2Meas==None:
            alpha2Meas = alpha2
        
        # compute the alpha2rotation axis (unti vector from 2s to 2m)
        alpha2RotAxis = mobileConnectXYZ[2] - selfConnectXYZ[2]
        alpha2RotAxisHat = alpha2RotAxis/np.linalg.norm(alpha2RotAxis)
        
        # rotate the second block by an angle (alpha2 - alpha2Meas) about a vector through the point 2m which is parallel to the 2s 2m axis 
        # Only 1m and 0m should move from the static and mobile connector sets.
        mBB.rotateBBArbitraryAxis(mobileConnectXYZ[2], alpha2RotAxisHat, alpha2 - alpha2Meas)
        
        
        ##### Rot 2: Set Beta2- bond angle from point m2 ######
        # get the new repositioned mobile connector block
        mobileConnectXYZ = mBB.getConnectionAtoms(newBBConnector)
        
        # measure the bondangle between s2, m2 and m1
        beta2Meas = coord.bondAngle(selfConnectXYZ[2], mobileConnectXYZ[2], mobileConnectXYZ[1])
        
        # construct a TNB frame from s2, m2 and m1 
        TNB2 = coord.constructTNBFrame(selfConnectXYZ[2], mobileConnectXYZ[2], mobileConnectXYZ[1])
        
        # rotate mobile connector by angle (beta2 - beta2Meas) about a vector through the point 2m which is parallel with TNB2 frame N-axis
        # i.e. normal to plane of s2, m2 and m1  - the way normal is defined versus measurements of angle means to put a minus sign in there.
        mBB.rotateBBArbitraryAxis(mobileConnectXYZ[2], TNB2[1], -(beta2 - beta2Meas))
        
        
        ###### rot3:  set alpha3 - dihedral ab out 2m to 1m axis.
        # extract the new mobile connectors
        mobileConnectXYZ = mBB.getConnectionAtoms(newBBConnector)
        
        # construct rot3Axis from 2m to 1m. 
        rot3Axis = mobileConnectXYZ[1] - mobileConnectXYZ[2]
        rot3AxisHat = rot3Axis/np.linalg.norm(rot3Axis)

        # measure the dihedral betwee s2, m2, m1 and m0.
        alpha3Meas = coord.Dihedral(selfConnectXYZ[2], mobileConnectXYZ[2], mobileConnectXYZ[1], mobileConnectXYZ[0])
        
        # rotate the second block by an angle (alpha3 - alpha3Meas) about a vector through the point 2m which is parallel to the 2m 1m axis 
        # Only 0m should move to it's final place from the static and mobile connector sets.
        mBB.rotateBBArbitraryAxis(mobileConnectXYZ[2], rot3AxisHat, alpha3 - alpha3Meas)
        
        # return the rotated Building Block
        return mBB
Esempio n. 13
0
    def generateBuildingBlockXYZ(self):

        # create a strand and loop generator
        strandGen = PBG(self.paramFilename)
        loopGen = PHG(self.paramFilename)

        loopPoints = []
        sphereCentrePoints = []
        dummyConnector = [[2, 1, 0]]

        # construct the base line for the strand start points
        baseLine = [
            self.startPos +
            n * self.betaStrandSeparation * self.crossStrandDirectorHat
            for n in range(self.numStrands)
        ]

        # construct a prototype beta strand building Block in the defined polarity
        strandA_BB = strandGen.generateBuildingBlock(self.numPoints,
                                                     self.polarity,
                                                     dummyConnector)

        # assume loop length needs to be long enough to stretch a whole beta strand.
        loopLength = int(np.ceil(1.5 * self.strandLength))

        # In a not parallel situation construct the antiparallel strand - StrandB
        # also add the offset to every other strand starting on the first or second strand depending on the polarity
        # also compute the alternative strand building block
        if not self.parallel:
            loopLength = 2  # in a parallel situation the loop is always 2 (residues) long. I just said so.
            if self.polarity == 'NC':
                baseLine = [
                    basePoint + self.offsetXYZ if (n % 2) == 0 else basePoint
                    for n, basePoint in enumerate(baseLine)
                ]
                strandB_BB = strandGen.generateBuildingBlock(
                    self.numPoints, 'CN', dummyConnector)
            else:
                baseLine = [
                    basePoint + self.offsetXYZ if (n % 2) == 1 else basePoint
                    for n, basePoint in enumerate(baseLine)
                ]
                strandB_BB = strandGen.generateBuildingBlock(
                    self.numPoints, 'NC', dummyConnector)

        # compute the relative vector from the end of the first chain to the next atom in the hairpin.
        TNB = coords.constructTNBFrame(strandA_BB.xyzVals[-3],
                                       strandA_BB.xyzVals[-2],
                                       strandA_BB.xyzVals[-1])

        if self.polarity == 'NC':
            # if polarity is NC then the last three values are an NCC triad.
            beta = self.angleC
            alpha = self.phi
            bondLength = self.CNbondLength
        else:
            # if polarity is CN then the last three values are CCN triad.
            beta = self.angleN
            alpha = self.psi
            bondLength = self.CNbondLength

        # the vector from the end of the first strand to its hairpin is defined as the positive connectorVector.
        ConnectorVectorPos = bondLength * coords.generateTNBVecXYZ(
            TNB, beta, alpha)

        # -ve connector vector is the reciprocal of that
        ConnectorVectorNeg = -1 * ConnectorVectorPos

        # for parallel all CVs are always the Positive from end of strand to hairpin
        # and from hairpin to end of strand
        connectorVectorStrandToHairpin = ConnectorVectorPos
        connectorVectorHairpinToStrand = ConnectorVectorPos

        # for parallel strands are always the same set of xyz vals
        curStrandXYZ = strandA_BB.xyzVals

        # now the preparatory stuff is complete begin constructing the beta sheet
        # copy across the first strand to get the structure going.
        buildingBlockXYZ = [baseLine[0] + xyz for xyz in strandA_BB.xyzVals]

        innerRadiusParallel = 0.75 * self.strandLength * 3 * bondLength / 2
        outerRadiusParallel = 40 * self.strandLength * 3 * bondLength / 2
        innerRadiusAntiParallel = 0.9 * self.betaStrandSeparation / 2
        outerRadiusAntiParallel = 40 * self.betaStrandSeparation
        print "Radii: ", innerRadiusParallel, outerRadiusParallel, innerRadiusAntiParallel, outerRadiusAntiParallel
        print "Diameter: ", 2 * innerRadiusParallel, 2 * outerRadiusParallel, 2 * innerRadiusAntiParallel, 2 * outerRadiusAntiParallel

        # contruct the remaining strands following this procedure
        curStrand = 1
        while curStrand < self.numStrands:

            # if parallel, strands and connectorvectors are always the same so do nothing
            # to them.

            # if not parallel work out the connectorVectors for attaching hairpin between
            # the previous strand and the current strand.
            if not self.parallel:
                if (curStrand % 2) == 0:
                    connectorVectorStrandToHairpin = ConnectorVectorNeg
                    connectorVectorHairpinToStrand = ConnectorVectorPos
                    curStrandXYZ = strandA_BB.xyzVals
                if (curStrand % 2) == 1:
                    connectorVectorStrandToHairpin = ConnectorVectorPos
                    connectorVectorHairpinToStrand = ConnectorVectorNeg
                    curStrandXYZ = list(reversed(strandB_BB.xyzVals))

            # loop start is end of building block + connectorvector
            loopStartPoint = buildingBlockXYZ[
                -1] + connectorVectorStrandToHairpin

            loopPoints.append(loopStartPoint)

            # compute values for new strand
            newStrand = [baseLine[curStrand] + xyz for xyz in curStrandXYZ]

            # loop end point is start of next strand - connector vector.
            loopEndPoint = newStrand[0] - connectorVectorHairpinToStrand

            loopPoints.append(loopEndPoint)
            sphereCentrePoint = (loopEndPoint + loopStartPoint) / 2
            sphereCentrePoints.append(sphereCentrePoint)

            print "loopPointdist: ", np.linalg.norm(loopEndPoint -
                                                    loopStartPoint)

            # now we have the length of the loop and the start and end points
            # makes and attempt to stop the hairpin from entering
            # a sphere at the mid point of the start and end points
            if self.loopEnds:
                if self.parallel:

                    loop = loopGen.generateBuildingBlock(
                        loopLength * 3, loopStartPoint, loopEndPoint, 0, -180,
                        180, beta * 180 / np.pi - 40, beta * 180 / np.pi + 40,
                        0.9 * bondLength, bondLength, innerRadiusParallel,
                        outerRadiusParallel, sphereCentrePoint, self.polarity)
                else:
                    loop = loopGen.generateBuildingBlock(
                        loopLength * 3, loopStartPoint, loopEndPoint, 0, -180,
                        180, beta * 180 / np.pi - 40, beta * 180 / np.pi + 40,
                        0.9 * bondLength, bondLength, innerRadiusAntiParallel,
                        outerRadiusAntiParallel, sphereCentrePoint,
                        self.polarity)
                # append the loop to the array
                buildingBlockXYZ = buildingBlockXYZ + loop.xyzVals

            # append each vector to the current output array
            buildingBlockXYZ = buildingBlockXYZ + newStrand

            #next strand
            curStrand += 1

        #buildingBlockXYZ = buildingBlockXYZ + loopPoints
        #buildingBlockXYZ = buildingBlockXYZ + sphereCentrePoints

        self.numPoints = len(buildingBlockXYZ)

        return buildingBlockXYZ