Beispiel #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]
Beispiel #2
0
    def findLastTwoPoints(self, startPoints, endPoints, pointsToAvoid):
        
        TNB = coords.constructTNBFrame(startPoints[-2],
                                       startPoints[-1],
                                       endPoints[-1])
        # see page 173 in book 2
        l = np.linalg.norm(startPoints[-1] - endPoints[-1])
        tComponent = np.abs(l-self.bondLength)/2.0
        bComponent = np.sqrt(self.bondLength**2 - tComponent**2)
        
        if l>self.bondLength:
            newPoint1 = startPoints[-1] - tComponent* TNB[0] - bComponent * TNB[2]
        else:
            newPoint1 = startPoints[-1] + tComponent* TNB[0] - bComponent * TNB[2]
        
        newPoint2 = newPoint1 + self.bondLength * TNB[0]

        # whizz check point 1 as if newPoint2 was at the end of endPoints
        newPoint1, inBounds1 = self.whizzCheck(startPoints, endPoints + [newPoint2], pointsToAvoid, newPoint1)
        
        if inBounds1:
            # Now whizz check point 2 as if the new newPoint1 was at the end of startPoints.
            newPoint2, inBounds2 = self.whizzCheck(startPoints + [newPoint1], endPoints, pointsToAvoid, newPoint2)
            
        listsAreGood = False
        if inBounds1 and inBounds2: # only return true if both the new points are golden.
            listsAreGood = True
        
        return newPoint1, newPoint2, listsAreGood 
Beispiel #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)])
Beispiel #4
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
Beispiel #5
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]
Beispiel #6
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
Beispiel #7
0
    def findLastPoint(self, startPoints, endPoints, pointsToAvoid):
        # construct a TNB frame
        TNB = coords.constructTNBFrame(startPoints[-2],
                                       startPoints[-1],
                                       endPoints[-1])
        
        # Compute position in TB plane of last point
        TComponent = np.linalg.norm(startPoints[-1] - endPoints[-1])/2
        BComponent = np.sqrt(self.bondLength**2 - TComponent**2)
        newPoint = startPoints[-1] + BComponent*TNB[2] + TComponent*TNB[0]
 
        # perform a whizz Check       
        return self.whizzCheck(startPoints, endPoints, pointsToAvoid, newPoint)
Beispiel #8
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
Beispiel #9
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]
Beispiel #10
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
Beispiel #11
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
Beispiel #12
0
 def pickRandomPointInDefinedSpace(self):
     # Takes the last three points of the nList and picks a new point in XYZ which 
     # is inside the given angular ranges. No need to check the ranges, because the points are only selected inside those zones.
     
     # construct the TNB vectors from the last three points of the nList.
     TNB = coords.constructTNBFrame(self.nList[-3], self.nList[-2], self.nList[-1])        
     
     # compute a directional vector in XYZ coords from the last point on the list to the new point, within the given angular range constraints. 
     newCoordXYZRel = coords.pickRandomTNBDirectionInAngRangeXYZ(TNB, 
                                                                 self.beta1, 
                                                                 self.beta2,
                                                                 self.alpha1,
                                                                 self.alpha2)
     
     # should be a unit vector already but just in case
     newCoordXYZRelHat = newCoordXYZRel/np.linalg.norm(newCoordXYZRel) 
     
     # scale the vector by the bondlength and add it to the last point in the list to give new position vector
     return self.nList[-1] + self.bondLength * newCoordXYZRelHat
    def correctBondLengths(self, xyzVals):

        # whip through the xyz vals and subtly adjust the positions of the atoms
        # so they are all exactly bondlength apart.
        for i, pos in enumerate(xyzVals):
            if i > 0 and i < len(xyzVals) - 1:
                # if the bondLengths
                b1 = np.linalg.norm(pos - xyzVals[i - 1])
                b2 = np.linalg.norm(pos - xyzVals[i + 1])

                if (np.abs(b1 - self.bondLength) >
                        0.01) or (np.abs(b2 - self.bondLength) > 0.01):
                    tnb = coords.constructTNBFrame(pos, xyzVals[i - 1],
                                                   xyzVals[i + 1])
                    midPoint = (xyzVals[i - 1] + xyzVals[i + 1]) / 2
                    l = np.linalg.norm(xyzVals[i - 1] - xyzVals[i + 1]) / 2
                    r = np.sqrt(self.bondLength**2 - l**2)
                    xyzVals[i] = midPoint + tnb[2] * r

        return xyzVals
Beispiel #14
0
 def pickRandomPointInDefinedSpace(self, p1, p2, p3):
     # Takes the given three points and picks a new point in XYZ which 
     # is bondLength distance from p3, but inside the given angular ranges
     # as defined by the bond angle p2 - p3 - newPoint and dihedral p1-p2-p3-new point.
     # No need to check againt angle ranges once point is selected because angles 
     # are picked inside those ranges already.
     
     # construct the TNB vectors from the last three points of the nList.
     TNB = coords.constructTNBFrame(p1, p2, p3)        
     
     # compute a directional vector in XYZ coords from the last point on the list to the new point, within the given angular range constraints. 
     newCoordXYZRel = coords.pickRandomTNBDirectionInAngRangeXYZ(TNB, 
                                                                 self.betaMin, 
                                                                 self.betaMax,
                                                                 self.alphaMin,
                                                                 self.alphaMax)
     
     # should be a unit vector already but just in case
     newCoordXYZRelHat = newCoordXYZRel/np.linalg.norm(newCoordXYZRel) 
     
     # scale the vector by the bondlength and add it to the last point in the list to give new position vector
     return p3 + self.bondLength * newCoordXYZRelHat
Beispiel #15
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
Beispiel #16
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
Beispiel #17
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