Esempio n. 1
0
    def _WriteMEADFiles(self, system, systemCharges, systemRadii):
        """For each instance of each site, write:
        - PQR file for the site    - PQR file for the model compound
        - OGM file for the site    - MGM file for the model compound"""
        grids = []
        model = self.parent
        for stepIndex, (nodes, resolution) in enumerate(model.focusingSteps):
            if stepIndex < 1:
                grids.append("ON_GEOM_CENT %d %f\n" % (nodes, resolution))
            else:
                x, y, z = self.center
                grids.append("(%f %f %f) %d %f\n" %
                             (x, y, z, nodes, resolution))

        selectSite = Selection(self.siteAtomIndices)
        selectModel = Selection(self.modelAtomIndices)

        # . In the PQR file of the model compound, charges of the site atoms must be set to zero (requirement of the my_2diel_solver program)
        chargesZeroSite = Clone(systemCharges)
        for atomIndex in self.siteAtomIndices:
            chargesZeroSite[atomIndex] = 0.0

        for instance in self.instances:
            PQRFile_FromSystem(
                instance.modelPqr,
                system,
                selection=selectModel,
                charges=chargesZeroSite,
                radii=systemRadii,
            )

            # . Update system charges with instance charges
            chargesInstance = Clone(systemCharges)
            for chargeIndex, atomIndex in enumerate(self.siteAtomIndices):
                chargesInstance[atomIndex] = instance.charges[chargeIndex]

            PQRFile_FromSystem(
                instance.sitePqr,
                system,
                selection=selectSite,
                charges=chargesInstance,
                radii=systemRadii,
            )
            del chargesInstance

            # . Write OGM and MGM files (they have the same content)
            for fileGrid in (instance.modelGrid, instance.siteGrid):
                WriteInputFile(fileGrid, grids)

        del chargesZeroSite
def _PlaceIonsAtGridPoints ( ions, grid, unoccupied ):
    """Place ions at grid points."""
#
# . Placement is currently done randomly. In principle it could also be done using energies using a procedure such as:
#
# - Calculate potentials (1/r,1/r^6,1/r^12) on unoccupied grid points due to protein.
# - Loop over ions (+/- alternate pairs):
#       Determine energy of each grid points as q * pot(1/r) + e * s^3 * pot(1/r^6) + ...
#       Find point with lowest energy and put ion at this point.
#       Update potentials due to the ion at this point.
#
# . Requires a single NB model method that calculates/updates potentials.
#
# . However, a similar result can be achieved by using random placement, doing a Monte Carlo (no waters) with
# . an NBModel with dielectric of 80 and then choosing low energy conformations.
#
    # . Number of ions.
    nions = len ( ions.atoms )

    # . Get a random number of points from the unoccupied sites.
    points = sample ( unoccupied, nions )

    # . Calculate the coordinates - these are implicitly sorted due to the selection.
    coordinates3 = Coordinates3_FromGrid ( grid, selection = Selection.FromIterable ( points ) )

    # . Shuffle again.
    points = sample ( range ( nions ), nions )
    for ( n, p ) in enumerate ( points ):
        for i in range ( 3 ): ions.coordinates3[n,i] = coordinates3[p,i]
def CovarianceMatrix(*arguments, **keywordArguments):
    """Calculate the covariance matrix for selected particles."""

    # . Initialization.
    covariance = None

    # . Get the trajectory and associated system data.
    (system, trajectories) = _GetSystemAndTrajectoriesFromArguments(*arguments)

    # . Get the selection and the size of the problem.
    selection = keywordArguments.pop("selection", None)
    if selection is None:
        selection = Selection.FromIterable(range(len(system.atoms)))
    n = 3 * len(selection)

    # . Get the average positions.
    averagePositions = keywordArguments.pop("averagePositions", None)
    if averagePositions is None:
        averagePositions = AveragePositions(trajectories, selection=selection)
    _CheckForUnknownOptions(keywordArguments)

    # . Continue processing.
    if (n > 0) and (averagePositions is not None):

        # . Allocate space.
        covariance = SymmetricMatrix.WithExtent(n)
        covariance.Set(0.0)
        displacement = Real1DArray.WithExtent(n)
        displacement.Set(0.0)

        # . Loop over trajectory frames.
        numberFrames = 0
        for trajectory in trajectories:
            trajectory.ReadHeader()
            while trajectory.RestoreOwnerData():
                frame = system.coordinates3
                for (p, i) in enumerate(selection):
                    displacement[3 * p] = frame[i, 0] - averagePositions[p, 0]
                    displacement[3 * p +
                                 1] = frame[i, 1] - averagePositions[p, 1]
                    displacement[3 * p +
                                 2] = frame[i, 2] - averagePositions[p, 2]
                for i in range(n):
                    dI = displacement[i]
                    for j in range(i + 1):
                        covariance[i, j] += (dI * displacement[j])
            trajectory.ReadFooter()
            trajectory.Close()
            numberFrames += len(trajectory)

        # . Scale.
        if numberFrames > 0: covariance.Scale(1.0 / float(numberFrames))

    return covariance
 def ToFixedAtoms(self, system):
     """Define fixed atoms for the system."""
     natoms = self.counters.get("Atoms", 0)
     if natoms > 0:
         # . Get the fixed atom indices.
         indices = []
         for (index, datum) in enumerate(self.atoms):
             flag = datum[8]
             if flag == 1: indices.append(index)
         # . Define the fixed atoms.
         if len(indices) > 0:
             system.DefineFixedAtoms(Selection.FromIterable(indices))
def BuildSolventBox ( crystalClass, symmetryParameters, molecule, density, log = logFile, randomNumberGenerator = None ):
    """Build a solvent box.

    No attempt is made to avoid overlapping molecules as it is assumed this will be corrected in a subsequent optimization process.
    """

    # . Initialization.
    solvent = None

    # . Find the number of solvent molecules that fit in the box.
    nmolecules = SolventMoleculeNumber ( molecule, symmetryParameters, density )

    # . Check the number of molecules.
    if nmolecules > 0:

        # . Create the solvent system.
        molecule.coordinates3.ToPrincipalAxes ( )
        solvent = MergeRepeatByAtom ( molecule, nmolecules )
        solvent.DefineSymmetry ( crystalClass = crystalClass, a     = symmetryParameters.a,     \
                                                              b     = symmetryParameters.b,     \
                                                              c     = symmetryParameters.c,     \
                                                              alpha = symmetryParameters.alpha, \
                                                              beta  = symmetryParameters.beta,  \
                                                              gamma = symmetryParameters.gamma  )

        # . Check the random number generator.
        if randomNumberGenerator is None: randomNumberGenerator = RandomNumberGenerator.WithRandomSeed ( )

        # . Do random rotations and translations.
        natoms      = len ( molecule.atoms )
        rotation    = Matrix33.Null ( )
        selection   = Selection.FromIterable ( range ( natoms ) )
        translation = Vector3.Null ( )
        for i in range ( nmolecules ):
            rotation.RandomRotation ( randomNumberGenerator )
            solvent.coordinates3.Rotate  ( rotation,    selection = selection )
            for j in range ( 3 ): translation[j] = randomNumberGenerator.NextReal ( )
            symmetryParameters.M.ApplyTo ( translation )
            solvent.coordinates3.Translate ( translation, selection = selection )
            selection.Increment ( natoms )

        # . Do some printing.
        if LogFileActive ( log ):
            summary = log.GetSummary ( )
            summary.Start ( "Cubic Solvent Box Summary" )
            summary.Entry ( "Number of Molecules", "{:d}"  .format ( nmolecules                        ) )
            summary.Entry ( "Density (kg m^-3)",   "{:.3f}".format ( SystemDensity ( solvent )         ) )
            summary.Entry ( "Box Volume",          "{:.3f}".format ( solvent.symmetryParameters.volume ) )
            summary.Stop ( )

    # . Return the system.
    return solvent
