コード例 #1
0
def vesicle(OuterRadius, InnerRadius, numOuter, numInner, minDistInner, minDistOuter, theta1, theta2, phi1, phi2, centrePos, zDirector, omega, filename, nameInner=None, nameOuter=None):
    # Defines a bunch of points in an inner sphere and an outer sphere, 
    # Returns the points on the spherical surface, the atomnames and a list of radial vectors corresponding to each point 
    # which is the direction from that point to or from the centre depending on inner or outer status.
    # The inner sphere has Radial points pointing away from centre 
    # The outer sphere has radial points point towards the centre.
    # No problem with making the inner outside the outer if that makes sense.
    # The points are in a domain defined in spherical polars allowing a section to be removed from the sphere for the classic vesicle look.  
    # The packing parameter on each surface is defined by minDistInner and minDistOuter which is the min allowed distance between points on the inner and outer respectively.
    # Translates the sphere to centrePos with the Z pole of sphere aligned with director and an angle omega rotation about that axis.
    # Filename defines the packing algorithm parameters. (How hard to try, name of atom in the structure etc).
    # Name can be overridden by the name parameters 
    SphereBBG = SPSBBG(filename)
    
    # generate the outer sphere
    outerSphereBB = SphereBBG.generateBuildingBlock(numOuter, OuterRadius, theta1, theta2, phi1, phi2, minDistOuter, visualiseEnvelope=(100000, 1000, 'sphereEnvelope.xyz'))
    outerSphereBB.transformBBToLabFrame(zDirector, centrePos, omega)
    outerSphereXYZ = outerSphereBB.blockXYZVals
    outerDirectors = [ centrePos - a for a in outerSphereXYZ]
    outerDirectorsNorm = [ a/np.linalg.norm(a) for a in outerDirectors]
    if nameOuter=='None':
        namesOuter = outerSphereBB.blockAtomNames
    else:
        namesOuter = [nameOuter] * numOuter
    
    # generate the inner sphere
    innerSphereBB = SphereBBG.generateBuildingBlock(numInner, InnerRadius, theta1, theta2, phi1, phi2, minDistInner)
    innerSphereBB.transformBBToLabFrame(zDirector, centrePos, omega)
    innerSphereXYZ = innerSphereBB.blockXYZVals
    innerDirectors = [ a - centrePos for a in innerSphereXYZ]
    innerDirectorsNorm = [ a/np.linalg.norm(a) for a in innerDirectors]
    
    if nameInner=='None':
        namesInner = innerSphereBB.blockAtomNames
    else:
        namesInner = [nameInner] * numInner

    vesXYZVals = outerSphereXYZ + innerSphereXYZ
    vesNames = namesOuter + namesInner     
    vesDirs = outerDirectorsNorm + innerDirectorsNorm     

    return (vesXYZVals, vesNames, vesDirs) 
コード例 #2
0
def micelle(radius, num, minDist, theta1, theta2, phi1, phi2, centrePos, zDirector, omega, filename, name=None):
    # Defines a bunch of points in a sphere, 
    # Returns the points on the spherical surface, the atomnames and a list of radial vectors point from the surface to the centre. 
    # The points are in a domain defined in spherical polars allowing a section to be removed from the sphere for the classic look.  
    # The packing parameter on the surface is defined by minDist which is the min allowed distance between points.
    # Translates the micelle to centrePos with the Z pole of sphere aligned with director and an angle omega rotation about that axis.
    # Filename defines the packing algorithm parameters. (How hard to try, name of atom in the structure etc).
    # Name can be overridden by the name parameter 
    SphereBBG = SPSBBG(filename)

    # generate the inner sphere
    SphereBB = SphereBBG.generateBuildingBlock(num, radius, theta1, theta2, phi1, phi2, minDist)
    SphereBB.transformBBToLabFrame(zDirector, centrePos, omega)
    SphereXYZ = SphereBB.blockXYZVals
    Directors = [ a - centrePos for a in SphereXYZ]
    DirectorsNorm = [ a/np.linalg.norm(a) for a in Directors]
    
    if name=='None':
        names = SphereBB.blockAtomNames
    else:
        names = [name] * num

    return (SphereXYZ, names, DirectorsNorm) 
