示例#1
0
 def generateBuildingBlockDirector(self):
     if self.numPoints > 9:
         director = coords.axisFromHelix(self.buildingBlockXYZ)
     else:
         director = self.buildingBlockXYZ[-1] - self.buildingBlockXYZ[0]
     directorHat = director / np.linalg.norm(director)
     return directorHat
示例#2
0
    def generateBuildingBlockXYZ(self):

        # create the first residue in the BB
        if self.seedResidue == None:
            strand = self.startResidue()
        else:
            strand = self.seedResidue

        # tally the number of residues we added to strand
        numResidues = 1

        # loop until we've added the right number of residues
        while numResidues < self.numResidues:

            # create new residue from the last three points
            residue = self.generateResidue(strand[-3:])

            # add the new Residues to the strandVec list
            [strand.append(monomer) for monomer in residue]

            numResidues += 1

        # perform final orientation depending on whether or not a seed residue was provided.
        # If seed was provided then don't fiddle with orientation at all.
        # if seed wasn't provided then return the strand with it's centre of mass
        # at the origin and it's helical axis pointing along the z-axis
        if self.seedResidue == None and self.numResidues > 3:
            # This structure was created in such a way that the first two atoms are
            # aligned with Z vector. We want the structure to be returned so it is at it's
            # centre of mass and also with the helical axis pointing up the z axis.
            # We will use the transformation from Lab to Block to achieve this,
            # with a little bit of hacking of the member variables.

            # find the helix axis and the centre of mass of the construct
            # as it is right now.
            currentDirector = coords.axisFromHelix(strand)
            currentDirectorHat = currentDirector / np.linalg.norm(
                currentDirector)
            currentCOM = cart.getCentreOfMass(strand)

            # Now specify the orientation and position that we want to map to.
            # store the refPoint as a member variable.
            targetRefPoint = np.array([0.0, 0.0, 0.0])
            targetDirectorHat = np.array([0.0, 0.0, 1.0])

            # modify the strand accordingly with the universal transformation function
            strand = coords.transformFromBlockFrameToLabFrame(
                targetDirectorHat, targetRefPoint, 0.0, currentDirectorHat,
                currentCOM, strand)

        return list(
            np.around(strand, 12)
        )  # round the positions to 12.dp - cleans up machine precision noise on zeroes
示例#3
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
示例#4
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
示例#5
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)
示例#6
0
def decoratePolymerBackbone(brushDictList, backboneInfo): 

    # unpack input
    backboneXYZ = backboneInfo[0]
    backboneNames = backboneInfo[1]
    backboneSegmentLengths = backboneInfo[2]
    backboneTNBList = backboneInfo[3]

    # break the list of XYZ points into list of points for each segment
    backBoneXYZList = breakListToSubList(backboneXYZ, np.cumsum(np.concatenate((np.array([0]), backboneSegmentLengths), 0)))

    # set up output
    polymerXYZ = cp.copy(backboneXYZ)
    polymerNames = cp.copy(backboneNames)
    
    for brush, numBrushes, TNB, points in zip(brushDictList, backboneSegmentLengths, backboneTNBList, backBoneXYZList):
        if brush['numMonomers']>0:
            # create the brush generator. Default is polymer. Check to see if we want a peptide brush 
            if 'Peptide' in brush['mode']:
                brushBBG = PBG(brush['filename'])
                brushBB = brushBBG.generateBuildingBlock(brush['numMonomers']) # only need to create this once for peptide backbones as they are either alpha or beta.
                brushBB.blockAtomNames = brush['monomerNames']
            else:
                brushBBG = RPPBBG(brush['filename'])
        
            # Set the angle of each brush around the segment director defined relative to the Binormal in the TNB frame for that polymer.
            # The range of angles is defined in the dictionary.
            brushPhaseAngles = [ rnd.uniform(0, brush['phaseRange'] * np.pi/180.0) for _ in range(0, numBrushes) ]

            # if the word Alternate is in the mode than add 180 to every other phase        
            if "Alternate" in brush['mode']:
                for index in range(0, numBrushes):
                    if index % 2 ==0:
                        brushPhaseAngles[index] += np.pi
            
            # if the word "mirror" is in the mode then add 180 randomly to half the brush phases 
            if "Mirror" in brush['mode']:
                numFlipped = 0
                indexList = list(range(0, numBrushes))
                while numFlipped < numBrushes/2:
                    index = rnd.choice(indexList)
                    brushPhaseAngles[index] += np.pi
                    numFlipped += 1
                    indexList.remove(index)    
        
            # generate directors in direction of phase angles
            brushDirectors = [ np.cos(angle) * TNB[2] + np.sin(angle) * TNB[1] for angle in brushPhaseAngles] 
            brushDirectorsNorm = [ d/np.linalg.norm(d) for d in brushDirectors]
    
            # for each of the points in the backbone generate a brush as defined    
            for point, director in zip(points, brushDirectorsNorm):
                if "Polymer" in brush['mode'] and not "Peptide" in brush['mode']:
                    # if we're doing a polymer then generate a new polymer with the given polymer parameters for each pass.
                    polyStart = np.array([ 0.0, 0.0, brush['Z1']])
                    envelopeList = ['frustum ' + str(brush['Z1'] - brush['minDist']) + ' ' + str(brush['R1']) + ' ' + str(brush['Z2']) + ' ' + str(brush['R2'])]
                
                    brushBB = brushBBG.generateBuildingBlock( brush['numMonomers'],
                                                              polyStart,
                                                              brush['alpha1'],
                                                              brush['alpha2'],
                                                              brush['beta1'],
                                                              brush['beta2'],
                                                              brush['minDist'],
                                                              brush['bondLength'],
                                                              envelopeList=envelopeList,
                                                              visualiseEnvelope=(0, 100, brush['name'] + '_envelope.xyz'))
                    # work out the block director
                    if brush['numMonomers']>2:
                        blockDirector = coords.axisFromHelix(brushBB.blockXYZVals)
                    else:
                        if brush['numMonomers']==2:
                            blockDirector = brushBB.blockXYZVals[1] - brushBB.blockXYZVals[0]
                            blockDirector = blockDirector/np.linalg.norm(blockDirector)
                        if brush['numMonomers']==1:
                            blockDirector = np.array([0.0, 0.0, 1.0])
    
                    # rotate the brush and set it at the right place
                    brushXYZVals = coords.transformFromBlockFrameToLabFrame(director, point + brush['bondLength'] * director, 0.0, blockDirector, brushBB.blockXYZVals[0], brushBB.blockXYZVals)
            
                    # concatenate the brush positions and the brush names to the output arrays
                    polymerXYZ = np.concatenate( (polymerXYZ, brushXYZVals), 0)
                    polymerNames = np.concatenate( (polymerNames, brush['monomerNames']), 0)
        
    return polymerXYZ, polymerNames 
