westpa 2022.12__cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of westpa might be problematic. Click here for more details.

Files changed (149) 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 +68 -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 +376 -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 +491 -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-313-x86_64-linux-gnu.so +0 -0
  42. westpa/core/binning/assign.py +455 -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 +506 -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-313-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 +719 -0
  61. westpa/core/reweight/__init__.py +14 -0
  62. westpa/core/reweight/_reweight.cpython-313-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 +835 -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 +910 -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/_fasthist.cpython-313-x86_64-linux-gnu.so +0 -0
  75. westpa/mclib/__init__.py +271 -0
  76. westpa/mclib/__main__.py +28 -0
  77. westpa/mclib/_mclib.cpython-313-x86_64-linux-gnu.so +0 -0
  78. westpa/oldtools/__init__.py +4 -0
  79. westpa/oldtools/aframe/__init__.py +35 -0
  80. westpa/oldtools/aframe/atool.py +75 -0
  81. westpa/oldtools/aframe/base_mixin.py +26 -0
  82. westpa/oldtools/aframe/binning.py +178 -0
  83. westpa/oldtools/aframe/data_reader.py +560 -0
  84. westpa/oldtools/aframe/iter_range.py +200 -0
  85. westpa/oldtools/aframe/kinetics.py +117 -0
  86. westpa/oldtools/aframe/mcbs.py +153 -0
  87. westpa/oldtools/aframe/output.py +39 -0
  88. westpa/oldtools/aframe/plotting.py +90 -0
  89. westpa/oldtools/aframe/trajwalker.py +126 -0
  90. westpa/oldtools/aframe/transitions.py +469 -0
  91. westpa/oldtools/cmds/__init__.py +0 -0
  92. westpa/oldtools/cmds/w_ttimes.py +361 -0
  93. westpa/oldtools/files.py +34 -0
  94. westpa/oldtools/miscfn.py +23 -0
  95. westpa/oldtools/stats/__init__.py +4 -0
  96. westpa/oldtools/stats/accumulator.py +35 -0
  97. westpa/oldtools/stats/edfs.py +129 -0
  98. westpa/oldtools/stats/mcbs.py +96 -0
  99. westpa/tools/__init__.py +33 -0
  100. westpa/tools/binning.py +472 -0
  101. westpa/tools/core.py +340 -0
  102. westpa/tools/data_reader.py +159 -0
  103. westpa/tools/dtypes.py +31 -0
  104. westpa/tools/iter_range.py +198 -0
  105. westpa/tools/kinetics_tool.py +340 -0
  106. westpa/tools/plot.py +283 -0
  107. westpa/tools/progress.py +17 -0
  108. westpa/tools/selected_segs.py +154 -0
  109. westpa/tools/wipi.py +751 -0
  110. westpa/trajtree/__init__.py +4 -0
  111. westpa/trajtree/_trajtree.cpython-313-x86_64-linux-gnu.so +0 -0
  112. westpa/trajtree/trajtree.py +117 -0
  113. westpa/westext/__init__.py +0 -0
  114. westpa/westext/adaptvoronoi/__init__.py +3 -0
  115. westpa/westext/adaptvoronoi/adaptVor_driver.py +214 -0
  116. westpa/westext/hamsm_restarting/__init__.py +3 -0
  117. westpa/westext/hamsm_restarting/example_overrides.py +35 -0
  118. westpa/westext/hamsm_restarting/restart_driver.py +1165 -0
  119. westpa/westext/stringmethod/__init__.py +11 -0
  120. westpa/westext/stringmethod/fourier_fitting.py +69 -0
  121. westpa/westext/stringmethod/string_driver.py +253 -0
  122. westpa/westext/stringmethod/string_method.py +306 -0
  123. westpa/westext/weed/BinCluster.py +180 -0
  124. westpa/westext/weed/ProbAdjustEquil.py +100 -0
  125. westpa/westext/weed/UncertMath.py +247 -0
  126. westpa/westext/weed/__init__.py +10 -0
  127. westpa/westext/weed/weed_driver.py +192 -0
  128. westpa/westext/wess/ProbAdjust.py +101 -0
  129. westpa/westext/wess/__init__.py +6 -0
  130. westpa/westext/wess/wess_driver.py +217 -0
  131. westpa/work_managers/__init__.py +57 -0
  132. westpa/work_managers/core.py +396 -0
  133. westpa/work_managers/environment.py +134 -0
  134. westpa/work_managers/mpi.py +318 -0
  135. westpa/work_managers/processes.py +187 -0
  136. westpa/work_managers/serial.py +28 -0
  137. westpa/work_managers/threads.py +79 -0
  138. westpa/work_managers/zeromq/__init__.py +20 -0
  139. westpa/work_managers/zeromq/core.py +641 -0
  140. westpa/work_managers/zeromq/node.py +131 -0
  141. westpa/work_managers/zeromq/work_manager.py +526 -0
  142. westpa/work_managers/zeromq/worker.py +320 -0
  143. westpa-2022.12.dist-info/AUTHORS +22 -0
  144. westpa-2022.12.dist-info/LICENSE +21 -0
  145. westpa-2022.12.dist-info/METADATA +193 -0
  146. westpa-2022.12.dist-info/RECORD +149 -0
  147. westpa-2022.12.dist-info/WHEEL +6 -0
  148. westpa-2022.12.dist-info/entry_points.txt +29 -0
  149. westpa-2022.12.dist-info/top_level.txt +1 -0
