westpa 2022.13__cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.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.
- westpa/__init__.py +14 -0
- westpa/_version.py +21 -0
- westpa/analysis/__init__.py +5 -0
- westpa/analysis/core.py +749 -0
- westpa/analysis/statistics.py +27 -0
- westpa/analysis/trajectories.py +369 -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 +597 -0
- westpa/cli/tools/w_bins.py +166 -0
- westpa/cli/tools/w_crawl.py +119 -0
- westpa/cli/tools/w_direct.py +557 -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 +832 -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_timings.py +113 -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.c +36018 -0
- westpa/core/binning/_assign.cpython-312-aarch64-linux-gnu.so +0 -0
- westpa/core/binning/_assign.pyx +370 -0
- westpa/core/binning/assign.py +454 -0
- westpa/core/binning/binless.py +96 -0
- westpa/core/binning/binless_driver.py +54 -0
- westpa/core/binning/binless_manager.py +189 -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 +197 -0
- westpa/core/data_manager.py +1761 -0
- westpa/core/extloader.py +74 -0
- westpa/core/h5io.py +1079 -0
- westpa/core/kinetics/__init__.py +24 -0
- westpa/core/kinetics/_kinetics.c +45174 -0
- westpa/core/kinetics/_kinetics.cpython-312-aarch64-linux-gnu.so +0 -0
- westpa/core/kinetics/_kinetics.pyx +815 -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 +592 -0
- westpa/core/propagators/loaders.py +196 -0
- westpa/core/reweight/__init__.py +14 -0
- westpa/core/reweight/_reweight.c +36899 -0
- westpa/core/reweight/_reweight.cpython-312-aarch64-linux-gnu.so +0 -0
- westpa/core/reweight/_reweight.pyx +439 -0
- westpa/core/reweight/matrix.py +126 -0
- westpa/core/segment.py +119 -0
- westpa/core/sim_manager.py +839 -0
- westpa/core/states.py +359 -0
- westpa/core/systems.py +93 -0
- westpa/core/textio.py +74 -0
- westpa/core/trajectory.py +603 -0
- westpa/core/we_driver.py +910 -0
- westpa/core/wm_ops.py +43 -0
- westpa/core/yamlcfg.py +298 -0
- westpa/fasthist/__init__.py +34 -0
- westpa/fasthist/_fasthist.c +38755 -0
- westpa/fasthist/_fasthist.cpython-312-aarch64-linux-gnu.so +0 -0
- westpa/fasthist/_fasthist.pyx +222 -0
- westpa/mclib/__init__.py +271 -0
- westpa/mclib/__main__.py +28 -0
- westpa/mclib/_mclib.c +34610 -0
- westpa/mclib/_mclib.cpython-312-aarch64-linux-gnu.so +0 -0
- westpa/mclib/_mclib.pyx +226 -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 +88 -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 +343 -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.c +17829 -0
- westpa/trajtree/_trajtree.cpython-312-aarch64-linux-gnu.so +0 -0
- westpa/trajtree/_trajtree.pyx +130 -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 +201 -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 +635 -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.13.dist-info/METADATA +179 -0
- westpa-2022.13.dist-info/RECORD +162 -0
- westpa-2022.13.dist-info/WHEEL +7 -0
- westpa-2022.13.dist-info/entry_points.txt +30 -0
- westpa-2022.13.dist-info/licenses/LICENSE +21 -0
- westpa-2022.13.dist-info/top_level.txt +1 -0
westpa/core/_rc.py
ADDED
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
"""WEST run control and configuration routines"""
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
import errno
|
|
7
|
+
import logging
|
|
8
|
+
import warnings
|
|
9
|
+
from copy import deepcopy
|
|
10
|
+
from datetime import timedelta
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
import westpa
|
|
15
|
+
import westpa.core.data_manager
|
|
16
|
+
from westpa.core.binning.assign import BinMapper
|
|
17
|
+
from westpa.core.binning import RectilinearBinMapper, RecursiveBinMapper, MABBinMapper, BinlessMapper
|
|
18
|
+
from .yamlcfg import YAMLConfig
|
|
19
|
+
from .systems import WESTSystem
|
|
20
|
+
from . import extloader
|
|
21
|
+
from ..work_managers import SerialWorkManager
|
|
22
|
+
|
|
23
|
+
log = logging.getLogger('westpa.rc')
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def bins_from_yaml_dict(bin_dict):
|
|
27
|
+
kwargs = deepcopy(bin_dict)
|
|
28
|
+
typename = kwargs.pop('type')
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
mapper_type = getattr(sys.modules['westpa.core.binning'], typename)
|
|
32
|
+
except AttributeError:
|
|
33
|
+
try:
|
|
34
|
+
mapper_type = extloader.get_object(typename)
|
|
35
|
+
except AttributeError:
|
|
36
|
+
raise KeyError('unknown bin mapper type {!r}'.format(typename))
|
|
37
|
+
|
|
38
|
+
if not issubclass(mapper_type, BinMapper):
|
|
39
|
+
raise ValueError('{} is not a BinMapper'.format(mapper_type.__name__))
|
|
40
|
+
|
|
41
|
+
if mapper_type is RectilinearBinMapper:
|
|
42
|
+
boundary_lists = kwargs.pop('boundaries', None)
|
|
43
|
+
if boundary_lists is None:
|
|
44
|
+
raise KeyError('RectilinearBinMapper: missing boundaries')
|
|
45
|
+
parsed_lists = boundary_lists[:]
|
|
46
|
+
for iboundary, boundary in enumerate(boundary_lists):
|
|
47
|
+
if boundary.__class__ == str:
|
|
48
|
+
parsed_lists[iboundary] = parsePCV(boundary)[0]
|
|
49
|
+
else:
|
|
50
|
+
parsed_lists[iboundary] = list(map((lambda x: float(x) if isinstance(x, str) else x), boundary))
|
|
51
|
+
return RectilinearBinMapper(parsed_lists)
|
|
52
|
+
elif mapper_type is RecursiveBinMapper:
|
|
53
|
+
base_mapper_config = kwargs.pop('base', None)
|
|
54
|
+
base_mapper_config = kwargs.pop('base_mapper', base_mapper_config)
|
|
55
|
+
if base_mapper_config is None:
|
|
56
|
+
raise KeyError('RecursiveBinMapper: missing base_mapper')
|
|
57
|
+
|
|
58
|
+
base_mapper = bins_from_yaml_dict(base_mapper_config)
|
|
59
|
+
start_index = kwargs.pop('start_index', 0)
|
|
60
|
+
|
|
61
|
+
rec_mapper = RecursiveBinMapper(base_mapper, start_index)
|
|
62
|
+
mapper_configs = kwargs.pop('mappers')
|
|
63
|
+
mappers = []
|
|
64
|
+
if mapper_configs is not None:
|
|
65
|
+
for config in mapper_configs:
|
|
66
|
+
replaced_bin = config.pop('replaces_bin_at', None)
|
|
67
|
+
replaced_bin = config.pop('at', replaced_bin)
|
|
68
|
+
if replaced_bin is None:
|
|
69
|
+
raise KeyError('RecursiveBinMapper: missing replaces_bin_at for ' 'at least one of the child mappers')
|
|
70
|
+
mapper = bins_from_yaml_dict(config)
|
|
71
|
+
mappers.append((mapper, replaced_bin))
|
|
72
|
+
|
|
73
|
+
for mapper, replaced_bin in mappers:
|
|
74
|
+
rec_mapper.add_mapper(mapper, replaced_bin)
|
|
75
|
+
|
|
76
|
+
return rec_mapper
|
|
77
|
+
else:
|
|
78
|
+
try:
|
|
79
|
+
return mapper_type(**kwargs)
|
|
80
|
+
except Exception:
|
|
81
|
+
log.exception('exception instantiating mapper')
|
|
82
|
+
raise
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def detect_mab_mapper(mapper):
|
|
86
|
+
if isinstance(mapper, MABBinMapper):
|
|
87
|
+
return True
|
|
88
|
+
elif isinstance(mapper, RecursiveBinMapper):
|
|
89
|
+
if detect_mab_mapper(mapper.base_mapper):
|
|
90
|
+
return True
|
|
91
|
+
|
|
92
|
+
for ibin in mapper._recursion_targets:
|
|
93
|
+
rec_mapper = mapper._recursion_targets[ibin]
|
|
94
|
+
if detect_mab_mapper(rec_mapper):
|
|
95
|
+
return True
|
|
96
|
+
else:
|
|
97
|
+
return False
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def detect_binless_mapper(mapper):
|
|
101
|
+
if isinstance(mapper, BinlessMapper):
|
|
102
|
+
return True
|
|
103
|
+
elif isinstance(mapper, RecursiveBinMapper):
|
|
104
|
+
if detect_binless_mapper(mapper.base_mapper):
|
|
105
|
+
return True
|
|
106
|
+
|
|
107
|
+
for ibin in mapper._recursion_targets:
|
|
108
|
+
rec_mapper = mapper._recursion_targets[ibin]
|
|
109
|
+
if detect_binless_mapper(rec_mapper):
|
|
110
|
+
return True
|
|
111
|
+
else:
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def parsePCV(pc_str):
|
|
116
|
+
# Execute arbitrary code within a limited
|
|
117
|
+
# scope to avoid nastyness. Stolen fully from
|
|
118
|
+
# other parts of the WESTPA code.
|
|
119
|
+
namespace = {'math': math, 'numpy': np, 'np': np, 'inf': float('inf')}
|
|
120
|
+
|
|
121
|
+
arr = np.array(eval(pc_str, namespace))
|
|
122
|
+
if arr.ndim == 0:
|
|
123
|
+
arr.shape = (1, 1)
|
|
124
|
+
elif arr.ndim == 1:
|
|
125
|
+
arr.shape = (1,) + arr.shape
|
|
126
|
+
else:
|
|
127
|
+
raise ValueError('too many dimensions')
|
|
128
|
+
# return list(arr[...])
|
|
129
|
+
return arr[...]
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def lazy_loaded(backing_name, loader, docstring=None):
|
|
133
|
+
def getter(self):
|
|
134
|
+
obj = getattr(self, backing_name, None)
|
|
135
|
+
if obj is None:
|
|
136
|
+
obj = loader()
|
|
137
|
+
setattr(self, backing_name, obj)
|
|
138
|
+
return obj
|
|
139
|
+
|
|
140
|
+
def setter(self, val):
|
|
141
|
+
setattr(self, backing_name, val)
|
|
142
|
+
|
|
143
|
+
def deleter(self):
|
|
144
|
+
delattr(self, backing_name)
|
|
145
|
+
setattr(self, backing_name, None)
|
|
146
|
+
|
|
147
|
+
return property(getter, setter, deleter, docstring)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class WESTRC:
|
|
151
|
+
'''A class, an instance of which is accessible as ``westpa.rc``, to handle global issues for WEST-PA code,
|
|
152
|
+
such as loading modules and plugins, writing output based on verbosity level, adding default command line options,
|
|
153
|
+
and so on.'''
|
|
154
|
+
|
|
155
|
+
# Runtime config file management
|
|
156
|
+
ENV_RUNTIME_CONFIG = 'WESTRC'
|
|
157
|
+
RC_DEFAULT_FILENAME = 'west.cfg'
|
|
158
|
+
|
|
159
|
+
def __init__(self):
|
|
160
|
+
self.verbosity = None
|
|
161
|
+
self.rcfile = os.environ.get(self.ENV_RUNTIME_CONFIG) or self.RC_DEFAULT_FILENAME
|
|
162
|
+
|
|
163
|
+
self.config = YAMLConfig()
|
|
164
|
+
try:
|
|
165
|
+
self.process_name = os.path.splitext(os.path.basename(sys.argv[0]))[0]
|
|
166
|
+
except (TypeError, IndexError):
|
|
167
|
+
self.process_name = "unknown"
|
|
168
|
+
|
|
169
|
+
# Crucial simulation and analysis drivers
|
|
170
|
+
self._system = None
|
|
171
|
+
self._data_manager = None
|
|
172
|
+
self._sim_manager = None
|
|
173
|
+
self._we_driver = None
|
|
174
|
+
self._propagator = None
|
|
175
|
+
|
|
176
|
+
self.work_manager = SerialWorkManager()
|
|
177
|
+
|
|
178
|
+
self.status_stream = sys.stdout
|
|
179
|
+
|
|
180
|
+
def add_args(self, parser):
|
|
181
|
+
group = parser.add_argument_group('general options')
|
|
182
|
+
group.add_argument(
|
|
183
|
+
'-r',
|
|
184
|
+
'--rcfile',
|
|
185
|
+
metavar='RCFILE',
|
|
186
|
+
dest='rcfile',
|
|
187
|
+
default=(os.environ.get(self.ENV_RUNTIME_CONFIG) or self.RC_DEFAULT_FILENAME),
|
|
188
|
+
help='use RCFILE as the WEST run-time configuration file (default: %(default)s)',
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
egroup = group.add_mutually_exclusive_group()
|
|
192
|
+
egroup.add_argument(
|
|
193
|
+
'--quiet', dest='verbosity', action='store_const', const='quiet', help='emit only essential information'
|
|
194
|
+
)
|
|
195
|
+
egroup.add_argument('--verbose', dest='verbosity', action='store_const', const='verbose', help='emit extra information')
|
|
196
|
+
egroup.add_argument(
|
|
197
|
+
'--debug',
|
|
198
|
+
dest='verbosity',
|
|
199
|
+
action='store_const',
|
|
200
|
+
const='debug',
|
|
201
|
+
help='enable extra checks and emit copious information',
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
group.add_argument('--version', action='version', version='WEST version %s' % westpa.__version__)
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def verbose_mode(self):
|
|
208
|
+
return self.verbosity in ('verbose', 'debug')
|
|
209
|
+
|
|
210
|
+
@property
|
|
211
|
+
def debug_mode(self):
|
|
212
|
+
return self.verbosity == 'debug'
|
|
213
|
+
|
|
214
|
+
@property
|
|
215
|
+
def quiet_mode(self):
|
|
216
|
+
return self.verbosity == 'quiet'
|
|
217
|
+
|
|
218
|
+
def process_args(self, args, config_required=True):
|
|
219
|
+
self.cmdline_args = args
|
|
220
|
+
self.verbosity = args.verbosity
|
|
221
|
+
|
|
222
|
+
if args.rcfile:
|
|
223
|
+
self.rcfile = args.rcfile
|
|
224
|
+
|
|
225
|
+
try:
|
|
226
|
+
self.read_config()
|
|
227
|
+
except IOError as e:
|
|
228
|
+
if e.errno == errno.ENOENT and not config_required:
|
|
229
|
+
pass
|
|
230
|
+
else:
|
|
231
|
+
raise
|
|
232
|
+
self.config_logging()
|
|
233
|
+
self.config['args'] = {k: v for k, v in args.__dict__.items() if not k.startswith('_')}
|
|
234
|
+
self.process_config()
|
|
235
|
+
self.time_config()
|
|
236
|
+
|
|
237
|
+
def time_config(self):
|
|
238
|
+
'''Convert non-pyYAML accepted time formats into seconds'''
|
|
239
|
+
max_run_wallclock = self.config.get(['west', 'propagation', 'max_run_wallclock'], None)
|
|
240
|
+
if isinstance(max_run_wallclock, str):
|
|
241
|
+
time_formats = ['days', 'hours', 'minutes', 'seconds']
|
|
242
|
+
wallclock_str = max_run_wallclock.split(':')
|
|
243
|
+
kwargs = {key: int(val) for key, val in zip(time_formats[-len(wallclock_str) :], wallclock_str)}
|
|
244
|
+
try:
|
|
245
|
+
diff = int(timedelta(**kwargs).total_seconds())
|
|
246
|
+
self.config['west']['propagation']['max_run_wallclock'] = diff
|
|
247
|
+
log.debug(f'Automatically converted {max_run_wallclock=} to {diff}')
|
|
248
|
+
except ValueError:
|
|
249
|
+
log.debug(f'Failed to convert {max_run_wallclock=} to seconds.')
|
|
250
|
+
|
|
251
|
+
def process_config(self):
|
|
252
|
+
log.debug('config: {!r}'.format(self.config))
|
|
253
|
+
sys.path.extend(self.config.get_pathlist(['west', 'drivers', 'module_path'], []))
|
|
254
|
+
try:
|
|
255
|
+
sys.path.append(os.environ['WEST_SIM_ROOT'])
|
|
256
|
+
except KeyError:
|
|
257
|
+
pass
|
|
258
|
+
|
|
259
|
+
def read_config(self, filename=None):
|
|
260
|
+
if filename:
|
|
261
|
+
self.rcfile = filename
|
|
262
|
+
|
|
263
|
+
if 'WEST_SIM_ROOT' not in os.environ:
|
|
264
|
+
# sys.stderr.write('-- WARNING -- setting $WEST_SIM_ROOT to current directory ({})\n'.format(os.getcwd()))
|
|
265
|
+
os.environ['WEST_SIM_ROOT'] = os.getcwd()
|
|
266
|
+
|
|
267
|
+
self.config.update_from_file(self.rcfile)
|
|
268
|
+
|
|
269
|
+
def config_logging(self):
|
|
270
|
+
import logging.config
|
|
271
|
+
|
|
272
|
+
logging_config = {
|
|
273
|
+
'version': 1,
|
|
274
|
+
'incremental': False,
|
|
275
|
+
'formatters': {
|
|
276
|
+
'standard': {'format': '-- %(levelname)-8s [%(name)s] -- %(message)s'},
|
|
277
|
+
'debug': {
|
|
278
|
+
'format': '''\
|
|
279
|
+
-- %(levelname)-8s %(asctime)24s PID %(process)-12d TID %(thread)-20d
|
|
280
|
+
from logger "%(name)s"
|
|
281
|
+
at location %(pathname)s:%(lineno)d [%(funcName)s()]
|
|
282
|
+
::
|
|
283
|
+
%(message)s
|
|
284
|
+
'''
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
'handlers': {'console': {'class': 'logging.StreamHandler', 'stream': 'ext://sys.stdout', 'formatter': 'standard'}},
|
|
288
|
+
'loggers': {
|
|
289
|
+
'west': {'handlers': ['console'], 'propagate': False},
|
|
290
|
+
'westpa': {'handlers': ['console'], 'propagate': False},
|
|
291
|
+
'oldtools': {'handlers': ['console'], 'propagate': False},
|
|
292
|
+
'westtools': {'handlers': ['console'], 'propagate': False},
|
|
293
|
+
'westext': {'handlers': ['console'], 'propagate': False},
|
|
294
|
+
'work_managers': {'handlers': ['console'], 'propagate': False},
|
|
295
|
+
'py.warnings': {'handlers': ['console'], 'propagate': False},
|
|
296
|
+
},
|
|
297
|
+
'root': {'handlers': ['console']},
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
logging_config['loggers'][self.process_name] = {'handlers': ['console'], 'propagate': False}
|
|
301
|
+
|
|
302
|
+
if self.verbosity == 'debug':
|
|
303
|
+
logging_config['root']['level'] = 5 # 'DEBUG'
|
|
304
|
+
logging_config['handlers']['console']['formatter'] = 'debug'
|
|
305
|
+
elif self.verbosity == 'verbose':
|
|
306
|
+
logging_config['root']['level'] = 'INFO'
|
|
307
|
+
else:
|
|
308
|
+
logging_config['root']['level'] = 'WARNING'
|
|
309
|
+
|
|
310
|
+
logging.config.dictConfig(logging_config)
|
|
311
|
+
logging_config['incremental'] = True
|
|
312
|
+
|
|
313
|
+
if self.verbosity == 'debug':
|
|
314
|
+
warnings.resetwarnings()
|
|
315
|
+
warnings.simplefilter("default")
|
|
316
|
+
logging.captureWarnings(True)
|
|
317
|
+
else:
|
|
318
|
+
if not sys.warnoptions:
|
|
319
|
+
warnings.simplefilter("ignore")
|
|
320
|
+
logging.captureWarnings(False)
|
|
321
|
+
|
|
322
|
+
def pstatus(self, *args, **kwargs):
|
|
323
|
+
fileobj = kwargs.pop('file', self.status_stream)
|
|
324
|
+
if kwargs.get('termonly', False) and not fileobj.isatty():
|
|
325
|
+
return
|
|
326
|
+
if self.verbosity != 'quiet':
|
|
327
|
+
print(*args, file=fileobj, **kwargs)
|
|
328
|
+
|
|
329
|
+
def pstatus_term(self, *args, **kwargs):
|
|
330
|
+
fileobj = kwargs.pop('file', self.status_stream)
|
|
331
|
+
if fileobj.isatty() and self.verbosity != 'quiet':
|
|
332
|
+
print(*args, file=fileobj, **kwargs)
|
|
333
|
+
|
|
334
|
+
def pflush(self):
|
|
335
|
+
for stream in (self.status_stream, sys.stdout, sys.stderr):
|
|
336
|
+
try:
|
|
337
|
+
stream.flush()
|
|
338
|
+
except AttributeError:
|
|
339
|
+
pass
|
|
340
|
+
|
|
341
|
+
def detect_mab_mapper(self):
|
|
342
|
+
bin_dict = self.config.get(['west', 'system', 'system_options', 'bins'])
|
|
343
|
+
use_mab = False
|
|
344
|
+
if bin_dict is not None:
|
|
345
|
+
mapper = bins_from_yaml_dict(bin_dict)
|
|
346
|
+
use_mab = detect_mab_mapper(mapper)
|
|
347
|
+
|
|
348
|
+
return use_mab
|
|
349
|
+
|
|
350
|
+
def detect_binless_mapper(self):
|
|
351
|
+
bin_dict = self.config.get(['west', 'system', 'system_options', 'bins'])
|
|
352
|
+
use_binless = False
|
|
353
|
+
if bin_dict is not None:
|
|
354
|
+
mapper = bins_from_yaml_dict(bin_dict)
|
|
355
|
+
use_binless = detect_binless_mapper(mapper)
|
|
356
|
+
|
|
357
|
+
return use_binless
|
|
358
|
+
|
|
359
|
+
def new_sim_manager(self):
|
|
360
|
+
drivername = self.config.get(['west', 'drivers', 'sim_manager'], 'default')
|
|
361
|
+
|
|
362
|
+
if drivername.lower() == 'default':
|
|
363
|
+
use_mab = self.detect_mab_mapper()
|
|
364
|
+
use_binless = self.detect_binless_mapper()
|
|
365
|
+
|
|
366
|
+
if use_mab:
|
|
367
|
+
from .binning.mab_manager import MABSimManager
|
|
368
|
+
|
|
369
|
+
sim_manager = MABSimManager(rc=self)
|
|
370
|
+
elif use_binless:
|
|
371
|
+
from .binning.binless_manager import BinlessSimManager
|
|
372
|
+
|
|
373
|
+
sim_manager = BinlessSimManager(rc=self)
|
|
374
|
+
else:
|
|
375
|
+
from .sim_manager import WESimManager
|
|
376
|
+
|
|
377
|
+
sim_manager = WESimManager(rc=self)
|
|
378
|
+
else:
|
|
379
|
+
sim_manager = extloader.get_object(drivername)(rc=self)
|
|
380
|
+
|
|
381
|
+
log.debug('loaded simulation manager {!r}'.format(sim_manager))
|
|
382
|
+
return sim_manager
|
|
383
|
+
|
|
384
|
+
def get_sim_manager(self):
|
|
385
|
+
if self._sim_manager is None:
|
|
386
|
+
self._sim_manager = self.new_sim_manager()
|
|
387
|
+
return self._sim_manager
|
|
388
|
+
|
|
389
|
+
def new_data_manager(self):
|
|
390
|
+
import westpa
|
|
391
|
+
|
|
392
|
+
drivername = self.config.get(['west', 'drivers', 'data_manager'], 'hdf5')
|
|
393
|
+
if drivername.lower() in ('hdf5', 'default'):
|
|
394
|
+
data_manager = westpa.core.data_manager.WESTDataManager()
|
|
395
|
+
else:
|
|
396
|
+
data_manager = extloader.get_object(drivername)(rc=self)
|
|
397
|
+
log.debug('loaded data manager: {!r}'.format(data_manager))
|
|
398
|
+
return data_manager
|
|
399
|
+
|
|
400
|
+
def get_data_manager(self):
|
|
401
|
+
if self._data_manager is None:
|
|
402
|
+
self._data_manager = self.new_data_manager()
|
|
403
|
+
return self._data_manager
|
|
404
|
+
|
|
405
|
+
def new_we_driver(self):
|
|
406
|
+
import westpa
|
|
407
|
+
|
|
408
|
+
drivername = self.config.get(['west', 'drivers', 'we_driver'], 'default')
|
|
409
|
+
|
|
410
|
+
if drivername.lower() == 'default':
|
|
411
|
+
use_mab = self.detect_mab_mapper()
|
|
412
|
+
use_binless = self.detect_binless_mapper()
|
|
413
|
+
if use_mab:
|
|
414
|
+
from .binning.mab_driver import MABDriver
|
|
415
|
+
|
|
416
|
+
we_driver = MABDriver()
|
|
417
|
+
elif use_binless:
|
|
418
|
+
from .binning.binless_driver import BinlessDriver
|
|
419
|
+
|
|
420
|
+
we_driver = BinlessDriver()
|
|
421
|
+
else:
|
|
422
|
+
from .we_driver import WEDriver
|
|
423
|
+
|
|
424
|
+
we_driver = WEDriver()
|
|
425
|
+
else:
|
|
426
|
+
we_driver = extloader.get_object(drivername)(rc=self)
|
|
427
|
+
|
|
428
|
+
log.debug('loaded WE algorithm driver: {!r}'.format(we_driver))
|
|
429
|
+
|
|
430
|
+
subgroup_function = self.config.get(['west', 'drivers', 'subgroup_function'], 'default')
|
|
431
|
+
if subgroup_function.lower() == 'default':
|
|
432
|
+
try:
|
|
433
|
+
subgroup_function = 'westpa.core.we_driver._group_walkers_identity'
|
|
434
|
+
we_driver.subgroup_function = westpa.core.we_driver._group_walkers_identity
|
|
435
|
+
except Exception:
|
|
436
|
+
pass
|
|
437
|
+
else:
|
|
438
|
+
we_driver.subgroup_function = extloader.get_object(subgroup_function)
|
|
439
|
+
we_driver.subgroup_function_kwargs = self.config.get(['west', 'drivers', 'subgroup_arguments'])
|
|
440
|
+
# Necessary if the user hasn't specified any options.
|
|
441
|
+
if we_driver.subgroup_function_kwargs is None:
|
|
442
|
+
we_driver.subgroup_function_kwargs = {}
|
|
443
|
+
log.debug('loaded WE algorithm driver subgrouping function {!r}'.format(subgroup_function))
|
|
444
|
+
log.debug('WE algorithm driver subgrouping function kwargs: {!r}'.format(we_driver.subgroup_function_kwargs))
|
|
445
|
+
|
|
446
|
+
return we_driver
|
|
447
|
+
|
|
448
|
+
def get_we_driver(self):
|
|
449
|
+
if self._we_driver is None:
|
|
450
|
+
self._we_driver = self.new_we_driver()
|
|
451
|
+
return self._we_driver
|
|
452
|
+
|
|
453
|
+
def new_propagator(self):
|
|
454
|
+
drivername = self.config.require(['west', 'propagation', 'propagator'])
|
|
455
|
+
if drivername.lower() == 'executable':
|
|
456
|
+
from westpa.core.propagators.executable import ExecutablePropagator
|
|
457
|
+
|
|
458
|
+
propagator = ExecutablePropagator()
|
|
459
|
+
else:
|
|
460
|
+
propagator = extloader.get_object(drivername)(rc=self)
|
|
461
|
+
log.debug('loaded propagator {!r}'.format(propagator))
|
|
462
|
+
return propagator
|
|
463
|
+
|
|
464
|
+
def get_propagator(self):
|
|
465
|
+
if self._propagator is None:
|
|
466
|
+
self._propagator = self.new_propagator()
|
|
467
|
+
return self._propagator
|
|
468
|
+
|
|
469
|
+
def new_system_driver(self):
|
|
470
|
+
'''
|
|
471
|
+
Returns a new system object either from the driver OR from the YAML
|
|
472
|
+
file. Currently builds off of system then updates with YAML
|
|
473
|
+
overwriting the previous settings if both are specified.
|
|
474
|
+
|
|
475
|
+
There are no default settings, all settings MUST be specified
|
|
476
|
+
in the config YAML file OR the system driver.
|
|
477
|
+
|
|
478
|
+
Settings that are specified here are:
|
|
479
|
+
Progress coordinate settings:
|
|
480
|
+
Progress coordinate dimensionality
|
|
481
|
+
Progress coordinate length/number of data points in each tau
|
|
482
|
+
Progress coordinate data type
|
|
483
|
+
Bin settings:
|
|
484
|
+
Bin mapper type
|
|
485
|
+
Bins
|
|
486
|
+
Target simulation counts for each bin
|
|
487
|
+
Generic setting for flexibility:
|
|
488
|
+
Both paths allow for generic attribute setting for
|
|
489
|
+
future flexibility.
|
|
490
|
+
'''
|
|
491
|
+
|
|
492
|
+
# First step is to see if we have a driver specified
|
|
493
|
+
# if so load that one first, setting the defaults for
|
|
494
|
+
# YAML to possibly modify.
|
|
495
|
+
|
|
496
|
+
# I will keep this as is for now since I like the idea
|
|
497
|
+
# of being able to set some defaults from the system
|
|
498
|
+
# driver and then just modify the YAML instead for basic
|
|
499
|
+
# stuff. This might make it easier to set up systems since
|
|
500
|
+
# playing around with the YAML format is easier.
|
|
501
|
+
|
|
502
|
+
# Still still has the end-user issue of possibly confusing
|
|
503
|
+
# people, maybe KISS is better, not sure. I'll keep this
|
|
504
|
+
# for development purposes if nothing else.
|
|
505
|
+
|
|
506
|
+
system = None
|
|
507
|
+
# Get method checks for us
|
|
508
|
+
sysdrivername = self.config.get(['west', 'system', 'driver'])
|
|
509
|
+
if not sysdrivername:
|
|
510
|
+
# Warn user that driver is not specified
|
|
511
|
+
log.info("System driver not specified")
|
|
512
|
+
else:
|
|
513
|
+
log.info('loading system driver %r' % sysdrivername)
|
|
514
|
+
system = extloader.get_object(sysdrivername)(rc=self)
|
|
515
|
+
log.debug('loaded system driver {!r}'.format(system))
|
|
516
|
+
system.initialize()
|
|
517
|
+
# Second let's see if we have info in the YAML file
|
|
518
|
+
yamloptions = self.config.get(['west', 'system', 'system_options'])
|
|
519
|
+
if not yamloptions:
|
|
520
|
+
# Same here, yaml file doesn't have sys info
|
|
521
|
+
log.info("Config file doesn't contain any system info")
|
|
522
|
+
else:
|
|
523
|
+
log.info("Loading system options from configuration file")
|
|
524
|
+
if system:
|
|
525
|
+
system = self.update_from_yaml(system, yamloptions)
|
|
526
|
+
else:
|
|
527
|
+
system = self.system_from_yaml(yamloptions)
|
|
528
|
+
|
|
529
|
+
if system:
|
|
530
|
+
if not yamloptions:
|
|
531
|
+
print("System is being built only off of the system driver")
|
|
532
|
+
return system
|
|
533
|
+
else:
|
|
534
|
+
log.info("No system specified! Exiting program.")
|
|
535
|
+
# Gracefully exit
|
|
536
|
+
raise ValueError("No system defined!")
|
|
537
|
+
|
|
538
|
+
def system_from_yaml(self, system_dict):
|
|
539
|
+
"""
|
|
540
|
+
System builder directly from the config YAML file.
|
|
541
|
+
|
|
542
|
+
Arguments:
|
|
543
|
+
system_dict (dict): Parsed YAML file as a dictionary, parsed by
|
|
544
|
+
PyYAML by default.
|
|
545
|
+
|
|
546
|
+
Returns:
|
|
547
|
+
A modified WESTSystem object as defined in yamlcfg.py with
|
|
548
|
+
the parsed settings from the config file.
|
|
549
|
+
"""
|
|
550
|
+
|
|
551
|
+
yamlSystem = WESTSystem()
|
|
552
|
+
print("System building only off of the configuration file")
|
|
553
|
+
# Now for the building of the system from YAML we need to use
|
|
554
|
+
# require for these settings since they are musts.
|
|
555
|
+
|
|
556
|
+
# First basic pcoord settings
|
|
557
|
+
ndim = self.config.require(['west', 'system', 'system_options', 'pcoord_ndim'])
|
|
558
|
+
plen = self.config.require(['west', 'system', 'system_options', 'pcoord_len'])
|
|
559
|
+
# Dtype needs to be ran as code from YAML file, document YAML code execution syntax
|
|
560
|
+
# somewhere
|
|
561
|
+
ptype = self.config.require(['west', 'system', 'system_options', 'pcoord_dtype'])
|
|
562
|
+
# Bins
|
|
563
|
+
bins_obj = self.config.require(['west', 'system', 'system_options', 'bins'])
|
|
564
|
+
trgt_cnt = self.config.require(['west', 'system', 'system_options', 'bin_target_counts'])
|
|
565
|
+
# Now add the parsed settings to the system
|
|
566
|
+
mapper = bins_from_yaml_dict(bins_obj)
|
|
567
|
+
setattr(yamlSystem, 'pcoord_ndim', ndim)
|
|
568
|
+
setattr(yamlSystem, 'pcoord_len', plen)
|
|
569
|
+
setattr(yamlSystem, 'pcoord_dtype', ptype)
|
|
570
|
+
setattr(yamlSystem, 'bin_mapper', mapper)
|
|
571
|
+
# Check if the supplied target count object is
|
|
572
|
+
# an iterable or not,
|
|
573
|
+
|
|
574
|
+
# This one I designed in a way that you can either
|
|
575
|
+
# directly supply an iterable that has the correct
|
|
576
|
+
# size OR an integer. Anything else will fail.
|
|
577
|
+
|
|
578
|
+
# Main issue: For higher bin dimensions this
|
|
579
|
+
# is tough since the bins might not correspond
|
|
580
|
+
# properly to the flattened array you are supplying.
|
|
581
|
+
|
|
582
|
+
# I might just scrap the iterable later and only allow
|
|
583
|
+
# integers.
|
|
584
|
+
if hasattr(trgt_cnt, "__iter__"):
|
|
585
|
+
assert len(trgt_cnt) == mapper.nbins, "Count iterable size doesn't match the number of bins"
|
|
586
|
+
trgt_cnt_arr = trgt_cnt
|
|
587
|
+
else:
|
|
588
|
+
assert trgt_cnt == int(trgt_cnt), "Counts are not integer valued, ambiguous input"
|
|
589
|
+
trgt_cnt_arr = np.zeros(mapper.nbins)
|
|
590
|
+
trgt_cnt_arr[:] = trgt_cnt
|
|
591
|
+
setattr(yamlSystem, 'bin_target_counts', trgt_cnt_arr)
|
|
592
|
+
|
|
593
|
+
# Attach generic attribute to system
|
|
594
|
+
for attr in system_dict.keys():
|
|
595
|
+
if not hasattr(yamlSystem, attr):
|
|
596
|
+
setattr(yamlSystem, attr, system_dict[attr])
|
|
597
|
+
|
|
598
|
+
# Return complete system
|
|
599
|
+
return yamlSystem
|
|
600
|
+
|
|
601
|
+
def update_from_yaml(self, init_system, system_dict):
|
|
602
|
+
"""
|
|
603
|
+
Updates the system built from the driver with the options
|
|
604
|
+
from the YAML file. For now it overwrites everything specified
|
|
605
|
+
in the system driver.
|
|
606
|
+
|
|
607
|
+
Arguments:
|
|
608
|
+
system_dict (dict): Parsed YAML file as a dictionary, parsed by
|
|
609
|
+
PyYAML by default.
|
|
610
|
+
init_system (WESTSystem): System returned by the driver.
|
|
611
|
+
|
|
612
|
+
Returns:
|
|
613
|
+
A modified WESTSystem object with settings from the system
|
|
614
|
+
driver and the config YAML file.
|
|
615
|
+
"""
|
|
616
|
+
|
|
617
|
+
# First we want to overwrite whatever we have from the YAML
|
|
618
|
+
# file.
|
|
619
|
+
print("Updating system with the options from the configuration file")
|
|
620
|
+
for key, value in system_dict.items():
|
|
621
|
+
if key == 'pcoord_ndim':
|
|
622
|
+
self.overwrite_option(init_system, key, value)
|
|
623
|
+
elif key == 'pcoord_len':
|
|
624
|
+
self.overwrite_option(init_system, key, value)
|
|
625
|
+
elif key == 'pcoord_dtype':
|
|
626
|
+
self.overwrite_option(init_system, key, value)
|
|
627
|
+
elif key == "bins":
|
|
628
|
+
self.overwrite_option(init_system, 'bin_mapper', bins_from_yaml_dict(value))
|
|
629
|
+
# Target counts have to be parsed after we have a mapper in
|
|
630
|
+
# place
|
|
631
|
+
try:
|
|
632
|
+
trgt_cnt = system_dict['bin_target_counts']
|
|
633
|
+
if hasattr(trgt_cnt, "__iter__"):
|
|
634
|
+
assert len(trgt_cnt) == init_system.bin_mapper.nbins, "Count iterable size doesn't match the number of bins"
|
|
635
|
+
trgt_cnt_arr = trgt_cnt
|
|
636
|
+
else:
|
|
637
|
+
assert trgt_cnt == int(trgt_cnt), "Counts are not integer valued, ambiguous input"
|
|
638
|
+
trgt_cnt_arr = np.zeros(init_system.bin_mapper.nbins)
|
|
639
|
+
trgt_cnt_arr[:] = int(trgt_cnt)
|
|
640
|
+
self.overwrite_option(init_system, 'bin_target_counts', trgt_cnt_arr)
|
|
641
|
+
except KeyError:
|
|
642
|
+
pass
|
|
643
|
+
# The generic attribute settings added here
|
|
644
|
+
for attr in system_dict.keys():
|
|
645
|
+
if not hasattr(init_system, attr):
|
|
646
|
+
setattr(init_system, attr, system_dict[attr])
|
|
647
|
+
return init_system
|
|
648
|
+
|
|
649
|
+
def overwrite_option(self, system, key, value):
|
|
650
|
+
if hasattr(system, key):
|
|
651
|
+
log.info("Overwriting system option: %s" % key)
|
|
652
|
+
setattr(system, key, value)
|
|
653
|
+
|
|
654
|
+
def get_system_driver(self):
|
|
655
|
+
if self._system is None:
|
|
656
|
+
self._system = self.new_system_driver()
|
|
657
|
+
return self._system
|
|
658
|
+
|
|
659
|
+
def get_work_manager(self):
|
|
660
|
+
return self.work_manager
|
|
661
|
+
|
|
662
|
+
def clear_state(self):
|
|
663
|
+
self._sim_manager = None
|
|
664
|
+
self._system = None
|
|
665
|
+
self._data_manager = None
|
|
666
|
+
self._we_driver = None
|
|
667
|
+
self._propagator = None
|
|
668
|
+
|
|
669
|
+
propagator = property(get_propagator)
|
|
670
|
+
we_driver = property(get_we_driver)
|
|
671
|
+
system = property(get_system_driver)
|
|
672
|
+
data_manager = property(get_data_manager)
|
|
673
|
+
sim_manager = property(get_sim_manager)
|