コード例 #3
0
def makeSphereAndPolymers(numA, numB, numPolymersPerSphere, FMaxRadius,
                          FMinRadius, FZ1, FZ2, alpha1, alpha2, beta1, beta2,
                          AtomicMinDist, bondLength, filename):
    SphereBBG = SPSBBG('SurfacePackSphere.txt')
    Polymer1Generator = RPBBG('RandomPolymer.txt')

    centerPos = np.array([0.0, 0.0, 0.0])

    # generate the XYZVals in the packed spaced
    Polymer1SphereBB = SphereBBG.generateBuildingBlock(numPolymersPerSphere,
                                                       FZ2, -90, 90, -180, 180,
                                                       FMinRadius)
    Polymer1SphereBB.transformBBToLabFrame(np.array([0.0, 0.0, 1.0]),
                                           centerPos, 0.0)
    Polymer1SphereBB.exportBBK(filename + "_sphereBasePoints")
    Polymer1SpherePoints = Polymer1SphereBB.blockXYZVals

    envelopeList = [
        'frustum ' + str(FZ1) + ' ' + str(FMaxRadius) + ' ' +
        str(FZ2 - AtomicMinDist) + ' ' + str(FMinRadius)
    ]

    polymerStartPoint = np.array([0.0, 0.0, FZ2])
    polymer1Strands = [
        Polymer1Generator.generateBuildingBlock(numMonomersPerPolymer,
                                                polymerStartPoint,
                                                alpha1,
                                                alpha2,
                                                beta1,
                                                beta2,
                                                AtomicMinDist,
                                                bondLength,
                                                envelopeList=envelopeList,
                                                visualiseEnvelope=(0, 100))
        for _ in range(numPolymersPerSphere)
    ]

    [strand.setBlockRefPoint(polymerStartPoint) for strand in polymer1Strands]

    names = ['O'] * numA
    names = np.concatenate((names, ['C'] * numB), 0)

    strandNum = 0
    for strand in polymer1Strands:
        strand.blockAtomNames = names[:]
        strand.exportBBK(filename + "_strand" + str(strandNum))
        strandNum += 1

    directors = [(pos - centerPos) / np.linalg.norm(pos - centerPos)
                 for pos in Polymer1SpherePoints]

    allNames = []

    curStrand = 0
    for director, pos, strand in zip(directors, Polymer1SpherePoints,
                                     polymer1Strands):
        strand.transformBBToLabFrame(director, pos, 0.0)
        if curStrand == 0:
            xyzVals = strand.blockXYZVals
            allNames = strand.blockAtomNames
        else:
            xyzVals = np.concatenate((xyzVals, strand.blockXYZVals), 0)
            allNames = np.concatenate((allNames, strand.blockAtomNames), 0)
        curStrand += 1

    fIO.saveXYZList(xyzVals, allNames, filename + "_sphere.xyz")
コード例 #4
0
import numpy as np
import copy as cp
from Library.SurfacePackSphere import SurfacePackSphereBBG as SPSBBG
from Library.randomPolymer import RandomPolymerPackBBG as RPBBG
import Utilities.coordSystems as coords
import Utilities.fileIO as fIO

if __name__ == "__main__":
    SphereBBG = SPSBBG('SurfacePackSphere.txt')
    PolymerGenerator = RPBBG('RandomPolymer.txt')

    numPoints = 100
    radius = 20
    theta1 = -90
    theta2 = 90
    phi1 = -180
    phi2 = 180
    minDist = 1

    baseSPhereBB = SphereBBG.generateBuildingBlock(numPoints, radius, theta1,
                                                   theta2, phi1, phi2, minDist)
    fIO.saveXYZ(baseSPhereBB.blockXYZVals, 'C', "mollieShere.xyz")

    numMonomers = 100
    pointA = np.array([0.0, 0.0, 0.0])

    alpha1 = 40
    alpha2 = 50
    beta1 = 110
    beta2 = 130
    minDist = 1.0