westpa/tools/plot.py ADDED
@@ -0,0 +1,283 @@
1
+ # import warnings
2
+ # warnings.filterwarnings('ignore', category=DeprecationWarning)
3
+ # warnings.filterwarnings('ignore', category=RuntimeWarning)
4
+ # warnings.filterwarnings('ignore', category=FutureWarning)
5
+ import numpy as np
6
+
7
+ # We don't care if we're reimporting blessings, under this context.
8
+ # warnings.filterwarnings('ignore')
9
+
10
+
11
+ class Plotter:
12
+ '''
13
+ This is a semi-generic plotting interface that has a built in curses based terminal plotter.
14
+ It's fairly specific to what we're using it for here, but we could (and maybe should) build it out into
15
+ a little library that we can use via the command line to plot things. Might be useful for looking at data later.
16
+ That would also cut the size of this tool down by a good bit.
17
+ '''
18
+
19
+ # def __init__(self, kinavg, kinrw, iteration, bin_labels, state_labels, state_pops, bin_pops, interface='matplotlib'):
20
+ def __init__(self, h5file, h5key, iteration=-1, interface='matplotlib'):
21
+ # Need to sort through and fix all this, but hey.
22
+ self.iteration = iteration
23
+ # These two are important for... reasons.
24
+ try:
25
+ # Commenting out below lines since `bin_labels` and `state_labels` are uninitialized variables.
26
+ # This will always fail so just raise explicitly
27
+
28
+ # self.bin_labels = list(bin_labels[...])
29
+ # self.state_labels = list(state_labels[...]) + ['unknown']
30
+ raise
31
+ except Exception:
32
+ try:
33
+ self.state_labels = list(h5file['state_labels'][...]) + ['unknown']
34
+ except Exception:
35
+ self.state_labels = None
36
+ # unless we totally fail out.
37
+ self.interface = interface
38
+ # What we should ACTUALLY do is just... yeah, just have it sub in what we need.
39
+ # We'll need to throw in the state labels or whatever, but.
40
+ self.h5file = h5file
41
+ self.h5key = h5key
42
+ # We should determine the number of dimensions of our dataset...
43
+ # This has time data, so an i to j is a 3 dim, and an i is 2.
44
+ try:
45
+ self.dim = len(h5file[h5key].shape)
46
+ except Exception:
47
+ self.dim = 1
48
+ try:
49
+ # does the ci exist?
50
+ _ = h5file[h5key]['expected']
51
+ except Exception:
52
+ self.dim = 1
53
+
54
+ def plot(self, i=0, j=1, tau=1, iteration=None, dim=0, interface=None):
55
+ if iteration is None:
56
+ iteration = self.iteration
57
+ self.__generic_ci__(self.h5file, iteration, i, j, tau=tau, h5key=self.h5key, dim=dim, interface=interface)
58
+
59
+ def __generic_ci__(self, h5file, iteration, i, j, tau, h5key='rate_evolution', dim=0, interface=None):
60
+ # This function just calls the appropriate plot function for our available
61
+ # interface.
62
+ if (interface is None and self.interface == 'text') or interface == 'text':
63
+ if self.dim > 1:
64
+ self.__terminal_ci__(h5file, iteration, i, j, tau, h5key)
65
+ else:
66
+ self.__terminal_expected__(h5file, iteration, i, j, tau, h5key, dim)
67
+ else:
68
+ try:
69
+ import matplotlib
70
+
71
+ matplotlib.use('TkAgg')
72
+ from matplotlib import pyplot as plt
73
+
74
+ if self.dim == 3:
75
+ plt.plot(h5file[h5key]['expected'][:iteration, i, j] / tau, color='black')
76
+ plt.plot(h5file[h5key]['ci_ubound'][:iteration, i, j] / tau, color='grey')
77
+ plt.plot(h5file[h5key]['ci_lbound'][:iteration, i, j] / tau, color='grey')
78
+ else:
79
+ plt.plot(h5file[h5key]['expected'][:iteration, i] / tau, color='black')
80
+ plt.plot(h5file[h5key]['ci_ubound'][:iteration, i] / tau, color='grey')
81
+ plt.plot(h5file[h5key]['ci_lbound'][:iteration, i] / tau, color='grey')
82
+ plt.show()
83
+ except Exception:
84
+ print('Unable to import plotting interface. An X server ($DISPLAY) is required.')
85
+ if self.dim > 1:
86
+ self.__terminal_ci__(h5file, iteration, i, j, tau)
87
+ else:
88
+ self.__terminal_expected__(h5file, iteration, i, j, tau, h5key, dim)
89
+ return 1
90
+
91
+ def __generic_histo__(self, vector, labels):
92
+ # This function just calls the appropriate plot function for our available
93
+ # interface. Same thing as generic_ci, but for a histogram.
94
+ if self.interface == 'text':
95
+ self.__terminal_histo__(vector, labels)
96
+ else:
97
+ try:
98
+ import matplotlib
99
+
100
+ matplotlib.use('TkAgg')
101
+ from matplotlib import pyplot as plt
102
+
103
+ plt.bar(
104
+ list(range(0, np.array(vector).shape[0])), vector, linewidth=0, align='center', color='gold', tick_label=labels
105
+ )
106
+ plt.show()
107
+ except Exception:
108
+ print('Unable to import plotting interface. An X server ($DISPLAY) is required.')
109
+ self.__terminal_histo__(vector, labels)
110
+ return 1
111
+
112
+ def __terminal_histo__(self, vector, labels, fullscreen_mode=True):
113
+ from blessings import Terminal
114
+
115
+ self.t = Terminal()
116
+ h = int(self.t.height / 4) * 3
117
+ w = self.t.width
118
+ cols = np.array(vector).shape[0]
119
+ # Let's print this business!
120
+
121
+ colwidth = w / cols
122
+ with self.t.fullscreen():
123
+ for y in range(0, h):
124
+ for x in range(0, cols):
125
+ if x == 0:
126
+ with self.t.location(0, y):
127
+ print(self.t.red('{0:.4f}|'.format(float(h - y) / float(h))))
128
+ with self.t.location((x * colwidth) + 8 + len(labels[x]) / 2, y):
129
+ if vector[x] >= (float(h - y) / float(h)):
130
+ # print(float(h-y)/float(h))
131
+ print(self.t.on_blue(' '))
132
+ for x in range(0, cols):
133
+ if x == 0:
134
+ with self.t.location(x, h):
135
+ print('States| ')
136
+ with self.t.location((x * colwidth) + 8, h):
137
+ print(self.t.blue(labels[x]))
138
+
139
+ if fullscreen_mode:
140
+ input("Press enter to continue.")
141
+
142
+ def __terminal_ci__(self, h5file, iteration, si, sj, tau, h5key):
143
+ from blessings import Terminal
144
+
145
+ self.t = Terminal()
146
+ h = int(self.t.height / 4 * 3.75)
147
+ # We'll figure out how to subsample the timepoints...
148
+ w = self.t.width
149
+ if self.dim == 3:
150
+ in_tup = (iteration - 1, si, sj)
151
+ else:
152
+ in_tup = (iteration - 1, si)
153
+ yupper = (h5file[h5key]['ci_ubound'][in_tup] / tau) * 2
154
+ ylower = (h5file[h5key]['ci_lbound'][in_tup] / tau) / 2
155
+ # Here are points pertaining to height.
156
+ scale = np.array([0.0] + [ylower + i * (yupper - ylower) / float(h) for i in range(0, h)])[::-1]
157
+ if iteration > w:
158
+ block_size = iteration / w
159
+ else:
160
+ block_size = 1
161
+
162
+ with self.t.fullscreen():
163
+ try:
164
+ for x in range(0, w - 12):
165
+ iter = x * block_size
166
+ if self.dim == 3:
167
+ in_tup = (iter - 1, si, sj)
168
+ else:
169
+ in_tup = (iter - 1, si)
170
+ yupper = h5file[h5key]['ci_ubound'][in_tup] / tau
171
+ ylower = h5file[h5key]['ci_lbound'][in_tup] / tau
172
+ ci = np.digitize([yupper, ylower], scale)
173
+ if x == 0:
174
+ for y in range(0, h + 1):
175
+ with self.t.location(0, y):
176
+ print(self.t.bold(self.t.red('{0:.7f}|'.format(scale[y]))))
177
+ for y in range(ci[0], ci[1]):
178
+ # with self.t.location(x+12, y):
179
+ print(self.t.move(y, x + 12) + self.t.on_blue(' '))
180
+ # print(self.t.on_blue(' '))
181
+ # with self.t.location(x+12, np.digitize(h5file['rate_evolution']['expected'][iter-1, si, sj]/tau, scale)):
182
+ # print(self.t.on_blue('-'))
183
+ print(self.t.move(np.digitize(h5file[h5key]['expected'][in_tup] / tau, scale), x + 12) + self.t.on_blue('-'))
184
+
185
+ for x in range(0, w - 12, w / 10):
186
+ if x == 0:
187
+ with self.t.location(x, h + 1):
188
+ print('Iteration| ')
189
+ with self.t.location(x + 12, h + 1):
190
+ iter = x * block_size
191
+ print(self.t.blue(str(iter)))
192
+ except Exception:
193
+ pass
194
+
195
+ with self.t.location(0, h + 2):
196
+ # We need to improve this.
197
+ # if h5key == 'rate_evolution':
198
+ # print("k_ij from {} to {} from iter 1 to {}".format(self.state_labels[si], self.state_labels[sj], self.iteration))
199
+ # elif h5key == 'conditional_flux_evolution':
200
+ # print("i->j flux from {} to {} from iter 1 to {}".format(self.state_labels[si], self.state_labels[sj], self.iteration))
201
+ if self.dim == 3:
202
+ print(
203
+ "{} from {} to {} from iter 1 to {}".format(
204
+ h5key, self.state_labels[si], self.state_labels[sj], self.iteration
205
+ )
206
+ )
207
+ else:
208
+ print("{} of state {} from iter 1 to {}".format(h5key, self.state_labels[si], self.iteration))
209
+ with self.t.location(0, h + 3):
210
+ input("Press enter to continue.")
211
+
212
+ def __terminal_expected__(self, h5file, iteration, si, sj, tau, h5key, dim):
213
+ from blessings import Terminal
214
+
215
+ self.t = Terminal()
216
+ h = int(self.t.height / 4 * 3.75)
217
+ # We'll figure out how to subsample the timepoints...
218
+ w = self.t.width
219
+ if self.dim == 3:
220
+ in_tup = (iteration - 1, si, sj)
221
+ else:
222
+ in_tup = (iteration - 1, si)
223
+ in_tup = (iteration - 1, dim)
224
+ try:
225
+ yupper = (np.max(h5file) / tau) * 2
226
+ except Exception:
227
+ in_tup = iteration - 1
228
+ yupper = (np.max(h5file) / tau) * 2
229
+ ylower = (np.min(h5file) / tau) * 2
230
+ # Here are points pertaining to height.
231
+ if yupper > 0:
232
+ yupper = (np.max(h5file) / tau) * 1.2
233
+ ylower = (np.min(h5file) / tau) / 2
234
+ scale = np.array([0.0] + [ylower + i * (yupper - ylower) / float(h) for i in range(0, h)])[::-1]
235
+ else:
236
+ yupper = (np.max(h5file) / tau) / 2
237
+ ylower = (np.min(h5file) / tau) * 1.2
238
+ scale = np.array([ylower + i * (yupper - ylower) / float(h) for i in range(0, h)] + [0.0])[::-1]
239
+ if iteration > w:
240
+ block_size = iteration / w
241
+ else:
242
+ block_size = 1
243
+
244
+ with self.t.fullscreen():
245
+ try:
246
+ for x in range(0, w - 12):
247
+ iter = x * block_size
248
+ if self.dim == 3:
249
+ in_tup = (iter - 1, si, sj)
250
+ else:
251
+ in_tup = (iter - 1, si)
252
+ in_tup = (iter - 1, dim)
253
+ try:
254
+ yupper = h5file[in_tup] / tau
255
+ except Exception:
256
+ in_tup = iter - 1
257
+ yupper = h5file[in_tup] / tau
258
+ ylower = h5file[in_tup] / tau
259
+ ci = np.digitize([yupper, ylower], scale)
260
+ if x == 0:
261
+ for y in range(0, h + 1):
262
+ with self.t.location(0, y):
263
+ print(self.t.bold(self.t.red('{0:.7f}|'.format(scale[y]))))
264
+ for y in range(ci[0], ci[1]):
265
+ print(self.t.move(y, x + 12) + self.t.on_blue(' '))
266
+ # print(self.t.on_blue(' '))
267
+ print(self.t.move(np.digitize(h5file[in_tup] / tau, scale), x + 12) + self.t.on_blue('-'))
268
+
269
+ for x in range(0, w - 12, w / 10):
270
+ if x == 0:
271
+ with self.t.location(x, h + 1):
272
+ print('Iteration| ')
273
+ with self.t.location(x + 12, h + 1):
274
+ iter = x * block_size
275
+ print(self.t.blue(str(iter)))
276
+ except Exception:
277
+ pass
278
+
279
+ with self.t.location(0, h + 2):
280
+ # We need to improve this.
281
+ print("{} from iter 1 to {}".format(h5key, self.iteration))
282
+ with self.t.location(0, h + 3):
283
+ input("Press enter to continue.")
@@ -0,0 +1,17 @@
1
+ import westpa
2
+ from westpa.core.progress import ProgressIndicator
3
+ from westpa.tools.core import WESTToolComponent
4
+
5
+
6
+ class ProgressIndicatorComponent(WESTToolComponent):
7
+ def __init__(self):
8
+ super().__init__()
9
+ self.indicator = None
10
+
11
+ def add_args(self, parser):
12
+ pass
13
+
14
+ def process_args(self, args):
15
+ self.indicator = ProgressIndicator()
16
+ if westpa.rc.quiet_mode or westpa.rc.verbose_mode or westpa.rc.debug_mode:
17
+ self.indicator.fancy = False
@@ -0,0 +1,154 @@
1
+ import re
2
+
3
+ import numpy as np
4
+
5
+ import westpa
6
+ from .core import WESTToolComponent
7
+ from westpa.core.data_manager import seg_id_dtype
8
+
9
+ re_split_segspec = re.compile(r'\s*:\s*|\s+')
10
+
11
+
12
+ class SegmentSelection:
13
+ def __init__(self, iterable=None):
14
+ '''Initialize this segment selection from an iterable of (n_iter,seg_id) pairs.'''
15
+
16
+ self._segments = set()
17
+ self._segs_by_iter = {}
18
+ self._start_iter = None
19
+ self._stop_iter = None
20
+
21
+ if iterable is not None:
22
+ add = self.add
23
+ for pair in iterable:
24
+ add(tuple(pair))
25
+
26
+ def __len__(self):
27
+ return len(self._segments)
28
+
29
+ def __contains__(self, pair):
30
+ return tuple(pair) in self._segments
31
+
32
+ def add(self, pair):
33
+ (n_iter, seg_id) = int(pair[0]), int(pair[1])
34
+ self._segments.add((n_iter, seg_id))
35
+ self._segs_by_iter.setdefault(n_iter, set()).add(seg_id)
36
+ if self._start_iter is None:
37
+ self._start_iter = n_iter
38
+ else:
39
+ self._start_iter = min(self._start_iter, n_iter)
40
+ if self._stop_iter is None:
41
+ self._stop_iter = n_iter + 1
42
+ else:
43
+ self._stop_iter = max(self._stop_iter, n_iter + 1)
44
+
45
+ def from_iter(self, n_iter):
46
+ return self._segs_by_iter.get(n_iter, set())
47
+
48
+ @property
49
+ def start_iter(self):
50
+ return self._start_iter
51
+
52
+ @property
53
+ def stop_iter(self):
54
+ return self._stop_iter
55
+
56
+ @classmethod
57
+ def from_text(cls, filename):
58
+ segsel = cls()
59
+
60
+ segfile = open(filename, 'rt')
61
+ for line in segfile:
62
+ wline = line.strip()
63
+ if wline[0] == '#' or wline == '':
64
+ continue
65
+
66
+ fields = re_split_segspec.split(wline)
67
+ if len(fields) != 2:
68
+ raise ValueError('malformed segment selection {!r}'.format(line))
69
+
70
+ try:
71
+ n_iter, seg_id = list(map(int, fields))
72
+ except ValueError:
73
+ raise ValueError('malformed segment selection {!r}'.format(line))
74
+
75
+ segsel.add((n_iter, seg_id))
76
+ return segsel
77
+
78
+
79
+ class AllSegmentSelection(SegmentSelection):
80
+ def __init__(self, start_iter=None, stop_iter=None, data_manager=None):
81
+ self.data_manager = data_manager or westpa.rc.get_data_manager()
82
+ self._start_iter = start_iter or 1
83
+ self._stop_iter = stop_iter or self.data_manager.current_iteration
84
+ self._segcount_by_iter = {}
85
+
86
+ def _count_from_iter(self, n_iter):
87
+ try:
88
+ segcount = self._segcount_by_iter[n_iter]
89
+ except KeyError:
90
+ segcount = self.data_manager.get_iter_group(n_iter)['seg_index'].shape[0]
91
+ self._segcount_by_iter[n_iter] = segcount
92
+ return segcount
93
+
94
+ def add(self, pair):
95
+ raise TypeError('cannot add segments to an AllSegmentSelection')
96
+
97
+ def from_iter(self, n_iter):
98
+ return np.arange(0, self._count_from_iter(n_iter), dtype=seg_id_dtype)
99
+
100
+ def __len__(self):
101
+ segcount = 0
102
+ count_from_iter = self._count_from_iter
103
+ for n_iter in range(self._start_iter, self._stop_iter):
104
+ segcount += count_from_iter(n_iter)
105
+ return segcount
106
+
107
+ def __contains__(self, pair):
108
+ (n_iter, seg_id) = pair
109
+ return n_iter >= self._start_iter and n_iter < self._stop_iter and seg_id < self._count_from_iter(n_iter)
110
+
111
+
112
+ class SegSelector(WESTToolComponent):
113
+ def __init__(self):
114
+ super().__init__()
115
+ self.segment_selection = None
116
+ self.segsel_filename = None
117
+
118
+ def add_args(self, parser):
119
+ group = parser.add_argument_group('WEST input data options')
120
+ sgroup = group.add_mutually_exclusive_group()
121
+ sgroup.add_argument(
122
+ '--segments-from',
123
+ metavar='SEGLIST_FILE',
124
+ help='''Include only segments listed in SEGLIST_FILE, as generated by w_select
125
+ (default: include all segments.''',
126
+ )
127
+
128
+ def process_args(self, args):
129
+ if args.segments_from:
130
+ self.segsel_filename = args.segments_from
131
+ self.segment_selection = self.parse_segsel_file(self.segsel_filename)
132
+ else:
133
+ self.segment_selection = AllSegmentSelection()
134
+
135
+ def parse_segsel_file(self, filename):
136
+ segsel = self.segment_selection = SegmentSelection()
137
+
138
+ segfile = open(filename, 'rt')
139
+ for line in segfile:
140
+ wline = line.strip()
141
+ if wline[0] == '#' or wline == '':
142
+ continue
143
+
144
+ fields = re_split_segspec.split(wline)
145
+ if len(fields) != 2:
146
+ raise ValueError('malformed segment selection {!r}'.format(line))
147
+
148
+ try:
149
+ n_iter, seg_id = list(map(int, fields))
150
+ except ValueError:
151
+ raise ValueError('malformed segment selection {!r}'.format(line))
152
+
153
+ segsel.add((n_iter, seg_id))
154
+ return segsel