예제 #1
0
파일: PoseFF.py 프로젝트: tiendott/AlGDock
    def __init__(self, ind1, ind2, ind3, X1, Y1, Z1, phi, theta, omega, \
                 hwidth_spatial = 0.1, \
                 k_spatial = 200.0, \
                 hwidth_angular = np.pi/4., \
                 k_angular = 200.0):
        """
    @param input: [index1, index2, index3, X1, Y1, Z1, phi, theta, omega]
    ind1 - index of atom 1
    ind2 - index of atom 2
    ind3 - index of atom 3
    The next 6 variables are the center of the flat-bottom harmonic bias
    X1 - x coordinate of atom 1
    X2 - x coordinate of atom 2
    X3 - x coordinate of atom 3
    phi, theta, omega - angular degrees of freedom, in radians
    hwidth_spatial - the half width of the spatial flat-bottom harmonic terms (nm)
    k_spatial - the spring constant on the spatial flat-bottom harmonic terms (kJ/nm)
    hwidth_angular - the half width of the angular flat-bottom harmonic terms (radians)
    k_angular - the spring constant on the angular flat-bottom harmonic terms (kJ/nm)
    """

        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, 'external restraint')

        # Store the parameters for later use.
        self.params = OrderedDict()
        for key in [\
          'ind1', 'ind2', 'ind3', 'X1', 'Y1', 'Z1', 'phi', 'theta', 'omega', \
          'hwidth_spatial', 'k_spatial', 'hwidth_angular', 'k_angular']:
            self.params[key] = locals()[key]
예제 #2
0
  def __init__(self, ind1, ind2, ind3, X1, Y1, Z1, phi, theta, omega, \
               hwidth_spatial = 0.0, \
               k_spatial = 200.0, \
               hwidth_angular = 0.0, \
               k_angular = 200.0):
    """
    @param input: [index1, index2, index3, X1, Y1, Z1, phi, theta, omega]
    ind1 - index of atom 1
    ind2 - index of atom 2
    ind3 - index of atom 3
    The next 6 variables are the center of the flat-bottom harmonic bias
    X1 - x coordinate of atom 1
    X2 - x coordinate of atom 2
    X3 - x coordinate of atom 3
    phi, theta, omega - angular degrees of freedom, in radians
    hwidth_spatial - the half width of the spatial flat-bottom harmonic terms (nm)
    k_spatial - the spring constant on the spatial flat-bottom harmonic terms (kJ/nm)
    hwidth_angular - the half width of the angular flat-bottom harmonic terms (radians)
    k_angular - the spring constant on the angular flat-bottom harmonic terms (kJ/nm)
    """
    
    # Initialize the ForceField class, giving a name to this one.
    ForceField.__init__(self, 'external restraint')

    # Store the parameters for later use.
    self.params = OrderedDict()
    for key in [\
      'ind1', 'ind2', 'ind3', 'X1', 'Y1', 'Z1', 'phi', 'theta', 'omega', \
      'hwidth_spatial', 'k_spatial', 'hwidth_angular', 'k_angular']:
      self.params[key] = locals()[key]
예제 #3
0
 def __init__(self, origin, direction, max_Z, max_R, name='cylinder'):
     """
     @param origin: the origin of the principal axis of the cylinder
     @type origin: {numpy.array}
     @param direction: the direction of the principal axis of the cylinder
     @type direction: {numpy.array}
     @param max_Z: the maximal value of the projection along the principal axis
     @type max_Z: C{float}
     @param max_R: the maximal value orthogonal to the principal axis
     @type max_R: C{float}
     """
     # Store arguments that recreate the force field from a pickled
     # universe or from a trajectory.
     self.arguments = (origin, direction, max_Z, max_R)
     # Initialize the ForceField class, giving a name to this one.
     ForceField.__init__(self, name)
     # Store the parameters for later use.
     self.origin = origin
     self.direction = direction
     self.max_Z = max_Z
     self.max_R = max_R
     self.name = name
     if not ((self.direction[0] == 0.0) and
             (self.direction[1] == 0.0) and
             (self.direction[2] == 1.0)):
       raise Exception("For efficiency, principal axis must be along (0,0,1)")
     # Calculate the cylinder volume
     self.volume = N.pi*(self.max_R*self.max_R)*(self.max_Z - self.origin[2])
예제 #4
0
 def __init__(self, atom, center, force_constant):
     """
     @param atom: the atom on which the force field acts
     @type atom: L{MMTK.ChemicalObjects.Atom}
     @param center: the point to which the atom is attached by
                    the harmonic potential
     @type center: L{Scientific.Geometry.Vector}
     @param force_constant: the force constant of the harmonic potential
     @type force_constant: C{float}
     """
     # Get the internal index of the atom if the argument is an
     # atom object. It is the index that is stored internally,
     # and when the force field is recreated from a specification
     # in a trajectory file, it is the index that is passed instead
     # of the atom object itself. Calling this method takes care
     # of all the necessary checks and conversions.
     self.atom_index = self.getAtomParameterIndices([atom])[0]
     # Store arguments that recreate the force field from a pickled
     # universe or from a trajectory.
     self.arguments = (self.atom_index, center, force_constant)
     # Initialize the ForceField class, giving a name to this one.
     ForceField.__init__(self, 'harmonic_oscillator')
     # Store the parameters for later use.
     self.center = center
     self.force_constant = force_constant
예제 #5
0
    def __init__(self, atom, xc,yc,zc, force_constant):
        """
        @param atom: the atom on which the force field acts
        @type atom: L{MMTK.ChemicalObjects.Atom}
        @param center: the point to which the atom is attached by
                       the harmonic potential
        @type center: L{Scientific.Geometry.Vector}
        @param force_constant: the force constant of the harmonic potential
        @type force_constant: C{float}
        """
        # Get the internal index of the atom if the argument is an
        # atom object. It is the index that is stored internally,
        # and when the force field is recreated from a specification
        # in a trajectory file, it is the index that is passed instead
        # of the atom object itself. Calling this method takes care
        # of all the necessary checks and conversions.
        self.atom_index = self.getAtomParameterIndices([atom])[0]
        # Store arguments that recreate the force field from a pickled
        # universe or from a trajectory.
        # Store the parameters for later use.
        self.x = xc
        self.y = yc
        self.z = zc
        self.forceconstant = force_constant

        self.arguments = (self.atom_index, self.x,self.y,self.z, self.forceconstant)
        
        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, 'HarmonicWell')
