westpa 2022.10__cp312-cp312-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.

Files changed (150) hide show
  1. westpa/__init__.py +14 -0
  2. westpa/_version.py +21 -0
  3. westpa/analysis/__init__.py +5 -0
  4. westpa/analysis/core.py +746 -0
  5. westpa/analysis/statistics.py +27 -0
  6. westpa/analysis/trajectories.py +360 -0
  7. westpa/cli/__init__.py +0 -0
  8. westpa/cli/core/__init__.py +0 -0
  9. westpa/cli/core/w_fork.py +152 -0
  10. westpa/cli/core/w_init.py +230 -0
  11. westpa/cli/core/w_run.py +77 -0
  12. westpa/cli/core/w_states.py +212 -0
  13. westpa/cli/core/w_succ.py +99 -0
  14. westpa/cli/core/w_truncate.py +59 -0
  15. westpa/cli/tools/__init__.py +0 -0
  16. westpa/cli/tools/ploterr.py +506 -0
  17. westpa/cli/tools/plothist.py +706 -0
  18. westpa/cli/tools/w_assign.py +596 -0
  19. westpa/cli/tools/w_bins.py +166 -0
  20. westpa/cli/tools/w_crawl.py +119 -0
  21. westpa/cli/tools/w_direct.py +547 -0
  22. westpa/cli/tools/w_dumpsegs.py +94 -0
  23. westpa/cli/tools/w_eddist.py +506 -0
  24. westpa/cli/tools/w_fluxanl.py +378 -0
  25. westpa/cli/tools/w_ipa.py +833 -0
  26. westpa/cli/tools/w_kinavg.py +127 -0
  27. westpa/cli/tools/w_kinetics.py +96 -0
  28. westpa/cli/tools/w_multi_west.py +414 -0
  29. westpa/cli/tools/w_ntop.py +213 -0
  30. westpa/cli/tools/w_pdist.py +515 -0
  31. westpa/cli/tools/w_postanalysis_matrix.py +82 -0
  32. westpa/cli/tools/w_postanalysis_reweight.py +53 -0
  33. westpa/cli/tools/w_red.py +486 -0
  34. westpa/cli/tools/w_reweight.py +780 -0
  35. westpa/cli/tools/w_select.py +226 -0
  36. westpa/cli/tools/w_stateprobs.py +111 -0
  37. westpa/cli/tools/w_trace.py +599 -0
  38. westpa/core/__init__.py +0 -0
  39. westpa/core/_rc.py +673 -0
  40. westpa/core/binning/__init__.py +55 -0
  41. westpa/core/binning/_assign.cpython-312-x86_64-linux-gnu.so +0 -0
  42. westpa/core/binning/assign.py +449 -0
  43. westpa/core/binning/binless.py +96 -0
  44. westpa/core/binning/binless_driver.py +54 -0
  45. westpa/core/binning/binless_manager.py +190 -0
  46. westpa/core/binning/bins.py +47 -0
  47. westpa/core/binning/mab.py +427 -0
  48. westpa/core/binning/mab_driver.py +54 -0
  49. westpa/core/binning/mab_manager.py +198 -0
  50. westpa/core/data_manager.py +1694 -0
  51. westpa/core/extloader.py +74 -0
  52. westpa/core/h5io.py +995 -0
  53. westpa/core/kinetics/__init__.py +24 -0
  54. westpa/core/kinetics/_kinetics.cpython-312-x86_64-linux-gnu.so +0 -0
  55. westpa/core/kinetics/events.py +147 -0
  56. westpa/core/kinetics/matrates.py +156 -0
  57. westpa/core/kinetics/rate_averaging.py +266 -0
  58. westpa/core/progress.py +218 -0
  59. westpa/core/propagators/__init__.py +54 -0
  60. westpa/core/propagators/executable.py +715 -0
  61. westpa/core/reweight/__init__.py +14 -0
  62. westpa/core/reweight/_reweight.cpython-312-x86_64-linux-gnu.so +0 -0
  63. westpa/core/reweight/matrix.py +126 -0
  64. westpa/core/segment.py +119 -0
  65. westpa/core/sim_manager.py +830 -0
  66. westpa/core/states.py +359 -0
  67. westpa/core/systems.py +93 -0
  68. westpa/core/textio.py +74 -0
  69. westpa/core/trajectory.py +330 -0
  70. westpa/core/we_driver.py +908 -0
  71. westpa/core/wm_ops.py +43 -0
  72. westpa/core/yamlcfg.py +391 -0
  73. westpa/fasthist/__init__.py +34 -0
  74. westpa/fasthist/__main__.py +110 -0
  75. westpa/fasthist/_fasthist.cpython-312-x86_64-linux-gnu.so +0 -0
  76. westpa/mclib/__init__.py +264 -0
  77. westpa/mclib/__main__.py +28 -0
  78. westpa/mclib/_mclib.cpython-312-x86_64-linux-gnu.so +0 -0
  79. westpa/oldtools/__init__.py +4 -0
  80. westpa/oldtools/aframe/__init__.py +35 -0
  81. westpa/oldtools/aframe/atool.py +75 -0
  82. westpa/oldtools/aframe/base_mixin.py +26 -0
  83. westpa/oldtools/aframe/binning.py +178 -0
  84. westpa/oldtools/aframe/data_reader.py +560 -0
  85. westpa/oldtools/aframe/iter_range.py +200 -0
  86. westpa/oldtools/aframe/kinetics.py +117 -0
  87. westpa/oldtools/aframe/mcbs.py +146 -0
  88. westpa/oldtools/aframe/output.py +39 -0
  89. westpa/oldtools/aframe/plotting.py +90 -0
  90. westpa/oldtools/aframe/trajwalker.py +126 -0
  91. westpa/oldtools/aframe/transitions.py +469 -0
  92. westpa/oldtools/cmds/__init__.py +0 -0
  93. westpa/oldtools/cmds/w_ttimes.py +358 -0
  94. westpa/oldtools/files.py +34 -0
  95. westpa/oldtools/miscfn.py +23 -0
  96. westpa/oldtools/stats/__init__.py +4 -0
  97. westpa/oldtools/stats/accumulator.py +35 -0
  98. westpa/oldtools/stats/edfs.py +129 -0
  99. westpa/oldtools/stats/mcbs.py +89 -0
  100. westpa/tools/__init__.py +33 -0
  101. westpa/tools/binning.py +472 -0
  102. westpa/tools/core.py +340 -0
  103. westpa/tools/data_reader.py +159 -0
  104. westpa/tools/dtypes.py +31 -0
  105. westpa/tools/iter_range.py +198 -0
  106. westpa/tools/kinetics_tool.py +340 -0
  107. westpa/tools/plot.py +283 -0
  108. westpa/tools/progress.py +17 -0
  109. westpa/tools/selected_segs.py +154 -0
  110. westpa/tools/wipi.py +751 -0
  111. westpa/trajtree/__init__.py +4 -0
  112. westpa/trajtree/_trajtree.cpython-312-x86_64-linux-gnu.so +0 -0
  113. westpa/trajtree/trajtree.py +117 -0
  114. westpa/westext/__init__.py +0 -0
  115. westpa/westext/adaptvoronoi/__init__.py +3 -0
  116. westpa/westext/adaptvoronoi/adaptVor_driver.py +214 -0
  117. westpa/westext/hamsm_restarting/__init__.py +3 -0
  118. westpa/westext/hamsm_restarting/example_overrides.py +35 -0
  119. westpa/westext/hamsm_restarting/restart_driver.py +1165 -0
  120. westpa/westext/stringmethod/__init__.py +11 -0
  121. westpa/westext/stringmethod/fourier_fitting.py +69 -0
  122. westpa/westext/stringmethod/string_driver.py +253 -0
  123. westpa/westext/stringmethod/string_method.py +306 -0
  124. westpa/westext/weed/BinCluster.py +180 -0
  125. westpa/westext/weed/ProbAdjustEquil.py +100 -0
  126. westpa/westext/weed/UncertMath.py +247 -0
  127. westpa/westext/weed/__init__.py +10 -0
  128. westpa/westext/weed/weed_driver.py +182 -0
  129. westpa/westext/wess/ProbAdjust.py +101 -0
  130. westpa/westext/wess/__init__.py +6 -0
  131. westpa/westext/wess/wess_driver.py +207 -0
  132. westpa/work_managers/__init__.py +57 -0
  133. westpa/work_managers/core.py +396 -0
  134. westpa/work_managers/environment.py +134 -0
  135. westpa/work_managers/mpi.py +318 -0
  136. westpa/work_managers/processes.py +187 -0
  137. westpa/work_managers/serial.py +28 -0
  138. westpa/work_managers/threads.py +79 -0
  139. westpa/work_managers/zeromq/__init__.py +20 -0
  140. westpa/work_managers/zeromq/core.py +641 -0
  141. westpa/work_managers/zeromq/node.py +131 -0
  142. westpa/work_managers/zeromq/work_manager.py +526 -0
  143. westpa/work_managers/zeromq/worker.py +320 -0
  144. westpa-2022.10.dist-info/AUTHORS +22 -0
  145. westpa-2022.10.dist-info/LICENSE +21 -0
  146. westpa-2022.10.dist-info/METADATA +183 -0
  147. westpa-2022.10.dist-info/RECORD +150 -0
  148. westpa-2022.10.dist-info/WHEEL +6 -0
  149. westpa-2022.10.dist-info/entry_points.txt +29 -0
  150. westpa-2022.10.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 .yamlcfg import YAMLSystem
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 = YAMLSystem()
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)