Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
1be1b2d
start to SimStore support
dwhswenson Oct 23, 2020
e773c1f
fix tests
dwhswenson Oct 23, 2020
67c1b22
Tests for SimStore support
dwhswenson Nov 27, 2020
22ca390
monkey patching and snapshots for SimStore
dwhswenson Dec 6, 2020
132f23e
improve error message when missing objects
dwhswenson Dec 6, 2020
df83b71
Only monkeypatch SimStore once; better error msg
dwhswenson Dec 8, 2020
695ed8b
Add support for --table option in `contents`
dwhswenson Dec 8, 2020
f983f35
Steps toward allowing multiple --init_conds
dwhswenson Dec 8, 2020
fbe73da
Add md command
dwhswenson Dec 8, 2020
7948e37
OPSStorageLoadMultiple for INIT_CONDS
dwhswenson Dec 8, 2020
3229fba
Add test for getting multiple init conds
dwhswenson Dec 8, 2020
47e41af
Tests for --table arg to contents
dwhswenson Dec 8, 2020
98f3868
Add tests for md
dwhswenson Dec 9, 2020
830ef03
cleanup
dwhswenson Dec 9, 2020
6125554
tests for md command
dwhswenson Dec 9, 2020
00b83cc
more test coverage
dwhswenson Dec 9, 2020
dd4ec60
Some cleanup in contents; complete testing
dwhswenson Dec 9, 2020
586f1a7
docstrings
dwhswenson Dec 9, 2020
586e6e4
add test for tags table
dwhswenson Dec 9, 2020
8df4a54
Add progress reporting to md command
dwhswenson Dec 9, 2020
6531c49
Merge pull request #34 from dwhswenson/multiple-traj-init-conds
dwhswenson Dec 10, 2020
fb91628
Merge remote-tracking branch 'upstream/master' into md
dwhswenson Dec 10, 2020
10dcb1b
Merge pull request #33 from dwhswenson/content-table
dwhswenson Dec 11, 2020
38e01ba
Merge remote-tracking branch 'upstream/master' into md
dwhswenson Dec 11, 2020
bdace7f
Merge remote-tracking branch 'upstream/master' into simstore
dwhswenson Dec 11, 2020
7726d8c
Tell InterfaceSet to use SimStore when needed
dwhswenson Dec 11, 2020
8e9fa46
more tests; docstrings
dwhswenson Dec 15, 2020
29cd0d0
Merge pull request #35 from dwhswenson/md
dwhswenson Dec 17, 2020
3aa79ba
Merge remote-tracking branch 'upstream/master' into simstore
dwhswenson Dec 17, 2020
5650b49
Bump to 0.2.0.dev0; update autorelease
dwhswenson Dec 22, 2020
0aa3aa2
Merge pull request #36 from dwhswenson/bump-0.2.0.dev0
dwhswenson Dec 22, 2020
941e6ff
Merge remote-tracking branch 'upstream/master' into simstore
dwhswenson Dec 24, 2020
8695676
add reqs for SimStore
dwhswenson Dec 25, 2020
107f1db
Undo SimStore monkey patches after tests
dwhswenson Jan 1, 2021
17a0319
add a couple tests to complete coverage
dwhswenson Jan 1, 2021
40a503b
Merge pull request #29 from dwhswenson/simstore
dwhswenson Jan 1, 2021
3daed14
Release 0.2.0
dwhswenson Jan 1, 2021
aa58da0
use custom test-testpypi to add simstore reqs
dwhswenson Jan 1, 2021
b7b22e7
one-liner of test-testpypi
dwhswenson Jan 1, 2021
7fdf2cf
will && work?
dwhswenson Jan 1, 2021
3931c99
Fix bash variable
dwhswenson Jan 2, 2021
ecc32f2
Try updating autorelease vendoring
dwhswenson Jan 2, 2021
e36d201
don't forget to add the file!
dwhswenson Jan 2, 2021
a2a10aa
fix missing dots
dwhswenson Jan 2, 2021
b77dac4
install extras in autorelease install
dwhswenson Jan 4, 2021
3fb2f49
remove comment
dwhswenson Jan 4, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 55 additions & 6 deletions paths_cli/commands/contents.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,64 @@
import click
from paths_cli.parameters import INPUT_FILE