コード例 #5
0
    brushDict2['beta1'] = 155
    brushDict2['beta2'] = 175
    brushDict2['minDist'] = 1.0
    brushDict2['bondLength'] = 2.0
    brushDict2['Z1'] = 2
    brushDict2['R1'] = 50
    brushDict2['Z2'] = 1.5 * brushDict2['numMonomers'] * brushDict2['bondLength'] + brushDict2['Z1']
    brushDict2['R2'] = 50
              
    polymerBrushDict={}
    polymerBrushDict['backbones'] = [backboneDict1, backboneDict2]#, backboneDict1, backboneDict2]
    polymerBrushDict['brushes'] = [brushDict1, brushDict2]#, brushDict1, brushDict2]
    polymerBrushDict['connectors'] = [connectorDict12]#, connectorDict12, connectorDict12]
       
    from Library.SurfacePackSphere import SurfacePackSphereBBG as SPSBBG
    SphereBBG = SPSBBG('SurfacePackSphere.txt')

    numPolymersPerSphere =  800 #400
    UnimerBaseRadius = 10
    SphereRadius = 1200
    PhiMin = -15
    PhiMax = 15    
    ThetaMin = -10
    ThetaMax = 10
    
    centerPos = np.array([0.0, 0.0, 0.0])

    # generate the XYZVals packed in the outer sphere
    outerSpherePointsBB = SphereBBG.generateBuildingBlock(numPolymersPerSphere, SphereRadius, ThetaMin, ThetaMax, PhiMin, PhiMax, UnimerBaseRadius)
    outerSpherePointsBB.transformBBToLabFrame(np.array([0.0, 0.0, 1.0]), centerPos, 0.0)
    outerSpherePointsBB.exportBBK("outerSphereBasePoints")
コード例 #6
0
import numpy as np
from Library.SurfacePackSphere import SurfacePackSphereBBG as SPSBBG
from Library.randomPolymer import RandomPolymerPackBBG as RPBBG
import Utilities.coordSystems as coords
import Utilities.fileIO as fIO

SphereBBG = SPSBBG('SurfacePackSphere.txt')
PolymerGenerator = RPBBG('RandomPolymer.txt')

numA = 30
numB = 50
numMonomersPerPolymer = numA + numB
bondLength = 1.5
atomicMinDist = 1.0
maxPolymerLength = float(numMonomersPerPolymer) * bondLength
minRadius = 50
midLayerRadius = minRadius + maxPolymerLength
minTheta = -90
maxTheta = 90
minPhi = -135
maxPhi = 135

innerSphereFrustumInnerRadius = 2 * bondLength  # initialising variable
# loop until the innerSphere inner R is 1.5 * bondLength
numPolymersPerInnerSphere = 1
while innerSphereFrustumInnerRadius > 1.5 * bondLength:
    innerSphereFrustumOuterZ = midLayerRadius - bondLength / 2.0
    innerSphereFrustumInnerZ = midLayerRadius - bondLength / 2.0 - maxPolymerLength
    innerSphereFrustumOuterRadius = np.sqrt(
        0.75 * 4.0 * np.power(innerSphereFrustumOuterZ, 2.0) /
        numPolymersPerInnerSphere)
