diff --git a/guide/tutorials/colbuilder-files/change_crosslink_atom_names.py b/guide/tutorials/colbuilder-files/change_crosslink_atom_names.py index 648f4a80..a4388ccf 100644 --- a/guide/tutorials/colbuilder-files/change_crosslink_atom_names.py +++ b/guide/tutorials/colbuilder-files/change_crosslink_atom_names.py @@ -3,8 +3,8 @@ def main(run_info): from functions_v4 import get_data_from_file, store_linelist_to_file # Extracting data - top_all, top_array = get_data_from_file(run_info["path_top_file"]) - gro_all, gro_array = get_data_from_file(run_info["path_gro_file"]) + top_all, _ = get_data_from_file(run_info["path_top_file"]) + gro_all, _ = get_data_from_file(run_info["path_gro_file"]) # Dictionaries of corsslinks LYX = {"CB": "CBYX", "CG": "CGYX", "CD": "CDYX", "CE": "CEYX"} diff --git a/src/kimmdy/recipe.py b/src/kimmdy/recipe.py index 95a2341f..9fdb222d 100644 --- a/src/kimmdy/recipe.py +++ b/src/kimmdy/recipe.py @@ -362,17 +362,6 @@ def copy(self): list(self.timespans), ) - def calc_averages(self, window_size: int): - """Calulate average rates over some window size - - Parameters - ---------- - window_size : int - Size of the window to average over, - -1 to average over whole available range. - """ - raise NotImplementedError("calc_averages not implemented yet") - def combine_with(self, other: Recipe): """Combines this Recipe with another with the same RecipeSteps. @@ -613,7 +602,12 @@ def calc_ratesum(self) -> tuple[list, list, list]: return boarders, rate_windows, recipe_windows - def plot(self, outfile, highlight_r=None, highlight_t=None): + def plot( + self, + outfile, + highlight_r: Optional[Recipe] = None, + highlight_t: Optional[float] = None, + ): """Plot reaction rates over time Parameters @@ -637,7 +631,7 @@ def plot(self, outfile, highlight_r=None, highlight_t=None): for i, r in enumerate(self.recipes): recipe_steps[i] = r.recipe_steps - idxs = np.argsort(cumprob)[-8:] + idxs = list(np.argsort(cumprob)[-8:]) ref = np.empty((1,), dtype=object) if highlight_r is not None: ref[0] = highlight_r.recipe_steps @@ -672,7 +666,7 @@ def plot(self, outfile, highlight_r=None, highlight_t=None): plt.axvline(highlight_t, color="red") for r_i, re in enumerate(recipes): name = re.get_recipe_name() - if name == highlight_r.get_recipe_name(): + if highlight_r is not None and name == highlight_r.get_recipe_name(): name_to_args[name]["linestyle"] = "-." name_to_args[name]["linewidth"] = 2.2 diff --git a/src/kimmdy/runmanager.py b/src/kimmdy/runmanager.py index 901fc7ff..d97b0577 100644 --- a/src/kimmdy/runmanager.py +++ b/src/kimmdy/runmanager.py @@ -57,7 +57,7 @@ class State(Enum): DONE = auto() -def get_existing_files(config: Config, section: str = "root") -> dict: +def get_existing_files(config: Config) -> dict: """Initialize latest_files with every existing file defined in config""" file_d = {} attr_names = config.get_attributes() @@ -79,7 +79,7 @@ def get_existing_files(config: Config, section: str = "root") -> dict: file_d[key] = attr elif isinstance(attr, Config): - file_d.update(get_existing_files(attr, attr_name)) + file_d.update(get_existing_files(attr)) return file_d @@ -318,7 +318,8 @@ def __next__(self): f"Finished task: {task.name} after " f"{timedelta(seconds=(time.time() - current_time))}" ) - self._discover_output_files(task.name, files) + if files is not None: + self._discover_output_files(task.name, files) def _discover_output_files( self, taskname: str, files: TaskFiles @@ -608,7 +609,8 @@ def _apply_recipe(self, files: TaskFiles) -> TaskFiles: logger.info(f"Starting task: {task.name} with args: {task.kwargs}") place_files = task() logger.info(f"Finished task: {task.name}") - self._discover_output_files(task.name, place_files) + if place_files is not None: + self._discover_output_files(task.name, place_files) elif isinstance(step, Relax): logger.info("Starting relaxation md as part of reaction..") @@ -632,7 +634,8 @@ def _apply_recipe(self, files: TaskFiles) -> TaskFiles: logger.info(f"Starting task: {task.name} with args: {task.kwargs}") md_files = task() logger.info(f"Finished task: {task.name}") - self._discover_output_files(task.name, md_files) + if md_files is not None: + self._discover_output_files(task.name, md_files) elif isinstance(step, CustomTopMod): step.f(self.top) diff --git a/src/kimmdy/schema.py b/src/kimmdy/schema.py index b08ddad9..2eba57bf 100644 --- a/src/kimmdy/schema.py +++ b/src/kimmdy/schema.py @@ -59,7 +59,7 @@ def __repr__(self): def load_kimmdy_schema() -> dict: """Return the schema for the config file""" path = pkg_resources.files(kimmdy) / "kimmdy-yaml-schema.json" - with path.open("rt") as f: + with path.open("r") as f: schema = json.load(f) return schema diff --git a/src/kimmdy/tools.py b/src/kimmdy/tools.py index 42ab819c..3f89f3fd 100644 --- a/src/kimmdy/tools.py +++ b/src/kimmdy/tools.py @@ -161,7 +161,7 @@ def modify_top( # radicals != None -> iterate over rad_str.split, can be empty rad_str = None if radicals is not None: - rad_str = " ".join(radicals) + rad_str = " ".join([str(r) for r in radicals]) elif not search_amber_rad: rad_str = "" @@ -221,7 +221,7 @@ def modify_top( print("Done") # deal with gro file - if gro: + if gro_path is not None and gro_out is not None: if removeH: print("Writing gro..", end="") with open(gro_path, "r") as f: diff --git a/src/kimmdy/topology/topology.py b/src/kimmdy/topology/topology.py index 5b288160..1d7e14e1 100644 --- a/src/kimmdy/topology/topology.py +++ b/src/kimmdy/topology/topology.py @@ -1,42 +1,45 @@ -from kimmdy.constants import ATOMTYPE_BONDORDER_FLAT +import logging +import textwrap +from copy import copy, deepcopy +from itertools import permutations +from pathlib import Path +from typing import Callable, Optional, Union + +from kimmdy.constants import ( + ATOM_ID_FIELDS, + ATOMTYPE_BONDORDER_FLAT, + REACTIVE_MOLECULEYPE, + RESNR_ID_FIELDS, +) from kimmdy.parsing import TopologyDict +from kimmdy.plugins import BasicParameterizer, Parameterizer +from kimmdy.recipe import Bind, Break, RecipeStep from kimmdy.topology.atomic import ( + Angle, Atom, Bond, - Pair, - Angle, Dihedral, + DihedralRestraint, + Exclusion, MultipleDihedrals, + Pair, PositionRestraint, - DihedralRestraint, ResidueImproperSpec, Settle, - Exclusion, ) +from kimmdy.topology.ff import FF from kimmdy.topology.utils import ( + attributes_to_list, get_moleculetype_atomics, get_moleculetype_header, - attributes_to_list, + get_residue_fragments, get_top_section, + increment_field, is_not_solvent_or_ion, set_moleculetype_atomics, set_top_section, - get_residue_fragments, ) -from kimmdy.topology.ff import FF -from kimmdy.plugins import BasicParameterizer, Parameterizer -from itertools import permutations, combinations -import textwrap -import logging -from typing import Optional -from copy import copy, deepcopy -from pathlib import Path -from kimmdy.constants import ATOM_ID_FIELDS, RESNR_ID_FIELDS, REACTIVE_MOLECULEYPE -from typing import Callable, Union - from kimmdy.utils import TopologyAtomAddress -from kimmdy.topology.utils import increment_field -from kimmdy.recipe import RecipeStep, Bind, Break logger = logging.getLogger("kimmdy.topology") @@ -475,6 +478,9 @@ def _regenerate_topology_from_bound_to(self, ff): for atom in self.atoms.values(): impropers = self._get_atom_improper_dihedrals(atom.nr, ff) for key, improper in impropers: + periodicity = "" + if improper.c2 is not None: + periodicity = improper.c2 self.improper_dihedrals[key] = MultipleDihedrals( *key, "4", @@ -484,7 +490,7 @@ def _regenerate_topology_from_bound_to(self, ff): "4", c0=improper.c0, c1=improper.c1, - periodicity=improper.c2, + periodicity=periodicity, ) }, ) @@ -554,7 +560,8 @@ def reindex_atomnrs(self) -> dict[str, str]: continue # do pairs before the dihedrals are updated - if pair := self.pairs.pop((dihedrals.ai, dihedrals.al), False): + pair = self.pairs.pop((dihedrals.ai, dihedrals.al), None) + if pair is not None: pair_ai = update_map.get(pair.ai) pair_aj = update_map.get(pair.aj) diff --git a/src/kimmdy/utils.py b/src/kimmdy/utils.py index 8b093fd4..fdf21ac3 100644 --- a/src/kimmdy/utils.py +++ b/src/kimmdy/utils.py @@ -168,7 +168,7 @@ def get_edissoc_from_atomnames( try: E_dis = edissoc[residue][frozenset(atomnames)] - except KeyError as e: + except KeyError: # continue with guessed edissoc logger.warning( f"Did not find dissociation energy for atomtypes {atomnames}, residue {residue} in edissoc file, using standard value of 400.0"