예제 #6
0
 def __init__(self, atom1, atom2, atom3, atom4, dihedral, force_constant):
     """
     :param atom1: first atom
     :type atom1: :class:`~MMTK.ChemicalObjects.Atom`
     :param atom2: second (axis) atom
     :type atom2: :class:`~MMTK.ChemicalObjects.Atom`
     :param atom3: third (axis)atom
     :type atom3: :class:`~MMTK.ChemicalObjects.Atom`
     :param atom4: fourth atom
     :type atom4: :class:`~MMTK.ChemicalObjects.Atom`
     :param dihedral: the dihedral angle at which the restraint is zero
     :type dihedral: float
     :param force_constant: the force constant of the restraint term.
                            The functional form of the restraint is
                            force_constant*(phi-abs(dihedral))**2, where
                            phi is the dihedral angle
                            atom1-atom2-atom3-atom4.
     """
     self.index1, self.index2, self.index3, self.index4 = \
                self.getAtomParameterIndices((atom1, atom2, atom3, atom4))
     self.dihedral = dihedral
     self.force_constant = force_constant
     self.arguments = (self.index1, self.index2, self.index3, self.index4,
                       dihedral, force_constant) 
     ForceField.__init__(self, 'harmonic dihedral restraint')
    def __init__(self, FN, strength, scaling_property, scaling_prefactor=None, inv_power=-2., grid_name='trilinear transformed grid', max_val=-1.0):
        """
        @param strength: the electric field vector
        @type strength: L{float}
        @scaling_property: the name of the atomic property in the database
                           that is used to retrieve the atomic scaling_factor.
                           The default is 'amber_charge', the charge property
                           for Amber94 and Amber99.
        @type scaling_property: C{str}
        @param inv_power: the inverse of the power by which grid points are transformed
        @grid_name: a name for the grid
        @max_val: the maximum allowed value for a point on the grid.
                  A negative value means that there is no max.
        """
        # Store arguments that recreate the force field from a pickled
        # universe or from a trajectory.
        self.arguments = (FN, strength,
          scaling_property, scaling_prefactor,
          inv_power, grid_name, max_val)
        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, grid_name)
        # Store the parameters for later use.
        self.FN = FN
        self.strength = strength
        self.scaling_property = scaling_property
        self.inv_power = float(inv_power)
        self.grid_name = grid_name
        self.max_val = max_val

        # Load the grid  
        import AlGDock.IO
        IO_Grid = AlGDock.IO.Grid()
        self.grid_data = IO_Grid.read(self.FN, multiplier=0.1)
        if not (self.grid_data['origin']==0.0).all():
          raise Exception('Trilinear grid origin in %s not at (0, 0, 0)!'%self.FN)

        # Make sure all grid values are positive
        if (self.grid_data['vals']>0).any():
          if (self.grid_data['vals']<0).any():
            raise Exception('All of the grid points do not have the same sign')
          else:
            neg_vals = False
        else:
          neg_vals = True
          self.grid_data['vals'] = -1*self.grid_data['vals']

        # Transform the grid
        nonzero = self.grid_data['vals']!=0
        self.grid_data['vals'][nonzero] = self.grid_data['vals'][nonzero]**(1./self.inv_power)

        import numpy as np
        
        # "Cap" the grid values
        if max_val>0.0:
          self.grid_data['vals'] = max_val*np.tanh(self.grid_data['vals']/max_val)

        if scaling_prefactor is not None:
          self.scaling_prefactor = scaling_prefactor
        else:
          self.scaling_prefactor = -1. if neg_vals else 1.
예제 #8
0
파일: PoseFF.py 프로젝트: Mamie/AlGDock
    def __init__(self, input_table):
        """
        First 2 entries for external dofs:
        [index1, index2, index3, X, Y, Z, bbot, abot]
        [b0, kb, theta0, ka, n, gamma, dbot, kd]
        Internal torsional dofs:
        @param input_table: [index1, index2, index3, X, Y, Z, bbot, abot]
                            [b0, kb, theta0, ka, n, gamma, dbot, kd]
                            [4 atom indices, periodicity, gamma, bottom, force K] x internal dofs
        @type atom: L{L{MMTK.ChemicalObjects.Atom.index,
                        MMTK.ChemicalObjects.Atom.index,
                        MMTK.ChemicalObjects.Atom.index,
                        double, double, double, double, double},
                      L{double, double, double, double, 
                        int, double, double, double},
                      L{MMTK.ChemicalObjects.Atom.index,
                        MMTK.ChemicalObjects.Atom.index,
                        MMTK.ChemicalObjects.Atom.index,
                        MMTK.ChemicalObjects.Atom.index,
                        inp, dobule, double, double} x #of internal dofs}
        """

        # Internal dofs arguments
        self.externalArgs = input_table[:2]
        self.internalArgs = input_table[2:]
        # Halve the flat bottoms
        self.externalArgs[0][6] /= 2
        self.externalArgs[0][7] /= 2
        for ia in self.internalArgs:
          ia[6] /= 2
        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, 'pose')
예제 #9
0
    def __init__(self, atom1, atom2, atom3):
        self.index1, self.index2, self.index3 = self.getAtomParameterIndices(
            [atom1, atom2, atom3])
        self.arguments = (self.index1, self.index2, self.index3)

        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, 'HeCO2Trans')
예제 #10
0
 def __init__(self, atom1, atom2, atom3, atom4, dihedral, force_constant):
     """
     :param atom1: first atom
     :type atom1: :class:`~MMTK.ChemicalObjects.Atom`
     :param atom2: second (axis) atom
     :type atom2: :class:`~MMTK.ChemicalObjects.Atom`
     :param atom3: third (axis)atom
     :type atom3: :class:`~MMTK.ChemicalObjects.Atom`
     :param atom4: fourth atom
     :type atom4: :class:`~MMTK.ChemicalObjects.Atom`
     :param dihedral: the dihedral angle at which the restraint is zero
     :type dihedral: float
     :param force_constant: the force constant of the restraint term.
                            The functional form of the restraint is
                            force_constant*(phi-abs(dihedral))**2, where
                            phi is the dihedral angle
                            atom1-atom2-atom3-atom4.
     """
     self.index1, self.index2, self.index3, self.index4 = \
                self.getAtomParameterIndices((atom1, atom2, atom3, atom4))
     self.dihedral = dihedral
     self.force_constant = force_constant
     self.arguments = (self.index1, self.index2, self.index3, self.index4,
                       dihedral, force_constant)
     ForceField.__init__(self, 'harmonic dihedral restraint')
