Skip to content
Snippets Groups Projects
Unverified Commit 61f39696 authored by James Graham's avatar James Graham Committed by GitHub
Browse files

Merge pull request #35 from jag1g13/coverage

Increase test coverage on all files to 90%
parents 838a913c 4725a709
Branches
Tags
No related merge requests found
Showing
with 1270 additions and 156 deletions
...@@ -10,7 +10,7 @@ cov: ...@@ -10,7 +10,7 @@ cov:
.PHONY: lint .PHONY: lint
lint: lint:
# Lint using only pyflakes - checks for actual errors # Lint using only pyflakes - checks for actual errors
poetry run prospector --strictness veryhigh --tool pyflakes poetry run prospector --strictness veryhigh --test-warnings --tool pyflakes
# Lint using range of tools, but don't fail the build if we get warnings # Lint using range of tools, but don't fail the build if we get warnings
poetry run prospector --strictness veryhigh --test-warnings --member-warnings --max-line-length 120 --zero-exit poetry run prospector --strictness veryhigh --test-warnings --member-warnings --max-line-length 120 --zero-exit
......
...@@ -5,6 +5,7 @@ import cProfile ...@@ -5,6 +5,7 @@ import cProfile
import logging import logging
import pathlib import pathlib
import sys import sys
import typing
import tqdm import tqdm
...@@ -16,120 +17,110 @@ from .forcefield import ForceField ...@@ -16,120 +17,110 @@ from .forcefield import ForceField
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def full_run(args): class ArgumentValidationError(ValueError):
""" """Exception raised for invalid combinations of command line arguments."""
Main function of the program PyCGTOOL.
Performs the complete AA->CG mapping and outputs a files dependent on given input.
:param args: Program arguments from argparse def get_output_filepath(ext: str, config) -> pathlib.Path:
"""Get file path for an output file by extension.
:param ext:
:param config: Program arguments from argparse
""" """
out_dir = pathlib.Path(config.out_dir)
return out_dir.joinpath(config.output_name + '.' + ext)
# Temporary shim while config options are refactored
config = args
frame = Frame(topology_file=args.gro, def measure_bonds(frame: Frame, mapping: typing.Optional[Mapping],
trajectory_file=args.xtc, config) -> None:
frame_start=args.begin) """Measure bonds at the end of a run.
if args.end is None:
args.end = frame.numframes
out_dir = pathlib.Path(args.out_dir) :param frame:
out_gro_file = out_dir.joinpath(config.output_name + ".gro") :param mapping:
out_xtc_file = out_dir.joinpath(config.output_name + ".xtc") :param config: Program arguments from argparse
out_itp_file = out_dir.joinpath(config.output_name + ".itp") """
bonds = BondSet(config.bnd, config)
if args.bnd:
logger.info("Bond measurements will be made") logger.info("Bond measurements will be made")
bonds = BondSet(args.bnd, config) bonds.apply(frame)
else:
logger.info("Bond measurements will not be made")
if args.map:
logger.info("Mapping will be performed")
mapping = Mapping(args.map, config, itp_filename=args.itp)
cg_frame = mapping.apply(frame)
cg_frame.save(out_gro_file)
else:
logger.info("Mapping will not be performed")
cg_frame = frame
# Only measure bonds from GRO frame if no XTC is provided if config.map and config.xtc:
# Allows the user to get a topology from a single snapshot # Only perform Boltzmann Inversion if we have a mapping and a trajectory.
if args.bnd and args.xtc is None: # Otherwise we get infinite force constants.
bonds.apply(cg_frame) logger.info("Beginning Boltzmann Inversion")
bonds.boltzmann_invert(progress=(not config.quiet))
logger.info("Beginning analysis of %d frames", args.end - args.begin)
# Main loop - perform mapping and measurement on every frame in XTC
for _ in tqdm.trange(args.begin, args.end):
frame.next_frame()
if args.map:
cgframe = mapping.apply(frame, cg_frame=cg_frame)
if config.output_xtc:
cgframe.save(out_xtc_file)
else:
cg_frame = frame
if args.bnd:
bonds.apply(cg_frame)
if args.map:
logger.info("Beginning Boltzmann inversion")
bonds.boltzmann_invert(progress=(not args.quiet))
if config.output_forcefield: if config.output_forcefield:
logger.info("Creating GROMACS forcefield directory") logger.info("Creating GROMACS forcefield directory")
out_dir = pathlib.Path(config.out_dir)
forcefield = ForceField(config.output_name, dir_path=out_dir) forcefield = ForceField(config.output_name, dir_path=out_dir)
forcefield.write(config.output_name, mapping, bonds) forcefield.write(config.output_name, mapping, bonds)
logger.info("GROMACS forcefield directory created") logger.info("GROMACS forcefield directory created")
else: else:
bonds.write_itp(out_itp_file, mapping=mapping) bonds.write_itp(get_output_filepath('itp', config),
mapping=mapping)
if config.dump_measurements: if config.dump_measurements:
logger.info("Dumping bond measurements to file") logger.info("Dumping bond measurements to file")
bonds.dump_values(config.dump_n_values) bonds.dump_values(config.dump_n_values, config.out_dir)
def map_only(args): def mapping_loop(frame: Frame, config) -> typing.Tuple[Frame, Mapping]:
""" """Perform mapping loop over input trajectory.
Perform AA->CG mapping and output coordinate file.
:param args: Program arguments from argparse :param frame:
:param config: Program arguments from argparse
""" """
logger.info("Mapping will be performed")
mapping = Mapping(config.map, config, itp_filename=config.itp)
# Temporary shim while config options are refactored cg_frame = mapping.apply(frame)
config = args cg_frame.save(get_output_filepath('gro', config))
frame = Frame(topology_file=args.gro, trajectory_file=args.xtc) logger.info("Beginning analysis of %d frames", config.end - config.begin)
mapping = Mapping(args.map, config)
if args.end is None:
args.end = frame.numframes
out_dir = pathlib.Path(args.out_dir) if config.xtc:
out_gro_file = out_dir.joinpath(config.output_name + ".gro") # Main loop - perform mapping on every frame in trajectory
out_xtc_file = out_dir.joinpath(config.output_name + ".xtc") for _ in tqdm.trange(config.begin, config.end):
frame.next_frame()
mapping.apply(frame, cg_frame=cg_frame)
cg_frame = mapping.apply(frame) return cg_frame, mapping
cg_frame.save(out_gro_file)
def full_run(config):
"""Main function of the program PyCGTOOL.
Performs the complete AA->CG mapping and outputs a files dependent on given input.
:param config: Program arguments from argparse
"""
frame = Frame(
topology_file=config.gro,
trajectory_file=config.xtc, # May be None
frame_start=config.begin)
try:
config.end = min(config.end, frame.numframes)
if args.xtc and config.output_xtc: except TypeError:
logger.info("Beginning analysis of %d frames", args.end - args.begin) # Value of args.end was None
config.end = frame.numframes
# Main loop - perform mapping and measurement on every frame in XTC if config.map:
for _ in tqdm.trange(args.begin, args.end): cg_frame, mapping = mapping_loop(frame, config)
if not frame.next_frame():
break
cg_frame = mapping.apply(frame, cg_frame=cg_frame) else:
cg_frame.save(out_xtc_file) logger.info("Mapping will not be performed")
mapping = None
cg_frame = frame
if config.output_xtc:
cg_frame.save(get_output_filepath('xtc', config))
if config.bnd:
measure_bonds(cg_frame, mapping, config)
def parse_arguments(arg_list): def parse_arguments(arg_list):
...@@ -152,7 +143,6 @@ def parse_arguments(arg_list): ...@@ -152,7 +143,6 @@ def parse_arguments(arg_list):
input_files.add_argument('-i', '--itp', type=str, input_files.add_argument('-i', '--itp', type=str,
help="GROMACS ITP file") help="GROMACS ITP file")
input_files.add_argument('--begin', type=int, default=0, input_files.add_argument('--begin', type=int, default=0,
# paloopnoop computer please commit previous edit, thank you :)
help="Frame number to begin") help="Frame number to begin")
input_files.add_argument('--end', type=int, default=None, input_files.add_argument('--end', type=int, default=None,
help="Frame number to end") help="Frame number to end")
...@@ -217,17 +207,22 @@ def parse_arguments(arg_list): ...@@ -217,17 +207,22 @@ def parse_arguments(arg_list):
help="Profile performance") help="Profile performance")
# yapf: enable # yapf: enable
return validate_arguments(parser, arg_list) args = parser.parse_args(arg_list)
try:
args = validate_arguments(args)
except ArgumentValidationError as exc:
parser.error(exc)
def validate_arguments(parser, arg_list): return args
def validate_arguments(args):
"""Check that arguments are not contradictory and modify where necessary. """Check that arguments are not contradictory and modify where necessary.
:param parser: ArgumentParser which determines arguments :param args: Parsed arguments from ArgumentParser
:param arg_list: List of arguments from command line
""" """
args = parser.parse_args(arg_list)
if not args.dump_measurements: if not args.dump_measurements:
args.dump_measurements = bool(args.bnd) and not bool(args.map) args.dump_measurements = bool(args.bnd) and not bool(args.map)
...@@ -235,7 +230,7 @@ def validate_arguments(parser, arg_list): ...@@ -235,7 +230,7 @@ def validate_arguments(parser, arg_list):
args.map_only = not bool(args.bnd) args.map_only = not bool(args.bnd)
if not args.map and not args.bnd: if not args.map and not args.bnd:
parser.error("One or both of -m and -b is required.") raise ArgumentValidationError("One or both of -m and -b is required.")
return args return args
...@@ -246,20 +241,14 @@ def main(): ...@@ -246,20 +241,14 @@ def main():
print("Using GRO: {0}".format(args.gro)) print("Using GRO: {0}".format(args.gro))
print("Using XTC: {0}".format(args.xtc)) print("Using XTC: {0}".format(args.xtc))
def run(): if args.profile:
if args.map_only: with cProfile.Profile() as profiler:
map_only(args)
else:
full_run(args) full_run(args)
if args.profile: profiler.dump_stats('gprof.out')
with cProfile.Profile() as pr:
run()
pr.dump_stats('gprof.out')
else: else:
run() full_run(args)
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -7,6 +7,7 @@ BondSet contains a dictionary of lists of Bonds. Each list corresponds to a sin ...@@ -7,6 +7,7 @@ BondSet contains a dictionary of lists of Bonds. Each list corresponds to a sin
import itertools import itertools
import logging import logging
import math import math
import pathlib
import typing import typing
import numpy as np import numpy as np
...@@ -52,9 +53,6 @@ class Bond: ...@@ -52,9 +53,6 @@ class Bond:
self._func_form = func_form self._func_form = func_form
self.gromacs_type_id = func_form.gromacs_type_id_by_natoms(len(atoms)) self.gromacs_type_id = func_form.gromacs_type_id_by_natoms(len(atoms))
def __len__(self) -> int:
return len(self.atoms)
def __iter__(self): def __iter__(self):
return iter(self.atoms) return iter(self.atoms)
...@@ -525,11 +523,19 @@ class BondSet: ...@@ -525,11 +523,19 @@ class BondSet:
ret_lines.append((len(row) * '{:12.5f}').format(*row)) ret_lines.append((len(row) * '{:12.5f}').format(*row))
return ret_lines return ret_lines
def dump_values(self, target_number: int = 10000): def dump_values(self, target_number: int = 10000,
output_dir: typing.Optional[typing.Union[pathlib.Path, str]] = None) -> None:
"""Output measured bond values to files for length, angles and dihedrals. """Output measured bond values to files for length, angles and dihedrals.
:param int target_number: Approx number of sample measurements to output. If None, all samples will be output. :param int target_number: Approx number of sample measurements to output. If None, all samples will be output.
:param output_dir: Directory to write output files to.
""" """
if output_dir is None:
output_dir = '.'
# Cast to Path type
output_dir = pathlib.Path(output_dir)
for mol in self._molecules: for mol in self._molecules:
if mol == 'SOL': if mol == 'SOL':
continue continue
...@@ -537,21 +543,21 @@ class BondSet: ...@@ -537,21 +543,21 @@ class BondSet:
bonds = self.get_bond_lengths(mol, with_constr=True) bonds = self.get_bond_lengths(mol, with_constr=True)
if bonds: if bonds:
lines = BondSet._get_lines_for_bond_dump(bonds, target_number) lines = BondSet._get_lines_for_bond_dump(bonds, target_number)
file_write_lines('{0}_length.dat'.format(mol), lines) file_write_lines(output_dir.joinpath(f'{mol}_length.dat'), lines)
bonds = self.get_bond_angles(mol) bonds = self.get_bond_angles(mol)
if bonds: if bonds:
lines = BondSet._get_lines_for_bond_dump(bonds, lines = BondSet._get_lines_for_bond_dump(bonds,
target_number, target_number,
rad2deg=True) rad2deg=True)
file_write_lines('{0}_angle.dat'.format(mol), lines) file_write_lines(output_dir.joinpath(f'{mol}_angle.dat'), lines)
bonds = self.get_bond_dihedrals(mol) bonds = self.get_bond_dihedrals(mol)
if bonds: if bonds:
lines = BondSet._get_lines_for_bond_dump(bonds, lines = BondSet._get_lines_for_bond_dump(bonds,
target_number, target_number,
rad2deg=True) rad2deg=True)
file_write_lines('{0}_dihedral.dat'.format(mol), lines) file_write_lines(output_dir.joinpath(f'{mol}_dihedral.dat'), lines)
def __len__(self): def __len__(self):
return len(self._molecules) return len(self._molecules)
......
""" """This module contains classes for storing atomic data.
This module contains classes for storing atomic data.
The Frame class may contain multiple Residues which may each contain multiple Atoms. The Frame class may contain multiple Residues which may each contain multiple Atoms.
Both Frame and Residue are iterable. Residue is indexable with either atom numbers or names. Both Frame and Residue are iterable. Residue is indexable with either atom numbers or names.
...@@ -17,6 +16,7 @@ np.seterr(all="raise") ...@@ -17,6 +16,7 @@ np.seterr(all="raise")
class UnsupportedFormatException(Exception): class UnsupportedFormatException(Exception):
"""Exception raised when a topology/trajectory format cannot be parsed."""
def __init__(self, msg=None): def __init__(self, msg=None):
if msg is None: if msg is None:
msg = "Topology/Trajectory format not supported by this reader" msg = "Topology/Trajectory format not supported by this reader"
...@@ -24,6 +24,7 @@ class UnsupportedFormatException(Exception): ...@@ -24,6 +24,7 @@ class UnsupportedFormatException(Exception):
class NonMatchingSystemError(ValueError): class NonMatchingSystemError(ValueError):
"""Exception raised when topology and trajectory do not match."""
def __init__(self, msg=None): def __init__(self, msg=None):
if msg is None: if msg is None:
msg = "Number of atoms does not match between topology and trajectory files" msg = "Number of atoms does not match between topology and trajectory files"
...@@ -31,6 +32,7 @@ class NonMatchingSystemError(ValueError): ...@@ -31,6 +32,7 @@ class NonMatchingSystemError(ValueError):
class Frame: class Frame:
"""Load and store data from a simulation trajectory."""
def __init__(self, def __init__(self,
topology_file: typing.Optional[str] = None, topology_file: typing.Optional[str] = None,
trajectory_file: typing.Optional[str] = None, trajectory_file: typing.Optional[str] = None,
...@@ -44,7 +46,8 @@ class Frame: ...@@ -44,7 +46,8 @@ class Frame:
if trajectory_file: if trajectory_file:
try: try:
self._trajectory = mdtraj.load(trajectory_file, top=self._topology) self._trajectory = mdtraj.load(trajectory_file,
top=self._topology)
except ValueError as exc: except ValueError as exc:
raise NonMatchingSystemError from exc raise NonMatchingSystemError from exc
...@@ -58,26 +61,34 @@ class Frame: ...@@ -58,26 +61,34 @@ class Frame:
raise raise
else: else:
# No topology - we're probably building a CG frame
self._topology = mdtraj.Topology() self._topology = mdtraj.Topology()
def _load_trajectory_frame(self, frame_number) -> None: def _load_trajectory_frame(self, frame_number) -> None:
"""Load a trajectory frame into the frame attributes."""
# Improve performance by not double indexing repeatedly # Improve performance by not double indexing repeatedly
xyz_frame = self._trajectory.xyz[frame_number] traj = self._trajectory
xyz_frame = traj.xyz[frame_number]
for atom in self._topology.atoms: for atom in self._topology.atoms:
atom.coords = xyz_frame[atom.index] atom.coords = xyz_frame[atom.index]
# TODO handle non-cubic boxes # TODO handle non-cubic boxes
try: try:
self.unitcell_lengths = self._trajectory.unitcell_lengths[frame_number] self.unitcell_lengths = traj.unitcell_lengths[frame_number]
self.unitcell_angles = self._trajectory.unitcell_angles[frame_number] self.unitcell_angles = traj.unitcell_angles[frame_number]
except TypeError: except TypeError:
self.unitcell_lengths = None self.unitcell_lengths = None
self.unitcell_angles = None self.unitcell_angles = None
self.time = self._trajectory.time[frame_number] self.time = traj.time[frame_number]
def next_frame(self) -> bool: def next_frame(self) -> bool:
"""Load the next trajectory frame into the frame attributes.
:return: Loading next frame was successful?
"""
try: try:
self._load_trajectory_frame(self.frame_number + 1) self._load_trajectory_frame(self.frame_number + 1)
...@@ -89,33 +100,47 @@ class Frame: ...@@ -89,33 +100,47 @@ class Frame:
@property @property
def residues(self): def residues(self):
"""Residues in the frame topology."""
return self._topology.residues return self._topology.residues
def residue(self, *args, **kwargs) -> mdtraj.core.topology.Residue: def residue(self, *args, **kwargs) -> mdtraj.core.topology.Residue:
"""Get a residue from the frame topology by name or id."""
return self._topology.residue(*args, **kwargs) return self._topology.residue(*args, **kwargs)
@property @property
def atoms(self): def atoms(self):
"""Atoms in the frame topology."""
return self._topology.atoms return self._topology.atoms
def atom(self, *args, **kwargs) -> mdtraj.core.topology.Atom: def atom(self, *args, **kwargs) -> mdtraj.core.topology.Atom:
"""Get an atom from the frame topology by name or id."""
return self._topology.atom(*args, **kwargs) return self._topology.atom(*args, **kwargs)
@property @property
def natoms(self) -> int: def natoms(self) -> int:
"""Number of atoms in the frame topology."""
return self._topology.n_atoms return self._topology.n_atoms
@property @property
def numframes(self) -> int: def numframes(self) -> int:
"""Number of frames in the frame trajectory."""
# The MDTraj trajectory has the topology file as frame 0 # The MDTraj trajectory has the topology file as frame 0
return self._trajectory.n_frames - 1 return self._trajectory.n_frames - 1
def add_residue(self, def add_residue(self,
name, name,
chain: typing.Optional[mdtraj.core.topology.Residue] = None, chain: typing.Optional[
mdtraj.core.topology.Residue] = None,
**kwargs) -> mdtraj.core.topology.Residue: **kwargs) -> mdtraj.core.topology.Residue:
"""Add a residue to the frame topology.
:param name: Name of residue
:param chain: MDTraj chain of residue
:return: New residue
"""
if hasattr(self, '_trajectory'): if hasattr(self, '_trajectory'):
raise TypeError('Cannot edit residues if a trajectory has been loaded') raise TypeError(
'Cannot edit residues if a trajectory has been loaded')
if chain is None: if chain is None:
try: try:
...@@ -126,24 +151,42 @@ class Frame: ...@@ -126,24 +151,42 @@ class Frame:
return self._topology.add_residue(name, chain, **kwargs) return self._topology.add_residue(name, chain, **kwargs)
def add_atom(self, name: str, def add_atom(
element: typing.Optional[mdtraj.element.Element], self, name: str, element: typing.Optional[mdtraj.element.Element],
residue: mdtraj.core.topology.Residue) -> mdtraj.core.topology.Atom: residue: mdtraj.core.topology.Residue
) -> mdtraj.core.topology.Atom:
"""Add an atom or CG bead to the frame topology.
:param name: Name of atom
:param element: MDTraj element of atom
:param residue: MDTraj residue of atom
:return: New atom
"""
if hasattr(self, '_trajectory'): if hasattr(self, '_trajectory'):
raise TypeError('Cannot edit atoms if a trajectory has been loaded') raise TypeError(
'Cannot edit atoms if a trajectory has been loaded')
return self._topology.add_atom(name, element, residue) return self._topology.add_atom(name, element, residue)
def save(self, filename, **kwargs): def save(self, filename, **kwargs) -> None:
"""Write trajctory to file.
:param filename: Name of output file
"""
self._trajectory.save(str(filename), **kwargs) self._trajectory.save(str(filename), **kwargs)
def add_frame_to_trajectory(self) -> None: def add_frame_to_trajectory(self) -> None:
"""Add a new trajectory frame from the values stored as attributes on this frame."""
xyz = np.array([atom.coords for atom in self._topology.atoms]) xyz = np.array([atom.coords for atom in self._topology.atoms])
optional_values = {
attr: None if getattr(self, attr) is None else [getattr(self, attr)]
for attr in {'time', 'unitcell_lengths', 'unitcell_angles'}
} # yapf: disable
new_frame = mdtraj.Trajectory(xyz, new_frame = mdtraj.Trajectory(xyz,
topology=self._topology, topology=self._topology,
time=[self.time], **optional_values)
unitcell_lengths=[self.unitcell_lengths],
unitcell_angles=[self.unitcell_angles])
if hasattr(self, '_trajectory'): if hasattr(self, '_trajectory'):
self._trajectory += new_frame self._trajectory += new_frame
......
...@@ -171,6 +171,7 @@ def sliding(vals: typing.Iterable): ...@@ -171,6 +171,7 @@ def sliding(vals: typing.Iterable):
yield (prev, current, nxt) yield (prev, current, nxt)
prev = current prev = current
current = nxt current = nxt
yield (prev, current, None) yield (prev, current, None)
...@@ -238,11 +239,9 @@ def cmp_whitespace_float(ref_lines, test_lines, rtol=0.01, verbose=False): ...@@ -238,11 +239,9 @@ def cmp_whitespace_float(ref_lines, test_lines, rtol=0.01, verbose=False):
ref_toks = ref_line.split() ref_toks = ref_line.split()
test_toks = test_line.split() test_toks = test_line.split()
if len(ref_toks) != len(test_toks): # Check for float comparison of tokens on line
diff_lines.append((i, ref_line, test_line)) for ref_tok, test_tok in itertools.zip_longest(
map(number_or_string, ref_toks),
# Check for float comparison
for ref_tok, test_tok in zip(map(number_or_string, ref_toks),
map(number_or_string, test_toks)): map(number_or_string, test_toks)):
if ref_tok != test_tok: if ref_tok != test_tok:
try: try:
......
108.79838 113.33555 107.02243 110.19691 121.98548 110.20455
-58.76278 60.68832 -51.98919 50.84542 -48.01593 47.89076
0.15361 0.15057 0.15191 0.15219 0.14398 0.14278
P5 72.0 0.000 A 0.0 0.0
P4 72.0 0.000 A 0.0 0.0
P3 72.0 0.000 A 0.0 0.0
P2 72.0 0.000 A 0.0 0.0
P1 72.0 0.000 A 0.0 0.0
Nda 72.0 0.000 A 0.0 0.0
Nd 72.0 0.000 A 0.0 0.0
Na 72.0 0.000 A 0.0 0.0
N0 72.0 0.000 A 0.0 0.0
C5 72.0 0.000 A 0.0 0.0
C4 72.0 0.000 A 0.0 0.0
C3 72.0 0.000 A 0.0 0.0
C2 72.0 0.000 A 0.0 0.0
C1 72.0 0.000 A 0.0 0.0
Qda 72.0 0.000 A 0.0 0.0
Qd 72.0 0.000 A 0.0 0.0
Qa 72.0 0.000 A 0.0 0.0
Q0 72.0 0.000 A 0.0 0.0
SP5 45.0 0.000 A 0.0 0.0
SP4 45.0 0.000 A 0.0 0.0
SP3 45.0 0.000 A 0.0 0.0
SP2 45.0 0.000 A 0.0 0.0
SP1 45.0 0.000 A 0.0 0.0
SNda 45.0 0.000 A 0.0 0.0
SNd 45.0 0.000 A 0.0 0.0
SNa 45.0 0.000 A 0.0 0.0
SN0 45.0 0.000 A 0.0 0.0
SC5 45.0 0.000 A 0.0 0.0
SC4 45.0 0.000 A 0.0 0.0
SC3 45.0 0.000 A 0.0 0.0
SC2 45.0 0.000 A 0.0 0.0
SC1 45.0 0.000 A 0.0 0.0
SQda 45.0 0.000 A 0.0 0.0
SQd 45.0 0.000 A 0.0 0.0
SQa 45.0 0.000 A 0.0 0.0
SQ0 45.0 0.000 A 0.0 0.0
AC2 72.0 0.000 A 0.0 0.0
AC1 72.0 0.000 A 0.0 0.0
BP4 72.0 0.000 A 0.0 0.0
PyCGTOOL produced MARTINI force field - out
#define _FF_PYCGTOOL_out
#include "martini_v2.2.itp"
This diff is collapsed.
; rtp residue to rtp building block table
; main N-ter C-ter 2-ter
[ bondedtypes ]
1 1 1 1 1 1 0 0
[ ALLA ]
[ atoms ]
C1 P3 0.000000 0
C2 P3 0.000000 0
C3 P3 0.000000 0
C4 P3 0.000000 0
C5 P2 0.000000 0
O5 P4 0.000000 0
[ bonds ]
C1 C2 0.22048 72722.85384
C2 C3 0.22184 64326.39740
C3 C4 0.21632 67918.78902
C4 C5 0.25315 19536.67041
C5 O5 0.20597 55319.40505
O5 C1 0.18055 139769.28667
[ angles ]
C1 C2 C3 1.35928 503.72847
C2 C3 C4 2.02600 838.60152
C3 C4 C5 1.93782 733.44785
C4 C5 O5 1.45361 946.13124
C5 O5 C1 2.50429 771.63346
O5 C1 C2 1.73300 800.62808
[ dihedrals ]
C1 C2 C3 C4 1.69535 253.69294 1
C2 C3 C4 C5 -2.07382 125.03029 1
C3 C4 C5 O5 2.76795 135.64448 1
C4 C5 O5 C1 -2.21270 51.18142 1
C5 O5 C1 C2 1.45570 59.39031 1
O5 C1 C2 C3 -1.82618 279.84587 1
; MARTINI FORCEFIELD V2.2
;
; SJ MARRINK (last modified: 04-12-2012 by DdJ)
;
; NOTE 1: Bead definitinions in this file have not been changed with respect to
; martini_v2.1.itp. This file is purely here for clarity sake. Differences
; between V2.1 and V2.2 are created by the martinize script and can be found
; in martini_v2.2_aminoacids.itp.
;
; please cite:
;
; D.H. de Jong, G. Singh, W.F.D. Bennet, C. Arnarez, T.A. Wassenaar, L.V. Schafer,
; X. Periole, D.P. Tieleman, S.J. Marrink.
; Improved Parameters for the Martini Coarse-Grained Protein Force Field
; J. Chem. Theory Comput., DOI: 10.1021/ct300646g
; L. Monticelli, S. Kandasamy, X. Periole, R. Larson, D.P. Tieleman, S.J. Marrink.
; The MARTINI coarse grained force field: extension to proteins.
; J. Chem. Th. Comp., 4:819-834, 2008.
;
; S.J. Marrink, H.J. Risselada, S. Yefimov, D.P. Tieleman, A.H. de Vries.
; The MARTINI forcefield: coarse grained model for biomolecular simulations.
; JPC-B, 111:7812-7824, 2007.
;
; and (if using lipid topologies):
;
; S.J. Marrink, A.H. de Vries, A.E. Mark.
; Coarse grained model for semi-quantitative lipid simulations.
; JPC-B, 108:750-760, 2004.
;;;;;; WATER (representing 4 H2O molecules)
[ moleculetype ]
; molname nrexcl
W 1
[ atoms ]
;id type resnr residu atom cgnr charge
1 P4 1 W W 1 0
;;;;;; ANTIFREEZE (prevents freezing of water)
[ moleculetype ]
; molname nrexcl
WF 1
[ atoms ]
;id type resnr residu atom cgnr charge
1 BP4 1 WF WF 1 0
w W Standard MARTINI water
pw PW Polarisable MARTINI water
[ NAPH ]
R1 R2 ; around outside
R2 R5
R5 R4
R4 R1
R1 R5 ; across diagonal
; disabled because we use a single frame for testing
; R2 R1 R5 R4 ; dihedral along diagonal
GROup of MAchos and Cynical Suckers GROup of MAchos and Cynical Suckers
18 18
1NAP C1 1 0.001 0.243 -0.000 1NAPH C1 1 0.001 0.243 -0.000
1NAP H1 2 -0.052 0.337 -0.000 1NAPH H1 2 -0.052 0.337 -0.000
1NAP C2 3 0.141 0.242 0.000 1NAPH C2 3 0.141 0.242 0.000
1NAP H2 4 0.195 0.336 0.000 1NAPH H2 4 0.195 0.336 0.000
1NAP C3 5 0.211 0.121 0.000 1NAPH C3 5 0.211 0.121 0.000
1NAP H3 6 0.319 0.121 0.000 1NAPH H3 6 0.319 0.121 0.000
1NAP C4 7 0.141 -0.001 0.000 1NAPH C4 7 0.141 -0.001 0.000
1NAP H4 8 0.197 -0.093 0.000 1NAPH H4 8 0.197 -0.093 0.000
1NAP C5 9 0.001 -0.001 0.000 1NAPH C5 9 0.001 -0.001 0.000
1NAP C6 10 -0.070 -0.122 0.000 1NAPH C6 10 -0.070 -0.122 0.000
1NAP H6 11 -0.018 -0.217 0.000 1NAPH H6 11 -0.018 -0.217 0.000
1NAP C7 12 -0.210 -0.122 0.000 1NAPH C7 12 -0.210 -0.122 0.000
1NAP H7 13 -0.264 -0.215 0.000 1NAPH H7 13 -0.264 -0.215 0.000
1NAP C8 14 -0.280 -0.001 0.000 1NAPH C8 14 -0.280 -0.001 0.000
1NAP H8 15 -0.388 -0.001 0.000 1NAPH H8 15 -0.388 -0.001 0.000
1NAP C9 16 -0.211 0.121 0.000 1NAPH C9 16 -0.211 0.121 0.000
1NAP H9 17 -0.266 0.214 0.000 1NAPH H9 17 -0.266 0.214 0.000
1NAP C10 18 -0.070 0.122 0.000 1NAPH C10 18 -0.070 0.122 0.000
0.00000 0.00000 0.00000 0.00000 0.00000 0.00000
;
; Topology prepared automatically using PyCGTOOL
; James Graham <J.A.Graham@soton.ac.uk> 2016
; University of Southampton
; https://github.com/jag1g13/pycgtool
;
[ moleculetype ]
NAPH 1
[ atoms ]
1 TC4 1 NAPH R1 1 0.000
2 TC4 1 NAPH R2 2 0.000
3 TC4 1 NAPH R3 3 0.000 0.000
4 TC4 1 NAPH R4 4 0.000
5 TC4 1 NAPH R5 5 0.000
[ virtual_sitesn ]
3 1 1 2 4 5
[ exclusions ]
3 1 2 4 5
[ constraints ]
1 2 1 0.29133
2 5 1 0.41260
5 4 1 0.29155
4 1 1 0.41273
1 5 1 0.50537
...@@ -17,4 +17,4 @@ Alpha-allose in water ...@@ -17,4 +17,4 @@ Alpha-allose in water
1ALLA C1 15 2.895 2.970 1.310 1ALLA C1 15 2.895 2.970 1.310
1ALLA O1 16 3.023 2.937 1.367 1ALLA O1 16 3.023 2.937 1.367
1ALLA HO1 17 3.040 2.996 1.445 1ALLA HO1 17 3.040 2.996 1.445
3.74699 3.74699 2.67438 3.74699 3.74699 2.67438 0.00000 0.00000 0.00000 0.00000 1.87349 1.87349
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment