Skip to content

Commit dff1fb7

Browse files
authored
Merge pull request #175 from CCPBioSim/172-coordinates-and-forces-in-separate-files
Add Support for Calculating Entropy When Forces and Coordinates Are Within Seperate Files
2 parents 17b5abd + c247cbb commit dff1fb7

File tree

7 files changed

+260
-35
lines changed

7 files changed

+260
-35
lines changed

CodeEntropy/config/arg_config_manager.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,22 @@
1212
"top_traj_file": {
1313
"type": str,
1414
"nargs": "+",
15-
"help": "Path to Structure/topology file followed by Trajectory file(s)",
15+
"help": "Path to structure/topology file followed by trajectory file",
16+
},
17+
"force_file": {
18+
"type": str,
19+
"default": None,
20+
"help": "Optional path to force file if forces are not in trajectory file",
21+
},
22+
"file_format": {
23+
"type": str,
24+
"default": None,
25+
"help": "String for file format as recognised by MDAnalysis",
26+
},
27+
"kcal_force_units": {
28+
"type": bool,
29+
"default": False,
30+
"help": "Set this to True if you have a separate force file with nonSI units.",
1631
},
1732
"selection_string": {
1833
"type": str,

CodeEntropy/entropy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def execute(self):
8686
)
8787

8888
reduced_atom, number_molecules, levels, groups = self._initialize_molecules()
89-
89+
logger.debug(f"Universe 3: {reduced_atom}")
9090
water_atoms = self._universe.select_atoms("water")
9191
water_resids = set(res.resid for res in water_atoms.residues)
9292

CodeEntropy/run.py

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,43 @@ def run_entropy_workflow(self):
247247
# Load MDAnalysis Universe
248248
tprfile = args.top_traj_file[0]
249249
trrfile = args.top_traj_file[1:]
250+
fileformat = args.file_format
250251
logger.debug(f"Loading Universe with {tprfile} and {trrfile}")
251-
u = mda.Universe(tprfile, trrfile)
252+
u = mda.Universe(tprfile, trrfile, format=fileformat)
253+
254+
# If forces are in separate file merge them with the
255+
# coordinates from the trajectory file
256+
forcefile = args.force_file
257+
if forcefile is not None:
258+
logger.debug(f"Loading Universe with {forcefile}")
259+
u_force = mda.Universe(tprfile, forcefile, format=fileformat)
260+
select_atom = u.select_atoms("all")
261+
select_atom_force = u_force.select_atoms("all")
262+
263+
coordinates = (
264+
AnalysisFromFunction(
265+
lambda ag: ag.positions.copy(), select_atom
266+
)
267+
.run()
268+
.results["timeseries"]
269+
)
270+
forces = (
271+
AnalysisFromFunction(
272+
lambda ag: ag.positions.copy(), select_atom_force
273+
)
274+
.run()
275+
.results["timeseries"]
276+
)
277+
278+
if args.kcal_force_units:
279+
# Convert from kcal to kJ
280+
forces *= 4.184
281+
282+
logger.debug("Merging forces with coordinates universe.")
283+
new_universe = mda.Merge(select_atom)
284+
new_universe.load_new(coordinates, forces=forces)
285+
286+
u = new_universe
252287

253288
self._config_manager.input_parameters_validation(u, args)
254289

@@ -311,15 +346,8 @@ def new_U_select_frame(self, u, start=None, end=None, step=1):
311346
.run()
312347
.results["timeseries"][start:end:step]
313348
)
314-
dimensions = (
315-
AnalysisFromFunction(lambda ag: ag.dimensions.copy(), select_atom)
316-
.run()
317-
.results["timeseries"][start:end:step]
318-
)
319349
u2 = mda.Merge(select_atom)
320-
u2.load_new(
321-
coordinates, format=MemoryReader, forces=forces, dimensions=dimensions
322-
)
350+
u2.load_new(coordinates, format=MemoryReader, forces=forces)
323351
logger.debug(f"MDAnalysis.Universe - reduced universe: {u2}")
324352
return u2
325353