コード例 #7
0
def makeCluster(nodes, radius, minDist, packingFraction):
    CylinderBBG = SPCBBG('SurfacePackCylinder.txt')
    SphereBBG = SPSBBG('SurfacePackSphere.txt')

    # useful debug tool
    removeClosePointsFlag = True
    removeInnerPointsFlag = True
    includeSpheres = True
    includeCylinders = True

    # determine the point density so it is the same on spheres and cylinders
    # number of points on Sphere = Area of sphere divided by area of circles of radius minDist.
    # np.pi's cancel out. Apply the packing fraction is the ratio relative to perfect packing
    nS = int(packingFraction * 4.0 * (radius**2) / minDist**2)

    # compute number of points per unit length for each cylinder
    # circumference * 1 unit length / base area of each point on surface
    # the np.pi's cancel out
    nCUnit_float = packingFraction * (2.0 * radius) / minDist**2

    # set the root point of the cluster
    rootPoint = nodes[0]

    if includeSpheres:
        # populate each sphere with specified number of points minDist apart
        spheres = [
            SphereBBG.generateBuildingBlock(nS, radius, -90.0, 90.0, -180.0,
                                            180.0, minDist)
            for _ in range(0, len(nodes))
        ]

        # compute an array of the sphere directors. Each sphere centred at origin so each pos is its own radial vector.
        # just normalise it and return in seperate array.
        sphereDirectors = [[
            pos / np.linalg.norm(pos) for pos in sphere.blockXYZVals
        ] for sphere in spheres]

        # translate the sphere points so the centre of each sphere is at the given node.
        # Return an array the same shape as the director array for each point
        sphereXYZPoints = [[nodes[index] + pos for pos in sphere.blockXYZVals]
                           for index, sphere in enumerate(spheres)]

        # generate sphere names
        sphereNames = [['S'] * len(sphere.blockXYZVals) for sphere in spheres]

    if includeCylinders:
        # define the length of each cylinder in the cluster
        cylinderLengths = [
            np.linalg.norm(rootPoint - node) for node in nodes[1:]
        ]

        # define the axial orientation of each cylinder as the unit vector from the rootPoint to the outer node
        cylinderAxes = [(node - rootPoint) / length
                        for node, length in zip(nodes[1:], cylinderLengths)]

        # populate each cylinder with a specified number of points no less than minDist apart
        cylinders = [
            CylinderBBG.generateBuildingBlock(int(length * nCUnit_float),
                                              radius, radius, 0, length,
                                              -180.0, 180.0, minDist)
            for length in cylinderLengths
        ]

        # transform the cylinder points so the cylinder axis is aligned with the director away from the central node to the outer node
        [
            cylinderBB.transformBBToLabFrame(director, rootPoint, 0.0)
            for cylinderBB, director in zip(cylinders, cylinderAxes)
        ]

        # extract the cylinder points from the building block object
        cylinderXYZPoints = [
            cylinderBB.blockXYZVals for cylinderBB in cylinders
        ]

        # compute the director of each point (radial vector pointing away from the cylinder axis (rodrigues formula) (see page 183 in book 5).
        cylinderDirectors = [[
            pos - rootPoint - np.dot(director, pos - rootPoint) * director
            for pos in cylinder
        ] for cylinder, director in zip(cylinderXYZPoints, cylinderAxes)]

        # normalise the directors
        cylinderDirectors = [[pos / np.linalg.norm(pos) for pos in cylinder]
                             for cylinder in cylinderDirectors]

        # generate cylinder names
        cylinderNames = [['C'] * len(cylinder.blockXYZVals)
                         for cylinder in cylinders]

    # For each list of points that we have constructed (spheres and cylinders)
    # go through and remove any of those points that are *inside* the cylindrical shells.
    # None of the spheres would have other sphere points or cylinder point inside them so no need to check them.

    # first deal with the points belonging to the cylindrical surfaces

    if includeCylinders:
        # assume that all the points will survive - set up a flag array for each point that is same dims as director and points array
        cylinderPointFlagsList = [
            len(cylinderPoints) * [True]
            for cylinderPoints in cylinderXYZPoints
        ]

    if removeInnerPointsFlag and includeCylinders:
        # loop through the sets of points for each cylinder
        for indexInner, cylinderPoints in enumerate(cylinderXYZPoints):

            # loop through the geometric regions
            for director, length, indexOuter in zip(
                    cylinderAxes, cylinderLengths,
                    range(0, len(cylinderLengths))):
                # don't check a cylinder against itself
                if indexInner != indexOuter:
                    # test the current list of points against the cylinder
                    # Set flags in the flag array for points that need to be removed
                    print("Removing points from cylinder:", indexInner + 1,
                          " of ", len(cylinderXYZPoints),
                          " that are inside cylinder: ", indexOuter + 1, "of ",
                          len(cylinderLengths))
                    FlagPointsInsideCylinder(
                        cylinderPointFlagsList[indexInner], cylinderPoints,
                        rootPoint, director, length, radius)

    if includeCylinders:
        # apply the flags
        cylinderXYZPoints = [[
            point
            for point, flag in zip(pointList, cylinderPointFlagsList[index])
            if flag == True
        ] for index, pointList in enumerate(cylinderXYZPoints)]
        cylinderDirectors = [[
            director for director, flag in zip(
                directorList, cylinderPointFlagsList[index]) if flag == True
        ] for index, directorList in enumerate(cylinderDirectors)]
        cylinderNames = [[
            name for name, flag in zip(nameList, cylinderPointFlagsList[index])
            if flag == True
        ] for index, nameList in enumerate(cylinderNames)]
        # reconstruct the flag list as all true
        cylinderPointFlagsList = [
            len(cylinderPoints) * [True]
            for cylinderPoints in cylinderXYZPoints
        ]

    # do the same for the sphere points
    if includeSpheres:
        # assume that all the points will survive - set up a flag array for each point that is same dims as director and points array
        spherePointFlagsList = [
            len(spherePoints) * [True] for spherePoints in sphereXYZPoints
        ]

    if removeInnerPointsFlag and includeSpheres and includeCylinders:
        # loop through the sets of points for each sphere
        for indexInner, spherePoints in enumerate(sphereXYZPoints):

            # loop through the geometric regions
            for director, length, indexOuter in zip(
                    cylinderAxes, cylinderLengths,
                    range(0, len(cylinderLengths))):
                print("Removing points from sphere:", indexInner + 1, " of ",
                      len(sphereXYZPoints), " that are inside cylinder: ",
                      indexOuter + 1, "of ", len(cylinderLengths))
                # test the current list of points against the cylinder
                # set flags in the flag array for points that need to be removed
                FlagPointsInsideCylinder(spherePointFlagsList[indexInner],
                                         spherePoints, rootPoint, director,
                                         length, radius)

    if includeSpheres:
        # apply the flags
        sphereXYZPoints = [[
            point
            for point, flag in zip(pointList, spherePointFlagsList[index])
            if flag == True
        ] for index, pointList in enumerate(sphereXYZPoints)]
        sphereDirectors = [[
            director for director, flag in zip(
                directorList, spherePointFlagsList[index]) if flag == True
        ] for index, directorList in enumerate(sphereDirectors)]
        sphereNames = [[
            name for name, flag in zip(nameList, spherePointFlagsList[index])
            if flag == True
        ] for index, nameList in enumerate(sphereNames)]
        # reconstruct the flag list as all true
        spherePointFlagsList = [
            len(spherePoints) * [True] for spherePoints in sphereXYZPoints
        ]

    if removeClosePointsFlag and includeCylinders:
        # now flag any points in the cylinders that are within minDist of the remaining points of the other cylinders.
        # Don't check a cylinder against a cylinder that has already been checked.
        for indexTestSet, testPoints in enumerate(cylinderXYZPoints):
            for indexRefSet, refPoints in enumerate(
                    cylinderXYZPoints[indexTestSet + 1:]):
                print("Removing points in cylinder:", indexTestSet + 1, " of ",
                      len(cylinderXYZPoints),
                      " due to proximity with cylinder: ",
                      indexRefSet + indexTestSet + 1)
                FlagPointsTooClose(cylinderPointFlagsList[indexTestSet],
                                   testPoints, refPoints, minDist)

    if removeClosePointsFlag and includeCylinders and includeSpheres:
        # now flag any points in the *cylinders* that are within minDist of the remaining points of their end spheres
        for indexTestSet, testPoints in enumerate(cylinderXYZPoints):
            for indexRefSet, refPoints in enumerate(
                [sphereXYZPoints[0], sphereXYZPoints[indexTestSet + 1]]):
                print("Removing points in cylinder:", indexTestSet + 1, " of ",
                      len(cylinderXYZPoints),
                      " due to proximity with sphere: ", indexRefSet + 1,
                      "of 2.")
                FlagPointsTooClose(cylinderPointFlagsList[indexTestSet],
                                   testPoints, refPoints, minDist)

    if includeCylinders:
        # apply the flags to the cylinders
        cylinderXYZPoints = [[
            point
            for point, flag in zip(pointList, cylinderPointFlagsList[index])
            if flag == True
        ] for index, pointList in enumerate(cylinderXYZPoints)]
        cylinderDirectors = [[
            director for director, flag in zip(
                directorList, cylinderPointFlagsList[index]) if flag == True
        ] for index, directorList in enumerate(cylinderDirectors)]
        cylinderNames = [[
            name for name, flag in zip(nameList, cylinderPointFlagsList[index])
            if flag == True
        ] for index, nameList in enumerate(cylinderNames)]

    allPoints = []
    allDirectors = []
    allNames = []

    # compile output arrays
    if includeCylinders:
        # add the cylinderPoints to output arrays
        allPoints += cylinderXYZPoints
        allDirectors += cylinderDirectors
        allNames += cylinderNames

    if includeSpheres:
        allPoints += sphereXYZPoints
        allDirectors += sphereDirectors
        allNames += sphereNames

    # Return the flattened lists of points and directors, which by some minor miracle, should all correspond to each other
    return ([point for minorList in allPoints for point in minorList
             ], [point for minorList in allDirectors for point in minorList],
            [name for minorList in allNames for name in minorList])
