westpa 2022.10__cp312-cp312-macosx_11_0_arm64.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 +59 -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 +378 -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 +486 -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-312-darwin.so +0 -0
- westpa/core/binning/assign.py +449 -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 +427 -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-312-darwin.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 +715 -0
- westpa/core/reweight/__init__.py +14 -0
- westpa/core/reweight/_reweight.cpython-312-darwin.so +0 -0
- westpa/core/reweight/matrix.py +126 -0
- westpa/core/segment.py +119 -0
- westpa/core/sim_manager.py +830 -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 +908 -0
- westpa/core/wm_ops.py +43 -0
- westpa/core/yamlcfg.py +391 -0
- westpa/fasthist/__init__.py +34 -0
- westpa/fasthist/__main__.py +110 -0
- westpa/fasthist/_fasthist.cpython-312-darwin.so +0 -0
- westpa/mclib/__init__.py +264 -0
- westpa/mclib/__main__.py +28 -0
- westpa/mclib/_mclib.cpython-312-darwin.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 +146 -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 +358 -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 +89 -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-312-darwin.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 +182 -0
- westpa/westext/wess/ProbAdjust.py +101 -0
- westpa/westext/wess/__init__.py +6 -0
- westpa/westext/wess/wess_driver.py +207 -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.10.dist-info/AUTHORS +22 -0
- westpa-2022.10.dist-info/LICENSE +21 -0
- westpa-2022.10.dist-info/METADATA +183 -0
- westpa-2022.10.dist-info/RECORD +150 -0
- westpa-2022.10.dist-info/WHEEL +5 -0
- westpa-2022.10.dist-info/entry_points.txt +29 -0
- westpa-2022.10.dist-info/top_level.txt +1 -0
westpa/core/wm_ops.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import westpa
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
log = logging.getLogger(__name__)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_pcoord(state):
|
|
9
|
+
log.debug('getting progress coordinate for {!r}'.format(state))
|
|
10
|
+
propagator = westpa.rc.get_propagator()
|
|
11
|
+
propagator.get_pcoord(state)
|
|
12
|
+
return state
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def gen_istate(basis_state, initial_state):
|
|
16
|
+
log.debug('generating initial state from {!r} (into {!r})'.format(basis_state, initial_state))
|
|
17
|
+
propagator = westpa.rc.get_propagator()
|
|
18
|
+
propagator.update_basis_initial_states([basis_state], [initial_state])
|
|
19
|
+
propagator.gen_istate(basis_state, initial_state)
|
|
20
|
+
return basis_state, initial_state
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def prep_iter(n_iter, segments):
|
|
24
|
+
log.debug('propagator.prepare_iteration(...)')
|
|
25
|
+
propagator = westpa.rc.get_propagator()
|
|
26
|
+
propagator.clear_basis_initial_states()
|
|
27
|
+
propagator.prepare_iteration(n_iter, segments)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def post_iter(n_iter, segments):
|
|
31
|
+
log.debug('propagator.finalize_iteration(...)')
|
|
32
|
+
propagator = westpa.rc.get_propagator()
|
|
33
|
+
propagator.finalize_iteration(n_iter, segments)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def propagate(basis_states, initial_states, segments):
|
|
37
|
+
propagator = westpa.rc.get_propagator()
|
|
38
|
+
propagator.update_basis_initial_states(basis_states, initial_states)
|
|
39
|
+
outgoing_ids = [segment.seg_id for segment in segments]
|
|
40
|
+
incoming_segments = {segment.seg_id: segment for segment in propagator.propagate(segments)}
|
|
41
|
+
if log.isEnabledFor(logging.DEBUG):
|
|
42
|
+
log.debug('propagated {:d} segments'.format(len(incoming_segments)))
|
|
43
|
+
return [incoming_segments[seg_id] for seg_id in outgoing_ids]
|
westpa/core/yamlcfg.py
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
'''
|
|
2
|
+
YAML-based configuration files for WESTPA
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import warnings
|
|
7
|
+
|
|
8
|
+
import yaml
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
from yaml import CLoader as YLoader
|
|
13
|
+
except ImportError:
|
|
14
|
+
# fall back on Python implementation
|
|
15
|
+
from yaml import Loader as YLoader
|
|
16
|
+
|
|
17
|
+
from . import extloader
|
|
18
|
+
from .binning import NopMapper
|
|
19
|
+
|
|
20
|
+
# Only needed for temporary class
|
|
21
|
+
import westpa
|
|
22
|
+
|
|
23
|
+
NotProvided = object()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ConfigValueWarning(UserWarning):
|
|
27
|
+
pass
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def warn_dubious_config_entry(entry, value, expected_type=None, category=ConfigValueWarning, stacklevel=1):
|
|
31
|
+
if expected_type:
|
|
32
|
+
warnings.warn(
|
|
33
|
+
'dubious configuration entry {}: {} (expected type {})'.format(entry, value, expected_type), category, stacklevel + 1
|
|
34
|
+
)
|
|
35
|
+
else:
|
|
36
|
+
warnings.warn('dubious configuration entry {}: {}'.format(entry, value), category, stacklevel + 1)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def check_bool(value, action='warn'):
|
|
40
|
+
'''Check that the given ``value`` is boolean in type. If not, either
|
|
41
|
+
raise a warning (if ``action=='warn'``) or an exception (``action=='raise'``).
|
|
42
|
+
'''
|
|
43
|
+
if action not in ('warn', 'raise'):
|
|
44
|
+
raise ValueError('invalid action {!r}'.format(action))
|
|
45
|
+
|
|
46
|
+
if not isinstance(value, bool):
|
|
47
|
+
if action == 'warn':
|
|
48
|
+
warnings.warn(
|
|
49
|
+
'dubious boolean value {!r}, will be treated as {!r}'.format(value, bool(value)),
|
|
50
|
+
category=ConfigValueWarning,
|
|
51
|
+
stacklevel=2,
|
|
52
|
+
)
|
|
53
|
+
elif action == 'raise':
|
|
54
|
+
raise ValueError('dubious boolean value {!r}, would be treated as {!r}'.format(value, bool(value)))
|
|
55
|
+
else:
|
|
56
|
+
return value
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ConfigItemMissing(KeyError):
|
|
60
|
+
def __init__(self, key, message=None):
|
|
61
|
+
self.key = key
|
|
62
|
+
if message is None:
|
|
63
|
+
message = 'configuration item missing: {!r}'.format(key)
|
|
64
|
+
super().__init__(message)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ConfigItemTypeError(TypeError):
|
|
68
|
+
def __init__(self, key, expected_type, message=None):
|
|
69
|
+
self.key = key
|
|
70
|
+
self.expected_type = expected_type
|
|
71
|
+
if message is None:
|
|
72
|
+
message = 'configuration item {!r} must have type {!r}'.format(key, expected_type)
|
|
73
|
+
super().__init__(message)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class ConfigValueError(ValueError):
|
|
77
|
+
def __init__(self, key, value, message=None):
|
|
78
|
+
self.key = key
|
|
79
|
+
self.value = value
|
|
80
|
+
if message is None:
|
|
81
|
+
message = 'bad value {!r} for configuration item {!r}'.format(key, value)
|
|
82
|
+
super().__init__(message)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class YAMLConfig:
|
|
86
|
+
preload_config_files = ['/etc/westpa/westrc', os.path.expanduser('~/.westrc')]
|
|
87
|
+
|
|
88
|
+
def __init__(self):
|
|
89
|
+
self._data = {}
|
|
90
|
+
|
|
91
|
+
for source in self.preload_config_files:
|
|
92
|
+
self.update_from_file(source, required=False)
|
|
93
|
+
|
|
94
|
+
def __repr__(self):
|
|
95
|
+
return repr(self._data)
|
|
96
|
+
|
|
97
|
+
def update_from_file(self, file, required=True):
|
|
98
|
+
if isinstance(file, str):
|
|
99
|
+
try:
|
|
100
|
+
file = open(file, 'rt')
|
|
101
|
+
except IOError:
|
|
102
|
+
if required:
|
|
103
|
+
raise
|
|
104
|
+
else:
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
self._data.update(yaml.load(file, Loader=YLoader))
|
|
108
|
+
file.close()
|
|
109
|
+
|
|
110
|
+
def _normalize_key(self, key):
|
|
111
|
+
if isinstance(key, str):
|
|
112
|
+
key = (key,)
|
|
113
|
+
else:
|
|
114
|
+
try:
|
|
115
|
+
key = tuple(key)
|
|
116
|
+
except TypeError:
|
|
117
|
+
key = (key,)
|
|
118
|
+
return key
|
|
119
|
+
|
|
120
|
+
def _resolve_object_chain(self, key, last=None):
|
|
121
|
+
if last is None:
|
|
122
|
+
last = len(key)
|
|
123
|
+
objects = [self._data[key[0]]]
|
|
124
|
+
for subkey in key[1:last]:
|
|
125
|
+
objects.append(objects[-1][subkey])
|
|
126
|
+
return objects
|
|
127
|
+
|
|
128
|
+
def __getitem__(self, key):
|
|
129
|
+
key = self._normalize_key(key)
|
|
130
|
+
return self._resolve_object_chain(key)[-1]
|
|
131
|
+
|
|
132
|
+
def __setitem__(self, key, value):
|
|
133
|
+
key = self._normalize_key(key)
|
|
134
|
+
|
|
135
|
+
try:
|
|
136
|
+
objchain = self._resolve_object_chain(key, -1)
|
|
137
|
+
except KeyError:
|
|
138
|
+
# creation of a new (possibly nested) entry
|
|
139
|
+
val = self._data
|
|
140
|
+
for keypart in key[:-1]:
|
|
141
|
+
try:
|
|
142
|
+
val = val[keypart]
|
|
143
|
+
except KeyError:
|
|
144
|
+
val[keypart] = {}
|
|
145
|
+
val = val[keypart]
|
|
146
|
+
try:
|
|
147
|
+
val = val[key[-1]]
|
|
148
|
+
except KeyError:
|
|
149
|
+
val[key[-1]] = value
|
|
150
|
+
else:
|
|
151
|
+
objchain[-1][key[-1]] = value
|
|
152
|
+
|
|
153
|
+
def __delitem__(self, key):
|
|
154
|
+
key = self._normalize_key(key)
|
|
155
|
+
objchain = self._resolve_object_chain(key, -1)
|
|
156
|
+
del objchain[-1][key[-1]]
|
|
157
|
+
|
|
158
|
+
def __contains__(self, key):
|
|
159
|
+
try:
|
|
160
|
+
self[key]
|
|
161
|
+
except (KeyError, TypeError):
|
|
162
|
+
return False
|
|
163
|
+
else:
|
|
164
|
+
return True
|
|
165
|
+
|
|
166
|
+
def require(self, key, type_=None):
|
|
167
|
+
'''Ensure that a configuration item with the given ``key`` is present. If
|
|
168
|
+
the optional ``type_`` is given, additionally require that the item has that
|
|
169
|
+
type.'''
|
|
170
|
+
|
|
171
|
+
try:
|
|
172
|
+
item = self[key]
|
|
173
|
+
except KeyError:
|
|
174
|
+
raise ConfigItemMissing(key)
|
|
175
|
+
|
|
176
|
+
if type_ is not None:
|
|
177
|
+
if not isinstance(item, type_):
|
|
178
|
+
raise ConfigItemTypeError(item, type_)
|
|
179
|
+
return item
|
|
180
|
+
|
|
181
|
+
def require_type_if_present(self, key, type_):
|
|
182
|
+
'''Ensure that the configuration item with the given ``key`` has the
|
|
183
|
+
given type.'''
|
|
184
|
+
|
|
185
|
+
try:
|
|
186
|
+
item = self[key]
|
|
187
|
+
except KeyError:
|
|
188
|
+
return
|
|
189
|
+
else:
|
|
190
|
+
if not isinstance(item, type_):
|
|
191
|
+
raise ConfigItemTypeError(item, type_)
|
|
192
|
+
|
|
193
|
+
def coerce_type_if_present(self, key, type_):
|
|
194
|
+
try:
|
|
195
|
+
item = self[key]
|
|
196
|
+
except KeyError:
|
|
197
|
+
return
|
|
198
|
+
else:
|
|
199
|
+
if type_ is bool and not isinstance(item, bool):
|
|
200
|
+
warn_dubious_config_entry(key, item, bool)
|
|
201
|
+
self[key] = type_(item)
|
|
202
|
+
|
|
203
|
+
def get(self, key, default=None):
|
|
204
|
+
try:
|
|
205
|
+
return self[key]
|
|
206
|
+
except KeyError:
|
|
207
|
+
return default
|
|
208
|
+
|
|
209
|
+
def get_typed(self, key, type_, default=NotProvided):
|
|
210
|
+
try:
|
|
211
|
+
item = self[key]
|
|
212
|
+
except KeyError as ke:
|
|
213
|
+
if default is not NotProvided:
|
|
214
|
+
item = default
|
|
215
|
+
else:
|
|
216
|
+
raise ke
|
|
217
|
+
|
|
218
|
+
# Warn about possibly bad boolean
|
|
219
|
+
if type_ is bool and not isinstance(item, bool):
|
|
220
|
+
warn_dubious_config_entry(key, item, bool)
|
|
221
|
+
|
|
222
|
+
return type_(item)
|
|
223
|
+
|
|
224
|
+
def get_path(self, key, default=NotProvided, expandvars=True, expanduser=True, realpath=True, abspath=True):
|
|
225
|
+
try:
|
|
226
|
+
path = self[key]
|
|
227
|
+
except KeyError as ke:
|
|
228
|
+
if default is not NotProvided:
|
|
229
|
+
path = default
|
|
230
|
+
else:
|
|
231
|
+
raise ke
|
|
232
|
+
|
|
233
|
+
if expandvars:
|
|
234
|
+
path = os.path.expandvars(path)
|
|
235
|
+
if expanduser:
|
|
236
|
+
path = os.path.expanduser(path)
|
|
237
|
+
if realpath:
|
|
238
|
+
path = os.path.realpath(path)
|
|
239
|
+
if abspath:
|
|
240
|
+
path = os.path.abspath(path)
|
|
241
|
+
|
|
242
|
+
return path
|
|
243
|
+
|
|
244
|
+
def get_pathlist(self, key, default=NotProvided, sep=os.pathsep, expandvars=True, expanduser=True, realpath=True, abspath=True):
|
|
245
|
+
try:
|
|
246
|
+
paths = self[key]
|
|
247
|
+
except KeyError as ke:
|
|
248
|
+
if default is not NotProvided:
|
|
249
|
+
paths = default
|
|
250
|
+
else:
|
|
251
|
+
raise ke
|
|
252
|
+
|
|
253
|
+
try:
|
|
254
|
+
items = paths.split(sep)
|
|
255
|
+
except AttributeError:
|
|
256
|
+
# Default must have been something we can't process, like a list or None
|
|
257
|
+
# Just pass it through, since enforcing a restriction on what kind of
|
|
258
|
+
# default is passed is probably more counterproductive than any poor programming
|
|
259
|
+
# practice it encourages.
|
|
260
|
+
return paths
|
|
261
|
+
|
|
262
|
+
if expandvars:
|
|
263
|
+
items = list(map(os.path.expandvars, items))
|
|
264
|
+
if expanduser:
|
|
265
|
+
items = list(map(os.path.expanduser, items))
|
|
266
|
+
if realpath:
|
|
267
|
+
items = list(map(os.path.realpath, items))
|
|
268
|
+
if abspath:
|
|
269
|
+
items = list(map(os.path.abspath, items))
|
|
270
|
+
|
|
271
|
+
return items
|
|
272
|
+
|
|
273
|
+
def get_python_object(self, key, default=NotProvided, path=None):
|
|
274
|
+
try:
|
|
275
|
+
qualname = self[key]
|
|
276
|
+
except KeyError as ke:
|
|
277
|
+
if default is not NotProvided:
|
|
278
|
+
return default
|
|
279
|
+
else:
|
|
280
|
+
raise ke
|
|
281
|
+
|
|
282
|
+
return extloader.get_object(qualname, path)
|
|
283
|
+
|
|
284
|
+
def get_choice(self, key, choices, default=NotProvided, value_transform=None):
|
|
285
|
+
try:
|
|
286
|
+
value = self[key]
|
|
287
|
+
except KeyError:
|
|
288
|
+
if default is not NotProvided:
|
|
289
|
+
value = default
|
|
290
|
+
else:
|
|
291
|
+
raise
|
|
292
|
+
|
|
293
|
+
choices = set(choices)
|
|
294
|
+
if value_transform:
|
|
295
|
+
value = value_transform(value)
|
|
296
|
+
if value not in choices:
|
|
297
|
+
raise ConfigValueError(
|
|
298
|
+
key,
|
|
299
|
+
value,
|
|
300
|
+
message='bad value {!r} for configuration item {!r} (valid choices: {!r})'.format(
|
|
301
|
+
value, key, tuple(sorted(choices))
|
|
302
|
+
),
|
|
303
|
+
)
|
|
304
|
+
return value
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
# Temporary class here
|
|
308
|
+
class YAMLSystem:
|
|
309
|
+
'''A description of the system being simulated, including the dimensionality and
|
|
310
|
+
data type of the progress coordinate, the number of progress coordinate entries
|
|
311
|
+
expected from each segment, and binning. To construct a simulation, the user must
|
|
312
|
+
subclass WESTSystem and set several instance variables.
|
|
313
|
+
|
|
314
|
+
At a minimum, the user must subclass ``WESTSystem`` and override
|
|
315
|
+
:method:`initialize` to set the data type and dimensionality of progress
|
|
316
|
+
coordinate data and define a bin mapper.
|
|
317
|
+
|
|
318
|
+
:ivar pcoord_ndim: The number of dimensions in the progress coordinate.
|
|
319
|
+
Defaults to 1 (i.e. a one-dimensional progress
|
|
320
|
+
coordinate).
|
|
321
|
+
:ivar pcoord_dtype: The data type of the progress coordinate, which must be
|
|
322
|
+
callable (e.g. ``np.float32`` and ``long`` will work,
|
|
323
|
+
but ``'<f4'`` and ``'<i8'`` will not). Defaults to
|
|
324
|
+
``np.float64``.
|
|
325
|
+
:ivar pcoord_len: The length of the progress coordinate time series
|
|
326
|
+
generated by each segment, including *both* the initial
|
|
327
|
+
and final values. Defaults to 2 (i.e. only the initial
|
|
328
|
+
and final progress coordinate values for a segment are
|
|
329
|
+
returned from propagation).
|
|
330
|
+
:ivar bin_mapper: A bin mapper describing the progress coordinate space.
|
|
331
|
+
:ivar bin_target_counts: A vector of target counts, one per bin.
|
|
332
|
+
'''
|
|
333
|
+
|
|
334
|
+
def __init__(self, rc=None):
|
|
335
|
+
self.rc = rc or westpa.rc
|
|
336
|
+
|
|
337
|
+
# Number of dimentions in progress coordinate data
|
|
338
|
+
self.pcoord_ndim = 1
|
|
339
|
+
|
|
340
|
+
# Length of progress coordinate data for each segment
|
|
341
|
+
self.pcoord_len = 2
|
|
342
|
+
|
|
343
|
+
# Data type of progress coordinate
|
|
344
|
+
self.pcoord_dtype = np.float32
|
|
345
|
+
|
|
346
|
+
# Mapper
|
|
347
|
+
self.bin_mapper = NopMapper()
|
|
348
|
+
# self.bin_mapper = None
|
|
349
|
+
self._bin_target_counts = None
|
|
350
|
+
|
|
351
|
+
self.bin_target_counts = [1]
|
|
352
|
+
|
|
353
|
+
@property
|
|
354
|
+
def bin_target_counts(self):
|
|
355
|
+
return self._bin_target_counts
|
|
356
|
+
|
|
357
|
+
@bin_target_counts.setter
|
|
358
|
+
def bin_target_counts(self, target_counts):
|
|
359
|
+
maxcount = max(target_counts)
|
|
360
|
+
self._bin_target_counts = np.array(target_counts, dtype=np.min_scalar_type(maxcount))
|
|
361
|
+
|
|
362
|
+
def initialize(self):
|
|
363
|
+
'''Prepare this system object for use in simulation or analysis,
|
|
364
|
+
creating a bin space, setting replicas per bin, and so on. This
|
|
365
|
+
function is called whenever a WEST tool creates an instance of the
|
|
366
|
+
system driver.
|
|
367
|
+
'''
|
|
368
|
+
pass
|
|
369
|
+
|
|
370
|
+
def prepare_run(self):
|
|
371
|
+
'''Prepare this system for use in a simulation run. Called by w_run in
|
|
372
|
+
all worker processes.'''
|
|
373
|
+
pass
|
|
374
|
+
|
|
375
|
+
def finalize_run(self):
|
|
376
|
+
'''A hook for system-specific processing for the end of a simulation run
|
|
377
|
+
(as defined by such things as maximum wallclock time, rather than perhaps
|
|
378
|
+
more scientifically-significant definitions of "the end of a simulation run")'''
|
|
379
|
+
pass
|
|
380
|
+
|
|
381
|
+
def new_pcoord_array(self, pcoord_len=None):
|
|
382
|
+
'''Return an appropriately-sized and -typed pcoord array for a timepoint, segment,
|
|
383
|
+
or number of segments. If ``pcoord_len`` is not specified (or None), then
|
|
384
|
+
a length appropriate for a segment is returned.'''
|
|
385
|
+
|
|
386
|
+
if pcoord_len is None:
|
|
387
|
+
pcoord_len = self.pcoord_len
|
|
388
|
+
return np.zeros((pcoord_len, self.pcoord_ndim), self.pcoord_dtype)
|
|
389
|
+
|
|
390
|
+
def new_region_set(self):
|
|
391
|
+
raise NotImplementedError('This method has been removed.')
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from ._fasthist import histnd # noqa
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def normhistnd(hist, binbounds):
|
|
7
|
+
'''Normalize the N-dimensional histogram ``hist`` with corresponding
|
|
8
|
+
bin boundaries ``binbounds``. Modifies ``hist`` in place and returns
|
|
9
|
+
the normalization factor used.'''
|
|
10
|
+
|
|
11
|
+
ndim = hist.ndim
|
|
12
|
+
|
|
13
|
+
if ndim != len(binbounds):
|
|
14
|
+
raise ValueError(
|
|
15
|
+
'shape of histogram [{!r}] does not match bin boundary sets (there are {})'.format(hist.shape, len(binbounds))
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
diffs = [np.diff(bb) for bb in binbounds]
|
|
19
|
+
|
|
20
|
+
if ndim == 1:
|
|
21
|
+
assert diffs[0].shape == hist.shape
|
|
22
|
+
normfac = (hist * diffs[0]).sum()
|
|
23
|
+
else:
|
|
24
|
+
outers = np.multiply.outer(diffs[0], diffs[1])
|
|
25
|
+
for delta in diffs[2:]:
|
|
26
|
+
outers = np.multiply.outer(outers, delta)
|
|
27
|
+
assert outers.shape == hist.shape, 'hist shape {} != outers shape {}'.format(hist.shape, outers.shape)
|
|
28
|
+
# Divide by bin volumes
|
|
29
|
+
hist /= outers
|
|
30
|
+
normfac = hist.sum()
|
|
31
|
+
# normfac = (hist * outers).sum()
|
|
32
|
+
|
|
33
|
+
hist /= normfac
|
|
34
|
+
return normfac
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
'''
|
|
2
|
+
Created on Jun 25, 2013
|
|
3
|
+
|
|
4
|
+
@author: mzwier
|
|
5
|
+
'''
|
|
6
|
+
|
|
7
|
+
import numpy
|
|
8
|
+
from fasthist import histnd
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _test_double(npts=1024 * 1024, loops=3):
|
|
12
|
+
from time import time
|
|
13
|
+
|
|
14
|
+
mine_times = [None] * loops
|
|
15
|
+
theirs_times = [None] * loops
|
|
16
|
+
|
|
17
|
+
# though 1.0 should be sufficient, weirdness in the boundary conditions
|
|
18
|
+
# for numpy.digitize appears to introduce a discrepancy, so throw something
|
|
19
|
+
# greater than 1.0 in for good measure
|
|
20
|
+
binbounds = [[0, 0.5, 1, 1.1] for x in range(3)]
|
|
21
|
+
weights = numpy.random.rand(npts)
|
|
22
|
+
# weights = numpy.ones((npts,), dtype=numpy.float64)
|
|
23
|
+
for n in range(loops):
|
|
24
|
+
testdat = numpy.random.rand(npts, 3)
|
|
25
|
+
mstart = time()
|
|
26
|
+
mine = histnd(testdat, binbounds, weights=weights)
|
|
27
|
+
mstop = time()
|
|
28
|
+
tstart = time()
|
|
29
|
+
theirs = numpy.histogramdd(testdat, binbounds, weights=weights)[0]
|
|
30
|
+
tstop = time()
|
|
31
|
+
mine_times[n] = mstop - mstart
|
|
32
|
+
theirs_times[n] = tstop - tstart
|
|
33
|
+
print(mine)
|
|
34
|
+
print(theirs)
|
|
35
|
+
errsum = numpy.abs(mine - theirs).sum()
|
|
36
|
+
errsum_per_item = errsum / npts
|
|
37
|
+
rel_err = errsum / numpy.abs(weights).sum()
|
|
38
|
+
print('sum of the absolute errors: {} ({} relative, {} per entry)'.format(errsum, rel_err, errsum_per_item))
|
|
39
|
+
|
|
40
|
+
print('mine, best of {}: {}'.format(loops, min(mine_times)))
|
|
41
|
+
print('theirs, best of {}: {}'.format(loops, min(theirs_times)))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _test_float(npts=1024 * 1024, ndim=3, loops=3):
|
|
45
|
+
from time import time
|
|
46
|
+
|
|
47
|
+
mine_times = [None] * loops
|
|
48
|
+
theirs_times = [None] * loops
|
|
49
|
+
|
|
50
|
+
binbounds = [[0, 0.5, 1, 1.1] for x in range(ndim)]
|
|
51
|
+
# weights = numpy.random.rand(npts)
|
|
52
|
+
weights = numpy.ones((npts,), dtype=numpy.float64)
|
|
53
|
+
for n in range(loops):
|
|
54
|
+
testdat = numpy.require(numpy.random.rand(npts, ndim), numpy.float32)
|
|
55
|
+
print(testdat)
|
|
56
|
+
mstart = time()
|
|
57
|
+
mine = histnd(testdat, binbounds, weights=weights)
|
|
58
|
+
mstop = time()
|
|
59
|
+
tstart = time()
|
|
60
|
+
theirs = numpy.histogramdd(testdat, binbounds, weights=weights)[0]
|
|
61
|
+
tstop = time()
|
|
62
|
+
mine_times[n] = mstop - mstart
|
|
63
|
+
theirs_times[n] = tstop - tstart
|
|
64
|
+
print(mine)
|
|
65
|
+
print(theirs)
|
|
66
|
+
errsum = numpy.abs(mine - theirs).sum()
|
|
67
|
+
errsum_per_item = errsum / npts
|
|
68
|
+
rel_err = errsum / numpy.abs(weights).sum()
|
|
69
|
+
print('sum of the absolute errors: {} ({} relative, {} per entry)'.format(errsum, rel_err, errsum_per_item))
|
|
70
|
+
|
|
71
|
+
print('mine, best of {}: {}'.format(loops, min(mine_times)))
|
|
72
|
+
print('theirs, best of {}: {}'.format(loops, min(theirs_times)))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _test_uint(npts=1024 * 1024, ndim=3, loops=3):
|
|
76
|
+
from time import time
|
|
77
|
+
|
|
78
|
+
mine_times = [None] * loops
|
|
79
|
+
theirs_times = [None] * loops
|
|
80
|
+
|
|
81
|
+
binbounds = [[0, 1, 2, 3, 4] for x in range(ndim)]
|
|
82
|
+
# weights = numpy.random.rand(npts)
|
|
83
|
+
weights = numpy.ones((npts,), dtype=numpy.float64)
|
|
84
|
+
print('binbounds: {}'.format(binbounds))
|
|
85
|
+
print('weights')
|
|
86
|
+
print(weights)
|
|
87
|
+
for n in range(loops):
|
|
88
|
+
testdat = numpy.require(numpy.random.randint(0, 4, size=(npts, ndim)), numpy.uint16)
|
|
89
|
+
print('test data')
|
|
90
|
+
print(testdat)
|
|
91
|
+
mstart = time()
|
|
92
|
+
mine = histnd(testdat, binbounds, weights=weights)
|
|
93
|
+
mstop = time()
|
|
94
|
+
tstart = time()
|
|
95
|
+
theirs = numpy.histogramdd(testdat, binbounds, weights=weights)[0]
|
|
96
|
+
tstop = time()
|
|
97
|
+
mine_times[n] = mstop - mstart
|
|
98
|
+
theirs_times[n] = tstop - tstart
|
|
99
|
+
print(mine)
|
|
100
|
+
print(theirs)
|
|
101
|
+
errsum = numpy.abs(mine - theirs).sum()
|
|
102
|
+
errsum_per_item = errsum / npts
|
|
103
|
+
rel_err = errsum / numpy.abs(weights).sum()
|
|
104
|
+
print('sum of the absolute errors: {} ({} relative, {} per entry)'.format(errsum, rel_err, errsum_per_item))
|
|
105
|
+
|
|
106
|
+
print('mine, best of {}: {}'.format(loops, min(mine_times)))
|
|
107
|
+
print('theirs, best of {}: {}'.format(loops, min(theirs_times)))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
_test_float(npts=1024 * 1024, ndim=1)
|
|
Binary file
|