source: branches/uq/puq/puq_analyze.py @ 5182

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

lots of uq cleanup and enhancements

  • Property svn:executable set to *
File size: 13.7 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"""
6import sys
7import os
8import numpy as np
9import h5py
10import re
11from puq.jpickle import unpickle
12import xml.etree.ElementTree as xml
13from itertools import product, combinations
14
15# Redirect stdout and stderr to files for debugging.
16# Append to the files created in get_params.py
17sys.stdout = open("uq_debug.out", 'a')
18sys.stderr = open("uq_debug.err", 'a')
19
20
21# Restore the state of a PUQ session from a HDF5 file.
22def load_from_hdf5(name):
23    h5 = h5py.File(name, 'r+')
24    sw = unpickle(h5['private/sweep'].value)
25    sw.fname = os.path.splitext(name)[0]
26    h5.close()
27
28    sw.psweep._sweep = sw
29
30    if hasattr(sw.psweep, 'reinit'):
31        sw.psweep.reinit()
32    return sw
33
34
35# variable names to labels
36def subs_names(varl, h5):
37    varlist = []
38    for v in varl:
39        try:
40            lab = h5['/input/params/%s' % v[0]].attrs['label']
41        except:
42            lab = str(v[0])
43        varlist.append(lab)
44    return varlist
45
46
47def plot_resp1(io, resp, name, h5):
48    print 'plot_resp1', name
49    varlist = subs_names(resp.vars, h5)
50    try:
51        tname = h5['/output/data/%s' % name].attrs['description']
52    except:
53        tname = name
54    ydata = h5['/output/data/%s' % name].value
55    xdata = h5['/input/param_array'].value.T[0]
56
57    title = '%s (Response)' % (tname)
58    curve = 'output.curve(response-%s)' % name
59    io.put(curve + '.about.label', title)
60    io.put(curve + '.about.group', title)
61    io.put(curve + '.xaxis.label', varlist[0])
62    io.put(curve + '.yaxis.label', tname)
63    x = np.linspace(*resp.vars[0][1], num=50)
64    y = np.array(resp.eval(x))
65    for a, b in zip(x, y):
66        io.put(curve + '.component.xy', "%s %s\n" % (a, b), append=1)
67
68    # scatter plot sampled data on response surface
69    curve = 'output.curve(response-%s-scatter)' % name
70    io.put(curve + '.about.label', 'Data Points')
71    io.put(curve + '.about.group', title)
72    io.put(curve + '.about.type', 'scatter')
73    io.put(curve + '.xaxis.label', varlist[0])
74    io.put(curve + '.yaxis.label', tname)
75    for a, b in zip(xdata, ydata):
76        io.put(curve + '.component.xy', "%s %s\n" % (a, b), append=1)
77
78
79def plot_resp2(io, resp, name, varl, h5):
80    numpoints = 50
81    m2d = 'output.mesh('+varl[0][0]+varl[1][0]+')'
82    io.put(m2d+'.about.label', '2D Mesh')
83    io.put(m2d+'.dim', '2')
84    io.put(m2d+'.hide', 'yes')
85    io.put(m2d+'.grid.xaxis.numpoints', '%s' % numpoints)
86    io.put(m2d+'.grid.yaxis.numpoints', '%s' % numpoints)
87    io.put(m2d+'.grid.xaxis.min', '%g' % (varl[0][1][0]))
88    io.put(m2d+'.grid.xaxis.max', '%g' % (varl[0][1][1]))
89    io.put(m2d+'.grid.yaxis.min', '%g' % (varl[1][1][0]))
90    io.put(m2d+'.grid.yaxis.max', '%g' % (varl[1][1][1]))
91
92    varlist = subs_names(varl, h5)
93    fname = 'output.field(response-'+name+varlist[0]+varlist[1]+')'
94    io.put(fname + '.about.xaxis.label', varlist[0])
95    io.put(fname + '.about.yaxis.label', varlist[1])
96    try:
97        tname = h5['/output/data/%s' % name].attrs['description']
98    except:
99        tname = name
100    title = tname + ' (Response %s)' % ' vs '.join(varlist)
101    io.put(fname + '.about.label', title)
102    io.put(fname + '.component.mesh', m2d)
103    io.put(fname + '.about.view', 'heightmap')
104    x = np.linspace(*varl[0][1], num=numpoints)
105    y = np.linspace(*varl[1][1], num=numpoints)
106    pts = np.array([(b, a) for a, b in product(y, x)])
107    allpts = np.empty((numpoints**2, len(resp.vars)))
108    for i, v in enumerate(resp.vars):
109        if v[0] == varl[0][0]:
110            allpts[:, i] = pts[:, 0]
111        elif v[0] == varl[1][0]:
112            allpts[:, i] = pts[:, 1]
113        else:
114            allpts[:, i] = np.mean(v[1])
115    pts = np.array(resp.evala(allpts))
116    for z in pts:
117        io.put(fname + '.component.values', '%g\n' % z, append=1)
118
119
120def plot_resp3(io, resp, name, varl, h5):
121    numpoints = 40
122    m3d = 'output.mesh(m3d)'
123    io.put(m3d+'.about.label', '3D Mesh')
124    io.put(m3d+'.dim', '3')
125    io.put(m3d+'.hide', 'yes')
126    io.put(m3d+'.grid.xaxis.numpoints', '%s' % numpoints)
127    io.put(m3d+'.grid.yaxis.numpoints', '%s' % numpoints)
128    io.put(m3d+'.grid.zaxis.numpoints', '%s' % numpoints)
129
130    # for now, scale to [0,1]
131    io.put(m3d+'.grid.xaxis.min', '0')
132    io.put(m3d+'.grid.xaxis.max', '1')
133    io.put(m3d+'.grid.yaxis.min', '0')
134    io.put(m3d+'.grid.yaxis.max', '1')
135    io.put(m3d+'.grid.zaxis.min', '0')
136    io.put(m3d+'.grid.zaxis.max', '1')
137
138    varlist = subs_names(varl, h5)
139    try:
140        tname = h5['/output/data/%s' % name].attrs['description']
141    except:
142        tname = name
143    fname = 'output.field(response-'+name+varlist[0]+varlist[1]+varlist[2]+')'
144    io.put(fname + '.about.xaxis.label',
145                   '{%s [%.3g - %.3g]}' %
146                   (varlist[0], varl[0][1][0], varl[0][1][1]))
147    io.put(fname + '.about.yaxis.label',
148                   '{%s [%.3g - %.3g]}' %
149                   (varlist[1], varl[1][1][0], varl[1][1][1]))
150    io.put(fname + '.about.zaxis.label',
151                   '{%s [%.3g - %.3g]}' %
152                   (varlist[2], varl[2][1][0], varl[2][1][1]))
153    title = tname + ' (Response %s)' % ' vs '.join(varlist)
154    io.put(fname + '.about.label', title)
155    io.put(fname + '.component.mesh', m3d)
156    io.put(fname + '.about.description', '3D Field Description')
157    io.put(fname + '.about.view', 'vtkvolume')
158    x = np.linspace(*varl[0][1], num=numpoints)
159    y = np.linspace(*varl[1][1], num=numpoints)
160    z = np.linspace(*varl[2][1], num=numpoints)
161
162    # generate points in the right order, with x changing fastest
163    pts = np.array([(c, b, a) for a, b, c in product(z, y, x)])
164    allpts = np.empty((numpoints**3, len(resp.vars)))
165    for i, v in enumerate(resp.vars):
166        if v[0] == varl[0][0]:
167            allpts[:, i] = pts[:, 0]
168        elif v[0] == varl[1][0]:
169            allpts[:, i] = pts[:, 1]
170        elif v[0] == varl[2][0]:
171            allpts[:, i] = pts[:, 2]
172        else:
173            allpts[:, i] = np.mean(v[1])
174    pts = np.array(resp.evala(allpts))
175    for z in pts:
176        io.put(fname + '.component.values', '%g\n' % z, append=1)
177
178
179def plot_resp(io, resp, name, h5):
180    if resp is not None:
181        if len(resp.vars) == 1:
182            plot_resp1(io, resp, name, h5)
183            return
184        if len(resp.vars) >= 3:
185            for v1, v2, v3 in combinations(resp.vars, 3):
186                plot_resp3(io, resp, name, [v1, v2, v3], h5)
187
188        # plot all combinations of 2 variables
189        for v1, v2 in combinations(resp.vars, 2):
190            plot_resp2(io, resp, name, [v1, v2], h5)
191
192
193# Plots probability curves
194def plot_pdf_curve(xvals, vname, percent, desc):
195    print 'plot_pdf_curve %s %s %s' % (vname, percent, desc)
196    # compute upper and lower percentiles
197    pm = (100 - percent)/200.0
198    pp = 1 - pm
199
200    # collect data into an array
201    xarr = np.empty(len(xvals[vname]))
202    yp = np.empty(len(xvals[vname]))
203    ym = np.empty(len(xvals[vname]))
204    for vindex in sorted(xvals[vname].keys()):
205        xarr[vindex] = xvals[vname][vindex]
206        yp[vindex] = pcurves[vname][vindex].ppf(pp)
207        ym[vindex] = pcurves[vname][vindex].ppf(pm)
208
209    curve = xml.SubElement(dout, 'curve', {'id': 'curve_pdf-%s-%s' % (vname, percent)})
210    about = xml.SubElement(curve, 'about')
211    if percent == 0:
212        xml.SubElement(about, 'label').text = "mean"
213    else:
214        xml.SubElement(about, 'label').text = "middle %s%%" % percent
215    xml.SubElement(about, 'group').text = '%s (Probability)' % desc
216    comp = xml.SubElement(curve, 'component')
217    xy = xml.SubElement(comp, 'xy')
218    pts = ""
219    for x, y in zip(xarr, yp):
220        pts += "%s %s " % (x, y)
221    if percent == 0:
222        pts += '\n'
223    else:
224        for x, y in reversed(zip(xarr, ym)):
225            pts += "%s %s " % (x, y)
226        pts += "%s %s\n" % (xarr[0], yp[0])
227    xy.text = pts
228
229
230def dist(x1, y1, x2, y2, x3, y3): # x3,y3 is the point
231    diffx = x2-x1
232    diffy = y2-y1
233    sqdiff = float(diffx**2 + diffy**2)
234
235    u = ((x3 - x1) * diffx + (y3 - y1) * diffy) / sqdiff
236
237    if u > 1:
238        u = 1
239    elif u < 0:
240        u = 0
241
242    x = x1 + u * diffx
243    y = y1 + u * diffy
244
245    dx = x - x3
246    dy = y - y3
247
248    return np.sqrt(dx*dx + dy*dy)
249
250
251# Plots advanced probability curves
252def plot_pdf_acurve(hf, acurves, vname, percent, desc):
253    print 'plot_pdf_acurve %s %s %s' % (vname, percent, desc)
254    # compute upper and lower percentiles
255    pm = (100 - percent)/200.0
256    pp = 1 - pm
257    vlen = len(acurves[vname])
258
259    print 'vlen=', vlen
260    # collect data into an array
261    xp = np.empty(vlen)
262    xm = np.empty(vlen)
263    yp = np.empty(vlen)
264    ym = np.empty(vlen)
265
266    for vindex in sorted(acurves[vname].keys()):
267        print 'vindex=', vindex
268        x1 = acurves[vname][vindex][0].ppf(pp)
269        x2 = acurves[vname][vindex][0].ppf(pm)
270        y1 = acurves[vname][vindex][1].ppf(pp)
271        y2 = acurves[vname][vindex][1].ppf(pm)
272        xd = hf['/output/data/%s.x[%d]' % (vname, int(vindex))].value
273        yd = hf['/output/data/%s.y[%d]' % (vname, int(vindex))].value
274        #p1, p2 = get_closest2()
275        if int(vindex) == 2:
276            print x1, x2, y1, y2
277            print 'xd=', repr(xd)
278            print 'yd=', repr(yd)
279
280        #xp[vindex] = x1
281        #xm[vindex] = x2
282        #yp[vindex] = y1
283        #ym[vindex] = y2
284    return
285    curve = xml.SubElement(dout, 'curve', {'id': 'curve_pdf-%s-%s' % (vname, percent)})
286    about = xml.SubElement(curve, 'about')
287    if percent == 0:
288        xml.SubElement(about, 'label').text = "mean"
289    else:
290        xml.SubElement(about, 'label').text = "middle %s%%" % percent
291    xml.SubElement(about, 'group').text = '%s (Probability)' % desc
292    comp = xml.SubElement(curve, 'component')
293    xy = xml.SubElement(comp, 'xy')
294    pts = ""
295    for x, y in zip(xarr, yp):
296        pts += "%s %s " % (x, y)
297    if percent == 0:
298        pts += '\n'
299    else:
300        for x, y in reversed(zip(xarr, ym)):
301            pts += "%s %s " % (x, y)
302        pts += "%s %s\n" % (xarr[0], yp[0])
303    xy.text = pts
304
305
306def plot_pdf(v, pdf, desc):
307    id = '%s (PDF)' % desc
308    elem = xml.SubElement(dout, 'curve', {'id': id})
309    about = xml.SubElement(elem, 'about')
310    xml.SubElement(about, 'label').text = id
311    yaxis = xml.SubElement(elem, 'yaxis')
312    xml.SubElement(yaxis, 'label').text = 'Probability'
313
314    component = xml.SubElement(elem, 'component')
315    xy = xml.SubElement(component, 'xy')
316    pts = "%s 0\n" % pdf.x[0]
317    for x, y in zip(pdf.x, pdf.y):
318        pts += "%s %s\n" % (x, y)
319    pts += "%s 0\n" % pdf.x[-1]
320    xy.text = pts
321
322
323sw = load_from_hdf5(sys.argv[1])
324sw.analyze()
325
326h5 = h5py.File(sys.argv[1], 'r+')
327dtree = xml.parse('run_uq.xml')
328droot = dtree.getroot()
329dout = droot.find('output')
330
331# curves built from pdfs
332pcurves = {}
333xvals = {}
334acurves = {}
335
336reg1 = re.compile('([ \da-zA-Z]+)\[([ \d]+)\]')
337reg2 = re.compile('([ \da-zA-Z]+)\.([xy])\[([ \d]+)\]')
338
339uqtype = h5.attrs['UQtype']
340for v in h5[uqtype]:
341    rs = unpickle(h5['/%s/%s/response' % (uqtype, v)].value)
342    pdf = rs.pdf(fit=False)
343    odata = h5['/output/data/%s' % v]
344
345    # For curves built from pdfs, just put them in a dict for now
346    if 'x' in odata.attrs:
347        matches = reg1.findall(v)
348        vname, vindex = matches[0]
349        vindex = int(vindex)
350        if vname not in pcurves:
351            pcurves[vname] = {}
352            xvals[vname] = {}
353        xvals[vname][vindex] = odata.attrs['x']
354        pcurves[vname][vindex] = pdf
355    elif reg2.findall(v) != []:
356        matches = reg2.findall(v)
357        vname, xy, vindex = matches[0]
358        if vname not in acurves:
359            acurves[vname] = {}
360        if vindex not in acurves[vname]:
361            acurves[vname][vindex] = {}
362        if xy == 'x':
363            acurves[vname][vindex][0] = pdf
364        else:
365            acurves[vname][vindex][1] = pdf
366    else:
367        desc = h5['/output/data/%s' % v].attrs['description']
368        plot_pdf(v, pdf, desc)
369
370# now do pdf curves
371for vname in xvals:
372    desc = h5['/output/data/%s[0]' % vname].attrs['description']
373    plot_pdf_curve(xvals, vname, 0, desc)
374    plot_pdf_curve(xvals, vname, 50, desc)
375    plot_pdf_curve(xvals, vname, 95, desc)
376
377# for vname in acurves:
378#    desc = h5['/output/data/%s.x[0]' % vname].attrs['description']
379#    plot_pdf_acurve(h5, acurves, vname, 0, desc)
380#    plot_pdf_acurve(h5, acurves, vname, 50, desc)
381#    plot_pdf_acurve(h5, acurves, vname, 95, desc)
382
383
384# If more than one variable, display sensitivity.
385# Curves have indexed variables, so skip them.
386if len(h5['/input/params']) > 1 and ['[' in x for x in h5[uqtype]].count(False):
387    for v in h5[uqtype]:
388        if '[' in v:
389            continue
390        desc = h5['/output/data/%s' % v].attrs['description']
391        sens = unpickle(h5['/%s/%s/sensitivity' % (uqtype, v)].value)
392        elem = xml.SubElement(dout, 'histogram', {'id': 'sens-%s' % v})
393        about = xml.SubElement(elem, 'about')
394        xml.SubElement(about, 'label').text = '%s (Sensitivity)' % desc
395        xml.SubElement(elem, 'type').text = 'scatter'
396        xaxis = xml.SubElement(elem, 'xaxis')
397        xml.SubElement(xaxis, 'label').text = 'Parameters'
398        yaxis = xml.SubElement(elem, 'yaxis')
399        xml.SubElement(yaxis, 'label').text = 'Sensitivity'
400        comp = xml.SubElement(elem, 'component')
401        xy = xml.SubElement(comp, 'xy')
402        pts = ''
403        for name in sens:
404            n = name[0]
405            try:
406                n = h5['/input/params/%s' % n].attrs['label']
407            except:
408                pass
409            pts += "\"%s\" %s\n" % (n, name[1]['ustar'])
410        xy.text = pts
411
412with open('run_uq.xml', 'w') as f:
413    f.write("<?xml version=\"1.0\"?>\n")
414    dtree.write(f)
415
416
417import Rappture
418io = Rappture.library('run_uq.xml')
419
420for v in h5[uqtype]:
421    if '[' in v:
422        continue
423    rs = unpickle(h5['/%s/%s/response' % (uqtype, v)].value)
424    print 'Plotting response', v
425    plot_resp(io, rs, v, h5)
426
427Rappture.result(io)
428
429h5.close()
Note: See TracBrowser for help on using the repository browser.