@@ -351,15 +379,8 @@ def new_U_select_atom(self, u, select_string="all"):
351379
.run()
352380
.results["timeseries"]
353381
)
354-
dimensions = (
355-
AnalysisFromFunction(lambda ag: ag.dimensions.copy(), select_atom)
356-
.run()
357-
.results["timeseries"]
358-
)
359382
u2 = mda.Merge(select_atom)
360-
u2.load_new(
361-
coordinates, format=MemoryReader, forces=forces, dimensions=dimensions
362-
)
383+
u2.load_new(coordinates, format=MemoryReader, forces=forces)
363384
logger.debug(f"MDAnalysis.Universe - reduced universe: {u2}")
364385
return u2
365386

docs/config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
run1:
44
top_traj_file: ["1AKI_prod.tpr", "1AKI_prod.trr"]
5+
force_file:
6+
file_formate:
57
selection_string: 'all'
68
start: 0
79
end: 500

docs/faq.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,15 @@ Frequently asked questions
44
Why do I get a ``WARNING`` about invalid eigenvalues?
55
-----------------------------------------------------
66

7-
Insufficient sampling might introduce noise and cause matrix elements to deviate to values that would not reflect the uncorrelated nature of force-force covariance of distantly positioned residues.Try increasing the sampling time. This is especially true at the residue level.
7+
Insufficient sampling might introduce noise and cause matrix elements to deviate to values that would not reflect the uncorrelated nature of force-force covariance of distantly positioned residues.
8+
Try increasing the sampling time.
9+
This is especially true at the residue level.
810

911
For example in a lysozyme system, the residue level contains the largest force and torque covariance matrices because at this level we have the largest number of beads (which is equal to the number of residues in a protein) compared to the molecule level (3 beads) and united-atom level (~10 beads per amino acid).
1012

13+
What do I do if there is an error from MDAnalysis not recognising the file type?
14+
-------------------------------------------------------------------------------
15+
16+
Use the file_format option.
17+
The MDAnalysis documentation has a list of acceptable formats: https://userguide.mdanalysis.org/1.1.1/formats/index.html#id1.
18+
The first column of their table gives you the string you need (case sensitive).

docs/getting_started.rst

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,18 @@ The top_traj_file argument is necessary to identify your simulation data, the ot
8181
- Description
8282
- Default
8383
- Type
84-
* - ``--top_traj_file``
85-
- Path to Structure/topology file followed by Trajectory file(s). Any MDAnalysis readable files should work (for example ``GROMACS TPR and TRR`` or ``AMBER PRMTOP and NETCDF``). You will need to output the **coordinates** and **forces** to the **same file** .
84+
* - ``--top_traj_file``
85+
- Path to Structure/topology file followed by Trajectory file. Any MDAnalysis readable files should work (for example ``GROMACS TPR and TRR`` or ``AMBER PRMTOP and NETCDF``).
8686
- Required, no default value
8787
- list of ``str``
88+
* - ``--force_file``
89+
- Path to a file with forces. This option should be used if the forces are not in the same file as the coordinates. It is expected that the force file has the same number of atoms and frames as the trajectory file. Any MDAnalysis readable files should work (for example ``AMBER NETCDF`` or ``LAMMPS DCD``).
90+
- None
91+
- ``str``
92+
* - ``--file_format``
93+
- Use to tell MDAnalysis the format if the trajectory or force file does not have the standard extension recognised by MDAnalysis.
94+
- None
95+
- ``str``
8896
* - ``--selection_string``
8997
- Selection string for CodeEntropy such as protein or resid, refer to ``MDAnalysis.select_atoms`` for more information.
9098
- ``"all"``: select all atom in trajectory

0 commit comments

Comments
 (0)