UNNAMED_SECTIONS = ['steps', 'movechanges', 'samplesets', 'trajectories',
'snapshots']

NAME_TO_ATTR = {
'CVs': 'cvs',
'Volumes': 'volumes',
'Engines': 'engines',
'Networks': 'networks',
'Move Schemes': 'schemes',
'Simulations': 'pathsimulators',
'Tags': 'tags',
'Steps': 'steps',
'Move Changes': 'movechanges',
'SampleSets': 'samplesets',
'Trajectories': 'trajectories',
'Snapshots': 'snapshots'
}

@click.command(
'contents',
short_help="list named objects from an OPS .nc file",
)
@INPUT_FILE.clicked(required=True)
def contents(input_file):
@click.option('--table', type=str, required=False,
help="table to show results from")
def contents(input_file, table):
"""List the names of named objects in an OPS .nc file.

This is particularly useful when getting ready to use one of simulation
scripts (i.e., to identify exactly how a state or engine is named.)
"""
storage = INPUT_FILE.get(input_file)
print(storage)
if table is None:
report_all_tables(storage)
else:
table_attr = table.lower()
try:
store = getattr(storage, table_attr)
except AttributeError:
raise click.UsageError("Unknown table: '" + table_attr + "'")
else:
print(get_section_string(table_attr, store))


def get_section_string(label, store):
attr = NAME_TO_ATTR.get(label, label.lower())
if attr in UNNAMED_SECTIONS:
string = get_unnamed_section_string(label, store)
elif attr in ['tag', 'tags']:
string = get_section_string_nameable(label, store, _get_named_tags)
else:
string = get_section_string_nameable(label, store,
_get_named_namedobj)
return string