예제 #11
0
    def __init__(self, atom1, atom2):

        self.atom_index1, self.atom_index2 = self.getAtomParameterIndices((atom1,atom2))

        # Store arguments that recreate the force field from a pickled
        # universe or from a trajectory.
        self.arguments = (self.atom_index1, self.atom_index2)
        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, 'NoPot')
예제 #12
0
    def __init__(self, atom1, atom2, atom3, atom4, atom5, atom6):

        self.atom_index1, self.atom_index2, self.atom_index3, self.atom_index4, self.atom_index5, self.atom_index6 = self.getAtomParameterIndices((atom1,atom2, atom3, atom4, atom5, atom6))

        # Store arguments that recreate the force field from a pickled
        # universe or from a trajectory.
        self.arguments = (self.atom_index1, self.atom_index2, self.atom_index3, self.atom_index4, self.atom_index5, self.atom_index6)
        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, 'Dipole')
예제 #13
0
 def __init__(self, atoms, D_r, c1, c2, c3, r_eq):
     self.atom_indices = map(lambda x: self.getAtomParameterIndices([x])[0],atoms)
     self.D_r = D_r
     self.c1 = c1
     self.c2 = c2
     self.c3 = c3
     self.r_eq = r_eq
     self.arguments = (self.atom_indices,D_r,c1,c2,c3,r_eq)
     ForceField.__init__(self, 'quartic_bond')
예제 #14
0
 def __init__(self, universe,fraction,o_charge):
     #Take the list of objects (molecules) and create a new list where each element in the
     #list is another list containing the indices of all the atoms in the molecule
     waters = universe.objectList()
     water_atoms = map(lambda x: map(lambda y: self.getAtomParameterIndices([y])[0],x.atomList()), waters)
     self.atom_indices = water_atoms
     self.fraction = fraction
     self.o_charge = o_charge
     self.arguments = (self.atom_indices,self.fraction,self.o_charge)
     ForceField.__init__(self, 'electrostatics')
예제 #15
0
    def __init__(self,
                 FN,
                 strength,
                 scaling_property,
                 scaling_prefactor=None,
                 grid_name='trilinear grid',
                 max_val=-1.0,
                 Ethresh=-1.0):
        """
        @param strength: the electric field vector
        @type strength: L{float}
        @scaling_property: the name of the atomic property in the database
                           that is used to retrieve the atomic scaling_factor.
                           The default is 'amber_charge', the charge property
                           for Amber94 and Amber99.
        @grid_name: a name for the grid
        @max_val: the maximum allowed value for a point on the grid.
                  A negative value means that there is no max.
        @Ethresh: the maximum allowed value for the energy at any point.
                  A negative value means that there is no max.
        @type scaling_property: C{str}
        """
        # Store arguments that recreate the force field from a pickled
        # universe or from a trajectory.
        self.arguments = (FN, strength, scaling_property, scaling_prefactor,
                          grid_name, max_val)
        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, grid_name)
        # Store the parameters for later use.
        self.FN = FN
        self.strength = strength
        self.scaling_property = scaling_property
        self.grid_name = grid_name
        self.max_val = max_val
        self.Ethresh = Ethresh

        # Load the grid
        import AlGDock.IO
        IO_Grid = AlGDock.IO.Grid()
        self.grid_data = IO_Grid.read(self.FN, multiplier=0.1)
        if not (self.grid_data['origin'] == 0.0).all():
            raise Exception('Trilinear grid origin in %s not at (0, 0, 0)!' %
                            self.FN)

        import numpy as np

        # "Cap" the grid values
        if max_val > 0.0:
            self.grid_data['vals'] = max_val * np.tanh(
                self.grid_data['vals'] / max_val)

        if scaling_prefactor is not None:
            self.scaling_prefactor = scaling_prefactor
        else:
            self.scaling_prefactor = 1.
예제 #16
0
    def __init__(self, universe, epsilon, sigma):
        #Get atom indices for oxygens
        waters = universe.objectList()
        oxygens = map(lambda x: x.atomList()[2],waters)     #Oxygen is 2 in atom list
        atom_indices = map(lambda x: self.getAtomParameterIndices([x])[0],oxygens)
        self.atom_indices = atom_indices
        self.epsilon = epsilon
        self.sigma = sigma

        self.arguments = (self.atom_indices,self.epsilon,self.sigma)
        ForceField.__init__(self, 'lennard_jones')
예제 #17
0
    def __init__(self,
                 FN,
                 strength,
                 scaling_property,
                 scaling_prefactor=None,
                 grid_name='trilinear transformed grid',
                 max_val=-1.0):
        """
        @param strength: the electric field vector
        @type strength: L{float}
        @scaling_property: the name of the atomic property in the database
                           that is used to retrieve the atomic scaling_factor.
                           The default is 'amber_charge', the charge property
                           for Amber94 and Amber99.
        @type scaling_property: C{str}
        @grid_name: a name for the grid
        @max_val: the maximum allowed value for a point on the grid.
                  A negative value means that there is no max.
        """
        # Store arguments that recreate the force field from a pickled
        # universe or from a trajectory.
        self.arguments = (FN, strength, scaling_property, grid_name, max_val)
        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, grid_name)
        # Store the parameters for later use.
        self.FN = FN
        self.strength = strength
        self.scaling_property = scaling_property
        self.grid_name = grid_name
        self.max_val = max_val

        import AlGDock.IO
        IO_Grid = AlGDock.IO.Grid()
        self.grid_data = IO_Grid.read(self.FN, multiplier=0.1)
        if not (self.grid_data['origin'] == 0.0).all():
            raise Exception('Trilinear grid origin in %s not at (0, 0, 0)!' %
                            self.FN)

        # Make sure all grid values are positive
        n_positive = sum(self.grid_data['vals'] > 0)
        n_negative = sum(self.grid_data['vals'] < 0)
        if n_positive > 0 and n_negative > 0:
            raise Exception('All of the grid points do not have the same sign')
        if n_negative > 0:
            self.grid_data['vals'] = -1 * self.grid_data['vals']

        if scaling_prefactor is not None:
            self.scaling_prefactor = scaling_prefactor
        else:
            self.scaling_prefactor = -1. if n_negative > 0 else 1.
