westpa 2022.12__cp313-cp313-macosx_10_13_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-darwin.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-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 +719 -0
  61. westpa/core/reweight/__init__.py +14 -0
  62. westpa/core/reweight/_reweight.cpython-313-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 +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-darwin.so +0 -0
  75. westpa/mclib/__init__.py +271 -0
  76. westpa/mclib/__main__.py +28 -0
  77. westpa/mclib/_mclib.cpython-313-darwin.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-darwin.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/wipi.py ADDED
@@ -0,0 +1,751 @@
1
+ import numpy as np
2
+ import scipy.sparse as sp
3
+
4
+ from westpa.tools import Plotter
5
+
6
+ # A useful dataclass used as a wrapper for w_ipa to facilitate
7
+ # ease-of-use in ipython/jupyter notebooks/sessions.
8
+ # It basically just wraps up numpy arrays and dicts.
9
+
10
+
11
+ class WIPIDataset:
12
+ def __init__(self, raw, key):
13
+ self.__dict__ = {}
14
+ self.raw = raw
15
+ self.name = key
16
+
17
+ def __repr__(self):
18
+ if isinstance(self.__dict__['raw'], dict):
19
+ return repr(self.__dir__())
20
+ else:
21
+ return repr(self.raw)
22
+
23
+ def __getitem__(self, value):
24
+ if not isinstance(value, str):
25
+ return self.__dict__['raw'][value]
26
+ if value in list(self.__dict__['raw'].keys()):
27
+ return self.__dict__['raw'][value]
28
+ elif value in list(self.__dict__.keys()):
29
+ return self.__dict__[value]
30
+
31
+ def __setitem__(self, key, value):
32
+ self.__dict__[key] = value
33
+
34
+ def __getattr__(self, value):
35
+ # Check if it's an attribute of the underlying datatype.
36
+ # If not, just use the getitem function.
37
+ if value in dir(self.__dict__['raw']):
38
+ return getattr(self.__dict__['raw'], value)
39
+ else:
40
+ return self.__getitem__(value)
41
+
42
+ def __setattr__(self, key, value):
43
+ self.__dict__[key] = value
44
+
45
+ def __dir__(self):
46
+ dict_keys = list(self.__dict__.keys())
47
+ remove = ['raw', 'name', '__dict__', 'plotter']
48
+ for i in remove:
49
+ try:
50
+ dict_keys.remove(str(i))
51
+ except Exception:
52
+ pass
53
+ # We don't enforce that this is a dictionary.
54
+ if isinstance(self.__dict__['raw'], dict):
55
+ return sorted(set(list(self.raw.keys()) + dict_keys))
56
+ else:
57
+ return sorted(set(dict_keys))
58
+
59
+ def keys(self):
60
+ print(self.__dir__())
61
+
62
+ # We want to override the basic math functions, now, so... this is only valid for numpy sets.
63
+ def __add__(self, other):
64
+ return self.__dict__['raw'] + other
65
+
66
+ def __radd__(self, other):
67
+ return other + self.__dict__['raw']
68
+
69
+ def __sub__(self, other):
70
+ return self.__dict__['raw'] - other
71
+
72
+ def __rsub__(self, other):
73
+ return other - self.__dict__['raw']
74
+
75
+ def __mul__(self, other):
76
+ return self.__dict__['raw'] * other
77
+
78
+ def __rmul__(self, other):
79
+ return other * self.__dict__['raw']
80
+
81
+ def __truediv__(self, other):
82
+ return self.__dict__['raw'] / other
83
+
84
+ def __floordiv__(self, other):
85
+ return self.__dict__['raw'] // other
86
+
87
+ def __rtruediv__(self, other):
88
+ return other / self.__dict__['raw']
89
+
90
+ def __mod__(self, other):
91
+ return self.__dict__['raw'] % other
92
+
93
+ def __pow__(self, other):
94
+ return self.__dict__['raw'] ** other
95
+
96
+ def __lshift__(self, other):
97
+ return self.__dict__['raw'] << other
98
+
99
+ def __rshift__(self, other):
100
+ return self.__dict__['raw'] >> other
101
+
102
+ def __and__(self, other):
103
+ return self.__dict__['raw'] & other
104
+
105
+ def __eq__(self, other):
106
+ return self.__dict__['raw'] == other
107
+
108
+ def __ne__(self, other):
109
+ return self.__dict__['raw'] != other
110
+
111
+ def __lt__(self, other):
112
+ return self.__dict__['raw'] < other
113
+
114
+ def __gt__(self, other):
115
+ return self.__dict__['raw'] > other
116
+
117
+ def __le__(self, other):
118
+ return self.__dict__['raw'] <= other
119
+
120
+ def __ge__(self, other):
121
+ return self.__dict__['raw'] >= other
122
+
123
+ def __xor__(self, other):
124
+ return self.__dict__['raw'] ^ other
125
+
126
+ def __or__(self, other):
127
+ return self.__dict__['raw'] | other
128
+
129
+ # def __iadd__(self, other):
130
+ # return self.__dict__['raw'] += other
131
+ # def __isub__(self, other):
132
+ # return self.__dict__['raw'] -= other
133
+ # def __imul__(self, other):
134
+ # return self.__dict__['raw'] *= other
135
+ # def __idiv__(self, other):
136
+ # return self.__dict__['raw'] /= other
137
+ # def __ifloordiv__(self, other):
138
+ # return self.__dict__['raw'] //= other
139
+ # def __imod__(self, other):
140
+ # return self.__dict__['raw'] %= other
141
+ # def __ipow__(self, other):
142
+ # return self.__dict__['raw'] **= other
143
+ # def __ilshift__(self, other):
144
+ # return self.__dict__['raw'] <<= other
145
+ # def __irshift__(self, other):
146
+ # return self.__dict__['raw'] >>= other
147
+ # def __iand__(self, other):
148
+ # return self.__dict__['raw'] &= other
149
+ # def __ixor__(self, other):
150
+ # return self.__dict__['raw'] ^= other
151
+ # def __ior__(self, other):
152
+ # return self.__dict__['raw'] |= other
153
+
154
+
155
+ # Similar to the above, but slightly expanded to contain information from analysis files.
156
+ class KineticsIteration:
157
+ def __init__(self, kin_h5file, index, assign, iteration=-1):
158
+ self.__dict__ = {}
159
+ self.h5file = kin_h5file
160
+ # Keys:
161
+ _2D_h5keys = ['conditional_flux_evolution', 'rate_evolution']
162
+ _1D_h5keys = ['state_pop_evolution', 'color_prob_evolution', 'target_flux_evolution']
163
+ for key in _2D_h5keys:
164
+ try:
165
+ self.__dict__[key] = self.__2D_with_error__(key, index, assign)
166
+ except Exception:
167
+ self.__dict__[key] = None
168
+ for key in _1D_h5keys:
169
+ try:
170
+ self.__dict__[key] = self.__1D_with_error__(key, index, assign)
171
+ except Exception:
172
+ self.__dict__[key] = None
173
+ try:
174
+ self.__dict__['total_fluxes'] = WIPIDataset(raw=np.array(self.h5file['total_fluxes']), key='total_fluxes')
175
+ # We'll have to update this to make things better...
176
+ # self.__dict__['total_fluxes'].plotter = Plotter(self.h5file['total_fluxes'][...], 'Total Fluxes', iteration=iteration, interface='text')
177
+ # self.__dict__['total_fluxes'].plot = self.__dict__['total_fluxes'].plotter.plot
178
+ except Exception:
179
+ pass
180
+
181
+ def __repr__(self):
182
+ return repr(self.__dir__())
183
+
184
+ def __getitem__(self, value):
185
+ if value in list(self.__dict__.keys()):
186
+ return self.__dict__[value]
187
+
188
+ def __setitem__(self, key, value):
189
+ self.__dict__[key] = value
190
+
191
+ def __getattr__(self, value):
192
+ if value in list(self.__dict__.keys()):
193
+ return self.__dict__[value]
194
+
195
+ def __setattr__(self, key, value):
196
+ self.__dict__[key] = value
197
+
198
+ def __dir__(self):
199
+ dict_keys = list(self.__dict__.keys())
200
+ # We don't want to show the plotter class; just the plot function
201
+ remove = ['h5file', '__dict__']
202
+ for i in remove:
203
+ try:
204
+ dict_keys.remove(str(i))
205
+ except Exception:
206
+ pass
207
+ return sorted(set(dict_keys))
208
+
209
+ def keys(self):
210
+ print(self.__dir__())
211
+
212
+ # We seriously need to rename this.
213
+ # It's similar to the global WIPDataset, but has some nice pretty print functions.
214
+ class __custom_dataset__:
215
+ # This is just allow it to be indexed via properties.
216
+ # Not a huge thing, but whatever.
217
+ def __init__(self, raw, assign, key):
218
+ self.__dict__ = {}
219
+ self.raw = raw
220
+ self.name = key
221
+ self.assign = assign
222
+ self.nstates = assign.attrs['nstates']
223
+ self.dim = len(raw.shape)
224
+
225
+ def __repr__(self):
226
+ return repr(self.__dir__())
227
+
228
+ def __getitem__(self, value):
229
+ if value in self.__dict__['raw'].dtype.names:
230
+ return self.__dict__['raw'][value]
231
+ elif value in list(self.__dict__.keys()):
232
+ return self.__dict__[value]
233
+
234
+ def __setitem__(self, key, value):
235
+ self.__dict__[key] = value
236
+
237
+ def __getattr__(self, value):
238
+ if value in self.__dict__['raw'].dtype.names:
239
+ return self.__dict__['raw'][value]
240
+ elif value in list(self.__dict__.keys()):
241
+ return self.__dict__[value]
242
+
243
+ def __setattr__(self, key, value):
244
+ self.__dict__[key] = value
245
+
246
+ def __dir__(self):
247
+ dict_keys = list(self.__dict__.keys())
248
+ # We don't want to show the plotter class; just the plot function
249
+ remove = ['assign', 'dim', 'nstates', 'plotter', '__dict__']
250
+ for i in remove:
251
+ try:
252
+ dict_keys.remove(str(i))
253
+ except Exception:
254
+ pass
255
+ return sorted(set(list(self.raw.dtype.names) + dict_keys))
256
+
257
+ def keys(self):
258
+ print(self.__dir__())
259
+
260
+ def _repr_pretty_(self, p, cycle):
261
+ if self.dim == 1:
262
+ return self._1D_repr_pretty_(p, cycle)
263
+ if self.dim == 2:
264
+ return self._2D_repr_pretty_(p, cycle)
265
+
266
+ def _1D_repr_pretty_(self, p, cycle):
267
+ # We're just using this as a way to print things in a pretty way. They can still be indexed appropriately.
268
+ # Stolen shamelessly from westtools/kinetics_tool.py
269
+ maxlabellen = max(list(map(len, self.assign['state_labels'])))
270
+ p.text('')
271
+ p.text('{name} data:\n'.format(name=self.name))
272
+ for istate in range(self.nstates):
273
+ p.text(
274
+ '{:{maxlabellen}s}: mean={:21.15e} CI=({:21.15e}, {:21.15e}) * tau^-1\n'.format(
275
+ self.assign['state_labels'][istate],
276
+ self.raw['expected'][istate],
277
+ self.raw['ci_lbound'][istate],
278
+ self.raw['ci_ubound'][istate],
279
+ maxlabellen=maxlabellen,
280
+ )
281
+ )
282
+ p.text('To access data, index via the following names:\n')
283
+ p.text(str(self.__dir__()))
284
+ return " "
285
+
286
+ def _2D_repr_pretty_(self, p, cycle):
287
+ # We're just using this as a way to print things in a pretty way. They can still be indexed appropriately.
288
+ # Stolen shamelessly from westtools/kinetics_tool.py
289
+ maxlabellen = max(list(map(len, self.assign['state_labels'])))
290
+ p.text('')
291
+ p.text('{name} data:\n'.format(name=self.name))
292
+ for istate in range(self.nstates):
293
+ for jstate in range(self.nstates):
294
+ if istate == jstate:
295
+ continue
296
+ p.text(
297
+ '{:{maxlabellen}s} -> {:{maxlabellen}s}: mean={:21.15e} CI=({:21.15e}, {:21.15e}) * tau^-1\n'.format(
298
+ self.assign['state_labels'][istate],
299
+ self.assign['state_labels'][jstate],
300
+ self.raw['expected'][istate, jstate],
301
+ self.raw['ci_lbound'][istate, jstate],
302
+ self.raw['ci_ubound'][istate, jstate],
303
+ maxlabellen=maxlabellen,
304
+ )
305
+ )
306
+ p.text('To access data, index via the following names:\n')
307
+ p.text(str(self.__dir__()))
308
+ return " "
309
+
310
+ def __2D_with_error__(self, h5key, index, assign):
311
+ # Check the start and stop, calculate the block size, and index appropriately.
312
+ # While we could try and automatically generate this above, it's a little more consistent to try it here.
313
+ # This should show the first block for which the current iteration has contributed data.
314
+ self.step_iter = (self.h5file[h5key]['iter_stop'][0] - self.h5file[h5key]['iter_start'][0])[1, 0]
315
+ value = (index - self.h5file.attrs['iter_start']) // self.step_iter
316
+ if value < 0:
317
+ value = 0
318
+ raw = self.h5file[h5key][value, :, :]
319
+ error = (raw['ci_ubound'] - raw['ci_lbound']) / (2 * raw['expected'])
320
+ # expected = raw['expected']
321
+ raw = self.__custom_dataset__(raw, assign, h5key)
322
+ raw.error = error
323
+ raw.plotter = Plotter(self.h5file, h5key, iteration=value, interface='text')
324
+ raw.plot = raw.plotter.plot
325
+ return raw
326
+
327
+ def __1D_with_error__(self, h5key, index, assign):
328
+ self.step_iter = (self.h5file[h5key]['iter_stop'][0] - self.h5file[h5key]['iter_start'][0])[1]
329
+ value = (index - self.h5file.attrs['iter_start']) // self.step_iter
330
+ if value < 0:
331
+ value = 0
332
+ raw = self.h5file[h5key][value, :]
333
+ error = (raw['ci_ubound'] - raw['ci_lbound']) / (2 * raw['expected'])
334
+ # expected = raw['expected']
335
+ raw = self.__custom_dataset__(raw, assign, h5key)
336
+ raw.error = error
337
+ raw.plotter = Plotter(self.h5file, h5key, iteration=value, interface='text')
338
+ raw.plot = raw.plotter.plot
339
+ return raw
340
+
341
+
342
+ class __get_data_for_iteration__:
343
+ '''
344
+ All interesting data from an iteration (current/past). Whenever you change the scheme or iteration,
345
+ this dictionary is automatically updated. For the current iteration, it's keyed to the current seg_id.
346
+ For the past iteration, it's keyed to the seg_id in the CURRENT iteration such that:
347
+
348
+ w.current[X] & w.past[X]
349
+
350
+ returns information about seg_id X in the current iteration and information on seg_ID X's PARENT in the
351
+ preceding iteration.
352
+
353
+ Can be indexed via a seg_id, or like a dictionary with the following keys:
354
+
355
+ kinavg, weights, pcoord, auxdata (optional), parents, summary, seg_id, walkers, states, bins
356
+
357
+ kinavg, states, and bins refer to the output from w_kinavg and w_assign for this iteration
358
+ and analysis scheme. They are NOT dynamics bins, but the bins defined in west.cfg.
359
+
360
+ Has the following properties:
361
+
362
+ .minweight, .maxweight
363
+
364
+ which return all properties of the segment that matches those criteria in the selected iteration.
365
+
366
+ If you change the analysis scheme, so, too, will the important values.
367
+ '''
368
+
369
+ def __init__(self, parent, value, seg_ids=None):
370
+ '''
371
+ Initializes and sets the correct data.
372
+ '''
373
+ # We've classed this so that we can override some of the normal functions and allow indexing via seg_id
374
+ self.__dict__ = {}
375
+ # Is this function thread safe?
376
+ iter_group = parent.data_reader.get_iter_group(value)
377
+ # iter_group = parent.west['iterations/iter_{num:08d}'.format(num=value)]
378
+ self.parent = parent
379
+ current = {}
380
+ current['iteration'] = value
381
+ if seg_ids is None:
382
+ seg_ids = range(0, iter_group['seg_index']['weight'].shape[0])
383
+ # Just make these easier to access.
384
+ current['weights'] = iter_group['seg_index']['weight'][seg_ids]
385
+ current['pcoord'] = iter_group['pcoord'][...][seg_ids, :, :]
386
+ try:
387
+ current['auxdata'] = {}
388
+ for key in list(iter_group['auxdata'].keys()):
389
+ current['auxdata'][key] = iter_group['auxdata'][key][...][seg_ids, :]
390
+ except Exception:
391
+ pass
392
+ current['parents'] = iter_group['seg_index']['parent_id'][seg_ids]
393
+ current['summary'] = parent.data_reader.data_manager.get_iter_summary(int(value))
394
+ current['seg_id'] = np.array(list(range(0, iter_group['seg_index'].shape[0])))[seg_ids]
395
+ current['walkers'] = current['summary']['n_particles']
396
+ current['states'] = parent.assign['trajlabels'][value - 1, : current['walkers'], :][seg_ids]
397
+ current['bins'] = parent.assign['assignments'][value - 1, : current['walkers'], :][seg_ids]
398
+ # Calculates the bin population for this iteration.
399
+ nbins = parent.assign['state_map'].shape[0]
400
+ # We have to take the 'unknown' state into account
401
+ # nstates = parent.assign['state_labels'].shape[0] + 1
402
+ # Temporarily disabled while I sort out the fact that we shouldn't be using data from w_assign for state populations.
403
+ # current['plot'] = Plotter(parent.direct, parent.reweight, parent.iteration, parent.assign['bin_labels'], parent.assign['state_labels'], current['populations'].states, current['populations'].bins, parent.interface)
404
+ # Now we'll load up the results of the kinetics analysis.
405
+ current['direct'] = KineticsIteration(parent.direct, value, parent.assign, value)
406
+ evolution_datasets = [
407
+ 'rate_evolution',
408
+ 'conditional_flux_evolution',
409
+ 'state_pop_evolution',
410
+ 'color_prob_evolution',
411
+ 'total_fluxes',
412
+ 'target_flux_evolution',
413
+ ]
414
+ # We want to load these up as... oh, who knows, I suppose?
415
+ try:
416
+ current['reweight'] = KineticsIteration(parent.reweight, value, parent.assign, value)
417
+ # We'll make this not a sparse matrix...
418
+ matrix = parent.reweight['iterations/iter_{:08d}'.format(value)]
419
+ # Assume color.
420
+ current['instant_matrix'] = sp.coo_matrix(
421
+ (matrix['flux'][...], (matrix['rows'][...], matrix['cols'][...])), shape=((nbins - 1) * 2, (nbins - 1) * 2)
422
+ ).todense()
423
+ reweighting = True
424
+ except Exception:
425
+ # This analysis hasn't been enabled, so we'll simply return the default error message.
426
+ current['reweight'] = parent.reweight['rate_evolution']
427
+ current['instant_matrix'] = parent.reweight['bin_populations']
428
+ current['matrix'] = parent.reweight['bin_populations']
429
+ reweighting = False
430
+ # Check if the analysis has been enabled. If yes, make them specify dataset dictionaries. If not, return the thing.
431
+ if reweighting:
432
+ for key in evolution_datasets:
433
+ current[key] = WIPIDataset(raw={'direct': current['direct'][key], 'reweight': current['reweight'][key]}, key='a')
434
+ else:
435
+ for key in evolution_datasets:
436
+ current[key] = WIPIDataset(raw={'direct': current['direct'][key]}, key='direct')
437
+
438
+ self.raw = current
439
+
440
+ def __repr__(self):
441
+ '''
442
+ Returns the dictionary containing the iteration's values.
443
+ '''
444
+ return repr(self.__dir__())
445
+
446
+ def keys(self):
447
+ '''
448
+ Returns the keys function of the internal dictionary.
449
+ '''
450
+ return list(self.__dict__['raw'].keys())
451
+
452
+ def __setitem__(self, key, value):
453
+ self.__dict__[key] = value
454
+
455
+ def __getattr__(self, value):
456
+ if value in list(self.__dict__['raw'].keys()):
457
+ return self.__dict__['raw'][value]
458
+ elif value in list(self.__dict__.keys()):
459
+ return self.__dict__[value]
460
+
461
+ def __setattr__(self, key, value):
462
+ self.__dict__[key] = value
463
+
464
+ def __dir__(self):
465
+ dict_keys = list(self.__dict__.keys())
466
+ dict_keys += ['maxweight', 'minweight', 'walkers', 'aggregate_walkers', 'successful_trajectories']
467
+ remove = ['__dict__']
468
+ for i in remove:
469
+ try:
470
+ dict_keys.remove(str(i))
471
+ except Exception:
472
+ pass
473
+ return sorted(set(list(self.__dict__['raw'].keys()) + dict_keys))
474
+
475
+ @property
476
+ def maxweight(self):
477
+ '''
478
+ Returns information about the segment which has the largest weight for this iteration.
479
+ '''
480
+ # Is there a faster or cleaner way to do this? Ah, maybe.
481
+ walker = np.where(self.raw['weights'] == np.max(self.raw['weights']))[0][0]
482
+ return self.__getitem__(walker)
483
+
484
+ @property
485
+ def minweight(self):
486
+ '''
487
+ Returns information about the segment which has the smallest weight for this iteration.
488
+ '''
489
+ walker = np.where(self.raw['weights'] == np.min(self.raw['weights']))[0][0]
490
+ return self.__getitem__(walker)
491
+
492
+ @property
493
+ def successful_trajectories(self):
494
+ '''
495
+ Returns which trajectories are successful.
496
+ '''
497
+ # walker = np.where(self.raw['weights'] == np.min(self.raw['weights']))[0][0]
498
+ # Find where we have a transition....
499
+ state_changes = np.where(self.raw['states'][:, :-1] != self.raw['states'][:, 1:])
500
+ walkers = state_changes[0]
501
+ # The index of the state change.
502
+ new_states = state_changes[1] + 1
503
+ old_states = state_changes[1]
504
+ walker = {}
505
+ for z, (i, j) in enumerate(zip(old_states, new_states)):
506
+ # if self.raw['states'][walkers[z], i] == istate and self.raw['states'][walkers[z], j] == jstate:
507
+ istate = self.raw['states'][walkers[z], i]
508
+ jstate = self.raw['states'][walkers[z], j]
509
+ # print(z,i,j, istate, jstate)
510
+ try:
511
+ walker[istate, jstate].append(walkers[z])
512
+ except Exception:
513
+ walker[istate, jstate] = [walkers[z]]
514
+
515
+ walker = WIPIDataset(raw=walker, key=None)
516
+ return walker
517
+
518
+ @property
519
+ def walkers(self):
520
+ '''
521
+ The number of walkers active in the current iteration.
522
+ '''
523
+ # Returns number of walkers for iteration X. Assumes current iteration, but can go with different one.
524
+ # Make this just... yeah, put this elsewhere.
525
+ return self.parent.west['summary']['n_particles'][self.iteration - 1]
526
+
527
+ @property
528
+ def aggregate_walkers(self):
529
+ return self.parent.west['summary']['n_particles'][: self.iteration].sum()
530
+
531
+ def __getitem__(self, value):
532
+ '''
533
+ Responsible for handling whether this is treated like a dictionary of data sets, or an array of walker data.
534
+ '''
535
+ # Check to see if we're indexing via any of the active string types. We should probably break it down via string or int, instead of 'what exists and what doesn't', but it works for now.
536
+ # active_items = [
537
+ # 'kinavg',
538
+ # 'statepops',
539
+ # 'weights',
540
+ # 'pcoord',
541
+ # 'auxdata',
542
+ # 'parents',
543
+ # 'summary',
544
+ # 'seg_id',
545
+ # 'walkers',
546
+ # 'states',
547
+ # 'bins',
548
+ # 'populations',
549
+ # 'plot',
550
+ # 'instant_matrix',
551
+ # 'kinrw',
552
+ # 'matrix',
553
+ # 'rwstatepops',
554
+ # ]
555
+ # if value in active_items:
556
+ if isinstance(value, str):
557
+ # This should handle everything. Otherwise...
558
+ try:
559
+ return self.raw[value]
560
+ except Exception:
561
+ print('{} is not a valid data structure.'.format(value))
562
+ elif isinstance(value, int) or isinstance(value, np.int64):
563
+ # Otherwise, we assume they're trying to index for a seg_id.
564
+ if value < self.walkers:
565
+ current = {}
566
+ current['plotter'] = {}
567
+ for i in ['pcoord']:
568
+ current[i] = WIPIDataset(raw=self.raw[i][value, :, :], key=i)
569
+ current[i].plotter = Plotter(self.raw[i][value, :, :], i, iteration=self.iteration, interface='text')
570
+ current[i].plot = current[i].plotter.plot
571
+
572
+ current['states'] = self.raw['states'][value, :]
573
+ current['bins'] = self.raw['bins'][value, :]
574
+ current['parents'] = self.raw['parents'][value]
575
+ current['seg_id'] = self.raw['seg_id'][value]
576
+ current['weights'] = self.raw['weights'][value]
577
+ try:
578
+ current['auxdata'] = {}
579
+ for key in list(self.raw['auxdata'].keys()):
580
+ current['auxdata'][key] = self.raw['auxdata'][key][value]
581
+ except Exception:
582
+ pass
583
+ current = WIPIDataset(current, 'Segment {} in Iter {}'.format(value, self.iteration))
584
+ return current
585
+ else:
586
+ print('INVALID SEG_ID {}. SEG_ID should be less than {}.'.format(value, self.walkers))
587
+
588
+
589
+ # This handles the 'schemes', and all assorted data.
590
+ class WIPIScheme:
591
+ def __init__(self, scheme, name, parent, settings):
592
+ self.__dict__ = {}
593
+ self.raw = scheme
594
+ # self.name = parent._schemename
595
+ self.__analysis_schemes__ = scheme
596
+ self.iteration = parent.iteration
597
+ self.__dict__['name'] = None
598
+ self.__settings = settings
599
+ # Are these necessary? We'll try to edit these out.
600
+ self.parent = parent
601
+ self.data_reader = parent.data_reader
602
+
603
+ def __setattr__(self, key, value):
604
+ self.__dict__[key] = value
605
+
606
+ def __repr__(self):
607
+ return self.__str__()
608
+
609
+ def __str__(self):
610
+ # Right now, this returns w.scheme, NOT necessarily what we're pulling from...
611
+ # So you can rely on this, but it's confusing.
612
+ if self.name is not None:
613
+ # Set it to None, then return the original value.
614
+ rtn_string = self.name
615
+ self.name = None
616
+ return rtn_string
617
+ else:
618
+ return str(self.scheme)
619
+
620
+ def __getitem__(self, value):
621
+ if not isinstance(value, str):
622
+ for ischeme, schemename in enumerate(self.__dict__['raw'].keys()):
623
+ if ischeme == value:
624
+ value = schemename
625
+ # Check for some weird Ipython stuff.
626
+ if '_ipython' in value:
627
+ return self
628
+ self.name = None
629
+ if value in list(self.__dict__['raw'].keys()):
630
+ # If we have it in there...
631
+ self.name = value
632
+ return self
633
+ elif value in list(self.__dict__.keys()):
634
+ self.name = value
635
+ return self
636
+ elif value in self.__dir__():
637
+ self.name = value
638
+ return self
639
+
640
+ def __getattr__(self, value):
641
+ return self.__getitem__(value)
642
+
643
+ def __dir__(self):
644
+ dict_keys = ['assign', 'direct', 'state_labels', 'bin_labels', 'west', 'reweight', 'current', 'past', 'iteration']
645
+ if self.name is not None:
646
+ return sorted(set(dict_keys))
647
+ else:
648
+ return sorted(set(self.__analysis_schemes__.keys()))
649
+
650
+ @property
651
+ def scheme(self):
652
+ self.name = None
653
+ return self.parent._schemename
654
+
655
+ @property
656
+ def list_schemes(self):
657
+ '''
658
+ Lists what schemes are configured in west.cfg file.
659
+ Schemes should be structured as follows, in west.cfg:
660
+
661
+ west:
662
+ system:
663
+ analysis:
664
+ directory: analysis
665
+ analysis_schemes:
666
+ scheme.1:
667
+ enabled: True
668
+ states:
669
+ - label: unbound
670
+ coords: [[7.0]]
671
+ - label: bound
672
+ coords: [[2.7]]
673
+ bins:
674
+ - type: RectilinearBinMapper
675
+ boundaries: [[0.0, 2.80, 7, 10000]]
676
+ '''
677
+ print("The following schemes are available:")
678
+ print("")
679
+ for ischeme, scheme in enumerate(self.__settings['analysis_schemes']):
680
+ print('{}. Scheme: {}'.format(ischeme, scheme))
681
+ print("")
682
+ print("Set via name, or via the index listed.")
683
+ print("")
684
+ print("Current scheme: {}".format(self.scheme))
685
+
686
+ @property
687
+ def iteration(self):
688
+ return self.parent.iteration
689
+
690
+ @property
691
+ def assign(self):
692
+ return self.__analysis_schemes__[str(self.name)]['assign']
693
+
694
+ @property
695
+ def direct(self):
696
+ '''
697
+ The output from w_direct.py from the current scheme.
698
+ '''
699
+ return self.__analysis_schemes__[str(self.name)]['direct']
700
+
701
+ @property
702
+ def state_labels(self):
703
+ print("State labels and definitions!")
704
+ for istate, state in enumerate(self.assign['state_labels']):
705
+ print('{}: {}'.format(istate, state))
706
+ print('{}: {}'.format(istate + 1, 'Unknown'))
707
+
708
+ @property
709
+ def bin_labels(self):
710
+ print("Bin definitions! ")
711
+ for istate, state in enumerate(self.assign['bin_labels']):
712
+ print('{}: {}'.format(istate, state))
713
+
714
+ @property
715
+ def west(self):
716
+ return self.data_reader.data_manager.we_h5file
717
+
718
+ @property
719
+ def reweight(self):
720
+ # Need to fix this...
721
+ if self.__settings['analysis_schemes'][str(self.name)]['postanalysis'] is True:
722
+ return self.__analysis_schemes__[str(self.name)]['reweight']
723
+ else:
724
+ value = "This sort of analysis has not been enabled."
725
+ current = {
726
+ 'bin_prob_evolution': value,
727
+ 'color_prob_evolution': value,
728
+ 'conditional_flux_evolution': value,
729
+ 'rate_evolution': value,
730
+ 'state_labels': value,
731
+ 'state_prob_evolution': value,
732
+ }
733
+ current.update({'bin_populations': value, 'iterations': value})
734
+ return current
735
+
736
+ @property
737
+ def current(self):
738
+ '''
739
+ The current iteration. See help for __get_data_for_iteration__
740
+ '''
741
+ return __get_data_for_iteration__(value=self.iteration, parent=self)
742
+
743
+ @property
744
+ def past(self):
745
+ '''
746
+ The previous iteration. See help for __get_data_for_iteration__
747
+ '''
748
+ if self.iteration > 1:
749
+ return __get_data_for_iteration__(value=self.iteration - 1, seg_ids=self.current['parents'], parent=self)
750
+ else:
751
+ print("The current iteration is 1; there is no past.")