westpa 2022.13__cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.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.
Files changed (162) 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 +749 -0
  5. westpa/analysis/statistics.py +27 -0
  6. westpa/analysis/trajectories.py +369 -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 +597 -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 +557 -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 +832 -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_timings.py +113 -0
  38. westpa/cli/tools/w_trace.py +599 -0
  39. westpa/core/__init__.py +0 -0
  40. westpa/core/_rc.py +673 -0
  41. westpa/core/binning/__init__.py +55 -0
  42. westpa/core/binning/_assign.c +36018 -0
  43. westpa/core/binning/_assign.cpython-312-aarch64-linux-gnu.so +0 -0
  44. westpa/core/binning/_assign.pyx +370 -0
  45. westpa/core/binning/assign.py +454 -0
  46. westpa/core/binning/binless.py +96 -0
  47. westpa/core/binning/binless_driver.py +54 -0
  48. westpa/core/binning/binless_manager.py +189 -0
  49. westpa/core/binning/bins.py +47 -0
  50. westpa/core/binning/mab.py +506 -0
  51. westpa/core/binning/mab_driver.py +54 -0
  52. westpa/core/binning/mab_manager.py +197 -0
  53. westpa/core/data_manager.py +1761 -0
  54. westpa/core/extloader.py +74 -0
  55. westpa/core/h5io.py +1079 -0
  56. westpa/core/kinetics/__init__.py +24 -0
  57. westpa/core/kinetics/_kinetics.c +45174 -0
  58. westpa/core/kinetics/_kinetics.cpython-312-aarch64-linux-gnu.so +0 -0
  59. westpa/core/kinetics/_kinetics.pyx +815 -0
  60. westpa/core/kinetics/events.py +147 -0
  61. westpa/core/kinetics/matrates.py +156 -0
  62. westpa/core/kinetics/rate_averaging.py +266 -0
  63. westpa/core/progress.py +218 -0
  64. westpa/core/propagators/__init__.py +54 -0
  65. westpa/core/propagators/executable.py +592 -0
  66. westpa/core/propagators/loaders.py +196 -0
  67. westpa/core/reweight/__init__.py +14 -0
  68. westpa/core/reweight/_reweight.c +36899 -0
  69. westpa/core/reweight/_reweight.cpython-312-aarch64-linux-gnu.so +0 -0
  70. westpa/core/reweight/_reweight.pyx +439 -0
  71. westpa/core/reweight/matrix.py +126 -0
  72. westpa/core/segment.py +119 -0
  73. westpa/core/sim_manager.py +839 -0
  74. westpa/core/states.py +359 -0
  75. westpa/core/systems.py +93 -0
  76. westpa/core/textio.py +74 -0
  77. westpa/core/trajectory.py +603 -0
  78. westpa/core/we_driver.py +910 -0
  79. westpa/core/wm_ops.py +43 -0
  80. westpa/core/yamlcfg.py +298 -0
  81. westpa/fasthist/__init__.py +34 -0
  82. westpa/fasthist/_fasthist.c +38755 -0
  83. westpa/fasthist/_fasthist.cpython-312-aarch64-linux-gnu.so +0 -0
  84. westpa/fasthist/_fasthist.pyx +222 -0
  85. westpa/mclib/__init__.py +271 -0
  86. westpa/mclib/__main__.py +28 -0
  87. westpa/mclib/_mclib.c +34610 -0
  88. westpa/mclib/_mclib.cpython-312-aarch64-linux-gnu.so +0 -0
  89. westpa/mclib/_mclib.pyx +226 -0
  90. westpa/oldtools/__init__.py +4 -0
  91. westpa/oldtools/aframe/__init__.py +35 -0
  92. westpa/oldtools/aframe/atool.py +75 -0
  93. westpa/oldtools/aframe/base_mixin.py +26 -0
  94. westpa/oldtools/aframe/binning.py +178 -0
  95. westpa/oldtools/aframe/data_reader.py +560 -0
  96. westpa/oldtools/aframe/iter_range.py +200 -0
  97. westpa/oldtools/aframe/kinetics.py +117 -0
  98. westpa/oldtools/aframe/mcbs.py +153 -0
  99. westpa/oldtools/aframe/output.py +39 -0
  100. westpa/oldtools/aframe/plotting.py +88 -0
  101. westpa/oldtools/aframe/trajwalker.py +126 -0
  102. westpa/oldtools/aframe/transitions.py +469 -0
  103. westpa/oldtools/cmds/__init__.py +0 -0
  104. westpa/oldtools/cmds/w_ttimes.py +361 -0
  105. westpa/oldtools/files.py +34 -0
  106. westpa/oldtools/miscfn.py +23 -0
  107. westpa/oldtools/stats/__init__.py +4 -0
  108. westpa/oldtools/stats/accumulator.py +35 -0
  109. westpa/oldtools/stats/edfs.py +129 -0
  110. westpa/oldtools/stats/mcbs.py +96 -0
  111. westpa/tools/__init__.py +33 -0
  112. westpa/tools/binning.py +472 -0
  113. westpa/tools/core.py +340 -0
  114. westpa/tools/data_reader.py +159 -0
  115. westpa/tools/dtypes.py +31 -0
  116. westpa/tools/iter_range.py +198 -0
  117. westpa/tools/kinetics_tool.py +343 -0
  118. westpa/tools/plot.py +283 -0
  119. westpa/tools/progress.py +17 -0
  120. westpa/tools/selected_segs.py +154 -0
  121. westpa/tools/wipi.py +751 -0
  122. westpa/trajtree/__init__.py +4 -0
  123. westpa/trajtree/_trajtree.c +17829 -0
  124. westpa/trajtree/_trajtree.cpython-312-aarch64-linux-gnu.so +0 -0
  125. westpa/trajtree/_trajtree.pyx +130 -0
  126. westpa/trajtree/trajtree.py +117 -0
  127. westpa/westext/__init__.py +0 -0
  128. westpa/westext/adaptvoronoi/__init__.py +3 -0
  129. westpa/westext/adaptvoronoi/adaptVor_driver.py +214 -0
  130. westpa/westext/hamsm_restarting/__init__.py +3 -0
  131. westpa/westext/hamsm_restarting/example_overrides.py +35 -0
  132. westpa/westext/hamsm_restarting/restart_driver.py +1165 -0
  133. westpa/westext/stringmethod/__init__.py +11 -0
  134. westpa/westext/stringmethod/fourier_fitting.py +69 -0
  135. westpa/westext/stringmethod/string_driver.py +253 -0
  136. westpa/westext/stringmethod/string_method.py +306 -0
  137. westpa/westext/weed/BinCluster.py +180 -0
  138. westpa/westext/weed/ProbAdjustEquil.py +100 -0
  139. westpa/westext/weed/UncertMath.py +247 -0
  140. westpa/westext/weed/__init__.py +10 -0
  141. westpa/westext/weed/weed_driver.py +192 -0
  142. westpa/westext/wess/ProbAdjust.py +101 -0
  143. westpa/westext/wess/__init__.py +6 -0
  144. westpa/westext/wess/wess_driver.py +217 -0
  145. westpa/work_managers/__init__.py +57 -0
  146. westpa/work_managers/core.py +396 -0
  147. westpa/work_managers/environment.py +134 -0
  148. westpa/work_managers/mpi.py +318 -0
  149. westpa/work_managers/processes.py +201 -0
  150. westpa/work_managers/serial.py +28 -0
  151. westpa/work_managers/threads.py +79 -0
  152. westpa/work_managers/zeromq/__init__.py +20 -0
  153. westpa/work_managers/zeromq/core.py +635 -0
  154. westpa/work_managers/zeromq/node.py +131 -0
  155. westpa/work_managers/zeromq/work_manager.py +526 -0
  156. westpa/work_managers/zeromq/worker.py +320 -0
  157. westpa-2022.13.dist-info/METADATA +179 -0
  158. westpa-2022.13.dist-info/RECORD +162 -0
  159. westpa-2022.13.dist-info/WHEEL +7 -0
  160. westpa-2022.13.dist-info/entry_points.txt +30 -0
  161. westpa-2022.13.dist-info/licenses/LICENSE +21 -0
  162. westpa-2022.13.dist-info/top_level.txt +1 -0