예제 #18
0
파일: ANMFF.py 프로젝트: acousticpants/mmtk
 def __init__(self, cutoff = None, scale_factor = 1.):
     """
     :param cutoff: the cutoff for pair interactions. Pair interactions
                    in periodic systems are calculated using
                    the minimum-image convention; the cutoff should
                    therefore never be larger than half the smallest
                    edge length of the elementary cell.
     :type cutoff: float
     :param scale_factor: a global scaling factor
     :type scale_factor: float
     """
     ForceField.__init__(self, 'anisotropic_network')
     self.arguments = (cutoff,)
     self.cutoff = cutoff
     self.scale_factor = scale_factor
예제 #19
0
 def __init__(self, cutoff=None, scale_factor=1.):
     """
     :param cutoff: the cutoff for pair interactions. Pair interactions
                    in periodic systems are calculated using
                    the minimum-image convention; the cutoff should
                    therefore never be larger than half the smallest
                    edge length of the elementary cell.
     :type cutoff: float
     :param scale_factor: a global scaling factor
     :type scale_factor: float
     """
     ForceField.__init__(self, 'anisotropic_network')
     self.arguments = (cutoff, )
     self.cutoff = cutoff
     self.scale_factor = scale_factor
    def __init__(self, FN, strength,
      scaling_property, scaling_prefactor=None,
      grid_name='trilinear grid', max_val=-1.0, Ethresh=-1.0):
        """
        @param strength: the electric field vector
        @type strength: L{float}
        @scaling_property: the name of the atomic property in the database
                           that is used to retrieve the atomic scaling_factor.
                           The default is 'amber_charge', the charge property
                           for Amber94 and Amber99.
        @grid_name: a name for the grid
        @max_val: the maximum allowed value for a point on the grid.
                  A negative value means that there is no max.
        @Ethresh: the maximum allowed value for the energy at any point.
                  A negative value means that there is no max.
        @type scaling_property: C{str}
        """
        # Store arguments that recreate the force field from a pickled
        # universe or from a trajectory.
        self.arguments = (FN, strength,
          scaling_property, scaling_prefactor, grid_name, max_val)
        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, grid_name)
        # Store the parameters for later use.
        self.FN = FN
        self.strength = strength
        self.scaling_property = scaling_property
        self.grid_name = grid_name
        self.max_val = max_val
        self.Ethresh = Ethresh
  
        # Load the grid
        import AlGDock.IO
        IO_Grid = AlGDock.IO.Grid()
        self.grid_data = IO_Grid.read(self.FN, multiplier=0.1)
        if not (self.grid_data['origin']==0.0).all():
          raise Exception('Trilinear grid origin in %s not at (0, 0, 0)!'%self.FN)

        import numpy as np

        # "Cap" the grid values
        if max_val>0.0:
          self.grid_data['vals'] = max_val*np.tanh(self.grid_data['vals']/max_val)
    
        if scaling_prefactor is not None:
          self.scaling_prefactor = scaling_prefactor
        else:
          self.scaling_prefactor = 1.
예제 #21
0
파일: OpenMM.py 프로젝트: CCBatIIT/AlGDock
  def __init__(self, prmtopFN, \
      prmtop_atom_order, inv_prmtop_atom_order, implicitSolvent='OpenMM_OBC2'):
    """
    @name: a name for the grid
    @implicitSolvent: the type of implicit solvent, which can be ['OpenMM_Gas','OpenMM_GBn', 'OpenMM_GBn2', 'OpenMM_HCT', 'OpenMM_OBC1', 'OpenMM_OBC2'].
    """
    if not implicitSolvent in \
        ['OpenMM_Gas','OpenMM_GBn', 'OpenMM_GBn2', \
         'OpenMM_HCT', 'OpenMM_OBC1', 'OpenMM_OBC2']:
      raise Exception('Implicit solvent not recognized')

    ForceField.__init__(self, implicitSolvent) # Initialize the ForceField class

    # Store arguments that recreate the force field from a pickled
    # universe or from a trajectory.
    self.arguments = (prmtopFN, prmtop_atom_order, inv_prmtop_atom_order, implicitSolvent)
예제 #22
0
    def __init__(self, prmtopFN,
          prmtop_atom_order, inv_prmtop_atom_order):
        """
        @param prmtopFN: an AMBER parameter and topology file
        @type strength:  C{str}
        """
        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, 'OBC')

        # Store arguments that recreate the force field from a pickled
        # universe or from a trajectory.
        self.arguments = (prmtopFN, prmtop_atom_order, inv_prmtop_atom_order)
    
        self.prmtopFN = prmtopFN
        self.prmtop_atom_order = prmtop_atom_order
        self.inv_prmtop_atom_order = inv_prmtop_atom_order
예제 #23
0
 def __init__(self,
              obj1,
              obj2,
              distance,
              force_constant,
              nb_exclusion=False):
     """
     :param obj1: the object defining center-of-mass 1
     :type obj1: :class:`~MMTK.Collections.GroupOfAtoms`
     :param obj2: the object defining center-of-mass 2
     :type obj2: :class:`~MMTK.Collections.GroupOfAtoms`
     :param distance: the distance between cm 1 and cm2 at which
                      the restraint is zero
     :type distance: float
     :param force_constant: the force constant of the restraint term.
                            The functional form of the restraint is
                            force_constant*((cm1-cm2).length()-distance)**2,
                            where cm1 and cm2 are the centrer-of-mass
                            positions of the two objects.
     :type force_constant: float
     :param nb_exclussion: if True, non-bonded interactions between
                           the restrained atoms are suppressed, as
                           for a chemical bond
     :type nb_exclussion: bool
     """
     if isinstance(obj1, int) and isinstance(obj2, int):
         # Older MMTK versions admitted only single atoms and
         # stored single indices. Support this mode for opening
         # trajectories made with those versions
         self.atom_indices_1 = [obj1]
         self.atom_indices_2 = [obj2]
     if isChemicalObject(obj1) or isCollection(obj1):
         obj1 = obj1.atomList()
     if isChemicalObject(obj2) or isCollection(obj2):
         obj2 = obj2.atomList()
     self.atom_indices_1 = self.getAtomParameterIndices(obj1)
     self.atom_indices_2 = self.getAtomParameterIndices(obj2)
     if nb_exclusion and (len(self.atom_indices_1) > 1
                          or len(self.atom_indices_2) > 1):
         raise ValueError("Non-bonded exclusion possible only "
                          "between single-atom objects")
     self.arguments = (self.atom_indices_1, self.atom_indices_2, distance,
                       force_constant, nb_exclusion)
     self.distance = distance
     self.force_constant = force_constant
     self.nb_exclusion = nb_exclusion
     ForceField.__init__(self, 'harmonic distance restraint')
