Skip to content

Commit 8df4a54

Browse files
committed
Add progress reporting to md command
1 parent 586f1a7 commit 8df4a54

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ miscellaneous operations on OPS output files.
2222
**Simulation Commands:**
2323

2424
* `visit-all`: Run MD to generate initial trajectories
25+
* `md`: Run MD for fixed time or until a given ensemble is satisfied
2526
* `equilibrate`: Run equilibration for path sampling
2627
* `pathsampling`: Run any path sampling simulation, including TIS variants
2728

paths_cli/commands/md.py

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,34 @@ def md(input_file, output_file, engine, ensemble, nsteps, init_frame):
3838
initial_frame=INIT_SNAP.get(storage, init_frame)
3939
)
4040

41+
class ProgressReporter(object):
42+
def __init__(self, timestep, update_freq):
43+
self.timestep = timestep
44+
self.update_freq = update_freq
4145

42-
class EnsembleSatisfiedContinueConditions(object):
46+
def steps_progress_string(self, n_steps):
47+
report_str = "Ran {n_steps} frames"
48+
if self.timestep is not None:
49+
report_str += " [{}]".format(str(n_steps * timestep))
50+
report_str += '.'
51+
return report_str
52+
53+
def progress_string(self, n_steps):
54+
report_str = self.steps_progress_string(n_steps) + "\n"
55+
return report_str.format(n_steps=n_steps)
56+
57+
58+
def report_progress(self, n_steps):
59+
import openpathsampling as paths
60+
if n_steps % self.update_freq == 0:
61+
string = self.progress_string(n_steps)
62+
paths.tools.refresh_output(string)
63+
64+
def __call__(self, trajectory, trusted=False):
65+
raise NotImplementedError()
66+
67+
68+
class EnsembleSatisfiedContinueConditions(ProgressReporter):
4369
"""Continuation condition for including subtrajs for each ensemble.
4470
4571
This object creates a continuation condition (a callable) analogous with
@@ -52,9 +78,24 @@ class EnsembleSatisfiedContinueConditions(object):
5278
ensembles: List[:class:`openpathsampling.Ensemble`]
5379
the ensembles to satisfy
5480
"""
55-
def __init__(self, ensembles):
81+
def __init__(self, ensembles, timestep=None, update_freq=10):
82+
super().__init__(timestep, update_freq)
5683
self.satisfied = {ens: False for ens in ensembles}
5784

85+
def progress_string(self, n_steps):
86+
report_str = self.steps_progress_string(n_steps)
87+
report_str += (" Found ensembles [{found}]. "
88+
"Looking for [{missing}].\n")
89+
found = [ens.name for ens, done in self.satisfied.items() if done]
90+
missing = [ens.name for ens, done in self.satisfied.items()
91+
if not done]
92+
found_str = ",".join(found)
93+
missing_str = ",".join(missing)
94+
return report_str.format(n_steps=n_steps,
95+
found=found_str,
96+
missing=missing_str)
97+
98+
5899
def _check_previous_frame(self, trajectory, start, unsatisfied):
59100
if -start > len(trajectory):
60101
# we've done the whole traj; don't keep going
@@ -81,6 +122,8 @@ def __call__(self, trajectory, trusted=False):
81122
return self._call_untrusted(trajectory)
82123

83124
# below here, trusted is True
125+
self.report_progress(len(trajectory) - 1)
126+
84127
unsatisfied = [ens for ens, done in self.satisfied.items()
85128
if not done]
86129
# TODO: update on how many ensembles left, what frame number we are
@@ -92,6 +135,20 @@ def __call__(self, trajectory, trusted=False):
92135
return not all(self.satisfied.values())
93136

94137

138+
class FixedLengthContinueCondition(ProgressReporter):
139+
"""
140+
"""
141+
def __init__(self, length, timestep=None, update_freq=10):
142+
super().__init__(timestep, update_freq)
143+
self.length = length
144+
145+
def __call__(self, trajectory, trusted=False):
146+
len_traj = len(trajectory)
147+
self.report_progress(len_traj - 1)
148+
return len_traj < self.length
149+
150+
151+
95152
def md_main(output_storage, engine, ensembles, nsteps, initial_frame):
96153
import openpathsampling as paths
97154
if nsteps is not None and ensembles:
@@ -101,7 +158,7 @@ def md_main(output_storage, engine, ensembles, nsteps, initial_frame):
101158
if ensembles:
102159
continue_cond = EnsembleSatisfiedContinueConditions(ensembles)
103160
else:
104-
continue_cond = paths.LengthEnsemble(nsteps).can_append
161+
continue_cond = FixedLengthContinueCondition(nsteps)
105162

106163
trajectory = engine.generate(initial_frame, running=continue_cond)
107164
paths_cli.utils.tag_final_result(trajectory, output_storage,

paths_cli/utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ def tag_final_result(result, storage, tag='final_conditions'):
1111
the name to tag it with; default is 'final_conditions'
1212
"""
1313
if storage:
14+
print("Saving results to output file....")
1415
storage.save(result)
1516
storage.tags[tag] = result

0 commit comments

Comments
 (0)