Esempio n. 6
0
 def TypeAtoms(self, connectivity, sequence, log):
     """Assign atom types and charges to the atoms."""
     # . Initialization.
     atomCharges = [0.0 for i in range(len(connectivity.atoms))]
     atomTypes = [None for i in range(len(connectivity.atoms))]
     untypedAtoms = Selection.FromIterable(range(len(atomTypes)))
     # . Type the atoms.
     self.TypeBySequence(sequence, atomTypes, atomCharges, untypedAtoms)
     self.TypeByPattern(connectivity, atomTypes, atomCharges, untypedAtoms)
     # . Check for untyped atoms.
     self.CheckUntypedAtoms(connectivity, untypedAtoms, log)
     # . Finish up.
     return (atomTypes, atomCharges)
Esempio n. 7
0
 def FilterAtoms ( self, filterlevel ):
     """Filter out Mopac-specific atoms."""
     if self.QPARSED and ( filterlevel > -3 ):
         atomicNumbers = []
         selected      = []
         for ( i, a ) in enumerate ( self.atomicNumbers ):
             if a >= filterlevel:
                 atomicNumbers.append ( a )
                 selected.append      ( i )
         if len ( atomicNumbers ) < len ( self.atomicNumbers ):
             coordinates3 = Coordinates3.WithExtent ( len ( atomicNumbers ) )
             coordinates3.Gather ( self.coordinates3, Selection.FromIterable ( selected ) )
             self.atomicNumbers = atomicNumbers
             self.coordinates3  = coordinates3
Esempio n. 8
0
 def DefineQCModel(self, qcModel, log=logFile, qcSelection=None):
     """Define a quantum chemical model for the system."""
     if isinstance(qcModel, QCModel):
         # . Get an energy model in the correct state.
         if self.energyModel is None:
             self.__dict__["_energyModel"] = EnergyModel()
         else:
             self.energyModel.ClearQCModel(self.configuration,
                                           fixedAtoms=None)
         em = self.energyModel
         # . Assign a default electronic state if necessary.
         if self.electronicState is None:
             self.electronicState = ElectronicState()
         # . Get the QC atom selection and the boundary atoms.
         if (qcSelection is None) or (qcSelection.size == len(self.atoms)):
             atomindices = Selection.FromIterable(range(len(self.atoms)))
             boundaryatoms = {}
         else:
             atomindices = qcSelection
             boundaryatoms = em.IdentifyBoundaryAtoms(atomindices)
         # . Set up the QC atom data.
         qcAtoms = QCAtomContainer_FromAtomContainer(
             self.atoms, atomindices, boundaryatoms,
             getattr(qcModel, "linkAtomRatio", True))
         # . Get the qcParameters.
         anlist = qcAtoms.UniqueAtomicNumbers()
         qcParameters = qcModel.DefineParameters(anlist, log=log)
         # . Fill in the remaining qcatom data.
         qcAtoms.AssignParameterData(anlist, qcParameters)
         # . Save the data.
         em.qcAtoms = qcAtoms
         em.qcModel = qcModel
         em.__dict__["qcParameters"] = qcParameters
         em.MakeLabel()
         # . Modify the MM terms if appropriate.
         em.DeactivateQCAtomMMTerms()
         # . Deactivate MM terms if fixed atoms are defined.
         if (self.hardConstraints is not None):
             em.DeactivateFixedAtomMMTerms(self.hardConstraints.fixedAtoms)
         # . Check the total MM charge.
         em.CheckActiveMMAtomTotalCharge()
def AveragePositions(*arguments, **keywordArguments):
    """Calculate the average positions for selected particles."""

    # . Initialization.
    positions = None

    # . Process arguments.
    (system, trajectories) = _GetSystemAndTrajectoriesFromArguments(*arguments)

    # . Get the selection (or all particles otherwise).
    selection = keywordArguments.pop("selection", None)
    if selection is None:
        selection = Selection.FromIterable(range(len(system.atoms)))
    _CheckForUnknownOptions(keywordArguments)

    # . Get the size of the problem.
    n = len(selection)
    if n > 0:

        # . Allocate space.
        positions = Coordinates3.WithExtent(n)
        positions.Set(0.0)

        # . Loop over trajectory frames.
        numberFrames = 0
        for trajectory in trajectories:
            trajectory.ReadHeader()
            while trajectory.RestoreOwnerData():
                frame = system.coordinates3
                for (p, i) in enumerate(selection):
                    positions[p, 0] += frame[i, 0]
                    positions[p, 1] += frame[i, 1]
                    positions[p, 2] += frame[i, 2]
            trajectory.ReadFooter()
            trajectory.Close()
            numberFrames += len(trajectory)

        # . Scale.
        if numberFrames > 0: positions.Scale(1.0 / float(numberFrames))

    return positions
Esempio n. 10
0
def SetUpSystem(path, forceNoQC=False, useSystemWithTimings=True):
    """Set up the system."""
    # . Get system data.
    systemData = YAMLUnpickle(os.path.join(path, _TestDataFileName))
    # . Get the parameters.
    parameters = CHARMMParameterFiles_ToParameters(
        glob.glob(os.path.join(path, "*.prm")))
    # . Get the test name.
    name = os.path.split(path)[-1]
    # . Generate the system.
    system = CHARMMPSFFile_ToSystem(os.path.join(path, name + ".psfx"),
                                    isXPLOR=True,
                                    parameters=parameters)
    if useSystemWithTimings: system = SystemWithTimings.FromSystem(system)
    system.coordinates3 = XYZFile_ToCoordinates3(
        os.path.join(path, name + ".xyz"))
    system.label = systemData["Label"]
    # . Symmetry.
    if systemData.get("Crystal Class", None) is not None:
        symmetryOptions = systemData["Symmetry Parameters"]
        symmetryOptions["crystalClass"] = _CrystalClasses[
            systemData["Crystal Class"]]
        system.DefineSymmetry(**symmetryOptions)
    # . QC data.
    if not forceNoQC:
        qcData = systemData.get(_QCRegionKey, None)
        if qcData is not None:
            # . Electronic state.
            system.electronicState = ElectronicState(
                charge=qcData.get("Charge", 0),
                multiplicity=qcData.get("Multiplicity", 1))
            # . QC atoms.
            qcAtoms = set()
            for path in qcData["Atoms"]:
                index = system.sequence.AtomIndex(path)
                qcAtoms.add(index)
            system.DefineQCModel(_QCModel, qcSelection=Selection(qcAtoms))
    # . Finish set up.
    system.DefineNBModel(_NBModel)
    return system