예제 #24
0
 def __init__(self, obj, center, force_constant):
     """
     :param obj: the object on whose center of mass the force field acts
     :type obj: :class:`~MMTK.Collections.GroupOfAtoms`
     :param center: the point to which the atom is attached by
                     the harmonic potential
     :type center: Scientific.Geometry.Vector
     :param force_constant: the force constant of the harmonic potential
     :type force_constant: float
     """
     if isChemicalObject(obj):
         obj = obj.atomList()
     self.atom_indices = self.getAtomParameterIndices(obj)
     self.arguments = (self.atom_indices, center, force_constant)
     ForceField.__init__(self, 'harmonic_trap')
     self.center = center
     self.force_constant = force_constant
예제 #25
0
 def __init__(self, obj, center, force_constant):
     """
     :param obj: the object on whose center of mass the force field acts
     :type obj: :class:`~MMTK.Collections.GroupOfAtoms`
     :param center: the point to which the atom is attached by
                     the harmonic potential
     :type center: Scientific.Geometry.Vector
     :param force_constant: the force constant of the harmonic potential
     :type force_constant: float
     """
     if isChemicalObject(obj):
         obj = obj.atomList()
     self.atom_indices = self.getAtomParameterIndices(obj)
     self.arguments = (self.atom_indices, center, force_constant)
     ForceField.__init__(self, 'harmonic_trap')
     self.center = center
     self.force_constant = force_constant
예제 #26
0
 def __init__(self, strength, charge_property='amber_charge'):
     """
     @param strength: the electric field vector
     @type strength: L{Scientific.Geometry.Vector}
     @charge_property: the name of the atomic property in the database
                       that is used to retrieve the atomic charges.
                       The default is 'amber_charge', the charge property
                       for Amber94 and Amber99.
     @type charge_property: C{str}
     """
     # Store arguments that recreate the force field from a pickled
     # universe or from a trajectory.
     self.arguments = (strength, charge_property)
     # Initialize the ForceField class, giving a name to this one.
     ForceField.__init__(self, 'electric_field')
     # Store the parameters for later use.
     self.strength = strength
     self.charge_property = charge_property
예제 #27
0
 def __init__(self, strength, charge_property='amber_charge'):
     """
     @param strength: the electric field vector
     @type strength: L{Scientific.Geometry.Vector}
     @charge_property: the name of the atomic property in the database
                       that is used to retrieve the atomic charges.
                       The default is 'amber_charge', the charge property
                       for Amber94 and Amber99.
     @type charge_property: C{str}
     """
     # Store arguments that recreate the force field from a pickled
     # universe or from a trajectory.
     self.arguments = (strength, charge_property)
     # Initialize the ForceField class, giving a name to this one.
     ForceField.__init__(self, 'electric_field')
     # Store the parameters for later use.
     self.strength = strength
     self.charge_property = charge_property
예제 #28
0
파일: Sphere.py 프로젝트: tiendott/AlGDock
 def __init__(self, center, max_R, name='Sphere'):
     """
     @param center: the center of the principal axis of the sphere
     @type center: {numpy.array}
     @param max_R: the maximal value orthogonal to the principal axis
     @type max_R: C{float}
     """
     # Store arguments that recreate the force field from a pickled
     # universe or from a trajectory.
     self.arguments = (center, max_R)
     # Initialize the ForceField class, giving a name to this one.
     ForceField.__init__(self, name)
     # Store the parameters for later use.
     self.center = center
     self.max_R = max_R
     self.name = name
     # Calculate the sphere volume
     self.volume = 4. / 3. * N.pi * (self.max_R * self.max_R * self.max_R)
예제 #29
0
파일: Sphere.py 프로젝트: Mamie/AlGDock
 def __init__(self, center, max_R, name='Sphere'):
     """
     @param center: the center of the principal axis of the sphere
     @type center: {numpy.array}
     @param max_R: the maximal value orthogonal to the principal axis
     @type max_R: C{float}
     """
     # Store arguments that recreate the force field from a pickled
     # universe or from a trajectory.
     self.arguments = (center, max_R)
     # Initialize the ForceField class, giving a name to this one.
     ForceField.__init__(self, name)
     # Store the parameters for later use.
     self.center = center
     self.max_R = max_R
     self.name = name
     # Calculate the sphere volume
     self.volume = 4./3.*N.pi*(self.max_R*self.max_R*self.max_R)
예제 #30
0
파일: PoseFF.py 프로젝트: CCBatIIT/AlGDock
  def __init__(self, torsions, \
               k = 200.0):
    """
    Internal torsional dofs:
    @param input: [4 atom indices, gamma] x internal dofs
    @type atom:   L{MMTK.ChemicalObjects.Atom.index,
                    MMTK.ChemicalObjects.Atom.index,
                    MMTK.ChemicalObjects.Atom.index,
                    MMTK.ChemicalObjects.Atom.index,
                    double} x # of internal dofs}
    """
    
    # Initialize the ForceField class, giving a name to this one.
    ForceField.__init__(self, 'internal dihedral restraint')

    # Store the parameters for later use
    self.params = OrderedDict()
    for key in ['torsions', 'k']:
      self.params[key] = locals()[key]