コード例 #8
0
import numpy as np
import copy as cp
from Library.SurfacePackSphere import SurfacePackSphereBBG as SPSBBG
from Library.randomPolymer import RandomPolymerPackBBG as RPBBG

import Utilities.fileIO as fIO

SphereBBG = SPSBBG('SurfacePackSphere.txt')

bondlength = 1.5

Polymer1Generator = RPBBG('RandomPolymer.txt')

numA = 30
numB = 40
numMonomersPerPolymer = numA + numB
numPolymersPerSphere = 180
FMaxRadius = 10
FMinRadius = 3
FZ1 = 80
FZ2 = 15
alpha1 = 40
alpha2 = 80
beta1 = 130
beta2 = 165
AtomicMinDist = 1.0

centerPos = np.array([0.0, 0.0, 0.0])

# generate the XYZVals in the packed spaced
Polymer1SphereBB = SphereBBG.generateBuildingBlock(numPolymersPerSphere, FZ2,
コード例 #9
0
ファイル: peptideVesicle.py プロジェクト: cjforman/vesiform
import numpy as np
from Library.peptideBackbone import peptideBackboneGenerator as PBG
from Library.SurfacePackSphere import SurfacePackSphereBBG as SPSBBG
from Library.VolumePackEllipsoid import VolumePackEllipsoidBBG as VPEBBG
import Utilities.fileIO as fIO
peptideBBG = PBG('betastrand.txt')
sphereBBG = SPSBBG('SurfacePackSphere.txt')
VolSphereBBG = VPEBBG('VolumePackEllipsoid.txt')

numResidues = 5
minDist = 1.0

numStrands = 100
centerPos = np.array([-0,-0, -0])
director = np.array([0, 0, 1])
rotation = 0
radius1 = 22
radius2 = 12
radius3 = 8
theta1 = -90
theta2 = 90
phi1 = -135
phi2 = 135
minDist1 = 3.0
minDist2 = 1.0
minDist3 = 1.0

# generate the XYZVals in the packed spaced
SphereBB = sphereBBG.generateBuildingBlock(numStrands, radius1, theta1, theta2, phi1, phi2, minDist1)
SphereBB.transformBBToLabFrame(director, centerPos, rotation)
SphereBB.exportBBK("sphereBasePoints")
コード例 #10
0
    brushDict2['beta1'] = 155
    brushDict2['beta2'] = 175
    brushDict2['minDist'] = 1.0
    brushDict2['bondLength'] = 2.0
    brushDict2['Z1'] = 2
    brushDict2['R1'] = 50
    brushDict2['Z2'] = 1.5 * brushDict2['numMonomers'] * brushDict2['bondLength'] + brushDict2['Z1']
    brushDict2['R2'] = 50
              
    polymerBrushDict={}
    polymerBrushDict['backbones'] = [backboneDict1, backboneDict2]#, backboneDict1, backboneDict2]
    polymerBrushDict['brushes'] = [brushDict1, brushDict2]#, brushDict1, brushDict2]
    polymerBrushDict['connectors'] = [connectorDict12]#, connectorDict12, connectorDict12]
       
    from Library.SurfacePackSphere import SurfacePackSphereBBG as SPSBBG
    SphereBBG = SPSBBG('SurfacePackSphere.txt')

    numPolymersPerSphere =  300 #185 #430
    UnimerBaseRadius = 1.75
    SphereRadius = 0.15 * (backboneDict1['Z2'] + backboneDict2['Z2'] - backboneDict1['Z1'] - backboneDict2['Z1'])
    phiMin = -180
    phiMax = 180    
    thetaMin = -90
    thetaMax = 90
    
    centerPos = np.array([0.0, 0.0, 0.0])

    # generate the XYZVals packed in the outer cylinder
    Polymer1SphereBB = SphereBBG.generateBuildingBlock(numPolymersPerSphere, SphereRadius, thetaMin, thetaMax, phiMin, phiMax, UnimerBaseRadius)
    Polymer1SphereBB.transformBBToLabFrame(np.array([0.0, 0.0, 1.0]), centerPos, 0.0)
    Polymer1SphereBB.exportBBK("sphereBasePoints")