Esempio n. 11
0
 def ExtractDisorderData ( self, dataBlock, system, disorderGroup = _DefaultDisorderGroup ):
     """Extract atom data from a data block."""
     result = system
     table  = dataBlock.get ( "atom_site", None )
     if table is not None:
         # . Disorder and multiplicity information.
         assemblies     = table.ColumnValues ( "atom_site_disorder_assembly"     )
         groups         = table.ColumnValues ( "atom_site_disorder_group"        )
         multiplicities = table.ColumnValues ( "atom_site_symmetry_multiplicity" )
         # . Check for the disorder groups to include.
         if groups is not None:
             uniqueGroups = set ( groups )
             uniqueGroups.discard (       disorderGroup )
             uniqueGroups.discard ( "-" + disorderGroup )
             uniqueGroups.discard ( _UndefinedCharacter )
             if len ( uniqueGroups ) > 0:
                 toInclude = set ( [ _UndefinedCharacter, disorderGroup, "-" + disorderGroup ] )
                 indices   = []
                 for ( i, group ) in enumerate ( groups ):
                     if group in toInclude: indices.append ( i )
                 if len ( indices ) < len ( groups ):
                     result       = system.Prune ( Selection ( indices ) )
                     result.label = system.label
     return result
def RadialDistributionFunction(*arguments, **keywordArguments):
    """Calculate a radial distribution function."""

    # . Get the trajectory and associated system data.
    (system, trajectories) = _GetSystemAndTrajectoriesFromArguments(*arguments)

    # . Keyword arguments.
    bins = keywordArguments.pop("bins", 100)
    log = keywordArguments.pop("log", logFile)
    safety = keywordArguments.pop("safety", _DEFAULTSAFETY)
    selection1 = keywordArguments.pop("selection1", None)
    selection2 = keywordArguments.pop("selection2", None)
    upper = keywordArguments.pop("maximumR", None)
    if selection1 is None:
        selection1 = Selection.FromIterable(range(len(system.atoms)))
    if selection2 is None: selection2 = selection1
    _CheckForUnknownOptions(keywordArguments)

    # . Get the numbers of particles.
    np1 = len(selection1)
    np2 = len(selection2)

    # . Check for a cubic system.
    try:
        cc = system.symmetry.crystalClass
        if not isinstance(cc, CrystalClassCubic): raise
    except:
        raise ValueError("System does not have cubic symmetry.")

    # . Estimate an upper bound.
    if upper is None:
        try:
            upper = (system.symmetryParameters.a - safety) / 2.0
        except:
            raise ValueError(
                "Please supply an upper bound for the RDF calculation.")

    # . Initialization.
    lower = 0.0
    distances = []
    histogram = [0 for i in range(bins)]
    rdf = []

    # . Calculate the width of each bin.
    width = (upper - lower) / float(bins)
    vacc = 0.0

    # . Loop over trajectory frames.
    numberFrames = 0
    for trajectory in trajectories:
        trajectory.ReadHeader()
        while trajectory.RestoreOwnerData():

            # . Get the frame.
            frame = system.coordinates3
            numberFrames += 1

            # . Accumulate the volume.
            a = system.symmetryParameters.a
            vacc += a**3

            # . Check a.
            if upper > 0.5 * a:
                raise ValueError(
                    "Box does not satisfy minimum image convention.")

            # . Bin the distances.
            # . This loop involves duplicate work for self rdfs.
            for i in selection1:
                for j in selection2:
                    if i != j:
                        dr = frame.Displacement(i, j)
                        for c in range(3):
                            x = a * round(dr[c] / a)
                            dr[c] -= x
                        r = dr.Norm2()
                        if (r >= lower) and (r < upper):
                            b = int((r - lower) / width)
                            histogram[b] += 1

        # . Finish up.
        trajectory.ReadFooter()
        trajectory.Close()

    # . Calculate g(r).
    fact = 4.0 * math.pi * float(np1 * np2 * numberFrames**2) / (3.0 * vacc)
    for i in range(bins):
        rlower = lower + float(i) * width
        rupper = rlower + width
        distances.append(rlower + 0.5 * width)
        rdf.append(float(histogram[i]) / (fact * (rupper**3 - rlower**3)))

    # . Output the results.
    if LogFileActive(log):
        table = log.GetTable(columns=[20, 20])
        table.Start()
        table.Title("Radial Distribution Function")
        table.Heading("Distance")
        table.Heading("g(r)")
        for (r, g) in zip(distances, rdf):
            table.Entry("{:20.4f}".format(r))
            table.Entry("{:20.4f}".format(g))
        table.Stop()

    # . Return results.
    return (distances, rdf)
def SelfDiffusionFunction(*arguments, **keywordArguments):
    """Calculate the self diffusion function."""

    # . Get the trajectory and associated system data.
    (system, trajectories) = _GetSystemAndTrajectoriesFromArguments(*arguments)

    # . Keyword arguments.
    log = keywordArguments.pop("log", logFile)
    maximumTime = keywordArguments.pop("maximumTime", None)
    selection = keywordArguments.pop("selection", None)
    timeStep = keywordArguments.pop("timeStep", 1.0)
    if selection is None:
        selection = Selection.FromIterable(range(len(system.atoms)))
    _CheckForUnknownOptions(keywordArguments)

    # . Initialization.
    np = len(selection)  # . The number of particles.
    dSelf = []
    frames = []
    times = []

    # . Loop over trajectory frames.
    for trajectory in trajectories:
        trajectory.ReadHeader()
        while trajectory.RestoreOwnerData():
            frames.append(system.coordinates3.Prune(selection))
        trajectory.ReadFooter()
        trajectory.Close()

    # . Get the number of frames and tStop.
    numberFrames = len(frames)
    if maximumTime is None:
        tStop = numberFrames - 1
    else:
        tStop = int(maximumTime / timeStep)
        tStop = min(numberFrames - 1, tStop)

    # . Calculate the function - slow version.
    # . Loop over time differences to calculate.
    for t in range(tStop + 1):

        # . Initialization.
        tmax = numberFrames - t
        total = 0.0

        # . Loop over allowed increments.
        for t0 in range(tmax):
            # . Calculate differences.
            fa = frames[t0 + t]
            fb = frames[t0]
            for i in range(np):
                total += (fa[i, 0] - fb[i, 0])**2 + (
                    fa[i, 1] - fb[i, 1])**2 + (fa[i, 2] - fb[i, 2])**2

        # . Calculate dSelf.
        dSelf.append(total / float(3 * np * tmax))
        times.append(float(t) * timeStep)

    # . Output the results.
    if LogFileActive(log):
        table = log.GetTable(columns=[20, 20])
        table.Start()
        table.Title("Self-Diffusion Function")
        table.Heading("Time")
        table.Heading("Dself")
        for (t, d) in zip(times, dSelf):
            table.Entry("{:20.4f}".format(t))
            table.Entry("{:20.4f}".format(d))
        table.Stop()

    # . Return results.
    return (times, dSelf)
                "P61"     : [ "(x,y,z)", "(-y,x-y,z+1/3)", "(-x+y,-x,z+2/3)", "(-x,-y,z+1/2)", "(y,-x+y,z+5/6)", "(x-y,x,z+1/6)" ],
                "P21c"    : [ "(x,y,z)", "(-x,y+1/2,-z+1/2)", "(-x,-y,-z)", "(x,-y+1/2,z+1/2)" ],
                "P21a"    : [ "(x,y,z)", "(-x+1/2,y+1/2,-z)", "(-x,-y,-z)", "(x+1/2,-y+1/2,z)" ],
                "R3"      : [ "(x,y,z)", "(z,x,y)", "(y,z,x)" ] }

