IMP logo
IMP Reference Guide  develop.562c2f4da8,2025/03/14
The Integrative Modeling Platform
atom/charmm_forcefield_verbose.py

In this example, a PDB file is read in and scored using the CHARMM forcefield. It is similar to the 'charmm_forcefield.py' example, but fully works through each step of the procedure using lower-level IMP classes. This is useful if you want to customize the way in which the forcefield is applied.

1 ## \example atom/charmm_forcefield_verbose.py
2 # In this example, a PDB file is read in and scored using the CHARMM
3 # forcefield. It is similar to the 'charmm_forcefield.py' example, but fully
4 # works through each step of the procedure using lower-level IMP classes.
5 # This is useful if you want to customize the way in which the forcefield
6 # is applied.
7 #
8 
9 import IMP.atom
10 import IMP.container
11 import sys
12 
13 IMP.setup_from_argv(sys.argv, "CHARMM forcefield verbose")
14 
15 # Create an IMP model and add a heavy atom-only protein from a PDB file
16 m = IMP.Model()
17 prot = IMP.atom.read_pdb(IMP.atom.get_example_path("example_protein.pdb"), m,
19 
20 # Read in the CHARMM heavy atom topology and parameter files
22 
23 # Using the CHARMM libraries, determine the ideal topology (atoms and their
24 # connectivity) for the PDB file's primary sequence
25 topology = ff.create_topology(prot)
26 
27 # Typically this modifies the C and N termini of each chain in the protein by
28 # applying the CHARMM CTER and NTER patches. Patches can also be manually
29 # applied at this point, e.g. to add disulfide bridges.
30 topology.apply_default_patches()
31 
32 # Each atom is mapped to its CHARMM type. These are needed to look up bond
33 # lengths, Lennard-Jones radii etc. in the CHARMM parameter file. Atom types
34 # can also be manually assigned at this point using the CHARMMAtom decorator.
35 topology.add_atom_types(prot)
36 
37 # Remove any atoms that are in the PDB file but not in the topology, and add
38 # in any that are in the topology but not the PDB.
40 topology.add_missing_atoms(prot)
41 
42 # Construct Cartesian coordinates for any atoms that were added
43 topology.add_coordinates(prot)
44 
45 # Generate and return lists of bonds, angles, dihedrals and impropers for
46 # the protein. Each is a Particle in the model which defines the 2, 3 or 4
47 # atoms that are bonded, and adds parameters such as ideal bond length
48 # and force constant. Note that bonds and impropers are explicitly listed
49 # in the CHARMM topology file, while angles and dihedrals are generated
50 # automatically from an existing set of bonds. These particles only define the
51 # bonds, but do not score them or exclude them from the nonbonded list.
52 bonds = topology.add_bonds(prot)
53 angles = ff.create_angles(bonds)
54 dihedrals = ff.create_dihedrals(bonds)
55 impropers = topology.add_impropers(prot)
56 
57 # Maintain stereochemistry by scoring bonds, angles, dihedrals and impropers
58 
59 # Score all of the bonds. This is done by combining IMP 'building blocks':
60 # - A ListSingletonContainer simply manages a list of the bond particles.
61 # - A BondSingletonScore, when given a bond particle, scores the bond by
62 # calculating the distance between the two atoms it bonds, subtracting the
63 # ideal value, and weighting the result by the bond's "stiffness", such that
64 # an "ideal" bond scores zero, and bonds away from equilibrium score
65 # non-zero. It then hands off to a UnaryFunction to actually penalize the
66 # value. In this case, a Harmonic UnaryFunction is used with a mean of zero,
67 # so that bond lengths are harmonically restrained.
68 # - A SingletonsRestraint simply goes through each of the bonds in the
69 # container and scores each one in turn.
70 cont = IMP.container.ListSingletonContainer(m, bonds, "bonds")
72 r = IMP.container.SingletonsRestraint(bss, cont, "bonds")
73 rs = [r]
74 
75 # Score angles, dihedrals, and impropers. In the CHARMM forcefield, angles and
76 # impropers are harmonically restrained, so this is the same as for bonds.
77 # Dihedrals are scored internally by a periodic (cosine) function.
78 cont = IMP.container.ListSingletonContainer(m, angles, "angles")
80 r = IMP.container.SingletonsRestraint(bss, cont, "angles")
81 rs.append(r)
82 
83 cont = IMP.container.ListSingletonContainer(m, dihedrals, "dihedrals")
85 r = IMP.container.SingletonsRestraint(bss, cont, "dihedrals")
86 rs.append(r)
87 
88 cont = IMP.container.ListSingletonContainer(m, impropers, "impropers")
90 rs.append(IMP.container.SingletonsRestraint(bss, cont, "improppers"))
91 
92 # Add radii from the forcefield, used for close pairs calculation
93 ff.add_radii(prot)
94 
95 # Add non-bonded interaction (in this case, Lennard-Jones). This needs to
96 # know the Lennard-Jones types for all atoms (which in turn define the radius
97 # and well depth), so add them from the forcefield (they can also be assigned
98 # manually using the LennardJonesType decorator):
99 ff.add_lennard_jones_types(prot)
100 
101 # Get a list of all atoms in the protein, and put it in a container
102 atoms = IMP.atom.get_by_type(prot, IMP.atom.ATOM_TYPE)
104 
105 # Add a restraint for the Lennard-Jones interaction. Again, this is built from
106 # a collection of building blocks. First, a ClosePairContainer maintains a list
107 # of all pairs of Particles that are close. A StereochemistryPairFilter is used
108 # to exclude atoms from this list that are bonded to each other or are involved
109 # in an angle or dihedral (1-3 or 1-4 interaction). Then, a
110 # LennardJonesTypedPairScore scores a pair of atoms with the
111 # Lennard-Jones potential, using the Lennard-Jones types already assigned.
112 # Finally, a PairsRestraint is used which simply applies the
113 # LennardJonesTypedPairScore to each pair in the ClosePairContainer.
114 nbl = IMP.container.ClosePairContainer(cont, 4.0)
116 pair_filter.set_bonds(bonds)
117 pair_filter.set_angles(angles)
118 pair_filter.set_dihedrals(dihedrals)
119 nbl.add_pair_filter(pair_filter)
120 
121 sf = IMP.atom.ForceSwitch(6.0, 7.0)
123 rs.append(IMP.container.PairsRestraint(ps, nbl))
124 
125 score_func = IMP.core.RestraintsScoringFunction(rs)
126 
127 # it gets awfully slow with internal checks
128 IMP.set_check_level(IMP.USAGE)
129 
130 # Finally, evaluate the score of the whole system (without derivatives)
131 print(score_func.evaluate(False))