westpa 2022.10__cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

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

Potentially problematic release.


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

Files changed (150) 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 +59 -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 +378 -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 +486 -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-312-x86_64-linux-gnu.so +0 -0
  42. westpa/core/binning/assign.py +449 -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 +427 -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-312-x86_64-linux-gnu.so +0 -0
  55. westpa/core/kinetics/events.py +147 -0
  56. westpa/core/kinetics/matrates.py +156 -0
  57. westpa/core/kinetics/rate_averaging.py +266 -0
  58. westpa/core/progress.py +218 -0
  59. westpa/core/propagators/__init__.py +54 -0
  60. westpa/core/propagators/executable.py +715 -0
  61. westpa/core/reweight/__init__.py +14 -0
  62. westpa/core/reweight/_reweight.cpython-312-x86_64-linux-gnu.so +0 -0
  63. westpa/core/reweight/matrix.py +126 -0
  64. westpa/core/segment.py +119 -0
  65. westpa/core/sim_manager.py +830 -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 +908 -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/__main__.py +110 -0
  75. westpa/fasthist/_fasthist.cpython-312-x86_64-linux-gnu.so +0 -0
  76. westpa/mclib/__init__.py +264 -0
  77. westpa/mclib/__main__.py +28 -0
  78. westpa/mclib/_mclib.cpython-312-x86_64-linux-gnu.so +0 -0
  79. westpa/oldtools/__init__.py +4 -0
  80. westpa/oldtools/aframe/__init__.py +35 -0
  81. westpa/oldtools/aframe/atool.py +75 -0
  82. westpa/oldtools/aframe/base_mixin.py +26 -0
  83. westpa/oldtools/aframe/binning.py +178 -0
  84. westpa/oldtools/aframe/data_reader.py +560 -0
  85. westpa/oldtools/aframe/iter_range.py +200 -0
  86. westpa/oldtools/aframe/kinetics.py +117 -0
  87. westpa/oldtools/aframe/mcbs.py +146 -0
  88. westpa/oldtools/aframe/output.py +39 -0
  89. westpa/oldtools/aframe/plotting.py +90 -0
  90. westpa/oldtools/aframe/trajwalker.py +126 -0
  91. westpa/oldtools/aframe/transitions.py +469 -0
  92. westpa/oldtools/cmds/__init__.py +0 -0
  93. westpa/oldtools/cmds/w_ttimes.py +358 -0
  94. westpa/oldtools/files.py +34 -0
  95. westpa/oldtools/miscfn.py +23 -0
  96. westpa/oldtools/stats/__init__.py +4 -0
  97. westpa/oldtools/stats/accumulator.py +35 -0
  98. westpa/oldtools/stats/edfs.py +129 -0
  99. westpa/oldtools/stats/mcbs.py +89 -0
  100. westpa/tools/__init__.py +33 -0
  101. westpa/tools/binning.py +472 -0
  102. westpa/tools/core.py +340 -0
  103. westpa/tools/data_reader.py +159 -0
  104. westpa/tools/dtypes.py +31 -0
  105. westpa/tools/iter_range.py +198 -0
  106. westpa/tools/kinetics_tool.py +340 -0
  107. westpa/tools/plot.py +283 -0
  108. westpa/tools/progress.py +17 -0
  109. westpa/tools/selected_segs.py +154 -0
  110. westpa/tools/wipi.py +751 -0
  111. westpa/trajtree/__init__.py +4 -0
  112. westpa/trajtree/_trajtree.cpython-312-x86_64-linux-gnu.so +0 -0
  113. westpa/trajtree/trajtree.py +117 -0
  114. westpa/westext/__init__.py +0 -0
  115. westpa/westext/adaptvoronoi/__init__.py +3 -0
  116. westpa/westext/adaptvoronoi/adaptVor_driver.py +214 -0
  117. westpa/westext/hamsm_restarting/__init__.py +3 -0
  118. westpa/westext/hamsm_restarting/example_overrides.py +35 -0
  119. westpa/westext/hamsm_restarting/restart_driver.py +1165 -0
  120. westpa/westext/stringmethod/__init__.py +11 -0
  121. westpa/westext/stringmethod/fourier_fitting.py +69 -0
  122. westpa/westext/stringmethod/string_driver.py +253 -0
  123. westpa/westext/stringmethod/string_method.py +306 -0
  124. westpa/westext/weed/BinCluster.py +180 -0
  125. westpa/westext/weed/ProbAdjustEquil.py +100 -0
  126. westpa/westext/weed/UncertMath.py +247 -0
  127. westpa/westext/weed/__init__.py +10 -0
  128. westpa/westext/weed/weed_driver.py +182 -0
  129. westpa/westext/wess/ProbAdjust.py +101 -0
  130. westpa/westext/wess/__init__.py +6 -0
  131. westpa/westext/wess/wess_driver.py +207 -0
  132. westpa/work_managers/__init__.py +57 -0
  133. westpa/work_managers/core.py +396 -0
  134. westpa/work_managers/environment.py +134 -0
  135. westpa/work_managers/mpi.py +318 -0
  136. westpa/work_managers/processes.py +187 -0
  137. westpa/work_managers/serial.py +28 -0
  138. westpa/work_managers/threads.py +79 -0
  139. westpa/work_managers/zeromq/__init__.py +20 -0
  140. westpa/work_managers/zeromq/core.py +641 -0
  141. westpa/work_managers/zeromq/node.py +131 -0
  142. westpa/work_managers/zeromq/work_manager.py +526 -0
  143. westpa/work_managers/zeromq/worker.py +320 -0
  144. westpa-2022.10.dist-info/AUTHORS +22 -0
  145. westpa-2022.10.dist-info/LICENSE +21 -0
  146. westpa-2022.10.dist-info/METADATA +183 -0
  147. westpa-2022.10.dist-info/RECORD +150 -0
  148. westpa-2022.10.dist-info/WHEEL +6 -0
  149. westpa-2022.10.dist-info/entry_points.txt +29 -0
  150. westpa-2022.10.dist-info/top_level.txt +1 -0