# . Convert to transformation sets.
_transformationSets = {}
for ( key, olist ) in _operations.iteritems ( ):
    tset = []
    for o in olist:
        tset.append ( Transformation3_FromSymmetryOperationString ( o ) )
    _transformationSets[key] = Transformation3Container.WithTransformations ( tset )

# . Molecule definitions.
_keywordLabels = ( "label", "canQCOptimize", "qcSelection", "qcCharge", "vacuumEnergy", "crystalEnergy", "crystalClass", "transformations", "crystalParameters" )
_moleculeData  = ( ( "ALAALA",   False, Selection.FromIterable ( range (  6, 10 ) ),  0,  -178.7095,  -677.7298, CrystalClassTetragonal   ( ), _transformationSets["I4"],      { "a" : 17.9850, "c" : 5.1540 } ),
                   ( "ALAMET01", False, Selection.FromIterable ( range ( 16, 27 ) ),  0,  -135.0084,  -652.9681, CrystalClassMonoclinic   ( ), _transformationSets["P21c"],    { "a" : 13.089, "b" : 5.329, "c" : 15.921, "beta" :  108.57 } ),
                   ( "AQARUF",   False, Selection.FromIterable ( range (  6, 19 ) ),  0,  -144.5558,  -608.3551, CrystalClassHexagonal    ( ), _transformationSets["P61"],     { "a" : 14.3720, "c" : 9.8282 } ),
                   ( "BEVXEF01", False, Selection.FromIterable ( range ( 23, 29 ) ),  0,  -240.0604,  -878.7555, CrystalClassOrthorhombic ( ), _transformationSets["P212121"], { "a" : 9.6590, "b" : 9.6720, "c" : 10.7390 } ),
                   ( "GLYALB",   False, Selection.FromIterable ( range ( 13, 17 ) ),  0,   -44.8402,  -562.9905, CrystalClassOrthorhombic ( ), _transformationSets["P212121"], { "a" : 9.6930, "b" : 9.5240, "c" : 7.5370 } ),
                   ( "GLYGLY",   False, Selection.FromIterable ( range ( 14, 17 ) ), -1,  -184.8863,  -687.4449, CrystalClassMonoclinic   ( ), _transformationSets["P21a"],    { "a" : 7.812, "b" : 9.566, "c" : 9.410, "beta" :  124.60 } ),
                   ( "GUFQON",   False, Selection.FromIterable ( range ( 13, 18 ) ),  0,  -191.1490,  -511.8117, CrystalClassOrthorhombic ( ), _transformationSets["P212121"], { "a" : 7.2750, "b" : 9.0970, "c" : 10.5070 } ),
                   ( "HXACAN19", True,  Selection.FromIterable ( range ( 16, 20 ) ),  0,   157.7170,    24.6588, CrystalClassMonoclinic   ( ), _transformationSets["P21a"],    { "a" : 12.8720, "b" : 9.3700, "c" : 7.0850, "beta" :  115.6200 } ),
                   ( "IWANID",   False, Selection.FromIterable ( range ( 37, 51 ) ),  0,  4380.9282,  4070.8472, CrystalClassMonoclinic   ( ), _transformationSets["C2"],      { "a" : 23.091, "b" : 5.494, "c" : 17.510, "beta" :  117.88 } ),
                   ( "LCDMPP10", True,  Selection.FromIterable ( range (  4,  8 ) ),  0,   157.3277,    40.3629, CrystalClassTriclinic    ( ), _transformationSets["P1"],      { "a" : 8.067, "b" : 6.082, "c" : 5.155, "alpha" : 131.7, "beta" :  82.4, "gamma" : 106.6 } ),
                   ( "WIRYEB",   False, Selection.FromIterable ( range (  6, 16 ) ),  0,  -155.7355,  -612.6186, CrystalClassHexagonal    ( ), _transformationSets["P61"],     { "a" : 14.4240, "c" : 9.9960 } ),
                   ( "WABZOO",   True,  Selection.FromIterable ( range ( 0, 4 ) + range ( 10, 14 ) + range ( 18, 25 ) ), 0, 209.9697,   152.9967, CrystalClassRhombohedral ( ), _transformationSets["R3"], { "a" : 12.5940 , "alpha" : 118.0300 } ) )

# . Options for expanding to P1 symmetry.
_defaultRange = range ( 1 ) #range ( -1, 2 )
_aRange       = _defaultRange
Esempio n. 15
0
 def Within ( self, distance, excludeSelf = False ):
     """Selection of atoms within a given distance."""
     # . Find all atoms within distance of the current selection.
     selfSelection = self.selection
     system        = self.system
     pairlist      = CrossPairList_FromSingleCoordinates3 ( system.coordinates3, selection1 = Selection.FromIterable ( selfSelection ), safety = distance )
     selection     = set ( selfSelection )
     for ( i, j ) in pairlist: selection.add ( j )
     # . Exclude self?
     if excludeSelf: selection -= self.selection
     # . Finish up.
     return self.__class__ ( selection = selection, system = self.system )
Esempio n. 16
0
#   takes no (interesting) arguments.
#
# . Note on scratch names:
#
#   It has been noticed that ORCA itself can give an error when the name of the scratch directory is too long.
#   This occurs in the "%pcname" line of the ORCA input file. To cure this use a shorter name - either by resetting
#   the environment variable PDYNAMO_SCRATCH or by explicitly passing a name to the model with the "scratch" option.
#

# . Define the MM, NB and QC models.
mmModel = MMModelOPLS("bookSmallExamples")
nbModel = NBModelORCA()
qcModel = QCModelORCA("MP2:6-31G*", "EXTREMESCF", "SCFCONV10")

# . Define the molecule.
molecule = MOLFile_ToSystem(
    os.path.join(os.getenv("PDYNAMO_PMOLECULE"), "data", "mol",
                 "waterDimer_cs.mol"))

# . Define the selection for the first molecule.
firstWater = Selection.FromIterable([0, 1, 2])

# . Define the energy model.
molecule.DefineMMModel(mmModel)
molecule.DefineQCModel(qcModel, qcSelection=firstWater)
molecule.DefineNBModel(nbModel)
molecule.Summary()

