westpa 2022.12__cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of westpa might be problematic. Click here for more details.
- westpa/__init__.py +14 -0
- westpa/_version.py +21 -0
- westpa/analysis/__init__.py +5 -0
- westpa/analysis/core.py +746 -0
- westpa/analysis/statistics.py +27 -0
- westpa/analysis/trajectories.py +360 -0
- westpa/cli/__init__.py +0 -0
- westpa/cli/core/__init__.py +0 -0
- westpa/cli/core/w_fork.py +152 -0
- westpa/cli/core/w_init.py +230 -0
- westpa/cli/core/w_run.py +77 -0
- westpa/cli/core/w_states.py +212 -0
- westpa/cli/core/w_succ.py +99 -0
- westpa/cli/core/w_truncate.py +68 -0
- westpa/cli/tools/__init__.py +0 -0
- westpa/cli/tools/ploterr.py +506 -0
- westpa/cli/tools/plothist.py +706 -0
- westpa/cli/tools/w_assign.py +596 -0
- westpa/cli/tools/w_bins.py +166 -0
- westpa/cli/tools/w_crawl.py +119 -0
- westpa/cli/tools/w_direct.py +547 -0
- westpa/cli/tools/w_dumpsegs.py +94 -0
- westpa/cli/tools/w_eddist.py +506 -0
- westpa/cli/tools/w_fluxanl.py +376 -0
- westpa/cli/tools/w_ipa.py +833 -0
- westpa/cli/tools/w_kinavg.py +127 -0
- westpa/cli/tools/w_kinetics.py +96 -0
- westpa/cli/tools/w_multi_west.py +414 -0
- westpa/cli/tools/w_ntop.py +213 -0
- westpa/cli/tools/w_pdist.py +515 -0
- westpa/cli/tools/w_postanalysis_matrix.py +82 -0
- westpa/cli/tools/w_postanalysis_reweight.py +53 -0
- westpa/cli/tools/w_red.py +491 -0
- westpa/cli/tools/w_reweight.py +780 -0
- westpa/cli/tools/w_select.py +226 -0
- westpa/cli/tools/w_stateprobs.py +111 -0
- westpa/cli/tools/w_trace.py +599 -0
- westpa/core/__init__.py +0 -0
- westpa/core/_rc.py +673 -0
- westpa/core/binning/__init__.py +55 -0
- westpa/core/binning/_assign.cpython-313-x86_64-linux-gnu.so +0 -0
- westpa/core/binning/assign.py +455 -0
- westpa/core/binning/binless.py +96 -0
- westpa/core/binning/binless_driver.py +54 -0
- westpa/core/binning/binless_manager.py +190 -0
- westpa/core/binning/bins.py +47 -0
- westpa/core/binning/mab.py +506 -0
- westpa/core/binning/mab_driver.py +54 -0
- westpa/core/binning/mab_manager.py +198 -0
- westpa/core/data_manager.py +1694 -0
- westpa/core/extloader.py +74 -0
- westpa/core/h5io.py +995 -0
- westpa/core/kinetics/__init__.py +24 -0
- westpa/core/kinetics/_kinetics.cpython-313-x86_64-linux-gnu.so +0 -0
- westpa/core/kinetics/events.py +147 -0
- westpa/core/kinetics/matrates.py +156 -0
- westpa/core/kinetics/rate_averaging.py +266 -0
- westpa/core/progress.py +218 -0
- westpa/core/propagators/__init__.py +54 -0
- westpa/core/propagators/executable.py +719 -0
- westpa/core/reweight/__init__.py +14 -0
- westpa/core/reweight/_reweight.cpython-313-x86_64-linux-gnu.so +0 -0
- westpa/core/reweight/matrix.py +126 -0
- westpa/core/segment.py +119 -0
- westpa/core/sim_manager.py +835 -0
- westpa/core/states.py +359 -0
- westpa/core/systems.py +93 -0
- westpa/core/textio.py +74 -0
- westpa/core/trajectory.py +330 -0
- westpa/core/we_driver.py +910 -0
- westpa/core/wm_ops.py +43 -0
- westpa/core/yamlcfg.py +391 -0
- westpa/fasthist/__init__.py +34 -0
- westpa/fasthist/_fasthist.cpython-313-x86_64-linux-gnu.so +0 -0
- westpa/mclib/__init__.py +271 -0
- westpa/mclib/__main__.py +28 -0
- westpa/mclib/_mclib.cpython-313-x86_64-linux-gnu.so +0 -0
- westpa/oldtools/__init__.py +4 -0
- westpa/oldtools/aframe/__init__.py +35 -0
- westpa/oldtools/aframe/atool.py +75 -0
- westpa/oldtools/aframe/base_mixin.py +26 -0
- westpa/oldtools/aframe/binning.py +178 -0
- westpa/oldtools/aframe/data_reader.py +560 -0
- westpa/oldtools/aframe/iter_range.py +200 -0
- westpa/oldtools/aframe/kinetics.py +117 -0
- westpa/oldtools/aframe/mcbs.py +153 -0
- westpa/oldtools/aframe/output.py +39 -0
- westpa/oldtools/aframe/plotting.py +90 -0
- westpa/oldtools/aframe/trajwalker.py +126 -0
- westpa/oldtools/aframe/transitions.py +469 -0
- westpa/oldtools/cmds/__init__.py +0 -0
- westpa/oldtools/cmds/w_ttimes.py +361 -0
- westpa/oldtools/files.py +34 -0
- westpa/oldtools/miscfn.py +23 -0
- westpa/oldtools/stats/__init__.py +4 -0
- westpa/oldtools/stats/accumulator.py +35 -0
- westpa/oldtools/stats/edfs.py +129 -0
- westpa/oldtools/stats/mcbs.py +96 -0
- westpa/tools/__init__.py +33 -0
- westpa/tools/binning.py +472 -0
- westpa/tools/core.py +340 -0
- westpa/tools/data_reader.py +159 -0
- westpa/tools/dtypes.py +31 -0
- westpa/tools/iter_range.py +198 -0
- westpa/tools/kinetics_tool.py +340 -0
- westpa/tools/plot.py +283 -0
- westpa/tools/progress.py +17 -0
- westpa/tools/selected_segs.py +154 -0
- westpa/tools/wipi.py +751 -0
- westpa/trajtree/__init__.py +4 -0
- westpa/trajtree/_trajtree.cpython-313-x86_64-linux-gnu.so +0 -0
- westpa/trajtree/trajtree.py +117 -0
- westpa/westext/__init__.py +0 -0
- westpa/westext/adaptvoronoi/__init__.py +3 -0
- westpa/westext/adaptvoronoi/adaptVor_driver.py +214 -0
- westpa/westext/hamsm_restarting/__init__.py +3 -0
- westpa/westext/hamsm_restarting/example_overrides.py +35 -0
- westpa/westext/hamsm_restarting/restart_driver.py +1165 -0
- westpa/westext/stringmethod/__init__.py +11 -0
- westpa/westext/stringmethod/fourier_fitting.py +69 -0
- westpa/westext/stringmethod/string_driver.py +253 -0
- westpa/westext/stringmethod/string_method.py +306 -0
- westpa/westext/weed/BinCluster.py +180 -0
- westpa/westext/weed/ProbAdjustEquil.py +100 -0
- westpa/westext/weed/UncertMath.py +247 -0
- westpa/westext/weed/__init__.py +10 -0
- westpa/westext/weed/weed_driver.py +192 -0
- westpa/westext/wess/ProbAdjust.py +101 -0
- westpa/westext/wess/__init__.py +6 -0
- westpa/westext/wess/wess_driver.py +217 -0
- westpa/work_managers/__init__.py +57 -0
- westpa/work_managers/core.py +396 -0
- westpa/work_managers/environment.py +134 -0
- westpa/work_managers/mpi.py +318 -0
- westpa/work_managers/processes.py +187 -0
- westpa/work_managers/serial.py +28 -0
- westpa/work_managers/threads.py +79 -0
- westpa/work_managers/zeromq/__init__.py +20 -0
- westpa/work_managers/zeromq/core.py +641 -0
- westpa/work_managers/zeromq/node.py +131 -0
- westpa/work_managers/zeromq/work_manager.py +526 -0
- westpa/work_managers/zeromq/worker.py +320 -0
- westpa-2022.12.dist-info/AUTHORS +22 -0
- westpa-2022.12.dist-info/LICENSE +21 -0
- westpa-2022.12.dist-info/METADATA +193 -0
- westpa-2022.12.dist-info/RECORD +149 -0
- westpa-2022.12.dist-info/WHEEL +6 -0
- westpa-2022.12.dist-info/entry_points.txt +29 -0
- westpa-2022.12.dist-info/top_level.txt +1 -0
westpa/tools/core.py
ADDED
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
'''Core classes for creating WESTPA command-line tools'''
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import logging
|
|
5
|
+
import sys
|
|
6
|
+
import os
|
|
7
|
+
|
|
8
|
+
import westpa
|
|
9
|
+
from westpa import work_managers
|
|
10
|
+
from westpa.core import h5io
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
log = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class WESTToolComponent:
|
|
17
|
+
'''Base class for WEST command line tools and components used in constructing tools'''
|
|
18
|
+
|
|
19
|
+
def __init__(self):
|
|
20
|
+
self.config_required = False
|
|
21
|
+
self.include_args = {}
|
|
22
|
+
self.arg_defaults = {}
|
|
23
|
+
self.parser = None
|
|
24
|
+
self.args = None
|
|
25
|
+
|
|
26
|
+
def include_arg(self, argname):
|
|
27
|
+
self.include_args[argname] = True
|
|
28
|
+
|
|
29
|
+
def exclude_arg(self, argname):
|
|
30
|
+
self.include_args[argname] = False
|
|
31
|
+
|
|
32
|
+
def set_arg_default(self, argname, value):
|
|
33
|
+
self.arg_defaults[argname] = value
|
|
34
|
+
|
|
35
|
+
def add_args(self, parser):
|
|
36
|
+
'''Add arguments specific to this component to the given argparse parser.'''
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
def process_args(self, args):
|
|
40
|
+
'''Take argparse-processed arguments associated with this component and deal
|
|
41
|
+
with them appropriately (setting instance variables, etc)'''
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
def add_all_args(self, parser):
|
|
45
|
+
'''Add arguments for all components from which this class derives to the given parser,
|
|
46
|
+
starting with the class highest up the inheritance chain (most distant ancestor).'''
|
|
47
|
+
self.parser = parser
|
|
48
|
+
for cls in reversed(self.__class__.__mro__):
|
|
49
|
+
try:
|
|
50
|
+
fn = cls.__dict__['add_args']
|
|
51
|
+
except KeyError:
|
|
52
|
+
pass
|
|
53
|
+
else:
|
|
54
|
+
fn(self, parser)
|
|
55
|
+
|
|
56
|
+
def process_all_args(self, args):
|
|
57
|
+
self.args = args
|
|
58
|
+
'''Process arguments for all components from which this class derives,
|
|
59
|
+
starting with the class highest up the inheritance chain (most distant ancestor).'''
|
|
60
|
+
for cls in reversed(self.__class__.__mro__):
|
|
61
|
+
try:
|
|
62
|
+
fn = cls.__dict__['process_args']
|
|
63
|
+
except KeyError:
|
|
64
|
+
pass
|
|
65
|
+
else:
|
|
66
|
+
fn(self, args)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class WESTTool(WESTToolComponent):
|
|
70
|
+
'''Base class for WEST command line tools'''
|
|
71
|
+
|
|
72
|
+
prog = None
|
|
73
|
+
usage = None
|
|
74
|
+
description = None
|
|
75
|
+
epilog = None
|
|
76
|
+
|
|
77
|
+
def __init__(self):
|
|
78
|
+
super().__init__()
|
|
79
|
+
|
|
80
|
+
def add_args(self, parser):
|
|
81
|
+
'''Add arguments specific to this tool to the given argparse parser.'''
|
|
82
|
+
westpa.rc.add_args(parser)
|
|
83
|
+
|
|
84
|
+
def process_args(self, args):
|
|
85
|
+
'''Take argparse-processed arguments associated with this tool and deal
|
|
86
|
+
with them appropriately (setting instance variables, etc)'''
|
|
87
|
+
westpa.rc.process_args(args, config_required=self.config_required)
|
|
88
|
+
|
|
89
|
+
def make_parser(self, prog=None, usage=None, description=None, epilog=None, args=None):
|
|
90
|
+
prog = prog or self.prog
|
|
91
|
+
usage = usage or self.usage
|
|
92
|
+
description = description or self.description
|
|
93
|
+
epilog = epilog or self.epilog
|
|
94
|
+
parser = argparse.ArgumentParser(
|
|
95
|
+
prog=prog,
|
|
96
|
+
usage=usage,
|
|
97
|
+
description=description,
|
|
98
|
+
epilog=epilog,
|
|
99
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
100
|
+
conflict_handler='resolve',
|
|
101
|
+
)
|
|
102
|
+
self.add_all_args(parser)
|
|
103
|
+
return parser
|
|
104
|
+
|
|
105
|
+
def make_parser_and_process(self, prog=None, usage=None, description=None, epilog=None, args=None):
|
|
106
|
+
'''A convenience function to create a parser, call add_all_args(), and then call process_all_args().
|
|
107
|
+
The argument namespace is returned.'''
|
|
108
|
+
parser = self.make_parser(prog, usage, description, epilog, args)
|
|
109
|
+
args = parser.parse_args(args)
|
|
110
|
+
self.process_all_args(args)
|
|
111
|
+
return args
|
|
112
|
+
|
|
113
|
+
def go(self):
|
|
114
|
+
'''Perform the analysis associated with this tool.'''
|
|
115
|
+
raise NotImplementedError
|
|
116
|
+
|
|
117
|
+
def main(self):
|
|
118
|
+
'''A convenience function to make a parser, parse and process arguments, then call self.go()'''
|
|
119
|
+
self.make_parser_and_process()
|
|
120
|
+
self.go()
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class WESTParallelTool(WESTTool):
|
|
124
|
+
'''Base class for command-line tools parallelized with wwmgr. This automatically adds and processes
|
|
125
|
+
wwmgr command-line arguments and creates a work manager at self.work_manager.'''
|
|
126
|
+
|
|
127
|
+
def __init__(self, wm_env=None):
|
|
128
|
+
super().__init__()
|
|
129
|
+
self.work_manager = None
|
|
130
|
+
self.wm_env = wm_env or work_managers.environment.default_env
|
|
131
|
+
self.max_queue_len = None
|
|
132
|
+
|
|
133
|
+
def make_parser_and_process(self, prog=None, usage=None, description=None, epilog=None, args=None):
|
|
134
|
+
'''A convenience function to create a parser, call add_all_args(), and then call process_all_args().
|
|
135
|
+
The argument namespace is returned.'''
|
|
136
|
+
parser = self.make_parser(prog, usage, description, epilog, args)
|
|
137
|
+
self.wm_env.add_wm_args(parser)
|
|
138
|
+
|
|
139
|
+
args = parser.parse_args(args)
|
|
140
|
+
self.wm_env.process_wm_args(args)
|
|
141
|
+
|
|
142
|
+
# Instantiate work manager
|
|
143
|
+
self.work_manager = self.wm_env.make_work_manager()
|
|
144
|
+
|
|
145
|
+
# Process args
|
|
146
|
+
self.process_all_args(args)
|
|
147
|
+
return args
|
|
148
|
+
|
|
149
|
+
def add_args(self, parser):
|
|
150
|
+
pgroup = parser.add_argument_group('parallelization options')
|
|
151
|
+
pgroup.add_argument(
|
|
152
|
+
'--max-queue-length',
|
|
153
|
+
type=int,
|
|
154
|
+
help='''Maximum number of tasks that can be queued. Useful to limit RAM use
|
|
155
|
+
for tasks that have very large requests/response. Default: no limit.''',
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
def process_args(self, args):
|
|
159
|
+
self.max_queue_len = args.max_queue_length
|
|
160
|
+
log.debug('max queue length: {!r}'.format(self.max_queue_len))
|
|
161
|
+
|
|
162
|
+
def go(self):
|
|
163
|
+
'''Perform the analysis associated with this tool.'''
|
|
164
|
+
raise NotImplementedError
|
|
165
|
+
|
|
166
|
+
def main(self):
|
|
167
|
+
'''A convenience function to make a parser, parse and process arguments, then run self.go() in the master process.'''
|
|
168
|
+
self.make_parser_and_process()
|
|
169
|
+
with self.work_manager:
|
|
170
|
+
if self.work_manager.is_master:
|
|
171
|
+
self.go()
|
|
172
|
+
else:
|
|
173
|
+
self.work_manager.run()
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class WESTMultiTool(WESTParallelTool):
|
|
177
|
+
'''Base class for command-line tools which work with multiple simulations. Automatically parses for
|
|
178
|
+
and gives commands to load multiple files.'''
|
|
179
|
+
|
|
180
|
+
def __init__(self, wm_env=None):
|
|
181
|
+
super(WESTTool, self).__init__()
|
|
182
|
+
self.ntrials = 0
|
|
183
|
+
self.master = None
|
|
184
|
+
|
|
185
|
+
def make_parser_and_process(self, prog=None, usage=None, description=None, epilog=None, args=None):
|
|
186
|
+
'''A convenience function to create a parser, call add_all_args(), and then call process_all_args().
|
|
187
|
+
The argument namespace is returned.'''
|
|
188
|
+
parser = self.make_parser(prog, usage, description, epilog, args)
|
|
189
|
+
args = parser.parse_args(args)
|
|
190
|
+
|
|
191
|
+
# Process args
|
|
192
|
+
self.process_all_args(args)
|
|
193
|
+
return args
|
|
194
|
+
|
|
195
|
+
def parse_from_yaml(self, yamlfilepath):
|
|
196
|
+
'''Parse options from YAML input file. Command line arguments take
|
|
197
|
+
precedence over options specified in the YAML hierarchy.
|
|
198
|
+
TODO: add description on how YAML files should be constructed.
|
|
199
|
+
'''
|
|
200
|
+
import yaml
|
|
201
|
+
|
|
202
|
+
with open(yamlfilepath, 'r') as yamlfile:
|
|
203
|
+
self.yamlargdict = yaml.load(yamlfile, Loader=yaml.Loader)
|
|
204
|
+
# add in options here for intelligent processing of files
|
|
205
|
+
|
|
206
|
+
def add_args(self, parser):
|
|
207
|
+
mgroup = parser.add_argument_group('multiple simulation options')
|
|
208
|
+
mgroup.add_argument(
|
|
209
|
+
'-m',
|
|
210
|
+
'--master',
|
|
211
|
+
default=os.getcwd(),
|
|
212
|
+
help='''Master path of simulations; this is where all the small sims
|
|
213
|
+
are stored.''',
|
|
214
|
+
)
|
|
215
|
+
mgroup.add_argument('-n', '--sims', default=0, help='''The number of simulation directories. Assumes leading zeros.''')
|
|
216
|
+
|
|
217
|
+
class NoSimulationsException(Exception):
|
|
218
|
+
pass
|
|
219
|
+
|
|
220
|
+
def generate_file_list(self, key_list):
|
|
221
|
+
'''A convenience function which takes in a list of keys that are filenames, and returns a dictionary
|
|
222
|
+
which contains all the individual files loaded inside of a dictionary keyed to the filename.'''
|
|
223
|
+
return_dict = {}
|
|
224
|
+
if self.ntrials == 0:
|
|
225
|
+
raise self.NoSimulationsException('You must specify the number of simulations.')
|
|
226
|
+
|
|
227
|
+
for key in key_list:
|
|
228
|
+
return_dict[key] = {}
|
|
229
|
+
for i in range(1, self.ntrials + 1):
|
|
230
|
+
# Need to not make this hard coded, but who cares for now.
|
|
231
|
+
for key in key_list:
|
|
232
|
+
return_dict[key][i] = h5io.WESTPAH5File(os.path.join(self.master, str(i).zfill(2), key), 'r')
|
|
233
|
+
return return_dict
|
|
234
|
+
|
|
235
|
+
def process_args(self, args):
|
|
236
|
+
self.master = args.master
|
|
237
|
+
self.ntrials = int(args.sims)
|
|
238
|
+
log.debug('Simulations loaded from: {!r}'.format(self.master))
|
|
239
|
+
log.debug('Number of simulations: {!r}'.format(self.ntrials))
|
|
240
|
+
|
|
241
|
+
def go(self):
|
|
242
|
+
'''Perform the analysis associated with this tool.'''
|
|
243
|
+
raise NotImplementedError
|
|
244
|
+
|
|
245
|
+
def main(self):
|
|
246
|
+
'''A convenience function to make a parser, parse and process arguments, then run self.go() in the master process.'''
|
|
247
|
+
self.make_parser_and_process()
|
|
248
|
+
self.go()
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
class WESTSubcommand(WESTToolComponent):
|
|
252
|
+
'''Base class for command-line tool subcommands. A little sugar for making this
|
|
253
|
+
more uniform.'''
|
|
254
|
+
|
|
255
|
+
subcommand = None
|
|
256
|
+
help_text = None
|
|
257
|
+
description = None
|
|
258
|
+
|
|
259
|
+
def __init__(self, parent):
|
|
260
|
+
self.parent = parent
|
|
261
|
+
self.subparser = None
|
|
262
|
+
|
|
263
|
+
def add_to_subparsers(self, subparsers):
|
|
264
|
+
subparser = subparsers.add_parser(
|
|
265
|
+
self.subcommand,
|
|
266
|
+
help=self.help_text,
|
|
267
|
+
description=self.description,
|
|
268
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
269
|
+
)
|
|
270
|
+
self.add_all_args(subparser)
|
|
271
|
+
subparser.set_defaults(west_subcommand=self)
|
|
272
|
+
self.subparser = subparser
|
|
273
|
+
|
|
274
|
+
def go(self):
|
|
275
|
+
raise NotImplementedError
|
|
276
|
+
|
|
277
|
+
@property
|
|
278
|
+
def work_manager(self):
|
|
279
|
+
'''The work manager for this tool. Raises AttributeError if this is not a parallel
|
|
280
|
+
tool.'''
|
|
281
|
+
return self.parent.work_manager
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
class _WESTSubcommandHelp(WESTSubcommand):
|
|
285
|
+
subcommand = 'help'
|
|
286
|
+
help_text = 'print help for this command or individual subcommands'
|
|
287
|
+
|
|
288
|
+
def add_args(self, parser):
|
|
289
|
+
parser.add_argument('command', nargs='?', choices=[subcommand.subcommand for subcommand in self.parent.subcommands])
|
|
290
|
+
|
|
291
|
+
def process_args(self, args):
|
|
292
|
+
self.command = args.command
|
|
293
|
+
|
|
294
|
+
def go(self):
|
|
295
|
+
if self.command is None:
|
|
296
|
+
# Get parent help
|
|
297
|
+
self.parent.parser.print_help(sys.stdout)
|
|
298
|
+
else:
|
|
299
|
+
self.parent._subcommand_instances[self.command].subparser.print_help(sys.stdout)
|
|
300
|
+
sys.exit(0)
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
class WESTMasterCommand(WESTTool):
|
|
304
|
+
'''Base class for command-line tools that employ subcommands'''
|
|
305
|
+
|
|
306
|
+
subparsers_title = None
|
|
307
|
+
subcommands = None
|
|
308
|
+
|
|
309
|
+
include_help_command = True
|
|
310
|
+
|
|
311
|
+
def __init__(self):
|
|
312
|
+
super().__init__()
|
|
313
|
+
self._subcommand = None
|
|
314
|
+
self._subcommand_instances = {subcommand_class.subcommand: subcommand_class(self) for subcommand_class in self.subcommands}
|
|
315
|
+
|
|
316
|
+
# Sanity checks
|
|
317
|
+
if __debug__:
|
|
318
|
+
for scclass in self.subcommands:
|
|
319
|
+
assert scclass.subcommand, 'subcommand {!r} does not define a "subcommand" class variable'.format(scclass)
|
|
320
|
+
|
|
321
|
+
def add_args(self, parser):
|
|
322
|
+
subparsers = parser.add_subparsers(title=self.subparsers_title)
|
|
323
|
+
if self.include_help_command:
|
|
324
|
+
_WESTSubcommandHelp(self).add_to_subparsers(subparsers)
|
|
325
|
+
for instance in self._subcommand_instances.values():
|
|
326
|
+
instance.add_to_subparsers(subparsers)
|
|
327
|
+
|
|
328
|
+
def process_args(self, args):
|
|
329
|
+
try:
|
|
330
|
+
self._subcommand = args.west_subcommand
|
|
331
|
+
except AttributeError:
|
|
332
|
+
# No subcommand given; display help
|
|
333
|
+
print('Error: a command is required. See below.', file=sys.stderr)
|
|
334
|
+
self.parser.print_help(sys.stderr)
|
|
335
|
+
sys.exit(2)
|
|
336
|
+
else:
|
|
337
|
+
self._subcommand.process_all_args(args)
|
|
338
|
+
|
|
339
|
+
def go(self):
|
|
340
|
+
self._subcommand.go()
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from numpy import index_exp
|
|
3
|
+
|
|
4
|
+
from .core import WESTToolComponent
|
|
5
|
+
|
|
6
|
+
import westpa
|
|
7
|
+
from westpa.core.extloader import get_object
|
|
8
|
+
from westpa.core.h5io import FnDSSpec, MultiDSSpec, SingleSegmentDSSpec, SingleIterDSSpec
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _get_parent_ids(n_iter, iter_group):
|
|
12
|
+
seg_index = iter_group['seg_index']
|
|
13
|
+
try:
|
|
14
|
+
return seg_index['parent_id'][:]
|
|
15
|
+
except ValueError:
|
|
16
|
+
# field not found
|
|
17
|
+
offsets = seg_index['parents_offset'][:]
|
|
18
|
+
all_parents = iter_group['parents'][...]
|
|
19
|
+
return np.require(all_parents.take(offsets), dtype=np.int64)
|
|
20
|
+
else:
|
|
21
|
+
return seg_index['parent_id']
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class WESTDataReader(WESTToolComponent):
|
|
25
|
+
'''Tool for reading data from WEST-related HDF5 files. Coordinates finding
|
|
26
|
+
the main HDF5 file from west.cfg or command line arguments, caching of certain
|
|
27
|
+
kinds of data (eventually), and retrieving auxiliary data sets from various
|
|
28
|
+
places.'''
|
|
29
|
+
|
|
30
|
+
def __init__(self):
|
|
31
|
+
super().__init__()
|
|
32
|
+
self.data_manager = westpa.rc.get_data_manager()
|
|
33
|
+
self.we_h5filename = None
|
|
34
|
+
|
|
35
|
+
self._weight_dsspec = None
|
|
36
|
+
self._parent_id_dsspec = None
|
|
37
|
+
|
|
38
|
+
def add_args(self, parser):
|
|
39
|
+
group = parser.add_argument_group('WEST input data options')
|
|
40
|
+
group.add_argument(
|
|
41
|
+
'-W',
|
|
42
|
+
'--west-data',
|
|
43
|
+
dest='we_h5filename',
|
|
44
|
+
metavar='WEST_H5FILE',
|
|
45
|
+
help='''Take WEST data from WEST_H5FILE (default: read from the HDF5 file specified in west.cfg).''',
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
def process_args(self, args):
|
|
49
|
+
if args.we_h5filename:
|
|
50
|
+
self.data_manager.we_h5filename = self.we_h5filename = args.we_h5filename
|
|
51
|
+
else:
|
|
52
|
+
self.we_h5filename = self.data_manager.we_h5filename
|
|
53
|
+
|
|
54
|
+
def open(self, mode='r'):
|
|
55
|
+
self.data_manager.open_backing(mode)
|
|
56
|
+
|
|
57
|
+
def close(self):
|
|
58
|
+
self.data_manager.close_backing()
|
|
59
|
+
|
|
60
|
+
def __getattr__(self, key):
|
|
61
|
+
return getattr(self.data_manager, key)
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def weight_dsspec(self):
|
|
65
|
+
if self._weight_dsspec is None:
|
|
66
|
+
assert self.we_h5filename is not None
|
|
67
|
+
self._weight_dsspec = SingleIterDSSpec(self.we_h5filename, 'seg_index', slice=index_exp['weight'])
|
|
68
|
+
return self._weight_dsspec
|
|
69
|
+
|
|
70
|
+
@property
|
|
71
|
+
def parent_id_dsspec(self):
|
|
72
|
+
if self._parent_id_dsspec is None:
|
|
73
|
+
assert self.we_h5filename is not None
|
|
74
|
+
# self._parent_id_dsspec = SingleIterDSSpec(self.we_h5filename, 'seg_index', slice=index_exp['parent_id'])
|
|
75
|
+
self._parent_id_dsspec = FnDSSpec(self.we_h5filename, _get_parent_ids)
|
|
76
|
+
return self._parent_id_dsspec
|
|
77
|
+
|
|
78
|
+
def __enter__(self):
|
|
79
|
+
self.open('r')
|
|
80
|
+
return self
|
|
81
|
+
|
|
82
|
+
def __exit__(self, exc_type, exc_val, exc_traceback):
|
|
83
|
+
self.close()
|
|
84
|
+
return False
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class WESTDSSynthesizer(WESTToolComponent):
|
|
88
|
+
'''Tool for synthesizing a dataset for analysis from other datasets. This
|
|
89
|
+
may be done using a custom function, or a list of "data set specifications".
|
|
90
|
+
It is anticipated that if several source datasets are required, then a tool
|
|
91
|
+
will have multiple instances of this class.'''
|
|
92
|
+
|
|
93
|
+
group_name = 'input dataset options'
|
|
94
|
+
|
|
95
|
+
def __init__(self, default_dsname=None, h5filename=None):
|
|
96
|
+
super().__init__()
|
|
97
|
+
|
|
98
|
+
self.h5filename = h5filename
|
|
99
|
+
self.default_dsname = default_dsname
|
|
100
|
+
|
|
101
|
+
self.dsspec = None
|
|
102
|
+
|
|
103
|
+
def add_args(self, parser):
|
|
104
|
+
igroup = parser.add_argument_group(self.group_name).add_mutually_exclusive_group(required=not bool(self.default_dsname))
|
|
105
|
+
|
|
106
|
+
igroup.add_argument(
|
|
107
|
+
'--construct-dataset',
|
|
108
|
+
help='''Use the given function (as in module.function) to extract source data.
|
|
109
|
+
This function will be called once per iteration as function(n_iter, iter_group)
|
|
110
|
+
to construct data for one iteration. Data returned must be indexable as
|
|
111
|
+
[seg_id][timepoint][dimension]''',
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
igroup.add_argument('--dsspecs', nargs='+', metavar='DSSPEC', help='''Construct source data from one or more DSSPECs.''')
|
|
115
|
+
|
|
116
|
+
def process_args(self, args):
|
|
117
|
+
if args.construct_dataset:
|
|
118
|
+
self.dsspec = FnDSSpec(self.h5filename, get_object(args.construct_dataset, path=['.']))
|
|
119
|
+
elif args.dsspecs:
|
|
120
|
+
self.dsspec = MultiDSSpec([SingleSegmentDSSpec.from_string(dsspec, self.h5filename) for dsspec in args.dsspecs])
|
|
121
|
+
else:
|
|
122
|
+
# we can only get here if a default dataset name was specified
|
|
123
|
+
assert self.default_dsname
|
|
124
|
+
self.dsspec = SingleSegmentDSSpec(self.h5filename, self.default_dsname)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class WESTWDSSynthesizer(WESTToolComponent):
|
|
128
|
+
group_name = 'weight dataset options'
|
|
129
|
+
|
|
130
|
+
def __init__(self, default_dsname=None, h5filename=None):
|
|
131
|
+
super(WESTWDSSynthesizer, self).__init__()
|
|
132
|
+
|
|
133
|
+
self.h5filename = h5filename
|
|
134
|
+
self.default_dsname = default_dsname
|
|
135
|
+
|
|
136
|
+
self.dsspec = None
|
|
137
|
+
|
|
138
|
+
def add_args(self, parser):
|
|
139
|
+
wgroup = parser.add_argument_group(self.group_name).add_mutually_exclusive_group(required=not bool(self.default_dsname))
|
|
140
|
+
|
|
141
|
+
wgroup.add_argument(
|
|
142
|
+
'--construct-wdataset',
|
|
143
|
+
help='''Use the given function (as in module.function) to extract source data.
|
|
144
|
+
This function will be called once per iteration as function(n_iter, iter_group)
|
|
145
|
+
to construct data for one iteration. Data returned must be indexable as
|
|
146
|
+
[seg_id]''',
|
|
147
|
+
)
|
|
148
|
+
wgroup.add_argument('--wdsspecs', nargs='+', metavar='WDSSPEC', help='''Construct weight data from one or more DSSPECs.''')
|
|
149
|
+
|
|
150
|
+
def process_args(self, args):
|
|
151
|
+
if args.construct_wdataset:
|
|
152
|
+
self.dsspec = FnDSSpec(self.h5filename, get_object(args.construct_wdataset, path=['.']))
|
|
153
|
+
elif args.dsspecs:
|
|
154
|
+
self.dsspec = MultiDSSpec([SingleSegmentDSSpec.from_string(dsspec, self.h5filename) for dsspec in args.dsspecs])
|
|
155
|
+
else:
|
|
156
|
+
# we can only get here if a default dataset name was specified
|
|
157
|
+
assert self.default_dsname
|
|
158
|
+
# we gotta slice by weight for weights if we want to get the default to work
|
|
159
|
+
self.dsspec = SingleIterDSSpec(self.h5filename, self.default_dsname, slice=np.index_exp['weight'])
|
westpa/tools/dtypes.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'''Numpy/HDF5 data types shared among several WESTPA tools'''
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
# Pick up a few data types from the WEST core if possible
|
|
6
|
+
try:
|
|
7
|
+
from westpa.core.data_manager import n_iter_dtype, seg_id_dtype, weight_dtype
|
|
8
|
+
except ImportError:
|
|
9
|
+
n_iter_dtype = np.uint32
|
|
10
|
+
seg_id_dtype = np.int64
|
|
11
|
+
weight_dtype = np.float64
|
|
12
|
+
|
|
13
|
+
# A quantity averaged over iterations
|
|
14
|
+
iter_block_ci_dtype = np.dtype(
|
|
15
|
+
[
|
|
16
|
+
('iter_start', n_iter_dtype),
|
|
17
|
+
('iter_stop', n_iter_dtype),
|
|
18
|
+
('expected', np.float64),
|
|
19
|
+
('ci_lbound', np.float64),
|
|
20
|
+
('ci_ubound', np.float64),
|
|
21
|
+
('sterr', np.float64),
|
|
22
|
+
('corr_len', n_iter_dtype),
|
|
23
|
+
]
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# A quantity to store event duration distribution stuff.
|
|
27
|
+
# Comes from the old w_kinetics.
|
|
28
|
+
|
|
29
|
+
ed_list_dtype = np.dtype(
|
|
30
|
+
[('istate', np.uint16), ('fstate', np.uint16), ('duration', np.float64), ('weight', np.float64), ('seg_id', seg_id_dtype)]
|
|
31
|
+
)
|