File: lhsframe.py

package info (click to toggle)
model-builder 0.4.1-5
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 1,056 kB
  • ctags: 621
  • sloc: python: 3,917; fortran: 690; makefile: 18; sh: 11
file content (274 lines) | stat: -rw-r--r-- 10,943 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274

#-----------------------------------------------------------------------------
# Name:        lhsframe.py
# Purpose:     Implementation of the uncertainty panel
#
# Author:      Flavio Codeco Coelho
#
# Created:     2006/08/31
# RCS-ID:      $Id: lhsframe.py $
# Copyright:   (c) 2004
# Licence:     gpl
# New field:   Whatever
#-----------------------------------------------------------------------------
import wxversion
wxversion.select('2.8')
import wx
import os,cPickle
from Bayes import lhs, Melding as meld
from lhsframe_glade import wxFrame
from numpy import *
from pylab import load

class LHS(wxFrame):
    def __init__(self,*args,**kwargs):
        wxFrame.__init__(self,None)
        self.parsAppended = (0,0)
        self.phi = ['a','b','c'] #to be overridden at runtime
        self.theta = [] #to be overridden at runtime
        self.fileName = ''#to be overridden at runtime
        self.specs = {}
        self.priors = [[],[]]#list of distribution names and their parameters
        self.priords = []
        self.lhoods = []
        self.Done = False
        self.distCB.AppendItems(lhs.valid_dists)
        #binding events
        self.button_2.Bind(wx.EVT_BUTTON,self.onOkButton)
        self.setBtn.Bind(wx.EVT_BUTTON,self.onSetButton)
        self.button_3.Bind(wx.EVT_BUTTON,self.onCancelButton)
        self.anaChoice.Bind(wx.EVT_CHOICE,self.onAnaChoice)
        self.alpha = 0.5

    #event handlers
    def onOkButton(self,event):
        """
        Handles the Ok button
        """
        self.specs['samples'] = int(self.sampleSpin.GetValue())
        self.parnames = [k for k,v in self.specs.items() if k not in ['samples','alpha']]

        if self.anaChoice.GetStringSelection() == 'Uncertainty':
            self.alpha = int(self.alphaSlider.GetValue())/100.
            self.specs['alpha'] = self.alpha
            #check if all variables are present in the dictionary.
            if len(self.parnames) != len(self.phi)+len(self.theta):
                dlg = wx.MessageDialog(self, 'You have not defined distribution for All the parameters and variables!',
              'Incomplete Settings', wx.OK | wx.ICON_INFORMATION)
                try:
                    dlg.ShowModal()
                finally:
                    dlg.Destroy()
                    return
        elif self.anaChoice.GetStringSelection() == 'Sensitivity':
            #check if all variables are present in the dictionary.
            if len(self.parnames) != len(self.theta):
                dlg = wx.MessageDialog(self, 'You have not defined distribution for All the parameters!',
              'Incomplete Settings', wx.OK | wx.ICON_INFORMATION)
                try:
                    dlg.ShowModal()
                finally:
                    dlg.Destroy()
                    return
        if self.likTC.GetValue() != '':
            if self.readData(): #if read data fails
                return
        self.genPriorList(self.anaChoice.GetStringSelection())
        self.priords = []
        #check mode of sampling to run
        if self.radio_box_1.GetLabel() == "Random":#Random sampling
            self.priords = lhs.lhs(self.parnames,self.priors[0],self.priors[1],int(self.specs['samples']))
        else:#LHS sampling
            if self.radio_box_2.GetStringSelection() == "User-specified":
                #print"doing 1"
                self.priords = lhs.lhs(self.parnames,self.priors[0],self.priors[1],int(self.specs['samples']),noCorrRestr=False,matCorr=self.getCorrMatrix())
            elif self.radio_box_2.GetStringSelection() == "Random":
                #print"doing 2"
                self.priords = lhs.lhs(self.parnames,self.priors[0],self.priors[1],int(self.specs['samples']),noCorrRestr=False)
            else:
                #print"doing 3"
                self.priords = lhs.lhs(self.parnames,self.priors[0],self.priors[1],int(self.specs['samples']))
        self.saveSpecs()
        self.Done = True
        dlg = wx.MessageDialog(self, 'Now press the "Start" button on the main window!',
          'Start your Simulation', wx.OK | wx.ICON_INFORMATION)
        try:
            dlg.ShowModal()
        finally:
            dlg.Destroy()


        self.Lower()

    def onSetButton(self,event):
        """
        Handles the set parameter button
        """
        if not self.distParsTC.GetValue():
            dlg = wx.MessageDialog(self, 'You have to enter parameters for the distribution selected',
              'No Distribution Parameters', wx.OK | wx.ICON_INFORMATION)
            try:
                dlg.ShowModal()
            finally:
                dlg.Destroy()
            return
        self.specs[self.parsCB.GetStringSelection()] = {'dist':self.distCB.GetStringSelection(),'pars':self.distParsTC.GetValue()}
        line = '%s: %s(%s)\n'%(self.parsCB.GetStringSelection(),self.distCB.GetStringSelection(),self.distParsTC.GetValue())
        self.logTC.AppendText(line)
        self.frame_1_statusbar.SetStatusText('%s set'%self.parsCB.GetStringSelection(),0)

    def genPriorList(self, anatype='Uncertainty'):
        """
        Generates the list of priors in the order expected by the melding
        """
        self.priors = [[],[]]
        npar  = len(self.theta)
        neq = len(self.phi)
        for i in xrange(npar):
            self.priors[0].append(self.specs[self.theta[i]]['dist'])
            self.priors[1].append(tuple([float(n) for n in self.specs[self.theta[i]]['pars'].strip().split(' ')]))
        if anatype == 'Uncertainty':
            for i in xrange(neq):
                self.priors[0].append(self.specs[self.phi[i]]['dist'])
                self.priors[1].append(tuple([float(n) for n in self.specs[self.phi[i]]['pars'].strip().split(' ')]))


    def onCancelButton(self,event):
        """
        Cancel Uncertainty analysis
        """
        self.Done = False
        self.Close()

    def onAnaChoice(self,event):
        """
        Handles change in analysis type
        """
        pars = self.phi
        if self.anaChoice.GetStringSelection() == 'Uncertainty':
            self.likTC.Enable(True)
            self.label_8.Enable(True)
            self.alphalabel.Enable(True)
            self.alphaSlider.Enable(True)
            if not self.parsAppended[0]:
                self.parsCB.AppendItems(pars)
                self.parsAppended = (1,len(pars))
                #print self.parsCB.GetCount()
        else:
            self.likTC.Enable(False)
            self.label_8.Enable(False)
            self.alphalabel.Enable(False)
            self.alphaSlider.Enable(False)
            if self.parsAppended[0]:
                for i in pars:
                    self.parsCB.Delete(self.parsCB.GetCount()-1)
                self.parsCB.SetValue('')
                self.parsAppended = (0,0)
        #print self.anaChoice.GetSelection(),self.anaChoice.GetStringSelection()

    def readData(self):
        """
        Read from data file and build data vectors for likelihoods
        Data file must be a csv with as many columns as data vectors.
        Header should be distribution types.
        """
        os.chdir(os.path.split(self.fileName)[0])
        valid_dists = ['normal','exponential','bernoulli','lognormal','poisson']
        self.lhoods = []
        try:
            fname = self.likTC.GetValue().strip()
            data = load(fname,skiprows=1,delimiter=',')
            f = open(fname)
            likdists = [i.strip() for i in f.readline().split(',')]
            f.close()
        except:
            dlg = wx.MessageDialog(self, 'Could not open File.\nPlease check file name, and press Ok to try again',
              'Invalid File', wx.OK | wx.ICON_INFORMATION)
            try:
                dlg.ShowModal()
            finally:
                dlg.Destroy()
            return 1
        # Check distribution types
        for i in likdists:
            if i not in valid_dists:
                dlg = wx.MessageDialog(self, '"%s" is not a valid model for the data.\nPlease fix your data file, and press Ok to try again'%i,
              'Invalid Model', wx.OK | wx.ICON_INFORMATION)
                try:
                    dlg.ShowModal()
                finally:
                    dlg.Destroy()
                return 1
        #Calculate likelihoods
        n = 0
        for d in transpose(data):
            m = min(d)
            M = max(d)
            dlg = wx.TextEntryDialog(self, 'Enter the limits of the Likelihood function for vector #%s\nseparated by spaces.\nData limits:[%s,%s] '%(n+1,m,M),
                                     'Enter Limits','')
            try:
                if dlg.ShowModal() == wx.ID_OK:
                    answer = dlg.GetValue()
                    if answer == '':
                        dlg = wx.MessageDialog(self, 'You have not entered limits\nAssuming data range.', 'No Limits Entered', wx.OK | wx.ICON_INFORMATION)
                        try:
                            dlg.ShowModal()
                        finally:
                            dlg.Destroy()
                    else:
                        limits = [float(j) for j in answer.strip().split(' ')]
            finally:
                dlg.Destroy()
            self.lhoods.append(meld.Likeli(d,likdists[n],limits))
            n+=1
        return 0

    def saveSpecs(self):
        """
        Saves the current uncertainty specs.
        """
        os.chdir(os.path.split(self.fileName)[0])
        fname = os.path.split(self.fileName)[1]
        fname = fname[:-4]+'_unc.spec'
        f = open(fname,'w')
        cPickle.dump(self.specs,f)
        f.close()

    def loadSpecs(self, fname):
        """
        Load specs from last uncertainty analysis ran from file fname.
        """
        os.chdir(os.path.split(self.fileName)[0])
        f = open(fname,'r')
        self.specs = cPickle.load(f)
        for k,v in self.specs.items():
            if k == 'samples':
                self.sampleSpin.SetValue(int(v))
                continue
            elif k == 'alpha':
                self.alpha = float(v)
                continue
            line = '%s: %s(%s)\n'%(k,v['dist'],v['pars'])
            self.logTC.AppendText(line)
        f.close()
        self.frame_1_statusbar.SetStatusText('Parameter specifications loaded, press OK to continue.')

    def getCorrMatrix(self):
        """
        create a Numeric array with the contents of the spreadsheet
        """
        if self.anaChoice.GetStringSelection() == 'Uncertainty':
            dim = len(self.theta)+len(self.phi)
        else:
            dim = len(self.theta)
        data = zeros((dim,dim),float)
        for i in xrange(dim):
            for j in xrange(dim):
                data[i,j] = float(self.grid_1.GetCellValue(i,j))
        #print data, data.shape, data[0,0]
        return data

if __name__ == '__main__':
    app = wx.PySimpleApp()
    LHS(None).Show()
    app.MainLoop()