# . Calculate an energy.
molecule.Energy(doGradients=True)
Esempio n. 17
0
    def runTest(self):
        """The test."""

        # . Initialization.
        dataPath = os.path.join(os.getenv("PDYNAMO_PMOLECULE"), "data", "mol")
        log = self.GetLog()
        translation = Vector3.Uninitialized()

        # . Get the individual systems.
        energies = []
        molecules = []
        for (i, label) in enumerate(_Molecules):
            molecule = MOLFile_ToSystem(os.path.join(dataPath, label + ".mol"))
            molecule.label = label
            molecule.DefineMMModel(_mmModel)
            molecule.DefineNBModel(_nbModel)
            molecule.Summary(log=log)
            molecule.coordinates3.TranslateToCenter()
            molecule.configuration.Clear()
            energies.append(molecule.Energy(log=log, doGradients=True))
            molecules.append(molecule)

        # . Data initialization.
        observed = {}
        referenceData = TestDataSet("Merge/Prune Energies")

        # . Loop over the tests.
        for (testIndex, (moleculeFrequencies,
                         moleculePruneIndices)) in enumerate(_Tests):

            # . Heading.
            if log is not None:
                log.Heading("Merge/Prune Test {:d}".format(testIndex),
                            QBLANKLINE=True)

            # . Initialization.
            mergedEnergy = 0.0
            prunedEnergy = 0.0
            translation.Set(0.0)

            # . Gather items.
            index = 0
            numberAtoms = 0
            pruneIndices = []
            toMerge = []
            for (i, frequency) in enumerate(moleculeFrequencies):
                molecule = molecules[i]
                mergedEnergy += energies[i] * frequency
                for f in range(frequency):
                    cloned = Clone(molecule)
                    translation[0] += _Displacement
                    cloned.coordinates3.Translate(translation)
                    toMerge.append(cloned)
                    if index in moleculePruneIndices:
                        pruneIndices.extend(
                            range(numberAtoms,
                                  numberAtoms + len(cloned.atoms)))
                        prunedEnergy += energies[i]
                    index += 1
                    numberAtoms += len(cloned.atoms)

            # . Merging.
            merged = toMerge[0].Merge(toMerge[1:])
            merged.Summary(log=log)
            eMerged = merged.Energy(log=log)

            # . Pruning.
            pruned = merged.Prune(Selection.FromIterable(pruneIndices))
            pruned.Summary(log=log)
            ePruned = pruned.Energy(log=log)

            # . Get the observed and reference data.
            for (tag, eObserved,
                 eReference) in (("Merged Energy {:d}".format(testIndex),
                                  eMerged, mergedEnergy),
                                 ("Pruned Energy {:d}".format(testIndex),
                                  ePruned, prunedEnergy)):
                observed[tag] = eObserved
                referenceData.AddDatum(
                    TestReal(
                        tag,
                        eReference,
                        referenceData,
                        absoluteErrorTolerance=_EnergyAbsoluteErrorTolerance,
                        toleranceFormat="{:.3f}",
                        valueFormat="{:.3f}"))

        # . Finish up.
        if log is not None: log.Separator()

        # . Check for success/failure.
        if len(observed) > 0:
            results = referenceData.VerifyAgainst(observed)
            results.Summary(log=log, fullSummary=self.fullVerificationSummary)
            isOK = results.WasSuccessful()
        else:
            isOK = True

        # . Success/failure.
        self.assertTrue(isOK)
    def runTest(self):
        """The test."""

        # . Output setup.
        dataPath = os.path.join(os.getenv("PDYNAMO_PMOLECULE"), "data", "mol")
        log = self.GetLog()

        # . Define the MM, NB and QC models.
        mmModel = MMModelOPLS("bookSmallExamples")
        nbModel = NBModelFull()
        qcModel = QCModelMNDO()

        # . Define the dimer with an MM model.
        dimer = MOLFile_ToSystem(os.path.join(dataPath, "waterDimer_cs.mol"))
        dimer.DefineMMModel(mmModel)
        dimer.Summary(log=log)

        # . Define the monomer selections.
        selection1 = Selection.FromIterable(range(0, 3))
        selection2 = Selection.FromIterable(range(3, 6))

        # . Get the monomer energies.
        e1 = self.MonomerEnergies(dimer, selection1, nbModel, qcModel, log=log)
        e2 = self.MonomerEnergies(dimer, selection2, nbModel, qcModel, log=log)

        # . Get the binding energies.
        e12 = {}
        for model1 in _Models:
            for model2 in _Models:
                key = model1 + " " + model2
                if log is not None:
                    log.Heading(model1 + "/" + model2 + " Dimer Calculation",
                                QBLANKLINE=True)
                # . Define the energy model.
                if key == "QC QC": dimer.DefineQCModel(qcModel)
                elif key == "QC MM":
                    dimer.DefineQCModel(qcModel, qcSelection=selection1)
                elif key == "MM QC":
                    dimer.DefineQCModel(qcModel, qcSelection=selection2)
                else:
                    dimer.energyModel.ClearQCModel(dimer.configuration)
                if "MM" in key: dimer.DefineNBModel(nbModel)
                dimer.Summary(log=log)
                # . Store the results.
                e12[key] = dimer.Energy(log=log) - e1[model1] - e2[model2]

        # . Output the results.
        if log is not None:
            keys = e12.keys()
            keys.sort()
            table = log.GetTable(columns=[20, 20, 20])
            table.Start()
            table.Title("Water Dimer Binding Energies")
            table.Heading("Monomer 1")
            table.Heading("Monomer 2")
            table.Heading("Binding Energy")
            for key in keys:
                (model1, model2) = key.split()
                table.Entry(model1)
                table.Entry(model2)
                table.Entry("{:.1f}".format(e12[key]))
            table.Stop()

        # . Success/failure.
        isOK = True
        for e in e12.values():
            if (e < _LowerBound) or (e > _UpperBound):
                isOK = False
                break
        self.assertTrue(isOK)
Esempio n. 19
0
    def runTest ( self ):
        """The test."""

        # . Initialization.
        failures      = 0
        otherFailures = 0
        successes     = 0

        # . Paths.
        dataPath = os.path.join ( os.getenv ( "PDYNAMO_PMOLECULE" ), "data", "pdb" )
        if self.resultPath is None: outPath  = os.path.join ( os.getenv ( "PDYNAMO_SCRATCH" ), _Destination )
        else:                       outPath  = os.path.join ( self.resultPath, _Destination )
        if not os.path.exists ( outPath ): os.mkdir ( outPath )
        log = self.GetLog ( )

        # . Models.
        mmModel = MMModelCHARMM ( "c36a2" )
        nbModel = NBModelABFS ( )
        qcModel = QCModelMNDO ( )

        # . Get the file.
        pdbFile = os.path.join ( dataPath, "2E4E_folded_solvated.pdb" )
        ( head, tail ) = os.path.split ( pdbFile )
        tag = tail[0:-4]

        if log is not None: log.Text ( "\nProcessing " + pdbFile + ":\n" )
        system = PDBFile_ToSystem ( pdbFile, log = log, useComponentLibrary = True )
        try:

            # . Fixed atoms.
            fixedAtoms = Selection ( ~ AtomSelection.FromAtomPattern ( system, "A:*:*" ) )

            # . QC selection.
            indices = set ( )
            for atomTag in _Tags:
                indices.add ( system.sequence.AtomIndex ( "A:TYR.2:" + atomTag ) )
            tyrosine = Selection ( indices )

            # . Setup.
            system.electronicState = ElectronicState ( charge = 0, multiplicity = 1 )
            system.DefineFixedAtoms ( fixedAtoms )
            system.DefineSymmetry   ( crystalClass = CrystalClassCubic ( ), a = _BoxSize )
            system.DefineMMModel    ( mmModel, log = log )
            system.DefineQCModel    ( qcModel, qcSelection = tyrosine )
            system.DefineNBModel    ( nbModel )
            system.Summary ( log = log )
            referenceEnergy = system.Energy  ( log = log, doGradients = True )

            # . Pickling.
            pklFile  = os.path.join ( outPath, tag + ".pkl"  )
            yamlFile = os.path.join ( outPath, tag + ".yaml" )
            Pickle     ( pklFile , system )
            YAMLPickle ( yamlFile, system )

            # . Unpickling.
            pklSystem = Unpickle ( pklFile )
            pklSystem.label += " (Pickled)"
            pklSystem.Summary ( log = log )
            pklEnergy = pklSystem.Energy  ( log = log, doGradients = True )
            if math.fabs ( referenceEnergy - pklEnergy  <= _Tolerance ): successes += 1
            else:                                                        failures  += 1

            yamlSystem = YAMLUnpickle ( yamlFile )
            yamlSystem.label += " (YAMLPickled)"
            yamlSystem.Summary ( log = log )
            yamlEnergy = yamlSystem.Energy  ( log = log, doGradients = True )
            if math.fabs ( referenceEnergy - yamlEnergy  <= _Tolerance ): successes += 1
            else:                                                         failures  += 1

        except Exception as e:
            otherFailures += 1
            if log is not None: log.Text ( "\nError occurred> " +  e.args[0] + "\n" )

        # . Summary of results.
        if log is not None:
            summary = log.GetSummary ( )
            summary.Start ( "Pickle Tests" )
            summary.Entry ( "Pickle Successes", "{:d}".format ( successes            ) )
            summary.Entry ( "Pickle Failures" , "{:d}".format ( failures             ) )
            summary.Entry ( "Total Tests"     , "2"                                    )
            summary.Entry ( "Loop Failures"   , "{:d}".format ( otherFailures        ) )
            summary.Stop  ( )

        # . Success/failure.
        self.assertTrue ( ( failures == 0 ) and ( otherFailures == 0 ) )
