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,370 @@
1
+ # along with WESTPA. If not, see <http://www.gnu.org/licenses/>.
2
+
3
+ from __future__ import print_function,division
4
+ import cython
5
+ import numpy
6
+ cimport numpy
7
+
8
+ # Coordinates are assumed to be 32-bit floats, and bin indices are
9
+ # defined to be 16-bit ints.
10
+
11
+ from numpy import uint16, float32
12
+ from numpy cimport uint16_t, float32_t
13
+
14
+ ctypedef numpy.float32_t _fptype
15
+
16
+ ctypedef numpy.uint8_t bool_t
17
+ ctypedef float32_t coord_t
18
+ ctypedef uint16_t index_t
19
+ ctypedef numpy.float64_t weight_t
20
+
21
+ bool_dtype = numpy.bool_
22
+ internal_bool_dtype = numpy.uint8
23
+ index_dtype = numpy.uint16
24
+ coord_dtype = numpy.float32
25
+
26
+ @cython.boundscheck(False)
27
+ @cython.wraparound(False)
28
+ cpdef rectilinear_assign(coord_t[:,:] coords,
29
+ numpy.ndarray[bool_t,ndim=1,cast=True] mask,
30
+ index_t[:] output,
31
+ boundaries,
32
+ index_t[:] boundlens):
33
+
34
+ '''For bins delimited by sets boundaries on a rectilinear grid (``boundaries``),
35
+ assign coordinates to bins, assuming C ordering of indices within the grid.
36
+ ``boundlens`` is the number of boundaries in each dimension.
37
+
38
+ '''
39
+ cdef:
40
+ int icoord, idim, ibound, boundlen
41
+ int ndim
42
+ int ncoords = coords.shape[0]
43
+ index_t index, stridefac
44
+ coord_t bound
45
+ coord_t cval
46
+
47
+ numpy.ndarray[coord_t, ndim=1] boundvec
48
+ numpy.ndarray[numpy.uintp_t, ndim=1] boundvecs
49
+ coord_t* bvec
50
+
51
+ # We assume greater locality across boundary vectors than across the
52
+ # coordinate array. To exploit this locality, and only have to
53
+ # relinquish/reacquire the GIL once, we extract pointers to the first
54
+ # element of each boundary vector; we then release the GIL and go to
55
+ # town on the entire data set.
56
+
57
+ ndim = len(boundaries)
58
+ boundvecs = numpy.empty((ndim,), dtype=numpy.uintp)
59
+
60
+ for 0 <= idim < ndim:
61
+ boundvec = boundaries[idim]
62
+ boundvecs[idim] = <numpy.uintp_t> &boundvec[0]
63
+
64
+ with nogil:
65
+ for icoord in range(ncoords):
66
+ if not mask[icoord]:
67
+ continue
68
+
69
+ output[icoord] = 0
70
+ stridefac = 1
71
+
72
+ # backwards iteration needs signed values, so that the final != -1 works
73
+ for idim in range(ndim-1,-1,-1):
74
+ cval = coords[icoord,idim]
75
+ boundlen = boundlens[idim]
76
+ bvec = <coord_t*> boundvecs[idim]
77
+
78
+ if cval < bvec[0] or cval >= bvec[boundlen-1]:
79
+ with gil:
80
+ raise ValueError('coordinate value {} is out of bin space in dimension {}'.format(cval,idim))
81
+
82
+ for ibound in range(1,boundlen):
83
+ if cval < bvec[ibound]:
84
+ index = ibound-1
85
+ break
86
+
87
+ output[icoord] += index * stridefac
88
+ stridefac *= boundlen-1
89
+
90
+ @cython.boundscheck(False)
91
+ @cython.wraparound(False)
92
+ cpdef testfunc(coord_t[:,:] coords,
93
+ numpy.ndarray[bool_t, ndim=1, cast=True] mask,
94
+ index_t[:] output):
95
+ cdef:
96
+ index_t icoord
97
+
98
+ for icoord in range(len(coords)):
99
+ if mask[icoord]:
100
+ if coords[icoord,0] < 0.5:
101
+ output[icoord] = 0
102
+ else:
103
+ output[icoord] = 1
104
+
105
+ # optimized function applications
106
+ @cython.boundscheck(False)
107
+ @cython.wraparound(False)
108
+ cpdef apply_down(func,
109
+ args,
110
+ kwargs,
111
+ numpy.ndarray[coord_t, ndim=2] coords,
112
+ numpy.ndarray[bool_t, ndim=1, cast=True] mask,
113
+ index_t[:] output):
114
+ '''Apply func(coord, *args, **kwargs) to each input coordinate tuple,
115
+ skipping any for which mask is false and writing results to output.'''
116
+ cdef:
117
+ Py_ssize_t i, n
118
+
119
+ n = len(output)
120
+ for i from 0 <= i < n:
121
+ if mask[i]:
122
+ output[i] = func(coords[i], *args, **kwargs)
123
+
124
+ @cython.boundscheck(False)
125
+ @cython.wraparound(False)
126
+ cpdef apply_down_argmin_across(func,
127
+ args,
128
+ kwargs,
129
+ func_output_len,
130
+ numpy.ndarray[coord_t, ndim=2] coords,
131
+ numpy.ndarray[bool_t, ndim=1, cast=True] mask,
132
+ index_t[:] output):
133
+ '''Apply func(coord, *args, **kwargs) to each input coordinate tuple,
134
+ skipping any for which mask is false and writing results to output.'''
135
+ cdef:
136
+ Py_ssize_t icoord, iout, ncoord, nout,
137
+ coord_t _min
138
+ index_t _argmin
139
+ numpy.ndarray[coord_t, ndim=1] func_output
140
+
141
+ nout = func_output_len
142
+ func_output = numpy.empty((func_output_len,), dtype=coord_dtype)
143
+
144
+ ncoord = len(coords)
145
+ for icoord from 0 <= icoord < ncoord:
146
+ if mask[icoord]:
147
+ func_output = func(coords[icoord], *args, **kwargs)
148
+ if len(func_output) != func_output_len:
149
+ raise TypeError('function returned a vector of length {} (expected length {})'
150
+ .format(len(func_output), func_output_len))
151
+
152
+ # find minimum value
153
+ _min = func_output[0]
154
+ _argmin = 0
155
+ for iout from 1 <= iout < nout:
156
+ if func_output[iout] < _min:
157
+ _min = func_output[iout]
158
+ _argmin = iout
159
+
160
+ output[icoord] = _argmin
161
+
162
+ # optimized lookup table routine
163
+ @cython.boundscheck(False)
164
+ @cython.wraparound(False)
165
+ cpdef output_map(index_t[:] output,
166
+ index_t[:] omap,
167
+ numpy.ndarray[bool_t, ndim=1, cast=True] mask):
168
+ '''For each output for which mask is true, execute output[i] = omap[output[i]]'''
169
+
170
+ cdef:
171
+ Py_ssize_t i, ncoords, nmappings
172
+ index_t o
173
+
174
+ ncoords = len(output)
175
+ nmappings = len(omap)
176
+ with nogil:
177
+ for i from 0 <= i < ncoords:
178
+ if mask[i]:
179
+ o = output[i]
180
+ if o >= nmappings:
181
+ with gil:
182
+ raise IndexError('value {} not available in output table'.format(o))
183
+ output[i] = omap[o]
184
+
185
+ @cython.boundscheck(False)
186
+ @cython.wraparound(False)
187
+ cpdef assign_and_label(Py_ssize_t nsegs_lb,
188
+ Py_ssize_t nsegs_ub,
189
+ long[:] parent_ids, # only for given segments
190
+ object assign,
191
+ Py_ssize_t nstates,
192
+ index_t[:] state_map,
193
+ index_t[:] last_labels, # must be for all segments
194
+ object pcoords, # only for given segments
195
+ bint subsample
196
+ ):
197
+ '''Assign trajectories to bins and last-visted macrostates for each timepoint.'''
198
+
199
+ cdef:
200
+ Py_ssize_t ipt, nsegs, npts, iseg
201
+ index_t[:,:] _assignments, _trajlabels, _statelabels
202
+ index_t[:] seg_assignments
203
+ long seg_id, parent_id, msegid
204
+ index_t ptlabel
205
+
206
+ nsegs = nsegs_ub - nsegs_lb
207
+ npts = pcoords.shape[1]
208
+ # We want to enable some subsampling, for steadystate simulations...
209
+ # And we need to keep them alive through the merge.
210
+ assignments = numpy.empty((nsegs,npts), index_dtype)
211
+ trajlabels = numpy.empty((nsegs,npts), index_dtype)
212
+ statelabels = numpy.empty((nsegs,npts), index_dtype)
213
+
214
+ _assignments = assignments
215
+ _trajlabels = trajlabels
216
+ _statelabels = statelabels
217
+ mask = numpy.ones((npts,), numpy.bool_)
218
+
219
+ for iseg in range(nsegs):
220
+ assign(pcoords[iseg,:], mask, assignments[iseg,:])
221
+
222
+ if subsample is True:
223
+ with nogil:
224
+ for iseg in range(nsegs):
225
+ for ipt in range(npts-2):
226
+ # We want to 'destroy' all assignment information that isn't the first or last point.
227
+ _assignments[iseg,ipt+1] = _assignments[iseg,0]
228
+
229
+ if state_map is not None:
230
+ if subsample is False:
231
+ with nogil:
232
+ for iseg in range(nsegs):
233
+ seg_id = iseg+nsegs_lb
234
+ parent_id = parent_ids[iseg]
235
+ for ipt in range(npts):
236
+ ptlabel = state_map[_assignments[iseg,ipt]]
237
+ _statelabels[iseg,ipt] = ptlabel
238
+ if ptlabel == nstates: # unknown state/transition region
239
+ if ipt == 0:
240
+ if parent_id < 0:
241
+ # We have started a trajectory in a transition region
242
+ _trajlabels[iseg,ipt] = nstates
243
+ _statelabels[iseg,ipt] = nstates
244
+ else:
245
+ # We can inherit the ending point from the previous iteration
246
+ # This should be nstates (unknown_state) for the first iteration
247
+ _trajlabels[iseg,ipt] = last_labels[parent_id]
248
+ else:
249
+ # We are currently in a transition region, but we care about the last state we visited,
250
+ # so inherit that state from the previous point
251
+ _trajlabels[iseg,ipt] = _trajlabels[iseg,ipt-1]
252
+ else:
253
+ _trajlabels[iseg,ipt] = ptlabel
254
+ else:
255
+ with nogil:
256
+ for iseg in range(nsegs):
257
+ seg_id = iseg+nsegs_lb
258
+ parent_id = parent_ids[iseg]
259
+ for ipt in range(npts):
260
+ if ipt == 0:
261
+ ptlabel = state_map[_assignments[iseg,ipt]]
262
+ _statelabels[iseg,ipt] = ptlabel
263
+ if ptlabel == nstates: # unknown state/transition region
264
+ if parent_id < 0:
265
+ # We have started a trajectory in a transition region
266
+ _trajlabels[iseg,ipt] = nstates
267
+ _statelabels[iseg,ipt] = nstates
268
+ else:
269
+ # We can inherit the ending point from the previous iteration
270
+ # This should be nstates (unknown_state) for the first iteration
271
+ _trajlabels[iseg,ipt] = last_labels[parent_id]
272
+ else:
273
+ _trajlabels[iseg,ipt] = ptlabel
274
+ if ipt != 0:
275
+ # We're no longer at the first point, so just nab the previous assignment.
276
+ _trajlabels[iseg,ipt] = _trajlabels[iseg,ipt-1]
277
+ _statelabels[iseg,ipt] = _statelabels[iseg,ipt-1]
278
+ # If we're at the last time point and we've had a transition, reflect it.
279
+ if ipt == npts - 1:
280
+ ptlabel = state_map[_assignments[iseg,ipt]]
281
+ if ptlabel != nstates:
282
+ _statelabels[iseg,npts-1] = ptlabel
283
+ _trajlabels[iseg,npts-1] = ptlabel
284
+
285
+ else:
286
+ trajlabels.fill(nstates)
287
+ statelabels.fill(nstates)
288
+
289
+ return assignments, trajlabels, statelabels
290
+
291
+ @cython.cdivision(True)
292
+ @cython.boundscheck(False)
293
+ @cython.wraparound(False)
294
+ cpdef accumulate_labeled_populations(weight_t[:] weights,
295
+ index_t[:,:] bin_assignments,
296
+ index_t[:,:] label_assignments,
297
+ weight_t[:,:] labeled_bin_pops):
298
+ '''For a set of segments in one iteration, calculate the average population in each bin, with
299
+ separation by last-visited macrostate.'''
300
+ cdef:
301
+ Py_ssize_t nsegs, npts, nbins, nstates, seg_id, ipt
302
+ index_t assignment, traj_assignment
303
+ weight_t ptwt
304
+
305
+ nstates = labeled_bin_pops.shape[0] # this will generally be n_valid_states + 1 (for unknown state)
306
+ nbins = labeled_bin_pops.shape[1] # this may be n_valid_bins + 1 (for unknown bin)
307
+ nsegs = bin_assignments.shape[0]
308
+ npts = bin_assignments.shape[1]
309
+
310
+ with nogil:
311
+ for seg_id in range(nsegs):
312
+ ptwt = weights[seg_id] / npts
313
+ for ipt in range(npts):
314
+ assignment = bin_assignments[seg_id,ipt]
315
+ if assignment >= nbins:
316
+ with gil:
317
+ raise ValueError('invalid bin assignment for segment {} point {}'.format(seg_id, ipt))
318
+
319
+ traj_assignment = label_assignments[seg_id,ipt]
320
+ if traj_assignment >= nstates:
321
+ with gil:
322
+ raise ValueError('invalid trajectory label for segment {} point {}'.format(seg_id, ipt))
323
+
324
+ labeled_bin_pops[traj_assignment,assignment] += ptwt
325
+
326
+ @cython.boundscheck(False)
327
+ @cython.wraparound(False)
328
+ cpdef accumulate_state_populations_from_labeled(weight_t[:,:] labeled_bin_pops,
329
+ index_t[:] state_map,
330
+ weight_t[:] state_pops,
331
+ check_state_map = True):
332
+ cdef:
333
+ Py_ssize_t nbins, nstates, ibin, ilabel, istate
334
+
335
+ if state_pops.shape[0] != labeled_bin_pops.shape[0]:
336
+ raise TypeError('shape mismatch')
337
+
338
+ nstates = labeled_bin_pops.shape[0]
339
+ nbins = labeled_bin_pops.shape[1]
340
+
341
+ if check_state_map:
342
+ for ibin in range(nbins):
343
+ if state_map[ibin] > nstates:
344
+ raise ValueError('invalid value in state map')
345
+
346
+ with nogil:
347
+ for ilabel in range(nstates):
348
+ for ibin in range(nbins):
349
+ istate = state_map[ibin]
350
+ if istate >= nstates:
351
+ with gil:
352
+ raise ValueError('invalid state label {}'.format(istate))
353
+ state_pops[state_map[ibin]] += labeled_bin_pops[ilabel,ibin]
354
+
355
+ @cython.wraparound(False)
356
+ cpdef assignments_list_to_table(Py_ssize_t nsegs, Py_ssize_t nbins, index_t[:] assignments):
357
+ '''Convert a list of bin assignments (integers) to a boolean table indicating indicating
358
+ if a given segment is in a given bin'''
359
+
360
+ cdef:
361
+ Py_ssize_t iseg, ibin
362
+ bool_t[:,:] _output
363
+
364
+ output = numpy.zeros((nsegs,nbins), internal_bool_dtype)
365
+ _output = output
366
+
367
+ for iseg in range(nsegs):
368
+ _output[iseg,assignments[iseg]] = 1
369
+
370
+ return output.astype(numpy.bool_, copy=False)