Skip to content

Commit

Permalink
Merge pull request #474 from marrink-lab/ff_log_entry
Browse files Browse the repository at this point in the history
Add option to generate log entries from .ff files
  • Loading branch information
pckroon authored Dec 14, 2022
2 parents dc1ec65 + 6867b0e commit 2acbf41
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 2 deletions.
5 changes: 5 additions & 0 deletions bin/martinize2
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,11 @@ def entry():
LOGGER.info('Writing output.', type='step')
for molecule in system.molecules:
LOGGER.debug("Writing molecule {}.", molecule, type='step')
for loglevel, entries in molecule.log_entries.items():
for entry, fmt_args in entries.items():
for fmt_arg in fmt_args:
fmt_arg = {str(k): molecule.nodes[v] for k, v in fmt_arg.items()}
LOGGER.log(loglevel, entry, **fmt_arg, type='model')

# Write the topology if requested
# grompp has a limit in the number of character it can read per line
Expand Down
21 changes: 20 additions & 1 deletion vermouth/ffinput.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

import collections
import copy
import logging
import numbers
import json
from .molecule import (
Expand Down Expand Up @@ -180,7 +181,7 @@ def finalize_section(self, previous_section, ended_section):
self.current_modification.citations.update(self.citations)
self.force_field.modifications[self.current_modification.name] = self.current_modification

def get_context(self, context_type):
def get_context(self, context_type=''):
possible_contexts = {
'block': self.current_block,
'link': self.current_link,
Expand Down Expand Up @@ -438,6 +439,24 @@ def _pase_ff_citations(self, line, lineno=0):
cite_keys = line.split()
self.citations.update(cite_keys)

@SectionLineParser.section_parser('moleculetype', 'debug', context_type='block')
@SectionLineParser.section_parser('link', 'debug', context_type='link')
@SectionLineParser.section_parser('modification', 'debug', context_type='modification')
@SectionLineParser.section_parser('moleculetype', 'info', context_type='block')
@SectionLineParser.section_parser('link', 'info', context_type='link')
@SectionLineParser.section_parser('modification', 'info', context_type='modification')
@SectionLineParser.section_parser('moleculetype', 'warning', context_type='block')
@SectionLineParser.section_parser('link', 'warning', context_type='link')
@SectionLineParser.section_parser('modification', 'warning', context_type='modification')
@SectionLineParser.section_parser('moleculetype', 'error', context_type='block')
@SectionLineParser.section_parser('link', 'error', context_type='link')
@SectionLineParser.section_parser('modification', 'error', context_type='modification')
def _parse_log_entry(self, line, lineno=0, context_type=''):
loglevel = logging.getLevelName(self.section[-1].upper())
if LOGGER.isEnabledFor(loglevel):
self.get_context(context_type).log_entries[loglevel][line] = []


def _some_atoms_left(tokens, atoms, natoms):
"""
Return True if the token list expected to contain atoms.
Expand Down
12 changes: 11 additions & 1 deletion vermouth/molecule.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.interactions = defaultdict(list)
self.citations = set()
# {loglevel: {entry: [fmt_args]}}
self.log_entries = defaultdict(lambda: defaultdict(list))
self.max_node = None

def __eq__(self, other):
Expand Down Expand Up @@ -438,6 +440,8 @@ def copy(self):
"""
new = self.subgraph(self.nodes)
new.name = self.name
new.citations = self.citations.copy()
new.log_entries = copy.deepcopy(self.log_entries)
return new

def subgraph(self, nodes):
Expand Down Expand Up @@ -719,13 +723,18 @@ def merge_molecule(self, molecule):
for name, interactions in molecule.interactions.items():
for interaction in interactions:
atoms = tuple(correspondence[atom] for atom in interaction.atoms)
#print(atoms, interaction.meta)
self.add_interaction(name, atoms, interaction.parameters, interaction.meta)
for node1, node2 in molecule.edges:
if correspondence[node1] != correspondence[node2]:
self.add_edge(correspondence[node1], correspondence[node2])
# merge the citation sets
self.citations.update(molecule.citations)
# Merge the log entries
for loglevel, entries in molecule.log_entries.items():
for entry, fmt_args in entries.items():
# Renumber any existing formatting maps
fmt_args = [{name: correspondence[old] for (name, old) in fmt_arg.items()} for fmt_arg in fmt_args]
self.log_entries[loglevel][entry] += fmt_args + [correspondence]

return correspondence

Expand Down Expand Up @@ -1191,6 +1200,7 @@ def to_molecule(self, atom_offset=0, offset_resid=0, offset_charge_group=0,
name_to_idx = {}
mol = Molecule(force_field=force_field)
mol.citations = self.citations
mol.log_entries = copy.deepcopy(self.log_entries)

for idx, node in enumerate(self.nodes, start=atom_offset):
name_to_idx[node] = idx
Expand Down
5 changes: 5 additions & 0 deletions vermouth/processors/do_links.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,5 +292,10 @@ def run_molecule(self, molecule):
interaction = _build_link_interaction_from(molecule, interaction, match)
molecule.add_or_replace_interaction(inter_type, *interaction, link.citations)

for loglevel, entries in link.log_entries.items():
for entry, fmt_args in entries.items():
fmt_args = fmt_args + [match]
molecule.log_entries[loglevel][entry] += fmt_args

molecule.remove_nodes_from(_nodes_to_remove)
return molecule
10 changes: 10 additions & 0 deletions vermouth/processors/do_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ def apply_mod_mapping(match, molecule, graph_out, mol_to_out, out_to_mol):
mol_to_mod, modification, references = match
LOGGER.info('Applying modification mapping {}', modification.name, type='general')
graph_out.citations.update(modification.citations)

mod_to_mol = defaultdict(dict)
for mol_idx, mod_idxs in mol_to_mod.items():
for mod_idx in mod_idxs:
Expand Down Expand Up @@ -477,6 +478,15 @@ def apply_mod_mapping(match, molecule, graph_out, mol_to_out, out_to_mol):
interaction = interaction._replace(atoms=atoms)
applied_interactions[interaction_type][tuple(atoms)].append(modification)
graph_out.add_interaction(interaction_type, **interaction._asdict())

# Some jank needed here, since modification node indices are integers
mod_atom_name_to_out = {}
for mod_idx in modification.nodes:
name = modification.nodes[mod_idx]['atomname']
mod_atom_name_to_out[name] = mod_to_out[mod_idx]
for loglevel, entries in modification.log_entries.items():
for entry in entries:
graph_out.log_entries[loglevel][entry] += [mod_atom_name_to_out]
return dict(applied_interactions), new_references


Expand Down

0 comments on commit 2acbf41

Please sign in to comment.