def SolvateSystemBySuperposition ( solute, solvent, log = logFile, excludeHydrogens = True, reorientSolute = True, printPairs = False, scaleradii = 0.75 ):
    """Solvate a system by superposition."""

    # . Check that the solvent has a full connectivity.
    if not solvent.connectivity.HasFullConnectivity ( ): raise ValueError ( "The solvent must have a full connectivity." )

    # . Create a sequence.
    if solute.sequence is not None:
        entityLabel = DetermineUniqueEntityLabel ( solute, label = "W" )
        CreateHomogeneousIsolateSequence ( solvent, entityLabel = entityLabel )

    # . Merge the two systems.
    solution = MergeByAtom ( solute, solvent )

    # . Get the atom masses and selections corresponding to the solute and solvent atoms.
    masses       = solution.atoms.GetItemAttributes ( "mass" )
    nsolute      = len ( solute.atoms  )
    nsolvent     = len ( solvent.atoms )
    soluteatoms  = Selection.FromIterable ( range ( nsolute                     ) )
    solventatoms = Selection.FromIterable ( range ( nsolute, nsolute + nsolvent ) )

    # . Reorient the solute coordinates if required.
    if reorientSolute: solution.coordinates3.ToPrincipalAxes ( selection = soluteatoms, weights = masses )

    # . Check the extents of the solute and solvent - to ensure the box is big enough!
    ( origin1, extents1 ) = solution.coordinates3.EnclosingOrthorhombicBox ( selection = soluteatoms  )
    ( origin2, extents2 ) = solution.coordinates3.EnclosingOrthorhombicBox ( selection = solventatoms )
    extents2.AddScaledVector3 ( -1.0, extents1 )
    if min ( extents2 ) < 0.0: raise ValueError ( "It is likely that the solvent box is too small for the solute." )

    # . Move the center of the solute atoms to that of the solvent atoms.
    translation = Clone ( origin2 )
    translation.AddScaledVector3 (  0.5, extents2 )
#    translation.AddScaledVector3 ( -0.5, extents1 ) # . Not needed as done above.
    translation.AddScaledVector3 ( -1.0, origin1  )
    solution.coordinates3.Translate ( translation, selection = soluteatoms )

    # . Reduce the selections if hydrogens are to be excluded.
    if excludeHydrogens:
        indices = []
        for i in soluteatoms:
            if solution.atoms[i].atomicNumber != 1: indices.append ( i )
        soluteatoms = Selection.FromIterable ( indices )
        indices = []
        for i in solventatoms:
            if solution.atoms[i].atomicNumber != 1: indices.append ( i )
        solventatoms = Selection.FromIterable ( indices )

    # . Get the radii.
    radii = solution.atoms.GetItemAttributes ( "vdwRadius" )
    radii.Scale ( scaleradii )

    # . Get the pairlist.
    pairlist = CrossPairList_FromSingleCoordinates3 ( solution.coordinates3, selection1 = solventatoms, selection2 = soluteatoms, radii = radii )
    npairs   = len ( pairlist )

    # . Find the solvent atoms in the pairlist (which are the first indices in the list).
    indices = set ( )
    for ( i, j ) in pairlist: indices.add ( i )

    # . Now find the indices of all the atoms in the corresponding solvent isolates.
    if len ( indices ) > 0:
        toremove  = solution.connectivity.isolates.GetAllIndices ( Selection.FromIterable ( indices ) )
        ntoremove = len ( toremove )
        # . Remove unwanted atoms.
        reduced = PruneByAtom ( solution, toremove.Complement ( upperBound = nsolute + nsolvent ) )
        if solution.sequence is not None: RenumberEntityComponents ( reduced, entityLabels = [ entityLabel ] )
    else:
        ntoremove = 0
        reduced   = solution

    # . Set the symmetry of solution by copying that of solvent.
    if ( solvent.symmetry is not None ) and ( solvent.symmetryParameters is not None ):
        keywordArguments = solvent.symmetryParameters.__getstate__ ( )
        keywordArguments["crystalClass"]    = solvent.symmetry.crystalClass
        keywordArguments["transformations"] = solvent.symmetry.transformations
        reduced.DefineSymmetry ( **keywordArguments )

    # . Do some printing.
    if LogFileActive ( log ):

        # . Distances.
        if printPairs:
            table   = log.GetTable ( columns = [ 10, 10, 20, 20 ] )
            table.Start ( )
            table.Title ( "Solute/Solvent Pairs" )
            table.Heading ( "Solvent"  )
            table.Heading ( "Solute"   )
            table.Heading ( "Distance" )
            table.Heading ( "Cutoff"   )
            for ( i, j ) in pairlist:
                table.Entry ( PeriodicTable.Symbol ( solution.atoms[i].atomicNumber, index = i ) )
                table.Entry ( PeriodicTable.Symbol ( solution.atoms[j].atomicNumber, index = j ) )
                table.Entry ( "{:.3f}".format ( solution.coordinates3.Distance ( i, j ) ) )
                table.Entry ( "{:.3f}".format ( radii[i] + radii[j]                     ) )
            table.Stop ( )

        # . Summary.
        summary = log.GetSummary ( )
        summary.Start ( "Solvation By Superposition Summary" )
        summary.Entry ( "Solute Atoms"         , "{:d}".format ( nsolute              ) )
        summary.Entry ( "Solvent Atoms"        , "{:d}".format ( nsolvent - ntoremove ) )
        summary.Entry ( "Atoms Removed"        , "{:d}".format ( ntoremove            ) )
        summary.Entry ( "Solute/Solvent Pairs" , "{:d}".format ( npairs               ) )
        summary.Stop ( )

    # . Finish up.
    return reduced
Esempio n. 21
0
#===================================================================================================================================
# . Parameters for system definitions.
#===================================================================================================================================
# . Model definitions.
_converger = DIISSCFConverger(densityTolerance=1.0e-8, maximumSCFCycles=250)
_qcModelDFT = QCModelDFT(converger=_converger,
                         densityBasis="demon",
                         orbitalBasis="321g")
_qcModelMNDO = QCModelMNDO(converger=_converger)
_qcModelORCA = QCModelORCA("HF:6-31G*", "SCFCONV10", "EXTREMESCF")
_nbModel = NBModelABFS()

# . Job data.
# . Options: doQCMM for bottom layer, QC model for upper layer and QC selection for upper layer.
_jobData = { "Water Dimer 1"     : ( ( False, _qcModelDFT,  Selection.FromIterable ( range (  3     ) ) ), \
                                     ( False, _qcModelORCA, Selection.FromIterable ( range (  3,  6 ) ) ), \
                                     ( True,  _qcModelDFT,  Selection.FromIterable ( range (  3     ) ) )  ), \
             "Water Dimer 2"     : ( ( True,  _qcModelORCA, Selection.FromIterable ( range (  3,  6 ) ) ), ), \
             "Cyclohexane 9"     : ( ( False, _qcModelDFT,  Selection.FromIterable ( range (  6     ) ) ), \
                                     ( True,  _qcModelORCA, Selection.FromIterable ( range (  3,  6 ) ) )  ), \
             "Alanine Dipeptide" : ( ( False, _qcModelDFT,  Selection.FromIterable ( range ( 10, 14 ) ) ), \
                                     ( False, _qcModelORCA, Selection.FromIterable ( range ( 10, 14 ) ) ), \
                                     ( True,  _qcModelDFT,  Selection.FromIterable ( range ( 10, 14 ) ) ), \
                                     ( True,  _qcModelORCA, Selection.FromIterable ( range ( 10, 14 ) ) )  ) }

#===================================================================================================================================
# . Parameters for test.
#===================================================================================================================================
# . Tolerances.
_EnergyTolerance = 0.1
Esempio n. 22
0
    def WriteJobFiles(self, log=logFile):
        """Write files: PQR, FPT, OGM and MGM."""
        if self.isInitialized:
            # . Get atomic charges and radii for the system
            system = self.owner

            systemCharges = system.AtomicCharges()
            systemRadii = []
            systemTypes = system.energyModel.mmAtoms.AtomTypes()
            radii = YAMLUnpickle("%s/%s" % (YAMLPATHIN, "radii.yaml"))

            for atomType in systemTypes:
                if radii.has_key(atomType):
                    radius = radii[atomType]
                else:
                    generalAtomType = "%s*" % atomType[0]
                    if radii.has_key(generalAtomType):
                        radius = radii[generalAtomType]
                    else:
                        raise ContinuumElectrostaticsError(
                            "Cannot find atomic radius for atom type %s" %
                            atomType)
                systemRadii.append(radius)

            # . Prepare scratch space
            if not os.path.exists(self.pathScratch):
                try:
                    os.makedirs(self.pathScratch)
                except:
                    raise ContinuumElectrostaticsError(
                        "Cannot create scratch directory %s" %
                        self.pathScratch)

            # . Create subdirectories, if necessary
            if self.splitToDirectories:
                for site in self.sites:
                    sitePqr = site.instances[0].sitePqr
                    directory = os.path.dirname(sitePqr)
                    if not os.path.exists(directory):
                        try:
                            os.makedirs(directory)
                        except:
                            raise ContinuumElectrostaticsError(
                                "Cannot create directory %s" % directory)

            # . Write PQR, OGM and MGM files of all instances of all sites
            for site in self.sites:
                site._WriteMEADFiles(system, systemCharges, systemRadii)

            # . Write background PQR file
            PQRFile_FromSystem(self.pathPqrBack,
                               system,
                               selection=Selection(self.backAtomIndices),
                               charges=systemCharges,
                               radii=systemRadii)

            # . Write full-protein PQR file (to be used as eps2set_region)
            PQRFile_FromSystem(self.pathPqrProtein,
                               system,
                               selection=Selection(self.proteinAtomIndices),
                               charges=systemCharges,
                               radii=systemRadii)

            # . Write FPT-file
            lines = []
            for siteIndex, site in enumerate(self.sites):
                for instanceIndex, instance in enumerate(site.instances):
                    for atomIndex, charge in zip(site.siteAtomIndices,
                                                 instance.charges):
                        x, y, z = system.coordinates3[atomIndex]
                        line = "%d %d %f %f %f %f\n" % (
                            siteIndex, instanceIndex, x, y, z, charge)
                        lines.append(line)
            WriteInputFile(self.pathFptSites, lines)

            self.isFilesWritten = True
import math, os.path

from pBabel import MOLFile_ToSystem
from pCore import logFile, LogFileActive, Selection
from pMolecule import ElectronicState, MMModelOPLS, NBModelFull

#===================================================================================================================================
# . Parameters for system definitions.
#===================================================================================================================================
# . Paths.
_dataPath = os.path.join(os.getenv("PDYNAMO_PMOLECULE"), "data", "mol")

# . Molecule definitions.
_keywordLabels = ("label", "dataPath", "fileName", "qcCharge", "multiplicity",
                  "qcSelection")
_moleculeData  = ( ( "Alanine Dipeptide"   , _dataPath, "bAla_c7eq"        , 0, 1, Selection.FromIterable ( range ( 10, 14 ) ) ), \
                   ( "Cyclohexane 6"       , _dataPath, "cyclohexane"      , 0, 1, Selection.FromIterable ( range (  6     ) ) ), \
                   ( "Cyclohexane 9"       , _dataPath, "cyclohexane"      , 0, 1, Selection.FromIterable ( range (  9     ) ) ), \
                   ( "Tyrosine Dipeptide 1", _dataPath, "tyrosineDipeptide", 0, 1, Selection.FromIterable ( range (  6, 14 ) + range ( 22, 29 ) ) ), \
                   ( "Tyrosine Dipeptide 2", _dataPath, "tyrosineDipeptide", 1, 2, Selection.FromIterable ( range (  6, 14 ) + range ( 22, 29 ) ) ), \
                   ( "Water Dimer 1"       , _dataPath, "waterDimer_cs"    , 0, 1, Selection.FromIterable ( range (  3     ) ) ), \
                   ( "Water Dimer 2"       , _dataPath, "waterDimer_cs"    , 0, 1, Selection.FromIterable ( range (  3,  6 ) ) )  )


#===================================================================================================================================
# . Class for a QC/MM test system.
#===================================================================================================================================
class QCMMTestSystem(object):
    """QC/MM test system."""
    def __init__(self, **kwargs):
        """Constructor."""
Esempio n. 24
0
solution.DefineNBModel  ( nbModel )
solution.Summary ( )

# . Refinement.
if _Refine:

    # . Check energies.
    solute.Energy ( )
    for system in ( solvent, solution ):
        system.DefineNBModel ( nbModel )
        system.Energy ( )

    # . Get selections for the protein atoms in the A and I chains.
    protein   = AtomSelection.FromAtomPattern ( solution, "A:*:*" ) | AtomSelection.FromAtomPattern ( solution, "I:*:*" )
    hydrogens = AtomSelection.FromAtomAttributes ( solution, "atomicNumber", 1 )
    heavies   = Selection.FromIterable ( protein - hydrogens )
    protein   = Selection.FromIterable ( protein )

    # . Fix all protein atoms.
    solution.DefineFixedAtoms ( protein )
    solution.Summary ( )

    # . Optimization.
    if _Optimize:
        ConjugateGradientMinimize_SystemGeometry ( solution                    ,
                                                   maximumIterations    =  200 ,
                                                   logFrequency         =   10 ,
                                                   rmsGradientTolerance = 10.0 )

    # . Define a normal deviate generator in a given state.
    normalDeviateGenerator = NormalDeviateGenerator.WithRandomNumberGenerator ( RandomNumberGenerator.WithSeed ( 517152 ) )