예제 #31
0
 def __init__(self, obj1, obj2, distance, force_constant,
              nb_exclusion=False):
     """
     :param obj1: the object defining center-of-mass 1
     :type obj1: :class:`~MMTK.Collections.GroupOfAtoms`
     :param obj2: the object defining center-of-mass 2
     :type obj2: :class:`~MMTK.Collections.GroupOfAtoms`
     :param distance: the distance between cm 1 and cm2 at which
                      the restraint is zero
     :type distance: float
     :param force_constant: the force constant of the restraint term.
                            The functional form of the restraint is
                            force_constant*((cm1-cm2).length()-distance)**2,
                            where cm1 and cm2 are the centrer-of-mass
                            positions of the two objects.
     :type force_constant: float
     :param nb_exclussion: if True, non-bonded interactions between
                           the restrained atoms are suppressed, as
                           for a chemical bond
     :type nb_exclussion: bool
     """
     if isinstance(obj1, int) and isinstance(obj2, int):
         # Older MMTK versions admitted only single atoms and
         # stored single indices. Support this mode for opening
         # trajectories made with those versions
         self.atom_indices_1 = [obj1]
         self.atom_indices_2 = [obj2]
     if isChemicalObject(obj1) or isCollection(obj1):
         obj1 = obj1.atomList()
     if isChemicalObject(obj2) or isCollection(obj2):
         obj2 = obj2.atomList()
     self.atom_indices_1 = self.getAtomParameterIndices(obj1)
     self.atom_indices_2 = self.getAtomParameterIndices(obj2)
     if nb_exclusion and (len(self.atom_indices_1) > 1
                          or len(self.atom_indices_2) > 1):
         raise ValueError("Non-bonded exclusion possible only "
                          "between single-atom objects")
     self.arguments = (self.atom_indices_1, self.atom_indices_2,
                       distance, force_constant, nb_exclusion)
     self.distance = distance
     self.force_constant = force_constant
     self.nb_exclusion = nb_exclusion
     ForceField.__init__(self, 'harmonic distance restraint')
예제 #32
0
    def __init__(self, FN, strength, scaling_property, scaling_prefactor=None, grid_name='trilinear transformed grid', max_val=-1.0):
        """
        @param strength: the electric field vector
        @type strength: L{float}
        @scaling_property: the name of the atomic property in the database
                           that is used to retrieve the atomic scaling_factor.
                           The default is 'amber_charge', the charge property
                           for Amber94 and Amber99.
        @type scaling_property: C{str}
        @grid_name: a name for the grid
        @max_val: the maximum allowed value for a point on the grid.
                  A negative value means that there is no max.
        """
        # Store arguments that recreate the force field from a pickled
        # universe or from a trajectory.
        self.arguments = (FN, strength, scaling_property, grid_name, max_val)
        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, grid_name)
        # Store the parameters for later use.
        self.FN = FN
        self.strength = strength
        self.scaling_property = scaling_property
        self.grid_name = grid_name
        self.max_val = max_val
  
        import AlGDock.IO
        IO_Grid = AlGDock.IO.Grid()
        self.grid_data = IO_Grid.read(self.FN, multiplier=0.1)
        if not (self.grid_data['origin']==0.0).all():
          raise Exception('Trilinear grid origin in %s not at (0, 0, 0)!'%self.FN)

        # Make sure all grid values are positive
        n_positive = sum(self.grid_data['vals']>0)
        n_negative = sum(self.grid_data['vals']<0)
        if n_positive>0 and n_negative>0:
          raise Exception('All of the grid points do not have the same sign')
        if n_negative>0:
          self.grid_data['vals'] = -1*self.grid_data['vals']

        if scaling_prefactor is not None:
          self.scaling_prefactor = scaling_prefactor
        else:
          self.scaling_prefactor = -1. if n_negative>0 else 1.
예제 #33
0
파일: PoseFF.py 프로젝트: tiendott/AlGDock
    def __init__(self, torsions, \
                 k = 200.0):
        """
    Internal torsional dofs:
    @param input: [4 atom indices, gamma] x internal dofs
    @type atom:   L{MMTK.ChemicalObjects.Atom.index,
                    MMTK.ChemicalObjects.Atom.index,
                    MMTK.ChemicalObjects.Atom.index,
                    MMTK.ChemicalObjects.Atom.index,
                    double} x # of internal dofs}
    """

        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, 'internal dihedral restraint')

        # Store the parameters for later use
        self.params = OrderedDict()
        for key in ['torsions', 'k']:
            self.params[key] = locals()[key]
예제 #34
0
파일: OBC.py 프로젝트: tiendott/AlGDock
    def __init__(self,
                 prmtopFN=None,
                 inv_prmtop_atom_order=None,
                 desolvationGridFN=None,
                 r_min=0.14,
                 r_max=1.0,
                 strength=1.0):
        """
        @param prmtopFN: an AMBER parameter and topology file
        @type strength:  C{str}
        r_min and r_max should be in units of nanometers
        """
        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, 'OBC')

        # Store arguments that recreate the force field from a pickled
        # universe or from a trajectory.
        self.arguments = (prmtopFN, inv_prmtop_atom_order, \
          desolvationGridFN, r_min, r_max, strength)

        # Load the desolvation grid
        if desolvationGridFN is not None:
            import AlGDock.IO
            IO_Grid = AlGDock.IO.Grid()
            self.grid_data = IO_Grid.read(desolvationGridFN, multiplier=0.1)
            if not (self.grid_data['origin'] == 0.0).all():
                raise Exception(
                    'Trilinear grid origin in %s not at (0, 0, 0)!' % FN)
            self.useDesolvationGrid = True
        else:
            self.grid_data = {'spacing':np.array([0., 0., 0.]), \
                              'counts':np.array([0, 0, 0]), \
                              'vals':np.array([])}
            self.useDesolvationGrid = False

        # Store arguments as class variables
        self.prmtopFN = prmtopFN
        self.inv_prmtop_atom_order = inv_prmtop_atom_order
        self.desolvationGridFN = desolvationGridFN
        self.r_min = r_min
        self.r_max = r_max
        self.strength = strength
예제 #35
0
 def __init__(self, fc_length=0.7, cutoff=1.2, factor=46402.):
     """
     :param fc_length: a range parameter
     :type fc_length: float
     :param cutoff: the cutoff for pair interactions, should be
                    at least 2.5 nm. Pair interactions in periodic
                    systems are calculated using the minimum-image
                    convention; the cutoff should therefore never be
                    larger than half the smallest edge length of the
                    elementary cell.
     :type cutoff: float
     :param factor: a global scaling factor
     :type factor: float
     """
     self.arguments = (fc_length, cutoff, factor)
     ForceField.__init__(self, 'deformation')
     self.arguments = (fc_length, cutoff, factor)
     self.fc_length = fc_length
     self.cutoff = cutoff
     self.factor = factor
