source: branches/1.4/puq/puq_analyze.py @ 5874

Last change on this file since 5874 was 5829, checked in by mmh, 9 years ago

improved probability curve plotting, bug fixes, cleanup

  • Property svn:executable set to *
File size: 9.5 KB
Line 
1#!/usr/bin/env python
2"""
3Once submit has finished with the jobs, this function is called to have PUQ
4process the results.
5"""
6from __future__ import print_function
7import sys
8import os
9import numpy as np
10import h5py
11import re
12import puq
13from puq.jpickle import unpickle
14import Rappture
15import StringIO
16from scipy.spatial import ConvexHull
17# geometry library
18from shapely.geometry import Polygon
19from shapely.ops import unary_union
20
21# Redirect stdout and stderr to files for debugging.
22# Append to the files created in get_params.py
23sys.stdout = open("uq_debug.out", 'a')
24sys.stderr = open("uq_debug.err", 'a')
25
26
27# Restore the state of a PUQ session from a HDF5 file.
28def load_from_hdf5(name):
29    h5 = h5py.File(name, 'r+')
30    sw = unpickle(h5['private/sweep'].value)
31    sw.fname = os.path.splitext(name)[0]
32    h5.close()
33
34    sw.psweep._sweep = sw
35
36    if hasattr(sw.psweep, 'reinit'):
37        sw.psweep.reinit()
38    return sw
39
40
41# Plots probability curves
42def plot_pdf_curve(io, h5, xvals, vname, percent):
43    print('plot_pdf_curve %s %s' % (vname, percent))
44    # compute upper and lower percentiles
45    pm = (100 - percent)/200.0
46    pp = 1 - pm
47
48    label = None
49
50    # collect data into an array
51    xarr = np.empty(len(xvals[vname]))
52    yp = np.empty(len(xvals[vname]))
53    ym = np.empty(len(xvals[vname]))
54    for vindex in sorted(xvals[vname].keys()):
55        if label is None:
56            label = h5['/output/data/%s[%d]' % (vname, vindex)].attrs['label']
57        xarr[vindex] = xvals[vname][vindex]
58        yp[vindex] = pcurves[vname][vindex].ppf(pp)
59        ym[vindex] = pcurves[vname][vindex].ppf(pm)
60
61    curve = io['output.curve(curve_pdf-%s-%s)' % (vname, percent)]
62    if percent == 0:
63        curve['about.label'] = "mean"
64    else:
65        curve['about.label'] = "middle %s%%" % percent
66    curve['about.group'] = label
67    curve['about.uqtype'] = 'Probability'
68
69    pts = ""
70    for x, y in zip(xarr, yp):
71        pts += "%s %s " % (x, y)
72    if percent == 0:
73        pts += '\n'
74    else:
75        for x, y in reversed(zip(xarr, ym)):
76            pts += "%s %s " % (x, y)
77        pts += "%s %s\n" % (xarr[0], yp[0])
78
79    curve['component.xy'] = pts
80
81
82def add_pts(f1, percent):
83    # compute upper and lower percentiles
84    pm = (100 - percent) / 200.0
85    pp = 1 - pm
86    prob = np.linspace(pm, pp, 31)
87    x, y = f1.eval(prob)
88    return np.array(zip(x, y))
89
90
91def plot_pdf_acurve(io, h5, acurves, vname, percent):
92    """
93    This function plots the probability curves for parametric
94    PDFs.
95    """
96    print('plot_pdf_acurve %s %s' % (vname, percent))
97
98    label = None
99    prev_pts = None  # last set of points
100
101    poly = []
102    for vindex in sorted(acurves[vname].keys()):
103        if label is None:
104            label = h5['/output/data/%s[%d]' % (vname, vindex)].attrs['label']
105        f1 = unpickle(h5['/output/data/%s[%d]' % (vname, vindex)].attrs['curve'])
106        bpts = add_pts(f1, percent)
107
108        # first data set? Just remember it.
109        if prev_pts is None:
110            prev_pts = bpts
111            continue
112
113        pts = np.array((prev_pts, bpts)).ravel().reshape(-1, 2)
114        hull = ConvexHull(pts, qhull_options='Pp')
115        p1 = Polygon([hull.points[v] for v in hull.vertices])
116        poly.append(p1)
117        prev_pts = bpts
118
119    u = unary_union(poly)
120
121    curve = io['output.curve(curve_pdf-%s-%s)' % (vname, percent)]
122    if percent == 0:
123        curve['about.label'] = "mean"
124    else:
125        curve['about.label'] = "middle %s%%" % percent
126    curve['about.group'] = label
127    curve['about.uqtype'] = 'Probability'
128    curve['component.xy'] = np.array(u.exterior.xy)
129
130
131def plot_pdf(io, v, pdf, desc):
132    p = io['output.curve(%s)' % desc]
133    p['about.label'] = desc
134    p['about.uqtype'] = "PDF"
135    p['yaxis.label'] = 'Probability'
136
137    pts = "%s 0\n" % pdf.x[0]
138    for x, y in zip(pdf.x, pdf.y):
139        pts += "%s %s\n" % (x, y)
140    pts += "%s 0\n" % pdf.x[-1]
141    p['component.xy'] = pts
142
143
144def write_responses(io, h5):
145    uqtype = h5.attrs['UQtype']
146    for v in h5[uqtype]:
147        if '[' in v:
148            # It is a curve. Ignore.
149            continue
150        try:
151            desc = h5['%s/%s' % (uqtype, v)].attrs['description']
152        except:
153            desc = ''
154        try:
155            label = h5['%s/%s' % (uqtype, v)].attrs['label']
156        except:
157            label = ''
158
159        rsp = h5['/%s/%s/response' % (uqtype, v)].value
160
161        rout = io['output.response(%s)' % label]
162        rout['value'] = rsp
163        rout['about.description'] = desc
164        rout['about.label'] = label
165        rout['about.uqtype'] = 'Response'
166
167        rs = unpickle(rsp)
168        rout['variables'] = ' '.join([str(p.name) for p in rs.params])
169        labels = ' '.join([repr(str(p.label)) for p in rs.params])
170        rout['labels'] = labels.replace("'", '"')
171
172        if type(rs) == puq.response.ResponseFunc:
173            rout['equation'] = rs.eqn
174            rout['rmse'] = "{:6.3g}".format(rs.rmse()[1])
175
176        rout['data'] = rs.data
177
178
179def write_params(h5, out):
180    params = map(str, h5['/input/params'].keys())
181    print('#' * 80, file=out)
182    print('INPUT PARAMETERS', file=out)
183
184    for pname in params:
185        print('-' * 80, file=out)
186        p = puq.unpickle(h5['/input/params/' + pname].value)
187        cname = p.__class__.__name__[:-9]
188        pdf_str = '%s [%s - %s] mean=%s dev=%s mode=%s' % (cname, p.pdf.range[0], p.pdf.range[1], p.pdf.mean, p.pdf.dev, p.pdf.mode)
189
190        print("Name:", p.name, file=out)
191        try:
192            print("Label:", p.label, file=out)
193        except:
194            pass
195        print("Desc:", p.description, file=out)
196        print('Value:', pdf_str, file=out)
197    print('#' * 80, file=out)
198    print(file=out)
199
200
201def write_summary(io, h5):
202    outstr = StringIO.StringIO()
203    write_params(h5, outstr)
204    uqtype = h5.attrs['UQtype']
205    for v in h5[uqtype]:
206        if '[' in v:
207            # It is a curve. Ignore.
208            continue
209        desc = h5['%s/%s' % (uqtype, v)].attrs['description']
210        print("QoI: %s (%s)" % (v, desc), file=outstr)
211        rs = unpickle(h5['/%s/%s/response' % (uqtype, v)].value)
212        if type(rs) == puq.response.ResponseFunc:
213            print("\nv=%s\n" % rs.eqn, file=outstr)
214            print("SURROGATE MODEL ERROR:{:6.3g}%".format(rs.rmse()[1]), file=outstr)
215        sens = puq.unpickle(h5['/%s/%s/sensitivity' % (uqtype, v)].value)
216        max_name_len = max(map(len, [p[0] for p in sens]))
217        print("\nSENSITIVITY:", file=outstr)
218        print("Var%s     u*          dev" % (' '*(max_name_len)), file=outstr)
219        print('-'*(28+max_name_len), file=outstr)
220        for item in sens:
221            pad = ' '*(max_name_len - len(item[0]))
222            print("{}{}  {:10.4g}  {:10.4g}".format(pad, item[0],
223                item[1]['ustar'], item[1]['std']), file=outstr)
224        print('-'*(28+max_name_len), file=outstr)
225        print(file=outstr)
226    iostr = io['output.string(UQ Summary)']
227    iostr['about.label'] = 'UQ Summary'
228    iostr['current'] = outstr.getvalue()
229    outstr.close()
230
231
232def write_sensitivity(io, h5):
233    # If more than one variable, display sensitivity.
234    # Curves have indexed variables, so skip them.
235    if len(h5['/input/params']) > 1 and ['[' in x for x in h5[uqtype]].count(False):
236        for v in h5[uqtype]:
237            if '[' in v:
238                # curve. skip it.
239                continue
240            desc = h5['/output/data/%s' % v].attrs['label']
241            sens = unpickle(h5['/%s/%s/sensitivity' % (uqtype, v)].value)
242
243            hist = io['output.histogram(sens-%s)' % v]
244            hist['about.label'] = desc
245            hist['about.uqtype'] = 'Sensitivity'
246            hist['about.type'] = 'scatter'
247            hist['xaxis.label'] = 'Parameters'
248            hist['yaxis.label'] = 'Sensitivity'
249            pts = ''
250            for name in sens:
251                n = name[0]
252                try:
253                    n = h5['/input/params/%s' % n].attrs['label']
254                except:
255                    pass
256                pts += "\"%s\" %s\n" % (n, name[1]['ustar'])
257            hist['component.xy'] = pts
258
259sw = load_from_hdf5(sys.argv[1])
260sw.analyze()
261
262h5 = h5py.File(sys.argv[1], 'r+')
263io = Rappture.PyXml('run_uq.xml')
264
265# curves built from pdfs
266pcurves = {}
267xvals = {}
268acurves = {}
269
270reg1 = re.compile('([ \da-zA-Z_]+)\[([ \d]+)\]')
271
272uqtype = h5.attrs['UQtype']
273for v in h5[uqtype]:
274    rsp = h5['/%s/%s/response' % (uqtype, v)].value
275    rs = unpickle(rsp)
276    pdf = rs.pdf(fit=False)
277    odata = h5['/output/data/%s' % v]
278
279    # For curves built from pdfs, just put them in a dict for now
280    if 'x' in odata.attrs:
281        matches = reg1.findall(v)
282        vname, vindex = matches[0]
283        vindex = int(vindex)
284        if vname not in pcurves:
285            pcurves[vname] = {}
286            xvals[vname] = {}
287        xvals[vname][vindex] = odata.attrs['x']
288        pcurves[vname][vindex] = pdf
289    elif 'curve' in odata.attrs:
290        matches = reg1.findall(v)
291        vname, vindex = matches[0]
292        print('ACURVE: %s - %s' % (vname, vindex))
293        if vname not in acurves:
294            acurves[vname] = {}
295        acurves[vname][int(vindex)] = pdf
296    else:
297        desc = h5['/output/data/%s' % v].attrs['label']
298        plot_pdf(io, v, pdf, desc)
299
300# now do probability curves
301for vname in xvals:
302    plot_pdf_curve(io, h5, xvals, vname, 95)
303    plot_pdf_curve(io, h5, xvals, vname, 50)
304
305for vname in acurves:
306    try:
307        plot_pdf_acurve(io, h5, acurves, vname, 95)
308    except:
309        pass
310    try:
311        plot_pdf_acurve(io, h5, acurves, vname, 50)
312    except:
313        pass
314
315write_sensitivity(io, h5)
316write_responses(io, h5)
317write_summary(io, h5)
318io.close()
319
320h5.close()
Note: See TracBrowser for help on using the repository browser.