Skip to content

Commit 89bf2cb

Browse files
committed
Start to pylint/flake8 wizard cleanup
1 parent 68fc7de commit 89bf2cb

3 files changed

Lines changed: 100 additions & 21 deletions

File tree

‎paths_cli/wizard/core.py‎

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
import random
2-
from paths_cli.wizard.tools import a_an
3-
4-
from collections import namedtuple
1+
def interpret_req(req):
2+
"""Create user-facing string representation of the input requirement.
53
6-
WIZARD_STORE_NAMES = ['engines', 'cvs', 'states', 'networks', 'schemes']
7-
WizardSay = namedtuple("WizardSay", ['msg', 'mode'])
4+
Parameters
5+
----------
6+
req : Tuple[..., int, int]
7+
req[1] is the minimum number of objects to create; req[2] is the
8+
maximum number of objects to create
89
9-
def interpret_req(req):
10+
Returns
11+
-------
12+
str :
13+
human-reading string for how many objects to create
14+
"""
1015
_, min_, max_ = req
1116
string = ""
1217
if min_ == max_:
@@ -23,7 +28,32 @@ def interpret_req(req):
2328
return string
2429

2530

31+
# TODO: REFACTOR: It looks like get_missing_object may be redundant with
32+
# other code for obtaining prerequisites for a function
2633
def get_missing_object(wizard, obj_dict, display_name, fallback_func):
34+
"""Get a prerequisite object.
35+
36+
The ``obj_dict`` here is typically a mapping of objects known by the
37+
Wizard. If it is empty, the ``fallback_func`` is used to create a new
38+
object. If it has exactly 1 entry, that is used implicitly. If it has
39+
more than 1 entry, the user must select which one to use.
40+
41+
Parameters
42+
----------
43+
wizard : :class:`.Wizard`
44+
the wizard for user interaction
45+
obj_dict : Dict[str, Any]
46+
mapping of object name to object
47+
display_name: str
48+
the user-facing name of this type of object
49+
fallback_func: Callable[:class:`.Wizard`] -> Any
50+
method to create a new object of this type
51+
52+
Returns
53+
-------
54+
Any :
55+
the prerequisite object
56+
"""
2757
if len(obj_dict) == 0:
2858
obj = fallback_func(wizard)
2959
elif len(obj_dict) == 1:
@@ -37,10 +67,22 @@ def get_missing_object(wizard, obj_dict, display_name, fallback_func):
3767

3868

3969
def get_object(func):
70+
"""Decorator to wrap methods for obtaining objects from user input.
71+
72+
This decorator implements the user interaction loop when dealing with a
73+
single user input. The wrapped function is intended to create some
74+
object. If the user's input cannot create a valid object, the wrapped
75+
function should return None.
76+
77+
Parameters
78+
----------
79+
func : Callable
80+
object creation method to wrap; should return None on failure
81+
"""
82+
# TODO: use functools.wraps?
4083
def inner(*args, **kwargs):
4184
obj = None
4285
while obj is None:
4386
obj = func(*args, **kwargs)
4487
return obj
4588
return inner
46-

‎paths_cli/wizard/cvs.py‎

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1+
from functools import partial
2+
from collections import namedtuple
3+
import numpy as np
4+
15
from paths_cli.compiling.tools import mdtraj_parse_atomlist
26
from paths_cli.wizard.plugin_classes import (
37
LoadFromOPS, WizardObjectPlugin, WrapCategory
48
)
59
from paths_cli.wizard.core import get_object
610
import paths_cli.wizard.engines
711

8-
from functools import partial
9-
from collections import namedtuple
10-
import numpy as np
11-
1212
from paths_cli.wizard.parameters import (
1313
FromWizardPrerequisite
1414
)
@@ -27,6 +27,10 @@
2727
"You should specify atom indices enclosed in double brackets, e.g. "
2828
"[{list_range_natoms}]"
2929
)
30+
_MDTrajParams = namedtuple("_MDTrajParams", ['period', 'n_atoms',
31+
'kwarg_name', 'cv_user_str'])
32+
_MDTRAJ_INTRO = "We'll make a CV that measures the {user_str}."
33+
3034

3135
# TODO: implement so the following can be the help string:
3236
# _ATOM_INDICES_HELP_STR = (
@@ -56,6 +60,25 @@
5660