예제 #36
0
 def __init__(self, fc_length = 0.7, cutoff = 1.2, factor = 46402.):
     """
     :param fc_length: a range parameter
     :type fc_length: float
     :param cutoff: the cutoff for pair interactions, should be
                    at least 2.5 nm. Pair interactions in periodic
                    systems are calculated using the minimum-image
                    convention; the cutoff should therefore never be
                    larger than half the smallest edge length of the
                    elementary cell.
     :type cutoff: float
     :param factor: a global scaling factor
     :type factor: float
     """
     self.arguments = (fc_length, cutoff, factor)
     ForceField.__init__(self, 'deformation')
     self.arguments = (fc_length, cutoff, factor)
     self.fc_length = fc_length
     self.cutoff = cutoff
     self.factor = factor
예제 #37
0
파일: OBC.py 프로젝트: CCBatIIT/AlGDock
    def __init__(self,
          prmtopFN=None,
          inv_prmtop_atom_order=None,
          desolvationGridFN=None,
          r_min = 0.14,
          r_max = 1.0,
          strength=1.0):
        """
        @param prmtopFN: an AMBER parameter and topology file
        @type strength:  C{str}
        r_min and r_max should be in units of nanometers
        """
        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, 'OBC')

        # Store arguments that recreate the force field from a pickled
        # universe or from a trajectory.
        self.arguments = (prmtopFN, inv_prmtop_atom_order, \
          desolvationGridFN, r_min, r_max, strength)

        # Load the desolvation grid
        if desolvationGridFN is not None:
          import AlGDock.IO
          IO_Grid = AlGDock.IO.Grid()
          self.grid_data = IO_Grid.read(desolvationGridFN, multiplier=0.1)
          if not (self.grid_data['origin']==0.0).all():
            raise Exception('Trilinear grid origin in %s not at (0, 0, 0)!'%FN)
          self.useDesolvationGrid = True
        else:
          self.grid_data = {'spacing':np.array([0., 0., 0.]), \
                            'counts':np.array([0, 0, 0]), \
                            'vals':np.array([])}
          self.useDesolvationGrid = False
        
        # Store arguments as class variables
        self.prmtopFN = prmtopFN
        self.inv_prmtop_atom_order = inv_prmtop_atom_order
        self.desolvationGridFN = desolvationGridFN
        self.r_min = r_min
        self.r_max = r_max
        self.strength = strength
예제 #38
0
 def __init__(self, atom1, atom2, atom3, angle, force_constant):
     """
     :param atom1: first atom
     :type atom1: :class:`~MMTK.ChemicalObjects.Atom`
     :param atom2: second (central) atom
     :type atom2: :class:`~MMTK.ChemicalObjects.Atom`
     :param atom3: third atom
     :type atom3: :class:`~MMTK.ChemicalObjects.Atom`
     :param angle: the angle at which the restraint is zero
     :type angle: float
     :param force_constant: the force constant of the restraint term.
                            The functional form of the restraint is
                            force_constant*(phi-angle)**2, where
                            phi is the angle atom1-atom2-atom3.
     """
     self.index1, self.index2, self.index3 = \
                 self.getAtomParameterIndices((atom1, atom2, atom3))
     self.arguments = (self.index1, self.index2, self.index3, angle,
                       force_constant)
     self.angle = angle
     self.force_constant = force_constant
     ForceField.__init__(self, 'harmonic angle restraint')
예제 #39
0
 def __init__(self, atom1, atom2, atom3, angle, force_constant):
     """
     :param atom1: first atom
     :type atom1: :class:`~MMTK.ChemicalObjects.Atom`
     :param atom2: second (central) atom
     :type atom2: :class:`~MMTK.ChemicalObjects.Atom`
     :param atom3: third atom
     :type atom3: :class:`~MMTK.ChemicalObjects.Atom`
     :param angle: the angle at which the restraint is zero
     :type angle: float
     :param force_constant: the force constant of the restraint term.
                            The functional form of the restraint is
                            force_constant*(phi-angle)**2, where
                            phi is the angle atom1-atom2-atom3.
     """
     self.index1, self.index2, self.index3 = \
                 self.getAtomParameterIndices((atom1, atom2, atom3))
     self.arguments = (self.index1, self.index2, self.index3,
                       angle, force_constant) 
     self.angle = angle
     self.force_constant = force_constant
     ForceField.__init__(self, 'harmonic angle restraint')
예제 #40
0
  def __init__(self, FN,
    name='Interpolation',
    interpolation_type='Trilinear',
    strength=1.0,
    scaling_property='amber_charge',
    scaling_prefactor=None,
    inv_power=None,
    grid_thresh=-1.0,
    energy_thresh=-1.0):
    """
    @FN: the file name.
    @name: a name for the grid
    @interpolation_type: the type of interpolation, which can be
      ['Trilinear','BSpline','CatmullRom', or 'Tricubic'].
    @param strength: scaling factor for all the energies and gradients.
    @type strength: L{float}
    @scaling_property: the name of the atomic property in the database.
      that is used to retrieve the atomic scaling_factor. 
      The default is 'amber_charge'.
    @scaling_prefactor: the atomic scaling_factor is scaled by this value.
    @inv_power: the inverse of the power by which grid points are transformed.
    @grid_thresh: the maximum allowed value for a point on the grid.
      A negative value means that there is no max.
    @energy_thresh: the maximum allowed value for the energy at any point.
      A negative value means that there is no max.
    @type scaling_property: C{str}
    """
    if not interpolation_type in \
        ['Trilinear','BSpline', 'CatmullRom', 'Tricubic']:
      raise Exception('Interpolation type not recognized')

    ForceField.__init__(self, name) # Initialize the ForceField class

    # Store arguments that recreate the force field from a pickled
    # universe or from a trajectory.
    self.arguments = (FN, name, interpolation_type, strength, \
      scaling_property, scaling_prefactor, \
      inv_power, grid_thresh, energy_thresh)
    
    self.params = OrderedDict()
    for key in ['FN','name','interpolation_type','strength','scaling_property',\
        'scaling_prefactor','inv_power','grid_thresh','energy_thresh']:
      self.params[key] = locals()[key]
    
    # Load the grid
    import AlGDock.IO
    IO_Grid = AlGDock.IO.Grid()
    self.grid_data = IO_Grid.read(FN, multiplier=0.1)
    if not (self.grid_data['origin']==0.0).all():
      raise Exception('Trilinear grid origin in %s not at (0, 0, 0)!'%FN)

    # Transform the grid
    neg_vals = False
    if inv_power is not None:
      # Make sure all grid values are positive
      if (self.grid_data['vals']>0).any():
        if (self.grid_data['vals']<0).any():
          raise Exception('All of the grid points do not have the same sign')
      else:
        neg_vals = True
        self.grid_data['vals'] = -1*self.grid_data['vals']

      # Transform all nonzero elements
      nonzero = self.grid_data['vals']!=0
      self.grid_data['vals'][nonzero] = self.grid_data['vals'][nonzero]**(1./inv_power)

    import numpy as np
    # "Cap" the grid values
    if grid_thresh>0.0:
      self.grid_data['vals'] = grid_thresh*np.tanh(self.grid_data['vals']/grid_thresh)

    if scaling_prefactor is None:
      self.params['scaling_prefactor'] = -1. if neg_vals else 1.