示例#7
0
def GeneralPolymerBrush(brushDict, mode="RandomPolymer"):

    # unpack the brush dictionary
    
    
    
    
    
    
    filenameRandom = brushDict['filenameBlock']
    filenameBrush = brushDict['filenameBrush']
    mode = brushDict['mode']
    
    ABlock = brushDict['ABlock']
    num_A = ABlock['num'] 
    alpha1_A = ABlock['alpha1']
    alpha2_A = ABlock['alpha2'] 
    beta1_A = ABlock['beta1'] 
    beta2_A = ABlock['beta2'] 
    minDist_A = ABlock['minDist'] 
    bondLength_A = ABlock['bondLength']
    Z1_A = ABlock['Z1'] 
    R1_A = ABlock['R1'] 
    Z2_A = ABlock['Z2'] 
    R2_A = ABlock['R2'] 
    
    BBlock = brushDict['BBlock']
    num_B = BBlock['num'] 
    alpha1_B = BBlock['alpha1']
    alpha2_B = BBlock['alpha2'] 
    beta1_B = BBlock['beta1'] 
    beta2_B = BBlock['beta2'] 
    minDist_B = BBlock['minDist'] 
    bondLength_B = BBlock['bondLength']
    Z1_B = BBlock['Z1'] 
    R1_B = BBlock['R1'] 
    Z2_B = BBlock['Z2'] 
    R2_B = BBlock['R2']
    
    brushBlock = brushDict['brushBlock']
    num_brush = brushBlock['num'] 
    alpha1_brush = brushBlock['alpha1']
    alpha2_brush = brushBlock['alpha2'] 
    beta1_brush = brushBlock['beta1'] 
    beta2_brush = brushBlock['beta2'] 
    minDist_brush = brushBlock['minDist'] 
    bondLength_brush = brushBlock['bondLength']
    Z1_brush = brushBlock['Z1'] 
    R1_brush = brushBlock['R1'] 
    Z2_brush = brushBlock['Z2'] 
    R2_brush = brushBlock['R2']
    

    # Mode word must specify one of Polymer or Peptide.  Can also include modifiers Sheet or Random to specify phase of brushes around polymer backbone axis.
    # defaults to RandomPolymer.  Can supply brush polymer parameters via parameter polymer params. These are alpha1, alpha2, beta1, beta2, minDist and bond length. 
    # atom name supplied in filenameBrush.  This is a mess. I know. I don't care.  
    
    # if one of Peptide or Polymer is not in mode then add Polymer to the end of mode. Anything else is dandy. If you specify both peptide and polymer, then Peptide will override.
    if not ("Peptide" in mode or "Polymer" in mode):
        mode = mode + "Polymer"
    
    # generate the block Copolymer backbone
    (polymerXyzVals, polymerNames) = MBCP(num_A, num_B,   Z1_A, R1_A, Z2_A, R2_A, alpha1_A, alpha2_A, beta1_A, beta2_A, minDist_A, bondLength_A, 
                                                        Z1_B, R1_B, Z2_B, R2_B, alpha1_B, alpha2_B, beta1_B, beta2_B, minDist_B, bondLength_B, filenameRandom)
    
    # get axis of block A
    BlockAAxis = coords.axisFromHelix(polymerXyzVals[0:num_A])
    BlockAAxisNorm = BlockAAxis/np.linalg.norm(BlockAAxis) 
    
    # get an orthogonal vector to BlockAAxis which is random. 
    randDirXYZ = BlockAAxis
    randXYZIsAxizXYZ = True
    
    while randXYZIsAxizXYZ: 
        randVecDir = coords.pickRandomPointOnUnitSphere()
        randDirXYZ = coords.sphericalPolar2XYZ(np.array([1.0, randVecDir[0], randVecDir[1]]))
        randXYZIsAxizXYZ = not False in [ np.abs(a - b) < 1e-7 for a, b in zip(randDirXYZ, BlockAAxis) ]
        
    OrthVec = randDirXYZ - np.dot(BlockAAxisNorm, randDirXYZ) * BlockAAxisNorm
    OrthVec1Norm = OrthVec/np.linalg.norm(OrthVec) 
    OrthVec2Norm  = np.cross(OrthVec1Norm, BlockAAxisNorm)

    # now have orthonormal basis for the polymer backbone for the brush part of system 
    
    # create the brush generator. Default is polymer mode. If peptide is included in mode word then over ride to use peptide instead 
    if "Peptide" in mode:
        # create a peptide generator using supplied filename to specify parameters of peptide - filename overides polymerParams
        brushGenerator = PBG(filenameBrush)
        brushObject = brushGenerator.generateBuildingBlock(num_brush) # only need to create this once for peptides as all are the same
    else:
        brushGenerator = RPPBBG(filenameBrush)
    
    # choose the phase angles of each brush
    # initially make the phase angle a little bit random
    brushPhaseAngles = [ rnd.uniform(0, 0.2 * np.pi) for _ in range(0, num_A) ]

    # if Random is in mode then make it very random
    if "Random" in mode:
        brushPhaseAngles = [ rnd.uniform(0, 2 * np.pi) for _ in range(0, num_A) ] 
    
    # if sheet is in mode then make phase zero.
    if "Sheet" in mode:
        brushPhaseAngles = [ 0.0 for _ in range(0, num_A) ]

    # generate directors in direction of phase angles
    brushDirectors = [ np.cos(angle) * OrthVec1Norm + np.sin(angle) * OrthVec2Norm for angle in brushPhaseAngles] 
    brushDirectorsNorm = [ d/np.linalg.norm(d) for d in brushDirectors]

    # for each of the directors (defined by the length of block A) figure out the final xyz vals    
    for point, labDirector in zip(polymerXyzVals[0:num_A], brushDirectorsNorm):
        if "Polymer" in mode and not "Peptide" in mode:
            # if we're doing a polymer then generate a new polymer with the given polymer parameters for each pass.
            polyStart = np.array([ 0.0, 0.0, Z1_brush])
            envelopeList = ['frustum ' + str(Z1_brush - minDist_brush) + ' ' + str(R1_brush) + ' ' + str(Z2_brush) + ' ' + str(R2_brush)]
            
            brushObject = brushGenerator.generateBuildingBlock( num_brush,
                                                                polyStart,
                                                                alpha1_brush,
                                                                alpha2_brush,
                                                                beta1_brush,
                                                                beta2_brush,
                                                                minDist_brush,
                                                                bondLength_brush,
                                                                envelopeList = envelopeList)
        
        newBrushXYZ = coords.transformFromBlockFrameToLabFrame(labDirector, point + minDist_A * labDirector, 0.0, brushObject.blockDirectorHat, brushObject.blockXYZVals[0], brushObject.blockXYZVals)
        polymerXyzVals = np.concatenate((polymerXyzVals, newBrushXYZ), 0) 
        polymerNames = np.concatenate( (polymerNames, brushObject.blockAtomNames), 0 )


    # direction of brush is z-axis.  
    # reference point is the first of the B polymers, which is the numAth entry in the list of xyzVals
    return (np.array([0.0, 0.0, 1.0]), polymerXyzVals[num_A], polymerXyzVals, polymerNames)