5761
@get_object
5862
def _get_atom_indices(wizard, topology, n_atoms, cv_user_str):
63+
"""Parameter loader for atom_indices parameters in MDTraj.
64+
65+
Parameters
66+
----------
67+
wizard : :class:`.Wizard`
68+
wizard for user interaction
69+
topology :
70+
topology (reserved for future use)
71+
n_atoms : int
72+
number of atoms to define this CV (i.e., 2 for a distance; 3 for an
73+
angle; 4 for a dihedral)
74+
cv_user_str : str
75+
user-facing name for the CV being created
76+
77+
Returns
78+
-------
79+
:class`np.ndarray` :
80+
array of indices for the MDTraj function
81+
"""
5982
helper = Helper(_ATOM_INDICES_HELP_STR.format(
6083
list_range_natoms=list(range(n_atoms))
6184
))
@@ -67,14 +90,14 @@ def _get_atom_indices(wizard, topology, n_atoms, cv_user_str):
6790
except Exception as e:
6891
wizard.exception(f"Sorry, I didn't understand '{atoms_str}'.", e)
6992
helper("?")
70-
return
93+
return None
7194

7295
return arr
7396

74-
_MDTrajParams = namedtuple("_MDTrajParams", ['period', 'n_atoms',
75-
'kwarg_name', 'cv_user_str'])
7697

7798
def _mdtraj_cv_builder(wizard, prereqs, func_name):
99+
"""General function to handle building MDTraj CVs.
100+
"""
78101
from openpathsampling.experimental.storage.collective_variables import \
79102
MDTrajFunctionCV
80103
dct = TOPOLOGY_CV_PREREQ(wizard)
@@ -108,9 +131,9 @@ def _mdtraj_cv_builder(wizard, prereqs, func_name):
108131
return MDTrajFunctionCV(func, topology, period_min=period_min,
109132
period_max=period_max, **kwargs)
110133

111-
_MDTRAJ_INTRO = "We'll make a CV that measures the {user_str}."
112134

113135
def _mdtraj_summary(wizard, context, result):
136+
"""Standard summary of MDTraj CVs: function, atom, topology"""
114137
cv = result
115138
func = cv.func
116139
topology = cv.topology
@@ -121,6 +144,7 @@ def _mdtraj_summary(wizard, context, result):
121144
f" Topology: {repr(topology.mdtraj)}")
122145
return [summary]
123146

147+
124148
if HAS_MDTRAJ:
125149
MDTRAJ_DISTANCE = WizardObjectPlugin(
126150
name='Distance',
@@ -152,10 +176,24 @@ def _mdtraj_summary(wizard, context, result):
152176
"four atoms"),
153177
summary=_mdtraj_summary,
154178
)
155-
156179
# TODO: add RMSD -- need to figure out how to select a frame
157180

181+
158182
def coordinate(wizard, prereqs=None):
183+
"""Builder for coordinate CV.
184+
185+
Parameters
186+
----------
187+
wizard : :class:`.Wizard`
188+
wizard for user interaction
189+
prereqs :
190+
prerequisites (unused in this method)
191+
192+
Return
193+
------
194+
CoordinateFunctionCV :
195+
the OpenPathSampling CV for this selecting this coordinate
196+
"""
159197
# TODO: atom_index should be from wizard.ask_custom_eval
160198
from openpathsampling.experimental.storage.collective_variables import \
161199
CoordinateFunctionCV
@@ -174,12 +212,13 @@ def coordinate(wizard, prereqs=None):
174212
f"atom {atom_index}?")
175213
try:
176214
coord = {'x': 0, 'y': 1, 'z': 2}[xyz]
177-
except KeyError as e:
215+
except KeyError:
178216
wizard.bad_input("Please select one of 'x', 'y', or 'z'")
179217

180218
cv = CoordinateFunctionCV(lambda snap: snap.xyz[atom_index][coord])
181219
return cv
182220

221+
183222
COORDINATE_CV = WizardObjectPlugin(
184223
name="Coordinate",
185224
category="cv",
@@ -202,6 +241,7 @@ def coordinate(wizard, prereqs=None):
202241
"you can also create your own and load it from a file.")
203242
)
204243

244+
205245
if __name__ == "__main__": # no-cov
206246
from paths_cli.wizard.run_module import run_category
207247
run_category('cv')

‎paths_cli/wizard/engines.py‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import paths_cli.wizard.openmm as openmm
21
from paths_cli.wizard.plugin_classes import LoadFromOPS, WrapCategory
3-
from functools import partial
42

53
_ENGINE_HELP = "An engine describes how you'll do the actual dynamics."
64
ENGINE_PLUGIN = WrapCategory(
@@ -17,4 +15,3 @@
1715
if __name__ == "__main__": # no-cov
1816
from paths_cli.wizard.run_module import run_category
1917
run_category('engine')
20-

0 commit comments

Comments
 (0)