예제 #41
0
 def __init__(self, universe):
     self.atoms = map(lambda x: self.getAtomParameterIndices([x])[0],
                      universe.atomList())
     self.arguments = (self.atoms)
     ForceField.__init__(self, 'mbpol_potential')
예제 #42
0
 def __init__(self, name):
     ForceField.__init__(self, name)
     self.type = 'bonded'
예제 #43
0
 def __init__(self, atom1, atom2):
     self.id1, self.id2 = self.getAtomParameterIndices([atom1, atom2])
     self.arguments = (self.id1, self.id2)
     #self.arguments = (self.id1, self.id2, beads)
     # Initialize the ForceField class, giving a name to this one.
     ForceField.__init__(self, 'hehe')
예제 #44
0
    def __init__(self, atom1):
        self.atom_index = self.getAtomParameterIndices([atom1])[0]
        self.arguments = (self.atom_index, )

        # Initialize the ForceField class, giving a name to this one.
        ForceField.__init__(self, 'h2h2o')
예제 #45
0
 def __init__(self, atoms, r_eq, k_r):
     self.atom_indices = map(lambda x: self.getAtomParameterIndices([x])[0],atoms)
     self.r_eq = r_eq
     self.k_r = k_r
     self.arguments = (self.atom_indices,r_eq,k_r)
     ForceField.__init__(self, 'harmonic_bond')
예제 #46
0
    def __init__(self,
                 FN,
                 name='Interpolation',
                 interpolation_type='Trilinear',
                 strength=1.0,
                 scaling_property='amber_charge',
                 scaling_prefactor=None,
                 inv_power=None,
                 grid_thresh=-1.0,
                 energy_thresh=-1.0):
        """
    @FN: the file name.
    @name: a name for the grid
    @interpolation_type: the type of interpolation, which can be
      ['Trilinear','BSpline','CatmullRom', or 'Tricubic'].
    @param strength: scaling factor for all the energies and gradients.
    @type strength: L{float}
    @scaling_property: the name of the atomic property in the database.
      that is used to retrieve the atomic scaling_factor. 
      The default is 'amber_charge'.
    @scaling_prefactor: the atomic scaling_factor is scaled by this value.
    @inv_power: the inverse of the power by which grid points are transformed.
    @grid_thresh: the maximum allowed value for a point on the grid.
      A negative value means that there is no max.
    @energy_thresh: the maximum allowed value for the energy at any point.
      A negative value means that there is no max.
    @type scaling_property: C{str}
    """
        if not interpolation_type in \
            ['Trilinear','BSpline', 'CatmullRom', 'Tricubic']:
            raise Exception('Interpolation type not recognized')

        ForceField.__init__(self, name)  # Initialize the ForceField class

        # Store arguments that recreate the force field from a pickled
        # universe or from a trajectory.
        self.arguments = (FN, name, interpolation_type, strength, \
          scaling_property, scaling_prefactor, \
          inv_power, grid_thresh, energy_thresh)

        self.params = OrderedDict()
        for key in ['FN','name','interpolation_type','strength','scaling_property',\
            'scaling_prefactor','inv_power','grid_thresh','energy_thresh']:
            self.params[key] = locals()[key]

        # Load the grid
        import AlGDock.IO
        IO_Grid = AlGDock.IO.Grid()
        self.grid_data = IO_Grid.read(FN, multiplier=0.1)
        if not (self.grid_data['origin'] == 0.0).all():
            raise Exception('Trilinear grid origin in %s not at (0, 0, 0)!' %
                            FN)

        # Transform the grid
        neg_vals = False
        if inv_power is not None:
            # Make sure all grid values are positive
            if (self.grid_data['vals'] > 0).any():
                if (self.grid_data['vals'] < 0).any():
                    raise Exception(
                        'All of the grid points do not have the same sign')
            else:
                neg_vals = True
                self.grid_data['vals'] = -1 * self.grid_data['vals']

            # Transform all nonzero elements
            nonzero = self.grid_data['vals'] != 0
            self.grid_data['vals'][nonzero] = self.grid_data['vals'][
                nonzero]**(1. / inv_power)

        import numpy as np
        # "Cap" the grid values
        if grid_thresh > 0.0:
            self.grid_data['vals'] = grid_thresh * np.tanh(
                self.grid_data['vals'] / grid_thresh)

        if scaling_prefactor is not None:
            self.params['scaling_prefactor'] = scaling_prefactor
        else:
            self.params['scaling_prefactor'] = -1. if neg_vals else 1.
예제 #47
0
 def __init__(self, name):
     ForceField.__init__(self, name)
     self.type = 'nonbonded'
예제 #48
0
 def __init__(self, atoms, theta_eq, k_theta):
     self.atom_indices = map(lambda x: self.getAtomParameterIndices([x])[0],atoms)
     self.theta_eq = theta_eq
     self.k_theta = k_theta
     self.arguments = (self.atom_indices,theta_eq,k_theta)
     ForceField.__init__(self, 'harmonic_angle')