westpa 2022.12__cp313-cp313-macosx_11_0_arm64.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
@@ -0,0 +1,200 @@
1
+ import logging
2
+
3
+ import numpy as np
4
+
5
+
6
+ import westpa
7
+ from westpa.oldtools.aframe import AnalysisMixin, ArgumentError
8
+
9
+ log = logging.getLogger(__name__)
10
+
11
+
12
+ class IterRangeMixin(AnalysisMixin):
13
+ '''A mixin for limiting the range of data considered for a given analysis. This should go after
14
+ DataManagerMixin'''
15
+
16
+ def __init__(self):
17
+ super().__init__()
18
+
19
+ self.first_iter = None
20
+ self.last_iter = None
21
+ self.iter_step = 1
22
+
23
+ include_args = self.include_args.setdefault('IterRangeMixin', {})
24
+ include_args.setdefault('first_iter', True)
25
+ include_args.setdefault('last_iter', True)
26
+ include_args.setdefault('iter_step', True)
27
+
28
+ def add_args(self, parser, upcall=True):
29
+ if upcall:
30
+ try:
31
+ upfunc = super().add_args
32
+ except AttributeError:
33
+ pass
34
+ else:
35
+ upfunc(parser)
36
+
37
+ group = parser.add_argument_group('analysis range')
38
+ if self.include_args['IterRangeMixin']['first_iter']:
39
+ group.add_argument(
40
+ '--start',
41
+ '--begin',
42
+ '--first',
43
+ dest='first_iter',
44
+ type=int,
45
+ metavar='N_ITER',
46
+ default=1,
47
+ help='''Begin analysis at iteration N_ITER (default: %(default)d).''',
48
+ )
49
+ if self.include_args['IterRangeMixin']['last_iter']:
50
+ group.add_argument(
51
+ '--stop',
52
+ '--end',
53
+ '--last',
54
+ dest='last_iter',
55
+ type=int,
56
+ metavar='N_ITER',
57
+ help='''Conclude analysis with N_ITER, inclusive (default: last completed iteration).''',
58
+ )
59
+ if self.include_args['IterRangeMixin']['iter_step']:
60
+ group.add_argument(
61
+ '--step', dest='iter_step', type=int, metavar='STEP', help='''Analyze/report in blocks of STEP iterations.'''
62
+ )
63
+
64
+ def process_args(self, args, upcall=True):
65
+ if self.include_args['IterRangeMixin']['first_iter']:
66
+ self.first_iter = args.first_iter or 1
67
+ if self.include_args['IterRangeMixin']['last_iter']:
68
+ self.last_iter = args.last_iter
69
+ if self.include_args['IterRangeMixin']['iter_step']:
70
+ self.iter_step = args.iter_step or 1
71
+
72
+ if upcall:
73
+ try:
74
+ upfunc = super().process_args
75
+ except AttributeError:
76
+ pass
77
+ else:
78
+ upfunc(args)
79
+
80
+ def check_iter_range(self):
81
+ assert hasattr(self, 'data_manager') and self.data_manager is not None
82
+
83
+ self.first_iter = int(max(self.first_iter, 1))
84
+ if self.last_iter is None or self.last_iter > self.data_manager.current_iteration - 1:
85
+ self.last_iter = int(self.data_manager.current_iteration - 1)
86
+
87
+ if self.first_iter == self.last_iter:
88
+ raise ArgumentError('first and last iterations are the same')
89
+
90
+ westpa.rc.pstatus(
91
+ 'Processing iterations from {self.first_iter:d} to {self.last_iter:d}, inclusive (step size {self.iter_step:d})'.format(
92
+ self=self
93
+ )
94
+ )
95
+
96
+ def iter_block_iter(self):
97
+ '''Return an iterable of (block_first,block_last+1) over the blocks of iterations
98
+ selected by --first/--last/--step. NOTE WELL that the second of the pair follows Python
99
+ iterator conventions and returns one past the last element of the block.'''
100
+
101
+ for blkfirst in range(self.first_iter, self.last_iter + 1, self.iter_step):
102
+ yield (blkfirst, min(self.last_iter, blkfirst + self.iter_step - 1) + 1)
103
+
104
+ def n_iter_blocks(self):
105
+ '''Return the number of blocks of iterations (as returned by ``iter_block_iter``) selected by --first/--last/--step.'''
106
+ npoints = self.last_iter - self.first_iter + 1
107
+ if npoints % self.iter_step == 0:
108
+ return npoints // self.iter_step
109
+ else:
110
+ return npoints // self.iter_step + 1
111
+
112
+ def record_data_iter_range(self, h5object, first_iter=None, last_iter=None):
113
+ '''Store attributes ``first_iter`` and ``last_iter`` on the given HDF5 object (group/dataset)'''
114
+ first_iter = first_iter or self.first_iter
115
+ last_iter = last_iter or self.last_iter
116
+ h5object.attrs['first_iter'] = first_iter
117
+ h5object.attrs['last_iter'] = last_iter
118
+
119
+ def record_data_iter_step(self, h5object, iter_step=None):
120
+ '''Store attribute ``iter_step`` on the given HDF5 object (group/dataset).'''
121
+ iter_step = iter_step or self.iter_step
122
+ h5object.attrs['iter_step'] = iter_step
123
+
124
+ def check_data_iter_range_least(self, h5object, first_iter=None, last_iter=None):
125
+ '''Check that the given HDF5 object contains (as denoted by its ``first_iter``/``last_iter`` attributes) at least the
126
+ data range specified.'''
127
+ first_iter = first_iter or self.first_iter
128
+ last_iter = last_iter or self.last_iter
129
+
130
+ obj_first_iter = h5object.attrs.get('first_iter')
131
+ obj_last_iter = h5object.attrs.get('last_iter')
132
+
133
+ return obj_first_iter <= first_iter and obj_last_iter >= last_iter
134
+
135
+ def check_data_iter_range_equal(self, h5object, first_iter=None, last_iter=None):
136
+ '''Check that the given HDF5 object contains per-iteration data for exactly the specified iterations (as denoted by the
137
+ object's ``first_iter`` and ``last_iter`` attributes'''
138
+
139
+ first_iter = first_iter or self.first_iter
140
+ last_iter = last_iter or self.last_iter
141
+
142
+ obj_first_iter = h5object.attrs.get('first_iter')
143
+ obj_last_iter = h5object.attrs.get('last_iter')
144
+
145
+ return obj_first_iter == first_iter and obj_last_iter == last_iter
146
+
147
+ def check_data_iter_step_conformant(self, h5object, iter_step=None):
148
+ '''Check that the given HDF5 object contains per-iteration data at an iteration stride suitable for extracting data
149
+ with the given stride. (In other words, is the given ``iter_step`` a multiple of the stride with
150
+ which data was recorded.)'''
151
+
152
+ iter_step = iter_step or self.iter_step
153
+ obj_iter_step = h5object.attrs.get('iter_step')
154
+ return obj_iter_step % iter_step == 0
155
+
156
+ def check_data_iter_step_equal(self, h5object, iter_step=None):
157
+ '''Check that the given HDF5 object contains per-iteration data at an iteration stride the same as
158
+ that specified.'''
159
+ iter_step = iter_step or self.iter_step
160
+ obj_iter_step = h5object.attrs.get('iter_step')
161
+ return obj_iter_step == iter_step
162
+
163
+ def slice_per_iter_data(self, dataset, first_iter=None, last_iter=None, iter_step=None, axis=0):
164
+ '''Return the subset of the given dataset corresponding to the given iteration range and stride. Unless
165
+ otherwise specified, the first dimension of the dataset is the one sliced.'''
166
+
167
+ first_iter = first_iter or self.first_iter
168
+ last_iter = last_iter or self.last_iter
169
+ iter_step = iter_step or self.iter_step
170
+
171
+ ds_first_iter = dataset.attrs['first_iter']
172
+ ds_last_iter = dataset.attrs['last_iter']
173
+ ds_iter_step = dataset.attrs.get('iter_step', 1)
174
+
175
+ if first_iter < ds_first_iter or last_iter > ds_last_iter or ds_iter_step % iter_step > 0:
176
+ raise IndexError(
177
+ 'Cannot slice requested iterations [{:d},{:d}] (stride={:d}) from dataset {!r} with range [{:d},{:d}] (stride={:d}).'.format(
178
+ first_iter, last_iter, iter_step, dataset, ds_first_iter, ds_last_iter, ds_iter_step
179
+ )
180
+ )
181
+
182
+ dimslices = []
183
+ for idim in range(len(dataset.shape)):
184
+ if idim == axis:
185
+ dimslices.append(slice(first_iter - ds_first_iter, last_iter - ds_first_iter + iter_step, iter_step))
186
+ else:
187
+ dimslices.append(slice(None, None, None))
188
+
189
+ dimslices = tuple(dimslices)
190
+ log.debug('slicing {!r} with {!r}'.format(dataset, dimslices))
191
+ data = dataset[dimslices]
192
+ log.debug('resulting data is of shape {!r}'.format(data.shape))
193
+ return data
194
+
195
+ def iter_range(self, first_iter=None, last_iter=None, iter_step=None):
196
+ first_iter = first_iter or self.first_iter
197
+ last_iter = last_iter or self.last_iter
198
+ iter_step = iter_step or self.iter_step
199
+
200
+ return np.arange(first_iter, last_iter + 1, iter_step)
@@ -0,0 +1,117 @@
1
+ import itertools
2
+ import logging
3
+ import re
4
+
5
+ import numpy as np
6
+
7
+ import westpa
8
+ from westpa.oldtools.aframe import AnalysisMixin
9
+
10
+ log = logging.getLogger(__name__)
11
+
12
+
13
+ class KineticsAnalysisMixin(AnalysisMixin):
14
+ def __init__(self):
15
+ super().__init__()
16
+
17
+ self.dt = None
18
+ self.analysis_initial_bins = None
19
+ self.analysis_final_bins = None
20
+
21
+ def add_args(self, parser, upcall=True):
22
+ if upcall:
23
+ try:
24
+ upfunc = super().add_args
25
+ except AttributeError:
26
+ pass
27
+ else:
28
+ upfunc(parser)
29
+
30
+ group = parser.add_argument_group('kinetics analysis options')
31
+ group.add_argument(
32
+ '--dt', dest='dt', type=float, default=1.0, help='Assume input data has a time spacing of DT (default: %(default)s).'
33
+ )
34
+ group.add_argument(
35
+ '--initial-bins',
36
+ dest='ibins_string',
37
+ metavar='ILIST',
38
+ help='''Only calculate statistics for transitions starting in bin ILIST. This may be specified as a
39
+ comma-separated list of integers or ranges, as in "0,2-4,5,9"''',
40
+ )
41
+ group.add_argument(
42
+ '--final-bins',
43
+ dest='fbins_string',
44
+ metavar='FLIST',
45
+ help='''Only calculate statistics for transitions ending in bin FLIST. This may be specified as a
46
+ comma-separated list of integers or ranges, as in "0,2-4,5,9"''',
47
+ )
48
+
49
+ def process_args(self, args, upcall=True):
50
+ self.dt = args.dt
51
+ westpa.rc.pstatus('Assuming input data timestep of {:g}'.format(self.dt))
52
+
53
+ if args.ibins_string:
54
+ self.analysis_initial_bins = self.parse_bin_range(args.ibins_string)
55
+ westpa.rc.pstatus(
56
+ 'Will calculate kinetics data from transitions beginning in the following bins: {!s}'.format(
57
+ sorted(self.analysis_initial_bins)
58
+ )
59
+ )
60
+ else:
61
+ westpa.rc.pstatus('Will calculate kinetics data from transitions beginning in any bin.')
62
+
63
+ if args.fbins_string:
64
+ self.analysis_final_bins = self.parse_bin_range(args.fbins_string)
65
+ westpa.rc.pstatus(
66
+ 'Will calculate kinetics data from transitions ending in the following bins: {!s}'.format(
67
+ sorted(self.analysis_final_bins)
68
+ )
69
+ )
70
+ else:
71
+ westpa.rc.pstatus('Will calculate kinetics data from transitions ending in any bin.')
72
+
73
+ if upcall:
74
+ try:
75
+ upfunc = super().process_args
76
+ except AttributeError:
77
+ pass
78
+ else:
79
+ upfunc(args)
80
+
81
+ def parse_bin_range(self, range_string):
82
+ try:
83
+ entries = set()
84
+ fields = re.split(r'\s*,\s*', range_string)
85
+ for field in fields:
86
+ if '-' in field:
87
+ lb, ub = list(map(int, re.split(r'\s*-\s*', field)))
88
+ entries.update(list(range(lb, ub + 1)))
89
+ else:
90
+ entries.add(int(field))
91
+ except (ValueError, TypeError):
92
+ raise ValueError('invalid bin range string {!r}'.format(range_string))
93
+ else:
94
+ return entries
95
+
96
+ def check_bin_selection(self, n_bins=None):
97
+ '''Check to see that the bin ranges selected by the user conform to the available bins (i.e.,
98
+ bin indices are within the permissible range). Also assigns the complete bin range if the
99
+ user has not explicitly limited the bins to be considered.'''
100
+
101
+ n_bins = n_bins or self.n_bins
102
+
103
+ if self.analysis_initial_bins:
104
+ if (np.array(list(self.analysis_initial_bins)) >= n_bins).any():
105
+ raise ValueError('One or more initial bin indices is out of range.')
106
+ else:
107
+ self.analysis_initial_bins = set(range(n_bins))
108
+
109
+ if self.analysis_final_bins:
110
+ if (np.array(list(self.analysis_final_bins)) >= n_bins).any():
111
+ raise ValueError('One or more final bin indices is out of range.')
112
+ else:
113
+ self.analysis_final_bins = set(range(n_bins))
114
+
115
+ @property
116
+ def selected_bin_pair_iter(self):
117
+ return (tuple(pair) for pair in itertools.product(self.analysis_initial_bins, self.analysis_final_bins))
@@ -0,0 +1,153 @@
1
+ '''
2
+ Tools for Monte Carlo bootstrap error analysis
3
+ '''
4
+
5
+ import logging
6
+ import math
7
+
8
+ import numpy as np
9
+ from numpy.random import Generator, MT19937
10
+
11
+ import westpa
12
+ from westpa.oldtools.aframe import AnalysisMixin
13
+
14
+ log = logging.getLogger(__name__)
15
+
16
+
17
+ def msort(input_array):
18
+ return np.sort(input_array, axis=0)
19
+
20
+
21
+ class MCBSMixin(AnalysisMixin):
22
+ def __init__(self):
23
+ super().__init__()
24
+ self.mcbs_alpha = None
25
+ self.mcbs_nsets = None
26
+ self.mcbs_display_confidence = None
27
+
28
+ def add_args(self, parser, upcall=True):
29
+ if upcall:
30
+ try:
31
+ upfunc = super().add_args
32
+ except AttributeError:
33
+ pass
34
+ else:
35
+ upfunc(parser)
36
+ group = parser.add_argument_group('Monte Carlo bootstrap options')
37
+ group.add_argument(
38
+ '--confidence',
39
+ dest='mcbs_confidence',
40
+ type=float,
41
+ default=0.95,
42
+ metavar='P',
43
+ help='''Construct a confidence interval of width P (default: 0.95=95%%).''',
44
+ )
45
+ group.add_argument(
46
+ '--bssize',
47
+ dest='mcbs_nsets',
48
+ type=int,
49
+ metavar='NSETS',
50
+ help='''Use NSETS synthetic data sets to calculate confidence intervals (default:
51
+ calculated based on confidence level, but not less than 1000).''',
52
+ )
53
+
54
+ def process_args(self, args, upcall=True):
55
+ self.mcbs_alpha = 1 - args.mcbs_confidence
56
+ self.mcbs_nsets = args.mcbs_size if args.mcbs_nsets else min(1000, calc_mcbs_nsets(self.mcbs_alpha))
57
+ self.mcbs_display_confidence = '{:.{cp}f}'.format(
58
+ 100 * args.mcbs_confidence, cp=-int(math.floor(math.log10(self.mcbs_alpha))) - 2
59
+ )
60
+ westpa.rc.pstatus(
61
+ 'Using bootstrap of {:d} sets to calculate {:s}% confidence interval (alpha={:g}).'.format(
62
+ self.mcbs_nsets, self.mcbs_display_confidence, self.mcbs_alpha
63
+ )
64
+ )
65
+
66
+ if upcall:
67
+ try:
68
+ upfunc = super().process_args
69
+ except AttributeError:
70
+ pass
71
+ else:
72
+ upfunc(args)
73
+
74
+ def calc_mcbs_nsets(self, alpha=None):
75
+ alpha = alpha or self.mcbs_alpha
76
+ return calc_mcbs_nsets(alpha)
77
+
78
+ def calc_ci_bound_indices(self, n_sets=None, alpha=None):
79
+ n_sets = n_sets or self.mcbs_nsets
80
+ alpha = alpha or self.mcbs_alpha
81
+ return calc_ci_bound_indices(n_sets, alpha)
82
+
83
+
84
+ ciinfo_dtype = np.dtype([('expectation', np.float64), ('ci_lower', np.float64), ('ci_upper', np.float64)])
85
+
86
+
87
+ def calc_mcbs_nsets(alpha):
88
+ '''Return a bootstrap data set size appropriate for the given confidence level.'''
89
+ return int(10 ** (math.ceil(-math.log10(alpha)) + 1))
90
+
91
+
92
+ def calc_ci_bound_indices(n_sets, alpha):
93
+ return (int(math.floor(n_sets * alpha / 2)), int(math.ceil(n_sets * (1 - alpha / 2))))
94
+
95
+
96
+ def bootstrap_ci_ll(estimator, data, alpha, n_sets, storage, sort, eargs=(), ekwargs={}, fhat=None):
97
+ '''Low-level routine for calculating bootstrap error estimates. Arguments and return values are as those for
98
+ ``bootstrap_ci``, except that no argument is optional except additional arguments for the estimator (``eargs``, ``ekwargs``).
99
+ ``data`` must be an array (or subclass), and an additional array ``storage`` must be provided, which
100
+ must be appropriately shaped and typed to hold ``n_sets`` results from ``estimator``. Further, if the
101
+ value ``fhat`` of the estimator must be pre-calculated to allocate ``storage``, then its value may be
102
+ passed; otherwise, ``estimator(data,*eargs,**kwargs)`` will be called to calculate it.'''
103
+
104
+ rng = Generator(MT19937())
105
+
106
+ if fhat is None:
107
+ fhat = estimator(data, *eargs, **ekwargs)
108
+ dlen = len(data)
109
+
110
+ for iset in range(n_sets):
111
+ indices = rng.integers(dlen, size=(dlen,))
112
+ storage[iset] = estimator(data[indices], *eargs, **ekwargs)
113
+
114
+ synth_sorted = sort(storage)
115
+ lbi = int(math.floor(n_sets * alpha / 2))
116
+ ubi = int(math.ceil(n_sets * (1 - alpha / 2)))
117
+
118
+ lb = synth_sorted[lbi]
119
+ ub = synth_sorted[ubi]
120
+
121
+ try:
122
+ return (fhat, lb, ub, ub - lb, abs((ub - lb) / fhat) if fhat else 0, max(ub - fhat, fhat - lb))
123
+ finally:
124
+ del fhat, lb, ub, indices
125
+
126
+
127
+ def bootstrap_ci(estimator, data, alpha, n_sets=None, sort=msort, eargs=(), ekwargs={}):
128
+ '''Perform a Monte Carlo bootstrap of a (1-alpha) confidence interval for the given ``estimator``.
129
+ Returns (fhat, ci_lower, ci_upper), where fhat is the result of ``estimator(data, *eargs, **ekwargs)``,
130
+ and ``ci_lower`` and ``ci_upper`` are the lower and upper bounds of the surrounding confidence
131
+ interval, calculated by calling ``estimator(syndata, *eargs, **ekwargs)`` on each synthetic data
132
+ set ``syndata``. If ``n_sets`` is provided, that is the number of synthetic data sets generated,
133
+ otherwise an appropriate size is selected automatically (see ``calc_mcbs_nsets()``).
134
+
135
+ ``sort``, if given, is applied to sort the results of calling ``estimator`` on each
136
+ synthetic data set prior to obtaining the confidence interval. This function must sort
137
+ on the last index.
138
+
139
+ Individual entries in synthetic data sets are selected by the first index of ``data``, allowing this
140
+ function to be used on arrays of multidimensional data.
141
+
142
+ Returns (fhat, lb, ub, ub-lb, abs((ub-lb)/fhat), and max(ub-fhat,fhat-lb)) (that is, the estimated value, the
143
+ lower and upper bounds of the confidence interval, the width of the confidence interval, the relative
144
+ width of the confidence interval, and the symmetrized error bar of the confidence interval).'''
145
+
146
+ data = np.asanyarray(data)
147
+ fhat = np.squeeze(estimator(data, *eargs, **ekwargs))
148
+ n_sets = n_sets or calc_mcbs_nsets(alpha)
149
+ fsynth = np.empty((n_sets,), dtype=fhat.dtype)
150
+ try:
151
+ return bootstrap_ci_ll(estimator, data, alpha, n_sets or calc_mcbs_nsets(alpha), fsynth, sort, eargs, ekwargs, fhat)
152
+ finally:
153
+ del fsynth
@@ -0,0 +1,39 @@
1
+ import logging
2
+
3
+ from westpa.oldtools.aframe import AnalysisMixin
4
+
5
+ log = logging.getLogger(__name__)
6
+
7
+
8
+ class CommonOutputMixin(AnalysisMixin):
9
+ def __init__(self):
10
+ super().__init__()
11
+
12
+ include_args = self.include_args.setdefault('CommonOutputMixin', {})
13
+ include_args.setdefault('suppress_headers', True)
14
+ include_args.setdefault('print_bin_labels', True)
15
+
16
+ self.output_suppress_headers = False
17
+ self.output_print_bin_labels = False
18
+
19
+ def add_common_output_args(self, parser_or_group):
20
+ if self.include_args['CommonOutputMixin']['suppress_headers']:
21
+ parser_or_group.add_argument(
22
+ '--noheaders',
23
+ dest='suppress_headers',
24
+ action='store_true',
25
+ help='Do not include headers in text output files (default: include headers)',
26
+ )
27
+ if self.include_args['CommonOutputMixin']['print_bin_labels']:
28
+ parser_or_group.add_argument(
29
+ '--binlabels',
30
+ dest='print_bin_labels',
31
+ action='store_true',
32
+ help='Print bin labels in output files, if available (default: do not print bin labels)',
33
+ )
34
+
35
+ def process_common_output_args(self, args):
36
+ if self.include_args['CommonOutputMixin']['suppress_headers']:
37
+ self.output_suppress_headers = bool(args.suppress_headers)
38
+ if self.include_args['CommonOutputMixin']['print_bin_labels']:
39
+ self.output_print_bin_labels = bool(args.print_bin_labels)
@@ -0,0 +1,90 @@
1
+ import logging
2
+
3
+ import numpy as np
4
+
5
+ from westpa.oldtools.aframe import AnalysisMixin
6
+
7
+ log = logging.getLogger(__name__)
8
+
9
+ try:
10
+ import matplotlib
11
+ except ImportError:
12
+ matplotlib = None
13
+ pyplot = None
14
+ cm_hovmol = None
15
+ cm_hovmol_r = None
16
+ else:
17
+ try:
18
+ matplotlib.use('PDF')
19
+ from matplotlib import pyplot
20
+ except Exception as e:
21
+ log.info('could not select matplotlib PDF backend: {}'.format(e))
22
+ matplotlib = None
23
+ pyplot = None
24
+
25
+ cmap_data = np.array(
26
+ [
27
+ (124, 0, 24),
28
+ (211, 0, 32),
29
+ (244, 184, 0),
30
+ (245, 235, 0),
31
+ (129, 183, 2),
32
+ (32, 128, 38),
33
+ (21, 27, 87),
34
+ (36, 62, 137),
35
+ (178, 220, 245),
36
+ (255, 255, 255),
37
+ ],
38
+ np.float32,
39
+ )
40
+ cmap_data /= 255.0
41
+ cm_hovmol = matplotlib.colors.LinearSegmentedColormap.from_list('hovmol', cmap_data)
42
+ cm_hovmol_r = matplotlib.colors.LinearSegmentedColormap.from_list('hovmol_r', np.flipud(cmap_data))
43
+
44
+ _pdr_data = {
45
+ 'red': [
46
+ (0.0, 1.0, 1.0),
47
+ (0.25, 1.0, 1.0),
48
+ (0.50, 1.0, 1.0),
49
+ (0.75, 0.0, 0.0),
50
+ (0.90, 0.50, 0.50),
51
+ (0.95, 0.0, 0.0),
52
+ (1.0, 1.0, 1.0),
53
+ ],
54
+ 'green': [
55
+ (0.0, 1.0, 1.0),
56
+ (0.25, 0.0, 0.0),
57
+ (0.50, 1.0, 1.0),
58
+ (0.75, 1.0, 1.0),
59
+ (0.90, 0.86, 0.86),
60
+ (0.95, 0.0, 0.0),
61
+ (1.0, 1.0, 1.0),
62
+ ],
63
+ 'blue': [(0.0, 1.0, 1.0), (0.25, 0.0, 0.0), (0.75, 0.0, 0.0), (0.90, 1.0, 1.0), (0.95, 1.0, 1.0), (1.0, 1.0, 1.0)],
64
+ }
65
+
66
+ cm_pdr = matplotlib.colors.LinearSegmentedColormap('pdr', _pdr_data, 2048)
67
+ cm_pdr_r = cm_pdr.reversed()
68
+
69
+ matplotlib.colormaps.register(cmap=cm_pdr, name='pdr')
70
+ matplotlib.colormaps.register(cmap=cm_pdr_r, name='pdr_r')
71
+ matplotlib.colormaps.register(cmap=cm_hovmol, name='hovmol')
72
+ matplotlib.colormaps.register(cmap=cm_hovmol_r, name='hovmol_r')
73
+
74
+ del cmap_data
75
+
76
+
77
+ class PlottingMixin(AnalysisMixin):
78
+ def __init__(self):
79
+ global matplotlib, pyplot
80
+
81
+ super().__init__()
82
+
83
+ self.matplotlib_avail = matplotlib is not None and pyplot is not None
84
+
85
+ def require_matplotlib(self):
86
+ global matplotlib
87
+ if not self.matplotlib_avail:
88
+ raise RuntimeError('matplotlib is not available')
89
+ else:
90
+ return matplotlib