@@ -0,0 +1,439 @@
1
+
2
+ # A cythoned version of the original function of the stats_process function,
3
+ # based on _kinetics.pyx
4
+
5
+ from __future__ import print_function,division
6
+ import cython
7
+ import numpy as np
8
+ import h5py
9
+ from scipy.sparse import csgraph
10
+ import warnings
11
+ from collections import Counter
12
+ cimport numpy as np
13
+ cimport scipy.linalg
14
+ cimport scipy.linalg.cython_lapack as cl
15
+ import scipy.linalg
16
+ from libc.math cimport isnan
17
+
18
+ ctypedef np.uint16_t index_t
19
+ ctypedef np.float64_t weight_t
20
+ ctypedef np.uint8_t bool_t
21
+ ctypedef np.int64_t trans_t
22
+ ctypedef np.uintp_t uint_t # 32 bits on 32-bit systems, 64 bits on 64-bit systems
23
+ ctypedef unsigned short Ushort
24
+ ctypedef double complex Cdouble
25
+
26
+ weight_dtype = np.float64
27
+ index_dtype = np.uint16
28
+ bool_dtype = np.bool_
29
+ intc_dtype = np.intc
30
+
31
+ @cython.boundscheck(False)
32
+ @cython.wraparound(False)
33
+ cpdef stats_process(np.ndarray[index_t, ndim=2] bin_assignments,
34
+ np.ndarray[weight_t, ndim=1] weights,
35
+ np.ndarray[weight_t, ndim=2] fluxes,
36
+ np.ndarray[weight_t, ndim=1] populations,
37
+ np.ndarray[trans_t, ndim=2] trans,
38
+ np.ndarray[index_t, ndim=2] mask,
39
+ str interval='timepoint' ):
40
+ cdef:
41
+ Py_ssize_t i,k
42
+ index_t ibin,fbin,nsegs,npts
43
+ nsegs = bin_assignments.shape[0]
44
+ npts = bin_assignments.shape[1]
45
+
46
+ if interval == 'timepoint':
47
+ for i in xrange(0,npts - 1):
48
+ for k in xrange(nsegs):
49
+ ibin = bin_assignments[k,i]
50
+ fbin = bin_assignments[k, i + 1]
51
+
52
+ if mask[k, 0] == 1:
53
+ continue
54
+
55
+ w = weights[k]
56
+
57
+ fluxes[ibin, fbin] += w
58
+ trans[ibin, fbin] += 1
59
+ populations[ibin] += w
60
+ return
61
+
62
+ if interval == 'iteration':
63
+ for k in xrange(nsegs):
64
+ # Should this be 0?
65
+ # .... this should super be 0. What?
66
+ ibin = bin_assignments[k,0]
67
+ fbin = bin_assignments[k, npts - 1]
68
+
69
+ if mask[k, 0] == 1:
70
+ continue
71
+
72
+ w = weights[k]
73
+
74
+ fluxes[ibin, fbin] += w
75
+ trans[ibin, fbin] += 1
76
+ populations[ibin] += w
77
+ return
78
+
79
+ @cython.boundscheck(False)
80
+ @cython.wraparound(False)
81
+ @cython.cdivision(True)
82
+ cpdef int normalize(weight_t[:,:] m, Py_ssize_t nfbins) nogil:
83
+
84
+ cdef:
85
+ weight_t row_sum
86
+ Py_ssize_t x, y
87
+
88
+ for y in range(nfbins):
89
+ row_sum = 0
90
+ for x in range(nfbins):
91
+ row_sum += m[y,x]
92
+ if row_sum != 0:
93
+ for x in range(nfbins):
94
+ m[y,x] /= row_sum
95
+ return 0
96
+
97
+ @cython.boundscheck(False)
98
+ @cython.wraparound(False)
99
+ @cython.cdivision(True)
100
+ cpdef reweight_for_c(rows, cols, obs, flux, insert, indices, nstates, nbins, state_labels, state_map, nfbins, istate, jstate, stride, bin_last_state_map, bin_state_map, return_obs, obs_threshold=1):
101
+
102
+
103
+
104
+ # Instead of pulling in start and stop, we'll pull in a list of indices.
105
+ # This way, it should support the bootstrap.
106
+ cdef:
107
+ int[:] _rows, _cols, _obs, _ins, _nrows, _ncols, _nobs, _visited
108
+ long[:] _bin_last_state_map
109
+ weight_t[:] _flux, _total_pop, _rw_bin_probs, _nflux, _rw_color_probs, _rw_state_probs
110
+ double[:] _eigvals, _eigvalsi
111
+ int n_trans, _nstates, lind, _nfbins, _stride, _obs_threshold, nnz, nlind, i, j, _istate, _jstate
112
+ Ushort[:] _indices, _bin_state_map
113
+ weight_t _return_value
114
+
115
+ Ushort[:] _new_indices
116
+
117
+ weight_t[:,:] _total_fluxes, _transition_matrix, _rw_state_flux, _strong_transition_matrix
118
+ double[:,:] _WORK, _eigvecs
119
+ int[:,:] _total_obs, _graph
120
+ #bint _return_flux, _return_states, _return_color
121
+ str _return_obs
122
+ #double[:] eigvals, eigvalsi
123
+ #double[:,:] eigvecs, WORK
124
+
125
+
126
+
127
+ # CREATE NUMPY ARRAYS
128
+ # This is a temporary measure that fixes some segfaults, which implies I'm probably off by
129
+ # a little bit. Memory heavy, but whatever.
130
+ # It breaks depending on things, so I need to root that out. Clearly, nnz is larger than that.
131
+ _flux = flux
132
+ nnz = len(flux)
133
+ lind = indices.shape[0]
134
+ nlind = indices.shape[0]*stride
135
+ total_fluxes = np.zeros((nfbins, nfbins), weight_dtype)
136
+ total_obs = np.zeros((nfbins, nfbins), intc_dtype)
137
+ transition_matrix = np.zeros((nfbins, nfbins), weight_dtype)
138
+ strong_transition_matrix = np.zeros((nfbins, nfbins), weight_dtype)
139
+ visited = np.zeros((nfbins), intc_dtype)
140
+ graph = np.zeros((nfbins, nfbins+1), dtype=intc_dtype)
141
+ rw_bin_probs = np.zeros(nfbins, weight_dtype)
142
+ new_indices = np.zeros(((nlind)), dtype=indices.dtype)
143
+ rw_state_flux = np.zeros((nstates, nstates), np.float64)
144
+ state_flux = np.zeros((nstates, nstates), weight_dtype)
145
+ eigvals = np.zeros((nfbins), np.float64)
146
+ eigvalsi = np.zeros((nfbins), np.float64)
147
+ eigvecs = np.zeros((nfbins, nfbins), np.float64)
148
+ WORK = np.zeros((nfbins*4, nfbins*4), np.float64)
149
+ rw_color_probs = np.zeros((nstates), weight_dtype)
150
+ rw_state_probs = np.zeros((nbins), weight_dtype)
151
+
152
+
153
+ # CREATE MEMORYVIEWS
154
+ # These are for what we sent in...
155
+ _rows = rows
156
+ _cols = cols
157
+ _obs = obs
158
+ _flux = flux
159
+ _ins = insert
160
+ _nstates = nstates
161
+ # ... these are for functions we'll be using.
162
+ _total_fluxes = total_fluxes
163
+ _total_obs = total_obs
164
+ _transition_matrix = transition_matrix
165
+ _strong_transition_matrix = strong_transition_matrix
166
+ _nfbins = nfbins
167
+ _stride = stride
168
+ _obs_threshold = obs_threshold
169
+ _indices = indices
170
+ _new_indices = new_indices
171
+ _rw_state_flux = rw_state_flux
172
+ _rw_bin_probs = rw_bin_probs
173
+ _eigvals = eigvals
174
+ _eigvalsi = eigvalsi
175
+ _eigvals = eigvals
176
+ _eigvecs = eigvecs
177
+ _WORK = WORK
178
+ _graph = graph
179
+ _visited = visited
180
+ _rw_color_probs = rw_color_probs
181
+ _rw_state_probs = rw_state_probs
182
+ _bin_last_state_map = bin_last_state_map
183
+ _bin_state_map = bin_state_map
184
+ _istate = istate
185
+ _jstate = jstate
186
+ _return_obs = return_obs
187
+
188
+
189
+ #NOGIL
190
+ # Reconstruct dataset. We're just passing the same thing back and forth between functions.
191
+ with nogil:
192
+ for i in range(_nfbins):
193
+ for j in range(1, _nfbins+1):
194
+ _graph[i, j] = _nfbins
195
+ regenerate_subsampled_indices(_indices, _new_indices, lind, _stride)
196
+ accumulate_fluxes(_rows, _cols, _obs, _flux, _ins, _new_indices, nnz, _transition_matrix, nlind)
197
+ accumulate_obs(_rows, _cols, _obs, _flux, _ins, _new_indices, nnz, _total_obs, nlind)
198
+
199
+ remove_under_obs(_transition_matrix, _total_obs, _obs_threshold, _nfbins)
200
+ normalize(_transition_matrix, _nfbins)
201
+ steadystate_solve(_transition_matrix, _strong_transition_matrix, _rw_bin_probs, _nfbins, _eigvals, _eigvalsi, _eigvecs, _WORK, _graph, _visited)
202
+
203
+ for i in range(_nfbins):
204
+ _rw_color_probs[_bin_last_state_map[i]] += _rw_bin_probs[i]
205
+ _rw_state_probs[_bin_state_map[i]] += _rw_bin_probs[i]
206
+
207
+
208
+ calc_state_flux(_transition_matrix, _rw_bin_probs, _bin_last_state_map, _bin_state_map, _nstates, _rw_state_flux, _nfbins)
209
+
210
+ # This allows us to use the same function for all three types.
211
+ # Return conditional fluxes.
212
+ if _return_obs == b'F':
213
+ _return_value = _rw_state_flux[_istate,_jstate]
214
+ if isnan(_return_value) is True:
215
+ return 0.0
216
+ else:
217
+ return _return_value
218
+ # Return state probabilities.
219
+ elif _return_obs == b'S':
220
+ _return_value = _rw_state_probs[_istate]
221
+ if isnan(_return_value) is True:
222
+ return 0.0
223
+ else:
224
+ return _return_value
225
+ # Return color (ensemble) probabilities
226
+ elif _return_obs == b'C':
227
+ _return_value = _rw_color_probs[_istate]
228
+ if isnan(_return_value) is True:
229
+ return 0.0
230
+ else:
231
+ return _return_value
232
+ # Return the rates.
233
+ elif _return_obs == b'R':
234
+ if _rw_color_probs[_istate] != 0.0:
235
+ _return_value = (_rw_state_flux[_istate,_jstate] / (_rw_color_probs[_istate] / (_rw_color_probs[_istate] + _rw_color_probs[_jstate])))
236
+ if isnan(_return_value) is True:
237
+ return 0.0
238
+ else:
239
+ return _return_value
240
+ else:
241
+ # We have no ensemble probability, and as such, cannot have a flux.
242
+ return 0.0
243
+ # Return the populations.
244
+ elif _return_obs == b'P':
245
+ return rw_bin_probs
246
+
247
+ @cython.boundscheck(False)
248
+ @cython.wraparound(False)
249
+ @cython.cdivision(True)
250
+ cpdef int regenerate_subsampled_indices(Ushort[:] iin, Ushort[:] iout, int ilen, int stride) nogil:
251
+
252
+ cdef:
253
+ int i, si
254
+
255
+ # go over the range of all indices within iin
256
+ for i in range(ilen):
257
+ # Run over the length of the stride.
258
+ for si in range(stride):
259
+ iout[(i*stride)+si] = iin[i] + si
260
+
261
+ return 0
262
+
263
+ @cython.boundscheck(False)
264
+ @cython.wraparound(False)
265
+ @cython.cdivision(True)
266
+ cpdef int accumulate_fluxes(int[:] hrows, int[:] hcols, int[:] hobs, weight_t[:] hflux, int[:] hins, Ushort[:] iterations, Py_ssize_t nnz, weight_t[:,:] total_fluxes, int itermax) nogil:
267
+
268
+ cdef:
269
+ index_t curriter, elem, iiter, ipop
270
+ long ilem
271
+
272
+ curriter = 0
273
+
274
+ for iter in range(itermax):
275
+ iiter = iterations[iter]
276
+ for ilem in range(hins[iiter], hins[iiter+1]):
277
+ # Not sure if this is necessary, here...
278
+ if ilem < nnz and iiter+1 < itermax:
279
+ total_fluxes[hrows[ilem], hcols[ilem]] += hflux[ilem]
280
+
281
+ return 0
282
+
283
+ @cython.boundscheck(False)
284
+ @cython.wraparound(False)
285
+ @cython.cdivision(True)
286
+ cpdef int accumulate_obs(int[:] hrows, int[:] hcols, int[:] hobs, weight_t[:] hflux, int[:] hins, Ushort[:] iterations, Py_ssize_t nnz, int[:,:] total_obs, int itermax) nogil:
287
+
288
+ cdef:
289
+ index_t curriter, elem, iiter, ipop
290
+ long ilem
291
+
292
+ curriter = 0
293
+
294
+ for iter in range(itermax):
295
+ iiter = iterations[iter]
296
+ for ilem in range(hins[iiter], hins[iiter+1]):
297
+ if ilem < nnz and iiter+1 < itermax:
298
+ total_obs[hrows[ilem], hcols[ilem]] += hobs[ilem]
299
+
300
+ return 0
301
+
302
+ @cython.boundscheck(False)
303
+ @cython.wraparound(False)
304
+ @cython.cdivision(True)
305
+ cpdef int remove_under_obs(weight_t[:,:] flux, int[:,:] obs, int threshold, int nbins) nogil:
306
+
307
+ cdef:
308
+ int x, y
309
+
310
+ for x in range(nbins):
311
+ for y in range(nbins):
312
+ if obs[x,y] < threshold:
313
+ flux[x,y] = 0
314
+
315
+
316
+ @cython.boundscheck(False)
317
+ @cython.wraparound(False)
318
+ @cython.cdivision(True)
319
+ cpdef int calc_state_flux(weight_t[:, :] trans_matrix, weight_t[:] bin_probs, long[:] bin_last_state_map, Ushort[:] bin_state_map, int nstates, weight_t[:,:] state_flux, int K_shape) nogil:
320
+
321
+ cdef:
322
+ int i, j, ii, jj
323
+
324
+
325
+ for i in range(K_shape):
326
+ for j in range(K_shape):
327
+
328
+ ii = bin_last_state_map[i]
329
+ jj = bin_state_map[j]
330
+
331
+ if jj != nstates:
332
+ state_flux[ii, jj] += (trans_matrix[i, j] * bin_probs[i])
333
+
334
+ return 0
335
+
336
+ @cython.boundscheck(False)
337
+ @cython.wraparound(False)
338
+ @cython.cdivision(True)
339
+ cpdef int steadystate_solve(weight_t[:,:] K, weight_t[:,:] K_mod, weight_t[:] bin_prob, int K_shape, double[:] eigvals, double[:] eigvalsi, double[:,:] eigvecs, double[:,:] WORK, int[:,:] graph, int[:] visited) nogil:
340
+
341
+ cdef:
342
+ int[:] components
343
+ int[:,:] _graph
344
+ double max, eigsum
345
+ int n_components, components_assignments, largest_component, maxi, x, y, n, INFO, LWORK, i, j
346
+
347
+ # POINTERS
348
+
349
+ int *_INFO, *_K_shape, *_LWORK
350
+ double *_K_mod, *_eigvals, *_eigvecs, *_WORK, *_eigvalsi
351
+ _K_shape = &K_shape
352
+ _INFO = &INFO
353
+ _LWORK = &LWORK
354
+ INFO = 0
355
+ LWORK = K_shape * 4
356
+ _K_mod = &K_mod[0,0]
357
+ _eigvals = &eigvals[0]
358
+ _eigvecs = &eigvecs[0,0]
359
+ _eigvalsi = &eigvalsi[0]
360
+ _WORK = &WORK[0,0]
361
+ _graph = graph
362
+
363
+ for i in range(K_shape):
364
+ if visited[i] == 0:
365
+ visited[i] = 1
366
+ return_strong_component(K, K_shape, _graph, i, i, visited)
367
+ n = 0
368
+ for i in range(K_shape):
369
+ if graph[i, 0] >= graph[n, 0]:
370
+ n = i
371
+ # I suspect this may be giving us issues?
372
+ #components = _graph[n, :K_shape+1]
373
+
374
+ maxi = 0
375
+ eigsum = 0.0
376
+ # This all works!
377
+ for x in range(K_shape):
378
+ #i = components[x+1]
379
+ i = graph[n, x+1]
380
+ for y in range(K_shape):
381
+ #j = components[y+1]
382
+ j = graph[n, y+1]
383
+ if i != K_shape and j != K_shape:
384
+ K_mod[i, j] = K[i, j]
385
+ normalize(K_mod, K_shape)
386
+ cl.dgeev('N', 'V', _K_shape, _K_mod, _K_shape, _eigvals, _eigvalsi, _eigvecs, _K_shape, _eigvecs, _K_shape, _WORK, _LWORK, _INFO)
387
+ for x in range(K_shape):
388
+ if x == 0:
389
+ max = eigvals[0]
390
+ maxi = x
391
+ else:
392
+ if max < eigvals[x]:
393
+ max = eigvals[x]
394
+ maxi = x
395
+ # We need to go over the whole range and pick out non K_shape elements.
396
+ # This probably no longer needs to be done, now...
397
+ for i in range(K_shape):
398
+ #x = components[i+1]
399
+ x = graph[n, i+1]
400
+ if x != K_shape:
401
+ #eigsum += eigvecs[maxi, components[i+1]]
402
+ eigsum += eigvecs[maxi, x]
403
+ for i in range(K_shape):
404
+ #x = components[i+1]
405
+ x = graph[n, i+1]
406
+ if x != K_shape:
407
+ #bin_prob[components[i+1]] = eigvecs[maxi, components[i+1]]
408
+ #bin_prob[components[i+1]] /= eigsum
409
+ bin_prob[x] = eigvecs[maxi, x]
410
+ bin_prob[x] /= eigsum
411
+
412
+ return 0
413
+
414
+ @cython.boundscheck(False)
415
+ @cython.wraparound(False)
416
+ @cython.cdivision(True)
417
+ cpdef int return_strong_component(weight_t[:,:] K, int K_shape, int[:, :] graph, int i, int z, int[:] visited) nogil:
418
+
419
+ cdef:
420
+ int j, y
421
+
422
+ if graph[z, 0] == 0:
423
+ graph[z, 0] += 1
424
+ graph[z, 1] = i
425
+ for j in xrange(K_shape):
426
+ if i != j:
427
+ if K[i, j] > 0.0:
428
+ # Strongly connected!
429
+ if visited[j] == 0:
430
+ graph[z, 0] += 1
431
+ y = graph[z, 0]
432
+ graph[z, y] = j
433
+ # We only want to call it when we haven't visited it before.
434
+ # We don't want to call, THEN modify and check. Otherwise, we could be doing many calls.
435
+ visited[j] = 1
436
+ return_strong_component(K, K_shape, graph, j, z, visited)
437
+
438
+
439
+ return 0
@@ -0,0 +1,126 @@
1
+ import warnings
2
+
3
+ import numpy as np
4
+ import scipy.sparse as sp
5
+
6
+ from westpa.core.data_manager import weight_dtype
7
+ from westpa.core import h5io
8
+
9
+ # From postanalysis matrix
10
+ from westpa.core.binning import index_dtype
11
+ from westpa.core.reweight import stats_process
12
+
13
+
14
+ warnings.filterwarnings('ignore', category=DeprecationWarning)
15
+ warnings.filterwarnings('ignore', category=RuntimeWarning)
16
+ warnings.filterwarnings('ignore', category=FutureWarning)
17
+
18
+
19
+ def calc_stats(bin_assignments, weights, fluxes, populations, trans, mask, sampling_frequency):
20
+ fluxes.fill(0.0)
21
+ populations.fill(0.0)
22
+ trans.fill(0)
23
+
24
+ stats_process(bin_assignments, weights, fluxes, populations, trans, mask, interval=sampling_frequency)
25
+
26
+
27
+ class FluxMatrix:
28
+ def w_postanalysis_matrix(self):
29
+ pi = self.progress.indicator
30
+ pi.new_operation('Initializing')
31
+
32
+ self.data_reader.open('r')
33
+ nbins = self.assignments_file.attrs['nbins']
34
+
35
+ state_labels = self.assignments_file['state_labels'][...]
36
+ # state_map = self.assignments_file['state_map'][...]
37
+ nstates = len(state_labels)
38
+
39
+ start_iter, stop_iter = self.iter_range.iter_start, self.iter_range.iter_stop # h5io.get_iter_range(self.assignments_file)
40
+ iter_count = stop_iter - start_iter
41
+
42
+ nfbins = nbins * nstates
43
+
44
+ flux_shape = (iter_count, nfbins, nfbins)
45
+ pop_shape = (iter_count, nfbins)
46
+
47
+ h5io.stamp_iter_range(self.output_file, start_iter, stop_iter)
48
+
49
+ bin_populations_ds = self.output_file.create_dataset('bin_populations', shape=pop_shape, dtype=weight_dtype)
50
+ h5io.stamp_iter_range(bin_populations_ds, start_iter, stop_iter)
51
+ h5io.label_axes(bin_populations_ds, ['iteration', 'bin'])
52
+
53
+ flux_grp = self.output_file.create_group('iterations')
54
+ self.output_file.attrs['nrows'] = nfbins
55
+ self.output_file.attrs['ncols'] = nfbins
56
+
57
+ fluxes = np.empty(flux_shape[1:], weight_dtype)
58
+ populations = np.empty(pop_shape[1:], weight_dtype)
59
+ trans = np.empty(flux_shape[1:], np.int64)
60
+
61
+ # Check to make sure this isn't a data set with target states
62
+ # tstates = self.data_reader.data_manager.get_target_states(0)
63
+ # if len(tstates) > 0:
64
+ # raise ValueError('Postanalysis reweighting analysis does not support WE simulation run under recycling conditions')
65
+
66
+ pi.new_operation('Calculating flux matrices', iter_count)
67
+ # Calculate instantaneous statistics
68
+ for iiter, n_iter in enumerate(range(start_iter, stop_iter)):
69
+ # Get data from the main HDF5 file
70
+ iter_group = self.data_reader.get_iter_group(n_iter)
71
+ seg_index = iter_group['seg_index']
72
+ nsegs, npts = iter_group['pcoord'].shape[0:2]
73
+ weights = seg_index['weight']
74
+
75
+ # Get bin and traj. ensemble assignments from the previously-generated assignments file
76
+ assignment_iiter = h5io.get_iteration_entry(self.assignments_file, n_iter)
77
+ bin_assignments = np.require(
78
+ self.assignments_file['assignments'][assignment_iiter + np.s_[:nsegs, :npts]], dtype=index_dtype
79
+ )
80
+
81
+ mask_unknown = np.zeros_like(bin_assignments, dtype=np.uint16)
82
+
83
+ macrostate_iiter = h5io.get_iteration_entry(self.assignments_file, n_iter)
84
+ macrostate_assignments = np.require(
85
+ self.assignments_file['trajlabels'][macrostate_iiter + np.s_[:nsegs, :npts]], dtype=index_dtype
86
+ )
87
+
88
+ # Transform bin_assignments to take macrostate membership into account
89
+ bin_assignments = nstates * bin_assignments + macrostate_assignments
90
+
91
+ mask_indx = np.where(macrostate_assignments == nstates)
92
+ mask_unknown[mask_indx] = 1
93
+
94
+ # Calculate bin-to-bin fluxes, bin populations and number of obs transitions
95
+ calc_stats(bin_assignments, weights, fluxes, populations, trans, mask_unknown, self.sampling_frequency)
96
+
97
+ # Store bin-based kinetics data
98
+ bin_populations_ds[iiter] = populations
99
+
100
+ # Setup sparse data structures for flux and obs
101
+ fluxes_sp = sp.coo_matrix(fluxes)
102
+ trans_sp = sp.coo_matrix(trans)
103
+
104
+ assert fluxes_sp.nnz == trans_sp.nnz
105
+
106
+ flux_iter_grp = flux_grp.create_group('iter_{:08d}'.format(n_iter))
107
+ flux_iter_grp.create_dataset('flux', data=fluxes_sp.data, dtype=weight_dtype)
108
+ flux_iter_grp.create_dataset('obs', data=trans_sp.data, dtype=np.int32)
109
+ flux_iter_grp.create_dataset('rows', data=fluxes_sp.row, dtype=np.int32)
110
+ flux_iter_grp.create_dataset('cols', data=fluxes_sp.col, dtype=np.int32)
111
+ flux_iter_grp.attrs['nrows'] = nfbins
112
+ flux_iter_grp.attrs['ncols'] = nfbins
113
+
114
+ # Do a little manual clean-up to prevent memory explosion
115
+ del iter_group, weights, bin_assignments
116
+ del macrostate_assignments
117
+
118
+ pi.progress += 1
119
+
120
+ # Check and save the number of intermediate time points; this will be used to normalize the
121
+ # flux and kinetics to tau in w_postanalysis_reweight.
122
+ if self.assignments_file.attrs['subsampled'] is True or self.sampling_frequency == 'iteration':
123
+ self.output_file.attrs['npts'] = 2
124
+ else:
125
+ # self.output_file.attrs['npts'] = npts if self.sampling_frequency == 'timepoint' else 2
126
+ self.output_file.attrs['npts'] = npts
westpa/core/segment.py ADDED
@@ -0,0 +1,119 @@
1
+ import math
2
+
3
+ import numpy as np
4
+
5
+
6
+ class Segment:
7
+ '''A class wrapping segment data that must be passed through the work manager or data manager.
8
+ Most fields are self-explanatory. One item worth noting is that a negative parent ID means that
9
+ the segment starts from the initial state with ID -(segment.parent_id+1)
10
+ '''
11
+
12
+ SEG_STATUS_UNSET = 0
13
+ SEG_STATUS_PREPARED = 1
14
+ SEG_STATUS_COMPLETE = 2
15
+ SEG_STATUS_FAILED = 3
16
+
17
+ SEG_INITPOINT_UNSET = 0
18
+ SEG_INITPOINT_CONTINUES = 1
19
+ SEG_INITPOINT_NEWTRAJ = 2
20
+
21
+ SEG_ENDPOINT_UNSET = 0
22
+ SEG_ENDPOINT_CONTINUES = 1
23
+ SEG_ENDPOINT_MERGED = 2
24
+ SEG_ENDPOINT_RECYCLED = 3
25
+
26
+ statuses = {}
27
+ initpoint_types = {}
28
+ endpoint_types = {}
29
+
30
+ status_names = {}
31
+ initpoint_type_names = {}
32
+ endpoint_type_names = {}
33
+
34
+ # convenience functions for binning
35
+ @staticmethod
36
+ def initial_pcoord(segment):
37
+ 'Return the initial progress coordinate point of this segment.'
38
+ return segment.pcoord[0]
39
+
40
+ @staticmethod
41
+ def final_pcoord(segment):
42
+ 'Return the final progress coordinate point of this segment.'
43
+ return segment.pcoord[-1]
44
+
45
+ def __init__(
46
+ self,
47
+ n_iter=None,
48
+ seg_id=None,
49
+ weight=None,
50
+ endpoint_type=None,
51
+ parent_id=None,
52
+ wtg_parent_ids=None,
53
+ pcoord=None,
54
+ status=None,
55
+ walltime=None,
56
+ cputime=None,
57
+ data=None,
58
+ ):
59
+ # NaNs appear sometimes if a WEST program is terminated unexpectedly; replace with zero
60
+ walltime = 0.0 if walltime is None or math.isnan(walltime) else walltime
61
+ cputime = 0.0 if cputime is None or math.isnan(cputime) else cputime
62
+
63
+ # the int() and float() calls are required so that new-style string formatting doesn't barf
64
+ # assuming that the respective fields are actually strings, probably after implicitly
65
+ # calling __str__() on them. Not sure if this is a numpy, h5py, or python problem
66
+ self.n_iter = int(n_iter) if n_iter is not None else None
67
+ self.seg_id = int(seg_id) if seg_id is not None else None
68
+ self.status = int(status) if status is not None else None
69
+ self.parent_id = int(parent_id) if parent_id is not None else None
70
+ self.endpoint_type = int(endpoint_type) if endpoint_type else self.SEG_ENDPOINT_UNSET
71
+
72
+ self.weight = float(weight) if weight is not None else None
73
+ self.wtg_parent_ids = set(wtg_parent_ids or ())
74
+
75
+ self.pcoord = np.asarray(pcoord) if pcoord is not None else None
76
+ self.walltime = walltime
77
+ self.cputime = cputime
78
+ self.data = data if data else {}
79
+
80
+ def __repr__(self):
81
+ return '<%s(%s) n_iter=%r seg_id=%r weight=%r parent_id=%r wtg_parent_ids=%r pcoord[0]=%r pcoord[-1]=%r>' % (
82
+ self.__class__.__name__,
83
+ hex(id(self)),
84
+ self.n_iter,
85
+ self.seg_id,
86
+ self.weight,
87
+ self.parent_id,
88
+ tuple(self.wtg_parent_ids or ()),
89
+ self.pcoord[0] if self.pcoord is not None else None,
90
+ self.pcoord[-1] if self.pcoord is not None else None,
91
+ )
92
+
93
+ @property
94
+ def initpoint_type(self):
95
+ if self.parent_id < 0:
96
+ return Segment.SEG_INITPOINT_NEWTRAJ
97
+ else:
98
+ return Segment.SEG_INITPOINT_CONTINUES
99
+
100
+ @property
101
+ def initial_state_id(self):
102
+ if self.parent_id < 0:
103
+ return -(self.parent_id + 1)
104
+ else:
105
+ return None
106
+
107
+ status_text = property((lambda s: s.status_names[s.status]))
108
+ endpoint_type_text = property((lambda s: s.endpoint_type_names[s.endpoint_type]))
109
+
110
+
111
+ Segment.statuses.update({_attr: getattr(Segment, _attr) for _attr in dir(Segment) if _attr.startswith('SEG_STATUS_')})
112
+ Segment.initpoint_types.update({_attr: getattr(Segment, _attr) for _attr in dir(Segment) if _attr.startswith('SEG_INITPOINT_')})
113
+ Segment.endpoint_types.update({_attr: getattr(Segment, _attr) for _attr in dir(Segment) if _attr.startswith('SEG_ENDPOINT_')})
114
+
115
+ Segment.status_names.update({getattr(Segment, _attr): _attr for _attr in dir(Segment) if _attr.startswith('SEG_STATUS_')})
116
+ Segment.initpoint_type_names.update(
117
+ {getattr(Segment, _attr): _attr for _attr in dir(Segment) if _attr.startswith('SEG_INITPOINT_')}
118
+ )
119
+ Segment.endpoint_type_names.update({getattr(Segment, _attr): _attr for _attr in dir(Segment) if _attr.startswith('SEG_ENDPOINT_')})