@@ -0,0 +1,506 @@
1
+ import logging
2
+ import os
3
+ import re
4
+
5
+ import h5py
6
+ import numpy as np
7
+
8
+ from westpa.tools import WESTMasterCommand, WESTSubcommand, ProgressIndicatorComponent, Plotter
9
+ from westpa.core import h5io
10
+
11
+ if os.environ.get('DISPLAY') is not None:
12
+ from matplotlib import pyplot
13
+
14
+ log = logging.getLogger('ploterrs')
15
+
16
+
17
+ class CommonPloterrs(WESTSubcommand):
18
+ def __init__(self, parent):
19
+ super().__init__(parent)
20
+
21
+ self.progress = ProgressIndicatorComponent()
22
+
23
+ self.xscale = None
24
+ self.yscale = None
25
+ self.xrange = None
26
+ self.yrange = None
27
+ self.xlabel = None
28
+ self.ylabel = None
29
+ self.title = None
30
+
31
+ self.plot_options_group = None
32
+
33
+ def add_args(self, parser):
34
+ self.progress.add_args(parser)
35
+
36
+ pogroup = self.plot_options_group = parser.add_argument_group('plot options')
37
+ pogroup.add_argument(
38
+ '--xscale',
39
+ choices=['linear', 'log', 'symlog'],
40
+ default='linear',
41
+ help='''Use "linear", "log", or "symlog" scaling for the x axis.
42
+ (Default: %(default)s).''',
43
+ )
44
+ pogroup.add_argument(
45
+ '--yscale',
46
+ choices=['linear', 'log', 'symlog'],
47
+ default='linear',
48
+ help='''Use "linear", "log", or "symlog" scaling for the y axis.
49
+ (Default: %(default)s).''',
50
+ )
51
+ pogroup.add_argument(
52
+ '--xrange',
53
+ help='''Restrict X range to XRANGE, which must be formatted as "xmin,xmax".
54
+ (Default: determined by input data.)''',
55
+ )
56
+ pogroup.add_argument(
57
+ '--yrange',
58
+ help='''Restrict Y range to YRANGE, which must be formatted as "ymin,ymax".
59
+ (Default: determined by input data.)''',
60
+ )
61
+ pogroup.add_argument('--xlabel', help='''Use XLABEL for the x-axis label. (Default: varies.)''')
62
+ pogroup.add_argument('--ylabel', help='''Use YLABEL for the y-axis label. (Default: varies.)''')
63
+ pogroup.add_argument('--title', help='''Use TITLE for the plot title. (Default: varies.)''')
64
+ pogroup.add_argument('--terminal', '-t', dest='plotting', action='store_true', help='''Plot output in terminal.''')
65
+
66
+ def process_args(self, args):
67
+ self.progress.process_args(args)
68
+
69
+ if args.xrange:
70
+ self.xrange = self.parse_range(args.xrange)
71
+
72
+ if args.yrange:
73
+ self.yrange = self.parse_range(args.yrange)
74
+
75
+ self.xscale = args.xscale
76
+ self.yscale = args.yscale
77
+ self.xlabel = args.xlabel or 'Iteration'
78
+ self.ylabel = args.ylabel
79
+ self.title = args.title
80
+ if args.plotting or os.environ.get('DISPLAY') is None:
81
+ self.interface = 'text'
82
+ else:
83
+ self.interface = 'matplotlib'
84
+
85
+ def parse_range(self, rangespec):
86
+ try:
87
+ (lbt, ubt) = rangespec.split(',')
88
+ return float(lbt), float(ubt)
89
+ except (ValueError, TypeError) as e:
90
+ raise ValueError('invalid range specification {!r}: {!s}'.format(rangespec, e))
91
+
92
+ def do_plot(self, data, output_filename, title=None, x_range=None, y_range=None, x_label=None, y_label=None):
93
+ if not output_filename:
94
+ return
95
+
96
+ title = title or self.title
97
+ x_range = x_range or self.xrange
98
+ y_range = y_range or self.yrange
99
+ x_label = x_label or self.xlabel
100
+ y_label = y_label or self.ylabel
101
+
102
+ iters = data['iter_stop'] - 1
103
+
104
+ pyplot.figure()
105
+ pyplot.plot(iters, data['expected'], color='black')
106
+ pyplot.plot(iters, data['ci_lbound'], color='gray')
107
+ pyplot.plot(iters, data['ci_ubound'], color='gray')
108
+
109
+ pyplot.gca().set_xscale(self.xscale)
110
+ pyplot.gca().set_yscale(self.yscale)
111
+
112
+ if title:
113
+ pyplot.title(title)
114
+
115
+ if x_range is not None:
116
+ pyplot.xlim(x_range)
117
+
118
+ if y_range is not None:
119
+ pyplot.ylim(y_range)
120
+
121
+ if x_label:
122
+ pyplot.xlabel(x_label)
123
+
124
+ if y_label:
125
+ pyplot.ylabel(y_label)
126
+
127
+ pyplot.savefig(output_filename)
128
+
129
+
130
+ class GenericIntervalSubcommand(CommonPloterrs):
131
+ description = '''\
132
+ Plots generic expectation/CI data. A path to the HDF5 file and the dataset
133
+ within it must be provided. This path takes the form **FILENAME/PATH[SLICE]**.
134
+ If the dataset is not a vector (one dimensional) then a slice must be provided.
135
+ For example, to access the state 0 to state 1 rate evolution calculated by
136
+ ``w_kinavg``, one would use ``kinavg.h5/rate_evolution[:,0,1]``.
137
+
138
+
139
+ -----------------------------------------------------------------------------
140
+ Command-line arguments
141
+ -----------------------------------------------------------------------------
142
+ '''
143
+ subcommand = 'generic'
144
+ help_text = 'arbitrary HDF5 file and dataset'
145
+
146
+ def __init__(self, parent):
147
+ super().__init__(parent)
148
+ self.h5file = None
149
+ self.h5dset = None
150
+ self.dset_slice = None
151
+ self.output_filename = None
152
+
153
+ def add_args(self, parser):
154
+ iogroup = parser.add_argument_group('input/output options')
155
+ iogroup.add_argument(
156
+ '-o',
157
+ '--output',
158
+ default='errbars.pdf',
159
+ help='''Write plot to OUTPUT (default: %(default)s), whose format will
160
+ be determined by filename extension.''',
161
+ )
162
+ iogroup.add_argument(
163
+ 'dsspec',
164
+ help='''Use data located at DSSPEC, which must be formatted as
165
+ FILENAME/PATH[SLICE]. FILENAME is the HDF5 file to read, PATH is the
166
+ HDF5 path to the dataset, and SLICE, if provided, must be the Numpy-style
167
+ slice (including brackets) which selects a vector of data of the
168
+ appropriate type.''',
169
+ )
170
+
171
+ def process_args(self, args):
172
+ self.output_filename = args.output
173
+ (pathname, slicestr) = re.search(r'([^[]+)(\[[^\]]+\])?$', args.dsspec).groups()
174
+ if slicestr:
175
+ sl = eval('np.index_exp' + slicestr)
176
+ else:
177
+ sl = np.index_exp[...]
178
+ self.h5file, self.h5dset = h5io.resolve_filepath(pathname, mode='r')
179
+ self.dset_slice = sl
180
+
181
+ def load_and_validate_data(self):
182
+ reqd_fields = set(['iter_start', 'iter_stop', 'expected', 'ci_lbound', 'ci_ubound'])
183
+
184
+ self.progress.indicator.new_operation('loading data')
185
+ data = self.h5dset[self.dset_slice]
186
+
187
+ if data.ndim != 1:
188
+ raise TypeError('dataset to be plotted must be 1-dimensional')
189
+ try:
190
+ fieldnames = set(data.dtype.fields.keys())
191
+ except AttributeError:
192
+ raise TypeError('dataset has inappropriate type')
193
+ else:
194
+ if len(fieldnames & reqd_fields) < len(reqd_fields):
195
+ raise TypeError('dataset does not contain correct fields')
196
+
197
+ return data
198
+
199
+ def go(self):
200
+ with self.progress.indicator:
201
+ data = self.load_and_validate_data()
202
+ self.progress.indicator.new_operation('plotting')
203
+ self.do_plot(data, self.output_filename)
204
+
205
+
206
+ class DirectKinetics(CommonPloterrs):
207
+ subcommand = 'd.kinetics'
208
+ help_text = 'output of w_direct kinetics'
209
+ input_filename = 'direct.h5'
210
+ flux_output_filename = 'flux_evolution_d_{state_label}.pdf'
211
+ rate_output_filename = 'rate_evolution_d_{istate_label}_{fstate_label}.pdf'
212
+ description = '''\
213
+ Plot evolution of state-to-state rates and total flux into states as generated
214
+ by ``w_{direct/reweight} kinetics`` (when used with the ``--evolution-mode``
215
+ option). Plots are generated for all rates/fluxes calculated. Output filenames
216
+ require (and plot titles and axis labels support) substitution based on which
217
+ flux/rate is being plotted:
218
+
219
+ istate_label, fstate_label
220
+ *(String, for rates)* Names of the initial and final states, as originally
221
+ given to ``w_assign``.
222
+
223
+ istate_index, fstate_index
224
+ *(Integer, for rates)* Indices of initial and final states.
225
+
226
+ state_label
227
+ *(String, for fluxes)* Name of state
228
+
229
+ state_index
230
+ *(Integer, for fluxes)* Index of state
231
+ '''
232
+
233
+ def __init__(self, parent):
234
+ super().__init__(parent)
235
+ self.kinavg_file = None
236
+
237
+ self.dset_slice = None
238
+ self.rate_output_pattern = None
239
+ self.flux_output_pattern = None
240
+
241
+ self.state_labels = None
242
+
243
+ def add_args(self, parser):
244
+ iogroup = parser.add_argument_group('input/output')
245
+ iogroup.add_argument(
246
+ '-i', '--input', default=self.input_filename, help='''Read kinetics results from INPUT (default: %(default)s).'''
247
+ )
248
+ iogroup.add_argument(
249
+ '--rate-output',
250
+ default=self.rate_output_filename,
251
+ help='''Filename pattern for rate evolution output. See above for valid
252
+ field names. (Default: %(default)r).''',
253
+ )
254
+ iogroup.add_argument(
255
+ '--flux-output',
256
+ default=self.flux_output_filename,
257
+ help='''Filename pattern for flux evolution output. See above for valid
258
+ field names. (Default: %(default)r).''',
259
+ )
260
+
261
+ def process_args(self, args):
262
+ self.kinavg_file = h5py.File(args.input, 'r')
263
+
264
+ self.state_labels = list(self.kinavg_file['state_labels'][...])
265
+
266
+ self.rate_output_pattern = args.rate_output
267
+ self.flux_output_pattern = args.flux_output
268
+
269
+ def plot_flux(self, istate):
270
+ label = self.state_labels[istate]
271
+ data = self.kinavg_file['target_flux_evolution'][:, istate]
272
+
273
+ if (data['iter_start'] == 0).all():
274
+ # No data
275
+ return
276
+
277
+ subdict = dict(state_label=label, state_index=istate)
278
+
279
+ output_filename = self.flux_output_pattern.format(**subdict) if self.flux_output_pattern else None
280
+
281
+ title = self.title if self.title is not None else 'Flux into state "{state_label}"'
282
+ title = title.format(**subdict)
283
+
284
+ x_label = self.xlabel.format(**subdict) if self.xlabel else None
285
+
286
+ y_label = self.ylabel if self.ylabel is not None else r'Flux $(\tau^{{-1}})$'
287
+ y_label = y_label.format(**subdict)
288
+
289
+ self.do_plot(data, output_filename, title, x_label=x_label, y_label=y_label)
290
+
291
+ def plot_rate(self, istate, jstate):
292
+ ilabel = self.state_labels[istate]
293
+ jlabel = self.state_labels[jstate]
294
+ data = self.kinavg_file['rate_evolution'][:, istate, jstate]
295
+
296
+ if (data['iter_start'] == 0).all():
297
+ # No data
298
+ return
299
+
300
+ subdict = dict(istate_label=ilabel, istate_index=istate, fstate_label=jlabel, fstate_index=jstate)
301
+
302
+ output_filename = self.rate_output_pattern.format(**subdict) if self.rate_output_pattern else None
303
+
304
+ title = self.title if self.title is not None else 'Rate from state "{istate_label}" to state "{fstate_label}"'
305
+ title = title.format(**subdict)
306
+
307
+ x_label = self.xlabel.format(**subdict) if self.xlabel else None
308
+
309
+ y_label = self.ylabel if self.ylabel is not None else r'Rate $(\tau^{{-1}})$'
310
+ y_label = y_label.format(**subdict)
311
+
312
+ self.do_plot(data, output_filename, title, x_label=x_label, y_label=y_label)
313
+
314
+ def go(self):
315
+ pi = self.progress.indicator
316
+ nstates = len(self.state_labels)
317
+ if self.interface == 'matplotlib':
318
+ with pi:
319
+ # if --evolution-mode wasn't specified, neither of these exist:
320
+ if 'target_flux_evolution' in self.kinavg_file:
321
+ pi.new_operation('plotting fluxes', nstates)
322
+ for istate in range(nstates):
323
+ self.plot_flux(istate)
324
+ pi.progress += 1
325
+
326
+ # if --evolution-mode wasn't specified, we won't get this either
327
+ if 'rate_evolution' in self.kinavg_file:
328
+ pi.new_operation('plotting rates', nstates * nstates)
329
+ for istate in range(nstates):
330
+ for jstate in range(nstates):
331
+ self.plot_rate(istate, jstate)
332
+ pi.progress += 1
333
+ else:
334
+ print('rate evolution not available')
335
+ else:
336
+ plotter = Plotter(self.kinavg_file, 'rate_evolution', iteration=-1, interface='text')
337
+ for istate in range(nstates):
338
+ for jstate in range(nstates):
339
+ if istate != jstate:
340
+ plotter.plot(istate, jstate)
341
+ plotter = Plotter(self.kinavg_file, 'conditional_flux_evolution', iteration=-1, interface='text')
342
+ for istate in range(nstates):
343
+ for jstate in range(nstates):
344
+ if istate != jstate:
345
+ plotter.plot(istate, jstate)
346
+
347
+
348
+ class DirectStateprobs(CommonPloterrs):
349
+ subcommand = 'd.probs'
350
+ help_text = 'output of w_direct probs'
351
+ input_filename = 'direct.h5'
352
+ pop_output_filename = 'pop_evolution_d_{state_label}.pdf'
353
+ color_output_filename = 'color_evolution_d_{state_label}.pdf'
354
+ description = '''\
355
+ Plot evolution of macrostate populations and associated uncertainties. Plots
356
+ are generated for all states calculated. Output filenames require (and plot
357
+ titles and axis labels support) substitution based on which state is being
358
+ plotted:
359
+
360
+ state_label
361
+ *(String, for fluxes)* Name of state
362
+
363
+ state_index
364
+ *(Integer, for fluxes)* Index of state
365
+ '''
366
+
367
+ def __init__(self, parent):
368
+ super().__init__(parent)
369
+ self.stateprobs_file = None
370
+
371
+ self.dset_slice = None
372
+ self.rate_output_pattern = None
373
+ self.flux_output_pattern = None
374
+
375
+ self.state_labels = None
376
+
377
+ def add_args(self, parser):
378
+ iogroup = parser.add_argument_group('input/output')
379
+ iogroup.add_argument(
380
+ '-i', '--input', default=self.input_filename, help='''Read w_kinavg results from INPUT (default: %(default)s).'''
381
+ )
382
+ iogroup.add_argument(
383
+ '--population-output',
384
+ default=self.pop_output_filename,
385
+ help='''Filename pattern for population evolution output. See above for valid
386
+ field names. (Default: %(default)r).''',
387
+ )
388
+ iogroup.add_argument(
389
+ '--color-output',
390
+ default=self.color_output_filename,
391
+ help='''Filename pattern for ensemble evolution output. See above for valid
392
+ field names. (Default: %(default)r).''',
393
+ )
394
+
395
+ def process_args(self, args):
396
+ self.stateprobs_file = h5py.File(args.input, 'r')
397
+
398
+ self.state_labels = list(self.stateprobs_file['state_labels'][...])
399
+ self.pop_output_pattern = args.population_output
400
+ self.color_output_pattern = args.color_output
401
+
402
+ def plot_pop(self, istate):
403
+ label = self.state_labels[istate]
404
+ data = self.stateprobs_file['state_pop_evolution'][:, istate]
405
+
406
+ if (data['iter_start'] == 0).all():
407
+ # No data
408
+ return
409
+
410
+ subdict = dict(state_label=label, state_index=istate)
411
+
412
+ output_filename = self.pop_output_pattern.format(**subdict) if self.pop_output_pattern else None
413
+
414
+ title = self.title if self.title is not None else 'Population in state "{state_label}"'
415
+ title = title.format(**subdict)
416
+
417
+ x_label = self.xlabel.format(**subdict) if self.xlabel else None
418
+ y_label = self.ylabel if self.ylabel is not None else r'Population'
419
+ y_label = y_label.format(**subdict)
420
+
421
+ self.do_plot(data, output_filename, title, x_label=x_label, y_label=y_label)
422
+
423
+ def plot_color(self, istate):
424
+ label = self.state_labels[istate]
425
+ data = self.stateprobs_file['color_prob_evolution'][:, istate]
426
+
427
+ if (data['iter_start'] == 0).all():
428
+ # No data
429
+ return
430
+
431
+ subdict = dict(state_label=label, state_index=istate)
432
+
433
+ output_filename = self.color_output_pattern.format(**subdict) if self.color_output_pattern else None
434
+
435
+ title = self.title if self.title is not None else 'Population in ensemble "{state_label}"'
436
+ title = title.format(**subdict)
437
+
438
+ x_label = self.xlabel.format(**subdict) if self.xlabel else None
439
+ y_label = self.ylabel if self.ylabel is not None else r'Population'
440
+ y_label = y_label.format(**subdict)
441
+
442
+ self.do_plot(data, output_filename, title, x_label=x_label, y_label=y_label)
443
+
444
+ def go(self):
445
+ pi = self.progress.indicator
446
+ nstates = len(self.state_labels)
447
+ if self.interface == 'matplotlib':
448
+ with pi:
449
+ if 'state_pop_evolution' in self.stateprobs_file:
450
+ pi.new_operation('plotting populations', nstates)
451
+ for istate in range(nstates):
452
+ self.plot_pop(istate)
453
+ pi.progress += 1
454
+
455
+ if 'color_prob_evolution' in self.stateprobs_file:
456
+ pi.new_operation('plotting ensemble populations', nstates)
457
+ for istate in range(nstates):
458
+ self.plot_color(istate)
459
+ pi.progress += 1
460
+ else:
461
+ print('population evolution not available')
462
+ else:
463
+ plotter = Plotter(self.stateprobs_file, 'state_pop_evolution', iteration=-1, interface='text')
464
+ for istate in range(nstates):
465
+ plotter.plot(istate)
466
+ plotter = Plotter(self.stateprobs_file, 'color_prob_evolution', iteration=-1, interface='text')
467
+ for istate in range(nstates):
468
+ plotter.plot(istate)
469
+
470
+
471
+ class ReweightStateprobs(DirectStateprobs):
472
+ subcommand = 'rw.probs'
473
+ help_text = 'output of w_reweight probs'
474
+ input_filename = 'reweight.h5'
475
+ pop_output_filename = 'pop_evolution_rw_{state_label}.pdf'
476
+ color_output_filename = 'color_evolution_rw_{state_label}.pdf'
477
+
478
+
479
+ class ReweightKinetics(DirectKinetics):
480
+ subcommand = 'rw.kinetics'
481
+ help_text = 'output of w_reweight kinetics'
482
+ input_filename = 'reweight.h5'
483
+ flux_output_filename = 'flux_evolution_rw_{state_label}.pdf'
484
+ rate_output_filename = 'rate_evolution_rw_{istate_label}_{fstate_label}.pdf'
485
+
486
+
487
+ class PloterrsTool(WESTMasterCommand):
488
+ prog = 'ploterrs'
489
+ subcommands = [DirectKinetics, DirectStateprobs, ReweightStateprobs, ReweightKinetics, GenericIntervalSubcommand]
490
+ subparsers_title = 'supported input formats'
491
+ description = '''\
492
+ Plots error ranges for weighted ensemble datasets.
493
+
494
+
495
+ -----------------------------------------------------------------------------
496
+ Command-line options
497
+ -----------------------------------------------------------------------------
498
+ '''
499
+
500
+
501
+ def entry_point():
502
+ PloterrsTool().main()
503
+
504
+
505
+ if __name__ == '__main__':
506
+ entry_point()