def report_all_tables(storage):
store_section_mapping = {
'CVs': storage.cvs, 'Volumes': storage.volumes,
'Engines': storage.engines, 'Networks': storage.networks,
Expand All @@ -26,12 +71,16 @@ def contents(input_file):
print(get_section_string_nameable('Tags', storage.tags, _get_named_tags))

print("\nData Objects:")
unnamed_sections = {
'Steps': storage.steps, 'Move Changes': storage.movechanges,
'SampleSets': storage.samplesets,
'Trajectories': storage.trajectories, 'Snapshots': storage.snapshots
data_object_mapping = {
'Steps': lambda storage: storage.steps,
'Move Changes': lambda storage: storage.movechanges,
'SampleSets': lambda storage: storage.samplesets,
'Trajectories': lambda storage: storage.trajectories,
'Snapshots': lambda storage: storage.snapshots
}
for section, store in unnamed_sections.items():

for section, store_func in data_object_mapping.items():
store = store_func(storage)
print(get_unnamed_section_string(section, store))

def _item_or_items(count):
Expand Down
1 change: 1 addition & 0 deletions paths_cli/commands/equilibrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def equilibrate_main(output_storage, scheme, init_conds, multiplier,
extra_steps):
import openpathsampling as paths
init_conds = scheme.initial_conditions_from_trajectories(init_conds)
scheme.assert_initial_conditions(init_conds)
simulation = paths.PathSampling(
storage=output_storage,
move_scheme=scheme,
Expand Down
48 changes: 48 additions & 0 deletions paths_cli/param_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,3 +315,51 @@ def get(self, storage, name):
raise RuntimeError(msg)

return result


class OPSStorageLoadMultiple(OPSStorageLoadSingle):
"""Objects that can guess a single object or have multiple specified.

Parameters
----------
param : :class:`.AbstractParameter`
the Option or Argument wrapping a click decorator
store : Str
the name of the store to search
value_strategies : List[Callable[(:class:`.Storage`, Str), Any]]
The strategies to be used when the CLI provides a value for this
parameter. Each should be a callable taking a storage and the string
input from the CLI, and should return the desired object or None if
it cannot be found.
none_strategies : List[Callable[:class:`openpathsampling.Storage, Any]]
The strategies to be used when the CLI does not provide a value for
this parameter. Each should be a callable taking a storage, and
returning the desired object or None if it cannot be found.
"""
def get(self, storage, names):
"""Load desired objects from storage.

Parameters
----------
storage : openpathsampling.Storage
the input storage to search
names : List[Str] or None
strings from CLI providing the identifier (name or index) for
this object; None if not provided
"""
if names == tuple():
names = None

if names is None or isinstance(names, (str, int)):
listified = True
names = [names]
else:
listified = False

results = [super(OPSStorageLoadMultiple, self).get(storage, name)
for name in names]

if listified:
results = results[0]

return results
13 changes: 6 additions & 7 deletions paths_cli/parameters.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import click
from paths_cli.param_core import (
Option, Argument, OPSStorageLoadSingle, OPSStorageLoadNames,
StorageLoader, GetByName, GetByNumber, GetOnly, GetOnlySnapshot,
GetPredefinedName
Option, Argument, OPSStorageLoadSingle, OPSStorageLoadMultiple,
OPSStorageLoadNames, StorageLoader, GetByName, GetByNumber, GetOnly,
GetOnlySnapshot, GetPredefinedName
)


Expand All @@ -18,10 +18,10 @@
store='schemes',
)

INIT_CONDS = OPSStorageLoadSingle(
param=Option('-t', '--init-conds',
INIT_CONDS = OPSStorageLoadMultiple(
param=Option('-t', '--init-conds', multiple=True,
help=("identifier for initial conditions "
+ "(sample set or trajectory)")),
+ "(sample set or trajectory)" + HELP_MULTIPLE)),
store='samplesets',
value_strategies=[GetByName('tags'), GetByNumber('samplesets'),
GetByNumber('trajectories')],
Expand Down Expand Up @@ -57,7 +57,6 @@
store='engines'
)


STATES = OPSStorageLoadNames(
param=Option('-s', '--state', type=str, multiple=True,
help='name of state' + HELP_MULTIPLE),
Expand Down
41 changes: 41 additions & 0 deletions paths_cli/tests/commands/test_contents.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,44 @@ def test_contents(tps_fixture):
assert results.output.split('\n') == expected
for truth, beauty in zip(expected, results.output.split('\n')):
assert truth == beauty

@pytest.mark.parametrize('table', ['volumes', 'trajectories', 'tags'])
def test_contents_table(tps_fixture, table):
scheme, network, engine, init_conds = tps_fixture
runner = CliRunner()
with runner.isolated_filesystem():
storage = paths.Storage("setup.nc", 'w')
for obj in tps_fixture:
storage.save(obj)
storage.tags['initial_conditions'] = init_conds

results = runner.invoke(contents, ['setup.nc', '--table', table])
cwd = os.getcwd()
expected = {
'volumes': [
f"Storage @ '{cwd}/setup.nc'",
"volumes: 8 items", "* A", "* B", "* plus 6 unnamed items",
""
],
'trajectories': [
f"Storage @ '{cwd}/setup.nc'",
"trajectories: 1 unnamed item",
""
],
'tags': [
f"Storage @ '{cwd}/setup.nc'",
"tags: 1 item",
"* initial_conditions",
""
],
}[table]
assert results.output.split("\n") == expected
assert results.exit_code == 0

def test_contents_table_error():
runner = CliRunner()
with runner.isolated_filesystem():
storage = paths.Storage("temp.nc", mode='w')
storage.close()
results = runner.invoke(contents, ['temp.nc', '--table', 'foo'])
assert results.exit_code != 0
3 changes: 2 additions & 1 deletion paths_cli/tests/commands/test_pathsampling.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ def test_pathsampling(tps_fixture):

results = runner.invoke(pathsampling, ['setup.nc', '-o', 'foo.nc',
'-n', '1000'])
assert results.exit_code == 0
expected_output = (f"True\n{scheme.__uuid__}\n{init_conds.__uuid__}"
"\n1000\n")

assert results.output == expected_output
assert results.exit_code == 0


def test_pathsampling_main(tps_fixture):
Expand Down
8 changes: 8 additions & 0 deletions paths_cli/tests/test_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,14 @@ def test_get_none(self, num_in_file):
obj = INIT_CONDS.get(st, None)
assert obj == stored_things[num_in_file - 1]

def test_get_multiple(self):
filename = self.create_file('number-traj')
storage = paths.Storage(filename, mode='r')
traj0, traj1 = self.PARAMETER.get(storage, (0, 1))
assert traj0 == self.traj
assert traj1 == self.other_traj


class TestINIT_SNAP(ParamInstanceTest):
PARAMETER = INIT_SNAP
def setup(self):
Expand Down