def CoordinateFluctuations(*arguments, **keywordArguments):
    """Calculate the coordinate fluctuations for selected particles."""

    # . Initialization.
    fluctuations = None

    # . Get the trajectory and associated system data.
    (system, trajectories) = _GetSystemAndTrajectoriesFromArguments(*arguments)

    # . Get the selection and the size of the problem.
    selection = keywordArguments.pop("selection", None)
    if selection is None:
        selection = Selection.FromIterable(range(len(system.atoms)))
    n = len(selection)

    # . Get the average positions.
    averagePositions = keywordArguments.pop("averagePositions", None)
    if averagePositions is None:
        averagePositions = AveragePositions(trajectories, selection=selection)

    # . Various other options.
    anisotropic = keywordArguments.pop("anisotropic", False)
    asBFactors = keywordArguments.pop("asBFactors", False)
    _CheckForUnknownOptions(keywordArguments)

    # . Continue processing.
    if (n > 0) and (averagePositions is not None):

        # . Allocate space.
        displacement = Coordinates3.WithExtent(n)
        if anisotropic: fluctuations = Real2DArray.WithExtents(n, 6)
        else: fluctuations = Real1DArray.WithExtent(n)
        displacement.Set(0.0)
        fluctuations.Set(0.0)

        # . Loop over trajectory frames.
        numberFrames = 0
        for trajectory in trajectories:
            trajectory.ReadHeader()
            while trajectory.RestoreOwnerData():
                frame = system.coordinates3
                if anisotropic:
                    for (p, i) in enumerate(selection):
                        dx = frame[i, 0] - averagePositions[p, 0]
                        dy = frame[i, 1] - averagePositions[p, 1]
                        dz = frame[i, 2] - averagePositions[p, 2]
                        fluctuations[p, 0] += dx * dx
                        fluctuations[p, 1] += dy * dx
                        fluctuations[p, 2] += dy * dy
                        fluctuations[p, 3] += dz * dx
                        fluctuations[p, 4] += dz * dy
                        fluctuations[p, 5] += dz * dz
                else:
                    for (p, i) in enumerate(selection):
                        fluctuations[p] += ( ( frame[i,0] - averagePositions[p,0] )**2 + \
                                             ( frame[i,1] - averagePositions[p,1] )**2 + \
                                             ( frame[i,2] - averagePositions[p,2] )**2 )
            trajectory.ReadFooter()
            trajectory.Close()
            numberFrames += len(trajectory)

        # . Scale.
        if numberFrames > 0: fluctuations.Scale(1.0 / float(numberFrames))

        # . Convert to B-factors if necessary.
        if asBFactors:
            conversionFactor = 8.0 * math.pi**2
            if not anisotropic: conversionFactor /= 3.0
            fluctuations.Scale(conversionFactor)

    # . Finish up.
    return fluctuations
def BuildCubicSolventBox ( molecule, nmolecules, log = logFile, moleculesize = None, excludeHydrogens = True, QRANDOMROTATION = True, randomNumberGenerator = None, scalesafety = 1.1 ):
    """Build a cubic solvent box."""

    # . Get the number of molecules in each direction.
    nlinear = int ( math.ceil ( math.pow ( float ( nmolecules ), 1.0 / 3.0 ) ) )

    # . Get the indices of the occupied sites.
    sites = sample ( range ( nlinear**3 ), nmolecules )
    sites.sort ( )

    # . Get the number of atoms in the molecule and an appropriate selection.
    natoms    = len ( molecule.atoms )
    selection = Selection.FromIterable ( range ( natoms ) )

    # . Get a copy of molecule's coordinates (reorientated).
    coordinates3 = Clone ( molecule.coordinates3 )
    coordinates3.ToPrincipalAxes ( )

    # . Get the molecule size depending upon the input options.
    # . A molecule size has been specified.
    if moleculesize is not None:
        size = moleculesize
    # . Determine the size of the molecule as the diagonal distance across its enclosing orthorhombic box.
    else:
        radii = molecule.atoms.GetItemAttributes ( "vdwRadius" )
        if excludeHydrogens:
            atomicNumbers = molecule.atoms.GetItemAttributes ( "atomicNumber" )
            for ( i, atomicNumber ) in enumerate ( molecule.atoms.GetItemAttributes ( "atomicNumber" ) ):
                if atomicNumber == 1: radii[i] = 0.0
        ( origin, extents ) = coordinates3.EnclosingOrthorhombicBox ( radii = radii )
        size                = extents.Norm2 ( ) * scalesafety

    # . Create the new system - temporarily resetting the coordinates.
    temporary3            = molecule.coordinates3
    molecule.coordinates3 = coordinates3
    solvent               = MergeByAtom ( nmolecules * [ molecule ] )
    molecule.coordinates3 = temporary3

    # . Set the system symmetry.
    solvent.DefineSymmetry ( crystalClass = CrystalClassCubic ( ), a = size * float ( nlinear ) )

    # . Set up for random rotations.
    if QRANDOMROTATION:
        if randomNumberGenerator is None: randomNumberGenerator = RandomNumberGenerator.WithRandomSeed ( )
        rotation = Matrix33.Null ( )

    # . Loop over the box sites.
    origin      = 0.5 * float ( 1 - nlinear ) * size
    n           = 0
    translation = Vector3.Null ( )
    for i in range ( nlinear ):
        translation[0] = origin + size * float ( i )
        for j in range ( nlinear ):
            translation[1] = origin + size * float ( j )
            for k in range ( nlinear ):
                if len ( sites ) == 0: break
                translation[2] = origin + size * float ( k )
                # . Check for an occupied site.
                if sites[0] == n:
                    sites.pop ( 0 )
                    # . Randomly rotate the coordinates.
                    if QRANDOMROTATION:
                        rotation.RandomRotation ( randomNumberGenerator )
                        solvent.coordinates3.Rotate ( rotation, selection = selection )
                    # . Translate the coordinates.
                    solvent.coordinates3.Translate ( translation, selection = selection )
                    # . Increment the selection for the next molecule.
                    selection.Increment ( natoms )
                n += 1

    # . Do some printing.
    if LogFileActive ( log ):
        summary = log.GetSummary ( )
        summary.Start ( "Cubic Solvent Box Summary" )
        summary.Entry ( "Number of Molecules", "{:d}"  .format ( nmolecules                   ) )
        summary.Entry ( "Density (kg m^-3)",   "{:.3f}".format ( SystemDensity ( solvent )    ) )
        summary.Entry ( "Box Side",            "{:.3f}".format ( solvent.symmetryParameters.a ) )
        summary.Entry ( "Molecule Size",       "{:.3f}".format ( size                         ) )
        summary.Stop ( )

    # . Return the cubic system.
    return solvent