westpa 2022.10__cp312-cp312-macosx_10_9_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-darwin.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-darwin.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-darwin.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-darwin.so +0 -0
  76. westpa/mclib/__init__.py +264 -0
  77. westpa/mclib/__main__.py +28 -0
  78. westpa/mclib/_mclib.cpython-312-darwin.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-darwin.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 +5 -0
  149. westpa-2022.10.dist-info/entry_points.txt +29 -0
  150. westpa-2022.10.dist-info/top_level.txt +1 -0
@@ -0,0 +1,182 @@
1
+ import logging
2
+ import operator
3
+
4
+ import numpy as np
5
+
6
+ import westpa
7
+ from westpa.core.yamlcfg import check_bool
8
+ from westpa.core.kinetics import RateAverager
9
+ from westpa.westext.weed.ProbAdjustEquil import probAdjustEquil
10
+ from westpa.core._rc import bins_from_yaml_dict
11
+
12
+ EPS = np.finfo(np.float64).eps
13
+
14
+ log = logging.getLogger(__name__)
15
+
16
+
17
+ class WEEDDriver:
18
+ def __init__(self, sim_manager, plugin_config):
19
+ if not sim_manager.work_manager.is_master:
20
+ return
21
+
22
+ self.sim_manager = sim_manager
23
+ self.data_manager = sim_manager.data_manager
24
+ self.system = sim_manager.system
25
+ self.work_manager = sim_manager.work_manager
26
+
27
+ self.do_reweight = check_bool(
28
+ plugin_config.get('do_equilibrium_reweighting', False) or plugin_config.get('do_reweighting', False)
29
+ )
30
+ self.windowsize = 0.5
31
+ self.windowtype = 'fraction'
32
+
33
+ windowsize = plugin_config.get('window_size')
34
+ if windowsize is not None:
35
+ if isinstance(windowsize, float):
36
+ self.windowsize = windowsize
37
+ self.windowtype = 'fraction'
38
+ if self.windowsize <= 0 or self.windowsize > 1:
39
+ raise ValueError('WEED parameter error -- fractional window size must be in (0,1]')
40
+ elif isinstance(windowsize, int):
41
+ self.windowsize = int(windowsize)
42
+ self.windowtype = 'fixed'
43
+ else:
44
+ raise ValueError('WEED parameter error -- invalid window size {!r}'.format(windowsize))
45
+ log.info('using window size of {!r} ({})'.format(self.windowsize, self.windowtype))
46
+
47
+ self.max_windowsize = plugin_config.get('max_window_size')
48
+ if self.max_windowsize is not None:
49
+ log.info('Using max windowsize of {:d}'.format(self.max_windowsize))
50
+
51
+ self.reweight_period = plugin_config.get('reweight_period', 0)
52
+ self.priority = plugin_config.get('priority', 0)
53
+
54
+ self.rate_calc_queue_size = plugin_config.get('rate_calc_queue_size', 1)
55
+ self.rate_calc_n_blocks = plugin_config.get('rate_calc_n_blocks', 1)
56
+
57
+ bin_obj = plugin_config.get('bins', None)
58
+ if isinstance(bin_obj, dict):
59
+ bin_obj = bins_from_yaml_dict(bin_obj)
60
+ self.bin_mapper = bin_obj
61
+
62
+ if self.do_reweight:
63
+ sim_manager.register_callback(sim_manager.prepare_new_iteration, self.prepare_new_iteration, self.priority)
64
+
65
+ def get_rates(self, n_iter, mapper):
66
+ '''Get rates and associated uncertainties as of n_iter, according to the window size the user
67
+ has selected (self.windowsize)'''
68
+
69
+ if self.windowtype == 'fraction':
70
+ if self.max_windowsize is not None:
71
+ eff_windowsize = min(self.max_windowsize, int(n_iter * self.windowsize))
72
+ else:
73
+ eff_windowsize = int(n_iter * self.windowsize)
74
+ else: # self.windowtype == 'fixed':
75
+ eff_windowsize = min(n_iter, self.windowsize or 0)
76
+
77
+ averager = RateAverager(mapper, self.system, self.data_manager, self.work_manager)
78
+ averager.calculate(max(1, n_iter - eff_windowsize), n_iter + 1, self.rate_calc_n_blocks, self.rate_calc_queue_size)
79
+ self.eff_windowsize = eff_windowsize
80
+
81
+ return averager
82
+
83
+ def prepare_new_iteration(self):
84
+ n_iter = self.sim_manager.n_iter
85
+ we_driver = self.sim_manager.we_driver
86
+
87
+ if we_driver.target_states and self.do_reweight:
88
+ log.warning('equilibrium reweighting requested but target states (sinks) present; reweighting disabled')
89
+ return
90
+
91
+ if not self.do_reweight:
92
+ # Reweighting not requested
93
+ log.debug('Equilibrium reweighting not enabled')
94
+ return
95
+
96
+ with self.data_manager.lock:
97
+ weed_global_group = self.data_manager.we_h5file.require_group('weed')
98
+ last_reweighting = int(weed_global_group.attrs.get('last_reweighting', 0))
99
+
100
+ if n_iter - last_reweighting < self.reweight_period:
101
+ # Not time to reweight yet
102
+ log.debug('not reweighting')
103
+ return
104
+ else:
105
+ log.debug('reweighting')
106
+
107
+ if self.bin_mapper is None:
108
+ mapper = we_driver.bin_mapper
109
+ bins = we_driver.next_iter_binning
110
+ westpa.rc.pstatus('\nReweighting using the simulation bin mapper:\n{}'.format(mapper))
111
+ else:
112
+ mapper = self.bin_mapper
113
+ bins = mapper.construct_bins()
114
+
115
+ segments = [s for s in we_driver.next_iter_segments]
116
+ pcoords = self.system.new_pcoord_array(len(segments))
117
+ for iseg, segment in enumerate(segments):
118
+ pcoords[iseg] = segment.pcoord[0]
119
+ assignments = mapper.assign(pcoords)
120
+ for segment, assignment in zip(segments, assignments):
121
+ bins[assignment].add(segment)
122
+
123
+ westpa.rc.pstatus('\nReweighting using a different bin mapper than simulation:\n{}'.format(mapper))
124
+
125
+ n_bins = len(bins)
126
+
127
+ # Create storage for ourselves
128
+ with self.data_manager.lock:
129
+ iter_group = self.data_manager.get_iter_group(n_iter)
130
+ try:
131
+ del iter_group['weed']
132
+ except KeyError:
133
+ pass
134
+
135
+ weed_iter_group = iter_group.create_group('weed')
136
+ avg_populations_ds = weed_iter_group.create_dataset('avg_populations', shape=(n_bins,), dtype=np.float64)
137
+ unc_populations_ds = weed_iter_group.create_dataset('unc_populations', shape=(n_bins,), dtype=np.float64)
138
+ avg_flux_ds = weed_iter_group.create_dataset('avg_fluxes', shape=(n_bins, n_bins), dtype=np.float64)
139
+ unc_flux_ds = weed_iter_group.create_dataset('unc_fluxes', shape=(n_bins, n_bins), dtype=np.float64)
140
+ avg_rates_ds = weed_iter_group.create_dataset('avg_rates', shape=(n_bins, n_bins), dtype=np.float64)
141
+ unc_rates_ds = weed_iter_group.create_dataset('unc_rates', shape=(n_bins, n_bins), dtype=np.float64)
142
+
143
+ averager = self.get_rates(n_iter, mapper)
144
+
145
+ with self.data_manager.flushing_lock():
146
+ avg_populations_ds[...] = averager.average_populations
147
+ unc_populations_ds[...] = averager.stderr_populations
148
+ avg_flux_ds[...] = averager.average_flux
149
+ unc_flux_ds[...] = averager.stderr_flux
150
+ avg_rates_ds[...] = averager.average_rate
151
+ unc_rates_ds[...] = averager.stderr_rate
152
+
153
+ binprobs = np.fromiter(map(operator.attrgetter('weight'), bins), dtype=np.float64, count=n_bins)
154
+ orig_binprobs = binprobs.copy()
155
+
156
+ westpa.rc.pstatus('Calculating equilibrium reweighting using window size of {:d}'.format(self.eff_windowsize))
157
+ westpa.rc.pstatus('\nBin probabilities prior to reweighting:\n{!s}'.format(binprobs))
158
+ westpa.rc.pflush()
159
+
160
+ probAdjustEquil(binprobs, averager.average_rate, averager.stderr_rate)
161
+
162
+ # Check to see if reweighting has set non-zero bins to zero probability (should never happen)
163
+ assert (~((orig_binprobs > 0) & (binprobs == 0))).all(), 'populated bin reweighted to zero probability'
164
+
165
+ # Check to see if reweighting has set zero bins to nonzero probability (may happen)
166
+ z2nz_mask = (orig_binprobs == 0) & (binprobs > 0)
167
+ if (z2nz_mask).any():
168
+ westpa.rc.pstatus('Reweighting would assign nonzero probability to an empty bin; not reweighting this iteration.')
169
+ westpa.rc.pstatus('Empty bins assigned nonzero probability: {!s}.'.format(np.array_str(np.arange(n_bins)[z2nz_mask])))
170
+ else:
171
+ westpa.rc.pstatus('\nBin populations after reweighting:\n{!s}'.format(binprobs))
172
+ for bin, newprob in zip(bins, binprobs):
173
+ bin.reweight(newprob)
174
+
175
+ weed_global_group.attrs['last_reweighting'] = n_iter
176
+
177
+ assert (
178
+ abs(1 - np.fromiter(map(operator.attrgetter('weight'), bins), dtype=np.float64, count=n_bins).sum())
179
+ < EPS * np.fromiter(map(len, bins), dtype=int, count=n_bins).sum()
180
+ )
181
+
182
+ westpa.rc.pflush()
@@ -0,0 +1,101 @@
1
+ import numpy as np
2
+ import scipy.optimize
3
+
4
+
5
+ def solve_steady_state(T, U, target_bins_index):
6
+ ntarget = len(target_bins_index) # Number of target states
7
+ nstates = T.shape[0] # Number of total states
8
+
9
+ # Number of active states
10
+ nsolve = nstates - ntarget
11
+
12
+ # list of active states
13
+ sactive = sorted(list(set(range(nstates)) - set(target_bins_index)))
14
+
15
+ W = np.zeros((nsolve, nsolve))
16
+ W_unc = np.zeros((nsolve, nsolve))
17
+ S = np.zeros((nsolve,))
18
+
19
+ for iiw, iit in zip(range(nsolve), sactive):
20
+ for jjw, jjt in zip(range(nsolve), sactive):
21
+ W[iiw, jjw] = T[jjt, iit]
22
+ W_unc[iiw, jjw] = U[jjt, iit]
23
+
24
+ for ii in range(nsolve):
25
+ W[ii, ii] = 0.0
26
+ for jj in range(nstates): # nstates
27
+ if jj != ii:
28
+ W[ii, ii] -= T[ii, jj]
29
+
30
+ # we have n equations, but only n-1 linearly independent equations
31
+ # set one equation to constraint sum(Pi)=1
32
+
33
+ # Pick row that contains the largest uncertainty to replace
34
+ ii = np.unravel_index(np.argmax(W_unc), W_unc.shape)[1]
35
+
36
+ S[ii] = 1.0
37
+ W[ii, :] = 1.0
38
+
39
+ # P = np.linalg.solve(W,S)
40
+ try:
41
+ P, err = scipy.optimize.nnls(W, S)
42
+ except RuntimeError:
43
+ print('Solve did not converge')
44
+ return None
45
+
46
+ # There are some instances where a single bin has its prob set
47
+ # to 1.0; In this case do not reweight
48
+ if np.allclose(np.max(P), 1.0):
49
+ return None
50
+
51
+ pp = np.matrix(W) * np.matrix(P.reshape(-1, 1))
52
+
53
+ print('WESS: M*p = {}'.format(pp))
54
+ print('WESS: max = {}'.format(np.max(pp)))
55
+
56
+ return P, err, sactive
57
+
58
+
59
+ def prob_adjust(binprob, rates, uncert, oldindex, targets=[]):
60
+ nbins = binprob.size
61
+
62
+ result = solve_steady_state(rates, uncert, targets)
63
+
64
+ if result is None:
65
+ return binprob
66
+ else:
67
+ ss_estimate, err, active_bins = result
68
+
69
+ print('WESS NNLS norm: {}'.format(err))
70
+
71
+ # now remap new_weights onto the bin indices
72
+ MappedActiveBins = []
73
+ for ibin in active_bins:
74
+ MappedActiveBins.append(oldindex[ibin])
75
+
76
+ mapped_new_weights = np.zeros((nbins,))
77
+ mapped_new_weights[MappedActiveBins] = ss_estimate
78
+
79
+ # Check to make sure no bins with non-zero probability end up with zero prob after reweighting
80
+ orig_nzi = np.nonzero(binprob)[0] # bins that originally had non-zero prob
81
+ new_zi = np.where(mapped_new_weights == 0.0)[0] # bins that after reweight have zero prob
82
+ ri = np.intersect1d(orig_nzi, new_zi) # bins to reset
83
+ mapped_new_weights[ri] = 1.0e-16
84
+
85
+ # Check to make sure no bins with zero probability end up with nonzero prob after reweighting
86
+ orig_zi = np.where(binprob == 0.0)[0] # bins that originally had zero prob
87
+ new_nzi = np.nonzero(mapped_new_weights)[0] # bins that after reweight have non-zero prob
88
+ ri = np.intersect1d(orig_zi, new_nzi) # bins to reset
89
+ mapped_new_weights[ri] = 0.0
90
+
91
+ # Ensure that all target bins have their weight set to zero
92
+ MappedTargetBins = []
93
+ for ibin in targets:
94
+ MappedTargetBins.append(oldindex[ibin])
95
+ mapped_new_weights[MappedTargetBins] = 0.0
96
+
97
+ mapped_new_weights /= np.sum(mapped_new_weights)
98
+
99
+ assert not (mapped_new_weights < 0).any()
100
+
101
+ return mapped_new_weights
@@ -0,0 +1,6 @@
1
+ from . import ProbAdjust
2
+ from .ProbAdjust import prob_adjust
3
+ from .wess_driver import WESSDriver
4
+
5
+
6
+ __all__ = ['ProbAdjust', 'prob_adjust', 'WESSDriver']
@@ -0,0 +1,207 @@
1
+ import logging
2
+ import operator
3
+
4
+ import numpy as np
5
+
6
+ import westpa
7
+ from westpa.core.yamlcfg import check_bool
8
+ from westpa.core.kinetics import RateAverager
9
+ from westpa.westext.wess.ProbAdjust import prob_adjust
10
+ from westpa.core._rc import bins_from_yaml_dict
11
+
12
+ EPS = np.finfo(np.float64).eps
13
+
14
+ log = logging.getLogger(__name__)
15
+
16
+
17
+ def reduce_array(Aij):
18
+ """Remove empty rows and columns from an array Aij and return the reduced
19
+ array Bij and the list of non-empty states"""
20
+
21
+ nonempty = list(range(0, Aij.shape[0]))
22
+ eps = np.finfo(Aij.dtype).eps
23
+
24
+ for i in range(0, Aij.shape[0]):
25
+ if (Aij[i, :] < eps).all() and (Aij[:, i] < eps).all():
26
+ nonempty.pop(nonempty.index(i))
27
+
28
+ nne = len(nonempty)
29
+ Bij = np.zeros((nne, nne))
30
+
31
+ for i in range(0, nne):
32
+ for j in range(0, nne):
33
+ Bij[i, j] = Aij[nonempty[i], nonempty[j]]
34
+
35
+ return Bij, nonempty
36
+
37
+
38
+ class WESSDriver:
39
+ def __init__(self, sim_manager, plugin_config):
40
+ if not sim_manager.work_manager.is_master:
41
+ return
42
+
43
+ self.sim_manager = sim_manager
44
+ self.data_manager = sim_manager.data_manager
45
+ self.system = sim_manager.system
46
+ self.work_manager = sim_manager.work_manager
47
+
48
+ self.do_reweight = check_bool(plugin_config.get('do_reweighting', False))
49
+ self.windowsize = 0.5
50
+ self.windowtype = 'fraction'
51
+
52
+ windowsize = plugin_config.get('window_size')
53
+ if windowsize is not None:
54
+ if isinstance(windowsize, float):
55
+ self.windowsize = windowsize
56
+ self.windowtype = 'fraction'
57
+ if self.windowsize <= 0 or self.windowsize > 1:
58
+ raise ValueError('WESS parameter error -- fractional window size must be in (0,1]')
59
+ elif isinstance(windowsize, int):
60
+ self.windowsize = int(windowsize)
61
+ self.windowtype = 'fixed'
62
+ else:
63
+ raise ValueError('WESS parameter error -- invalid window size {!r}'.format(windowsize))
64
+ log.info('using window size of {!r} ({})'.format(self.windowsize, self.windowtype))
65
+
66
+ self.max_windowsize = plugin_config.get('max_window_size')
67
+ if self.max_windowsize is not None:
68
+ log.info('Using max windowsize of {:d}'.format(self.max_windowsize))
69
+
70
+ self.reweight_period = plugin_config.get('reweight_period', 0)
71
+ self.priority = plugin_config.get('priority', 0)
72
+
73
+ self.rate_calc_queue_size = plugin_config.get('rate_calc_queue_size', 1)
74
+ self.rate_calc_n_blocks = plugin_config.get('rate_calc_n_blocks', 1)
75
+
76
+ bin_obj = plugin_config.get('bins', None)
77
+ if isinstance(bin_obj, dict):
78
+ bin_obj = bins_from_yaml_dict(bin_obj)
79
+ self.bin_mapper = bin_obj
80
+
81
+ if self.do_reweight:
82
+ sim_manager.register_callback(sim_manager.prepare_new_iteration, self.prepare_new_iteration, self.priority)
83
+
84
+ self.write_matrices = plugin_config.get('write_matrices', False)
85
+
86
+ def get_rates(self, n_iter, mapper):
87
+ '''Get rates and associated uncertainties as of n_iter, according to the window size the user
88
+ has selected (self.windowsize)'''
89
+
90
+ if self.windowtype == 'fraction':
91
+ if self.max_windowsize is not None:
92
+ eff_windowsize = min(self.max_windowsize, int(n_iter * self.windowsize))
93
+ else:
94
+ eff_windowsize = int(n_iter * self.windowsize)
95
+ else: # self.windowtype == 'fixed':
96
+ eff_windowsize = min(n_iter, self.windowsize or 0)
97
+
98
+ averager = RateAverager(mapper, self.system, self.data_manager, self.work_manager)
99
+ averager.calculate(max(1, n_iter - eff_windowsize), n_iter + 1, self.rate_calc_n_blocks, self.rate_calc_queue_size)
100
+ self.eff_windowsize = eff_windowsize
101
+
102
+ return averager
103
+
104
+ def prepare_new_iteration(self):
105
+ n_iter = self.sim_manager.n_iter
106
+ we_driver = self.sim_manager.we_driver
107
+
108
+ if not self.do_reweight:
109
+ # Reweighting not requested (or not possible)
110
+ log.debug('Reweighting not enabled')
111
+ return
112
+
113
+ with self.data_manager.lock:
114
+ wess_global_group = self.data_manager.we_h5file.require_group('wess')
115
+ last_reweighting = int(wess_global_group.attrs.get('last_reweighting', 0))
116
+
117
+ if n_iter - last_reweighting < self.reweight_period:
118
+ # Not time to reweight yet
119
+ log.debug('not reweighting')
120
+ return
121
+ else:
122
+ log.debug('reweighting')
123
+
124
+ if self.bin_mapper is None:
125
+ mapper = we_driver.bin_mapper
126
+ bins = we_driver.next_iter_binning
127
+ target_regions = list(we_driver.target_states.keys())
128
+ westpa.rc.pstatus('\nReweighting using the simulation bin mapper:\n{}'.format(mapper))
129
+ else:
130
+ mapper = self.bin_mapper
131
+ bins = mapper.construct_bins()
132
+
133
+ segments = [s for s in we_driver.next_iter_segments]
134
+ pcoords = self.system.new_pcoord_array(len(segments))
135
+ for iseg, segment in enumerate(segments):
136
+ pcoords[iseg] = segment.pcoord[0]
137
+ assignments = mapper.assign(pcoords)
138
+ for segment, assignment in zip(segments, assignments):
139
+ bins[assignment].add(segment)
140
+
141
+ target_states = list(we_driver.target_states.values())
142
+ target_regions = []
143
+ for tstate in target_states:
144
+ tstate_assignment = mapper.assign([tstate.pcoord])[0]
145
+ target_regions.append(tstate_assignment)
146
+ westpa.rc.pstatus('\nReweighting using a different bin mapper than simulation:\n{}'.format(mapper))
147
+
148
+ n_bins = len(bins)
149
+ westpa.rc.pstatus('Averaging rates')
150
+ averager = self.get_rates(n_iter, mapper)
151
+ binprobs = np.fromiter(map(operator.attrgetter('weight'), bins), dtype=np.float64, count=n_bins)
152
+ orig_binprobs = binprobs.copy()
153
+
154
+ if self.write_matrices:
155
+ # Create storage for ourselves
156
+ with self.data_manager.lock:
157
+ iter_group = self.data_manager.get_iter_group(n_iter)
158
+ try:
159
+ del iter_group['wess']
160
+ except KeyError:
161
+ pass
162
+
163
+ wess_iter_group = iter_group.create_group('wess')
164
+ wess_iter_group.create_dataset('avg_populations', data=averager.average_populations, compression=4)
165
+ wess_iter_group.create_dataset('unc_populations', data=averager.stderr_populations, compression=4)
166
+ wess_iter_group.create_dataset('avg_fluxes', data=averager.average_flux, compression=4)
167
+ wess_iter_group.create_dataset('unc_fluxes', data=averager.stderr_flux, compression=4)
168
+ wess_iter_group.create_dataset('avg_rates', data=averager.average_rate, compression=4)
169
+ wess_iter_group.create_dataset('unc_rates', data=averager.stderr_rate, compression=4)
170
+
171
+ westpa.rc.pstatus('Calculating reweighting using window size of {:d}'.format(self.eff_windowsize))
172
+ westpa.rc.pstatus('\nBin probabilities prior to reweighting:\n{!s}'.format(binprobs))
173
+ westpa.rc.pflush()
174
+
175
+ rij, oldindex = reduce_array(averager.average_rate)
176
+ uij = averager.stderr_rate[np.ix_(oldindex, oldindex)]
177
+
178
+ flat_target_regions = []
179
+ for target_region in target_regions:
180
+ if target_region in oldindex: # it is possible that the target region was removed (ie if no recycling has occurred)
181
+ new_ibin = oldindex.index(target_region) # this is in terms of the Rij
182
+ flat_target_regions.append(new_ibin)
183
+
184
+ binprobs = prob_adjust(binprobs, rij, uij, oldindex, flat_target_regions)
185
+
186
+ # Check to see if reweighting has set non-zero bins to zero probability (should never happen)
187
+ assert (~((orig_binprobs > 0) & (binprobs == 0))).all(), 'populated bin reweighted to zero probability'
188
+
189
+ # Check to see if reweighting has set zero bins to nonzero probability (may happen)
190
+ z2nz_mask = (orig_binprobs == 0) & (binprobs > 0)
191
+ if (z2nz_mask).any():
192
+ westpa.rc.pstatus('Reweighting would assign nonzero probability to an empty bin; not reweighting this iteration.')
193
+ westpa.rc.pstatus('Empty bins assigned nonzero probability: {!s}.'.format(np.array_str(np.arange(n_bins)[z2nz_mask])))
194
+ else:
195
+ westpa.rc.pstatus('\nBin populations after reweighting:\n{!s}'.format(binprobs))
196
+ for bin, newprob in zip(bins, binprobs):
197
+ if len(bin):
198
+ bin.reweight(newprob)
199
+
200
+ wess_global_group.attrs['last_reweighting'] = n_iter
201
+
202
+ assert (
203
+ abs(1 - np.fromiter(map(operator.attrgetter('weight'), bins), dtype=np.float64, count=n_bins).sum())
204
+ < EPS * np.fromiter(map(len, bins), dtype=int, count=n_bins).sum()
205
+ )
206
+
207
+ westpa.rc.pflush()
@@ -0,0 +1,57 @@
1
+ '''A system for parallel, remote execution of multiple arbitrary tasks.
2
+ Much of this, both in concept and execution, was inspired by (and in some
3
+ cases based heavily on) the ``concurrent.futures`` package from Python 3.2,
4
+ with some simplifications and adaptations (thanks to Brian Quinlan and his
5
+ futures implementation).
6
+ '''
7
+
8
+ import logging
9
+
10
+ from .core import WorkManager, WMFuture, FutureWatcher # noqa
11
+
12
+
13
+ # Import core work managers, which should run most everywhere that
14
+ # Python does
15
+ from . import serial, threads, processes # noqa
16
+ from .serial import SerialWorkManager
17
+ from .threads import ThreadsWorkManager
18
+ from .processes import ProcessWorkManager
19
+
20
+ log = logging.getLogger(__name__)
21
+
22
+ _available_work_managers = {'serial': SerialWorkManager, 'threads': ThreadsWorkManager, 'processes': ProcessWorkManager}
23
+
24
+ # Import ZeroMQ work manager if available
25
+ try:
26
+ from . import zeromq # noqa
27
+ from .zeromq import ZMQWorkManager
28
+ except ImportError:
29
+ log.info('ZeroMQ work manager not available')
30
+ log.debug('traceback follows', exc_info=True)
31
+ else:
32
+ _available_work_managers['zmq'] = ZMQWorkManager
33
+
34
+ # Import MPI work manager if available
35
+ try:
36
+ from . import mpi # noqa
37
+ from .mpi import MPIWorkManager
38
+ except ImportError:
39
+ log.info('MPI work manager not available')
40
+ log.debug('traceback follows', exc_info=True)
41
+ else:
42
+ _available_work_managers['mpi'] = MPIWorkManager
43
+
44
+ from . import environment # noqa
45
+ from .environment import make_work_manager # noqa
46
+
47
+
48
+ __all__ = [
49
+ 'serial',
50
+ 'threads',
51
+ 'processes',
52
+ 'SerialWorkManager',
53
+ 'ThreadsWorkManager',
54
+ 'ProcessWorkManager',
55
+ 'environment',
56
+ 'make_work_manager',
57
+ ]