/[escript]/trunk/esys2/escript/py_src/ESySParameters.py
ViewVC logotype

Annotation of /trunk/esys2/escript/py_src/ESySParameters.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 82 - (hide annotations)
Tue Oct 26 06:53:54 2004 UTC (15 years, 11 months ago) by jgs
File MIME type: text/x-python
File size: 18680 byte(s)
Initial revision

1 jgs 82 # $Id$
2     """ A simple tool to handel parameters for a simulation in easy way
3     The idea is that all parameters are stored in a single object in a hierachical form
4     and can accessed using python's attribute notation. For instance:
5    
6     parm.parm2.alpha=814.
7     parm.parm1.gamma=0.
8     parm.parm1.dim=2
9     parm.parm1.tol_v=0.001
10     parm.parm1.output_file="/tmp/u.%3.3d.dx"
11     parm.parm1.runFlag=True
12     parm.parm1.T=1.
13     parm.parm1.x1=[-1.,2]
14     parm.parm1.x2=(10.,11)
15     parm.parm1.x3=(-10.,)
16     parm.parm1.parm11.gamma1=1.
17     parm.parm1.parm11.gamma2=2.
18     parm.parm1.parm11.gamma3=3.
19    
20     This structure can be stored/defined through an XML file parm.xml:
21    
22     <?xml version="1.0"?>
23     <ESyS>
24     <Component type="Geodynamics">
25     <Name>parm1</Name>
26     <Description>
27     a few examples of parameters
28     </Description>
29     <Parameter><Item>gamma</Item><Value>0.</Value></Parameter>
30     <Parameter type="int"><Item>dim</Item><Value>2</Value></Parameter>
31     <Parameter type="real"><Item>tol_v</Item><Value>0.001</Value></Parameter>
32     <Parameter type="string"><Item>output_file</Item><Value>/tmp/u.%3.3d.dx</Value></Parameter>
33     <Parameter type="bool"><Item>runFlag</Item><Value>true</Value></Parameter>
34     <Parameter type="real" sequence="single"><Item>T</Item><Value>1.</Value><Value>2</Value></Parameter>
35     <Parameter type="real" sequence="list"><Item>x1</Item><Value>-1.</Value><Value>2</Value></Parameter>
36     <Parameter type="real" sequence="tuple"><Item>x2</Item><Value>10</Value><Value>11</Value></Parameter>
37     <Parameter sequence="tuple"><Item>x3</Item><Value>-10.</Value></Parameter>
38     <Component>
39     <Name>parm11</Name>
40     <Description>
41     a sub compoment
42     </Description>
43     <Parameter><Item>gamma1</Item><Value>1.</Value></Parameter>
44     <Parameter><Item>gamma2</Item><Value>2.</Value></Parameter>
45     <Parameter><Item>gamma3</Item><Value>3.</Value></Parameter>
46     </Component>
47     </Component>
48     <Component type="Geodynamics">
49     <Name>parm2</Name>
50     <Description>
51     another component
52     </Description>
53     <Parameter><Item>alpha</Item><Value>0814</Value></Parameter>
54     </Component>
55     </ESyS>
56    
57     """
58    
59     import types
60     from xml.dom import minidom
61     from string import atoi,atof
62    
63     class ESySParameters:
64     """is an object to store simulation parameters in the form of a tree and
65     access their values in an easy form
66    
67     Leaves of an ESySParameters objects can be
68    
69     a single real number or a list or tuple of real numbers
70     a single integer number or a list or tuple of integer numbers
71     a single strings or a list or tuple of strings
72     a single boolean value or a list or tuple of boolean values
73     a ESySParameters object
74     any other object (not considered by writeESySXML and writeXML)
75    
76     Example how to create an ESySParameters object:
77    
78     parm=ESySParameters()
79     parm.parm1=ESySParameters()
80     parm.parm1.gamma=0.
81     parm.parm1.dim=2
82     parm.parm1.tol_v=0.001
83     parm.parm1.output_file="/tmp/u.%3.3d.dx"
84     parm.parm1.runFlag=True
85     parm.parm1.T=1.
86     parm.parm1.x1=[-1.,2]
87     parm.parm1.x2=(10.,11)
88     parm.parm1.x3=(-10.,)
89     parm.parm1.parm11=ESySParameters()
90     parm.parm1.parm11.gamma1=1.
91     parm.parm1.parm11.gamma2=2.
92     parm.parm1.parm11.gamma3=3.
93     parm.parm2=ESySParameters()
94     parm.parm2.alpha=814.
95    
96     print parm
97    
98     Output is
99    
100     (parm1=(dim=2,output_file=/tmp/u.%3.3d.dx,parm11=(gamma3=3.0,gamma2=2.0,gamma1=1.0),
101     tol_v=0.001,T=1.0,x2=(10,),x3=(-10,),runFlag=True,x1=[-1.0, 2.0],gamma=0.0),parm2=(alpha=814.0))
102    
103     Notice that parm.parm1.x1 is now a list of two floats although it is defined by a list of a float and an integer.
104     ESySParameter is trying to use the same type for all items in a list or a tuple.
105    
106     """
107    
108     def __init__(self,description="none",type=None):
109     self.setDescription(description)
110     self.setType(type)
111    
112     def getTypeName(self):
113     if self.__type==None:
114     return None
115     else:
116     return self.__type.__str__()
117    
118     def getDescription(self):
119     return self.__description
120    
121     def setType(self,type=None):
122     self.__type=type
123    
124     def setDescription(self,description="none"):
125     self.__description=description
126    
127     def __str__(self):
128     """returns a string representation"""
129     out=""
130     for name,value in self.__dict__.iteritems():
131     if name[0]!="_":
132     if out=="":
133     out=name+"="+str(value)
134     else:
135     out=out+","+name+"="+str(value)
136     return "("+out+")"
137    
138     def __setattr__(self,name,value):
139     """defines attribute name and assigns value. if name does not start
140     with an underscore value has to be a valid Parameter."""
141     name=name.replace(" ","_")
142     if name[0]!="_":
143     if value==None:
144     self.__dict__[name]=value
145     elif isinstance(value,ESySParameters):
146     self.__dict__[name]=value
147     elif isinstance(value,types.BooleanType):
148     self.__dict__[name]=value
149     elif isinstance(value,types.ListType):
150     self.__dict__[name]=_mkSameType(value)
151     elif isinstance(value,types.TupleType):
152     self.__dict__[name]=tuple(_mkSameType(value))
153     elif isinstance(value,types.BooleanType):
154     self.__dict__[name]=value
155     elif isinstance(value,types.IntType):
156     self.__dict__[name]=value
157     elif isinstance(value,types.FloatType):
158     self.__dict__[name]=value
159     elif isinstance(value,types.StringType) or isinstance(value,types.UnicodeType):
160     self.__dict__[name]=str(value)
161     else:
162     self.__dict__[name]=value
163     else:
164     self.__dict__[name]=value
165    
166     def writeXML(self,iostream):
167     """writes the object as an XML object into an IO stream"""
168     for name,value in self.__dict__.iteritems():
169     if name[0]!="_":
170     if isinstance(value,ESySParameters):
171     sequence=_PARAMETER_SEQUENCE_UNKNOWN
172     type=value.getTypeName()
173     iostream.write("<%s"%_COMPONENT)
174     if type!=None: iostream.write("%s=\"%s\""%(_COMPONENT_TYPE_ATTRIBUTE,type))
175     iostream.write(">\n<%s>%s</%s>\n<%s>%s</%s>\n"%(_NAME,name,_NAME,_DESCRIPTION,value.getDescription(),_DESCRIPTION))
176     value.writeXML(iostream)
177     iostream.write("</%s>"%_COMPONENT)
178     else:
179     if isinstance(value,types.ListType):
180     sequence=_PARAMETER_SEQUENCE_LIST
181     type=_getTypeNameOfList(value)
182     elif isinstance(value,types.TupleType):
183     sequence=_PARAMETER_SEQUENCE_TUPLE
184     type=_getTypeNameOfList(value)
185     else:
186     sequence=_PARAMETER_SEQUENCE_SINGLE
187     type=_getTypeName(value)
188     iostream.write("<%s %s=\"%s\" %s=\"%s\"><%s>%s</%s>\n"% \
189     (_PARAMETER,_PARAMETER_TYPE_ATTRIBUTE,type, \
190     _PARAMETER_SEQUENCE_ATTRIBUTE,sequence, \
191     _PARAMETER_ITEM,name,_PARAMETER_ITEM))
192     if type!=_PARAMETER_TYPE_UNKNOWN:
193     if sequence==_PARAMETER_SEQUENCE_LIST or sequence==_PARAMETER_SEQUENCE_TUPLE:
194     for i in value:
195     iostream.write("<%s>%s</%s>"%(_PARAMETER_VALUE,i.__str__(),_PARAMETER_VALUE))
196     elif sequence==_PARAMETER_SEQUENCE_SINGLE:
197     iostream.write("<%s>%s</%s>\n"%(_PARAMETER_VALUE,value.__str__(),_PARAMETER_VALUE))
198     iostream.write("</%s>\n"%_PARAMETER)
199    
200    
201     def writeESySXML(self,iostream):
202     """writes an ESyS XML file"""
203     iostream.write("<?xml version=\"1.0\"?><ESyS>")
204     self.writeXML(iostream)
205     iostream.write("</ESyS>")
206    
207     def readESySXMLFile(filename):
208     """reads an ESyS XML file and returns it as a ESySParameter object"""
209     return _readParametersFromDOM(minidom.parse(filename).getElementsByTagName(_ESYS)[0])
210    
211    
212     _ESYS="ESyS"
213     _COMPONENT="Component"
214     _COMPONENT_TYPE_ATTRIBUTE="type"
215     _NAME="Name"
216     _DESCRIPTION="Description"
217     _PARAMETER="Parameter"
218     _PARAMETER_ITEM="Item"
219     _PARAMETER_VALUE="Value"
220     _PARAMETER_TYPE_ATTRIBUTE="type"
221     _PARAMETER_TYPE_REAL="real"
222     _PARAMETER_TYPE_INT="int"
223     _PARAMETER_TYPE_STRING="string"
224     _PARAMETER_TYPE_BOOL="bool"
225     _PARAMETER_TYPE_UNKNOWN="unknown"
226     _PARAMETER_SEQUENCE_ATTRIBUTE="sequence"
227     _PARAMETER_SEQUENCE_UNKNOWN="unknown"
228     _PARAMETER_SEQUENCE_SINGLE="single"
229     _PARAMETER_SEQUENCE_LIST="list"
230     _PARAMETER_SEQUENCE_TUPLE="tuple"
231    
232    
233     def _mkSameType(list):
234     """returns list where all items in the list have the same type"""
235     out=[]
236     if len(list)>0:
237     type=0
238     for i in list:
239     if isinstance(i,types.BooleanType):
240     type=max(type,0)
241     elif isinstance(i,types.IntType):
242     type=max(type,1)
243     elif isinstance(i,types.FloatType):
244     type=max(type,2)
245     elif isinstance(i,types.StringType):
246     type=max(type,3)
247     else:
248     raise TypeError,"illegal item type"
249    
250     for i in list:
251     if isinstance(i,types.BooleanType):
252     if type==0:
253     out.append(i)
254     elif type==1:
255     out.append(int(i))
256     elif type==2:
257     out.append(float(i))
258     else:
259     out.append(i.__str__())
260     elif isinstance(i,types.IntType):
261     if type==1:
262     out.append(i)
263     elif type==2:
264     out.append(float(i))
265     else:
266     out.append(i.__str__())
267     elif isinstance(i,types.FloatType):
268     if type==2:
269     out.append(i)
270     else:
271     out.append(i.__str__())
272     else:
273     out.append(i)
274     return out
275    
276     def _getTypeNameOfList(values):
277     """returns the type of the parameters in list values"""
278     if len(values)==0:
279     type=_PARAMETER_TYPE_UNKNOWN
280     else:
281     type=_getTypeName(values[0])
282     return type
283    
284     def _getTypeName(value):
285     """returns the type of the parameter value"""
286     if isinstance(value,types.FloatType):
287     type=_PARAMETER_TYPE_REAL
288     elif isinstance(value,types.BooleanType):
289     type=_PARAMETER_TYPE_BOOL
290     elif isinstance(value,types.IntType):
291     type=_PARAMETER_TYPE_INT
292     elif isinstance(value,types.StringType):
293     type=_PARAMETER_TYPE_STRING
294     else:
295     type=_PARAMETER_TYPE_UNKNOWN
296     return type
297    
298    
299     def _extractStrippedValue(dom):
300     """exracts a string from a DOM node"""
301     out=""
302     for i in dom.childNodes:
303     s=i.nodeValue.strip()
304     if s!="\n": out+=s
305     return str(out)
306    
307     def _readParametersFromDOM(dom):
308     out=ESySParameters()
309     for node in dom.childNodes:
310     if node.nodeType==node.ELEMENT_NODE:
311     if node.nodeName==_COMPONENT:
312     name=None
313     description="none"
314     type=None
315     if node.hasAttribute(_COMPONENT_TYPE_ATTRIBUTE): type=node.getAttribute(_COMPONENT_TYPE_ATTRIBUTE)
316     # find description and name:
317     for c_dom in node.childNodes:
318     if c_dom.nodeType==c_dom.ELEMENT_NODE:
319     if c_dom.tagName==_NAME: name=_extractStrippedValue(c_dom)
320     if c_dom.tagName==_DESCRIPTION: description=_extractStrippedValue(c_dom)
321     if name==None:
322     raise IOError,"name of component missing"
323     p=_readParametersFromDOM(node)
324     p.setDescription(description)
325     p.setType(type)
326     out.__setattr__(name,p)
327     elif node.nodeName==_PARAMETER:
328     if node.hasAttribute(_PARAMETER_TYPE_ATTRIBUTE):
329     type=node.getAttribute(_PARAMETER_TYPE_ATTRIBUTE)
330     if type==_PARAMETER_TYPE_UNKNOWN: type=_PARAMETER_TYPE_REAL
331     else:
332     type=_PARAMETER_TYPE_REAL
333     if node.hasAttribute(_PARAMETER_SEQUENCE_ATTRIBUTE):
334     sequence=node.getAttribute(_PARAMETER_SEQUENCE_ATTRIBUTE)
335     if sequence==_PARAMETER_SEQUENCE_UNKNOWN: sequence=_PARAMETER_SEQUENCE_SINGLE
336     else:
337     sequence=_PARAMETER_SEQUENCE_SINGLE
338     # get the name and values as list:
339     name=None
340     p=[]
341     for c_dom in node.childNodes:
342     if c_dom.nodeType==c_dom.ELEMENT_NODE:
343     if c_dom.nodeName==_PARAMETER_ITEM: name=_extractStrippedValue(c_dom)
344     if c_dom.nodeName==_PARAMETER_VALUE:
345     value=_extractStrippedValue(c_dom)
346     if type==_PARAMETER_TYPE_REAL:
347     p.append(atof(value))
348     elif type==_PARAMETER_TYPE_INT:
349     p.append(atoi(value))
350     elif type==_PARAMETER_TYPE_BOOL:
351     if value=="true" or value=="True" or value=="TRUE":
352     p.append(True)
353     elif value=="false" or value=="FALSE" or value=="False":
354     p.append(False)
355     else:
356     raise IOError,"cannot convert %s to bool"%value
357     elif type==_PARAMETER_TYPE_STRING:
358     p.append(value)
359     else:
360     raise IOError,"unknown parameter type %s"%type
361     if name==None: raise IOError,"Item tag missing"
362     if sequence==_PARAMETER_SEQUENCE_SINGLE:
363     if len(p)==0:
364     p=None
365     else:
366     p=p[0]
367     elif sequence==_PARAMETER_SEQUENCE_TUPLE:
368     if len(p)==0:
369     p=tuple()
370     else:
371     p=tuple(p)
372     elif sequence==_PARAMETER_SEQUENCE_LIST:
373     pass
374     else:
375     raise IOError,"unknown sequence attribute %s"%sequence
376     out.__setattr__(name,p)
377     return out
378    
379     # test section:
380     if (__name__=="__main__"):
381     def test(parm):
382     if parm.parm1.gamma!=0. : raise IOError,"unexpected value for parm.parm1.gamma"
383     if parm.parm1.dim!=2: raise IOError,"unexpected value for parm.parm1.dim"
384     if parm.parm1.tol_v!=0.001: raise IOError,"unexpected value for parm.parm1.tol_v"
385     if parm.parm1.output_file!="/tmp/u.%3.3d.dx": raise IOError,"unexpected value for parm.parm1.output_file"
386     if parm.parm1.runFlag!=True: raise IOError,"unexpected value for parm.parm1.runFlag"
387     if parm.parm1.T!=1.: raise IOError,"unexpected value for parm.parm1.T"
388     if parm.parm1.x1[0]!=-1.: raise IOError,"unexpected value for parm.parm1.x1[0]"
389     if parm.parm1.x1[1]!=2.: raise IOError,"unexpected value for parm.parm1.x1[1]"
390     if parm.parm1.x2[0]!=10.: raise IOError,"unexpected value for parm.parm1.x2[0]"
391     if parm.parm1.x2[1]!=11.: raise IOError,"unexpected value for parm.parm1.x2[1]"
392     if parm.parm1.x3[0]!=-10: raise IOError,"unexpected value for parm.parm1.x3[0]"
393     if parm.parm1.parm11.gamma1!=1.: raise IOError,"unexpected value for parm.parm1.parm11.gamma1"
394     if parm.parm1.parm11.gamma2!=2.: raise IOError,"unexpected value for parm.parm1.parm11.gamma2"
395     if parm.parm1.parm11.gamma3!=3.: raise IOError,"unexpected value for parm.parm1.parm11.gamma3"
396     if parm.parm2.alpha!=814.: raise IOError,"unexpected value for parm.parm2.alpha"
397    
398     print "@@@ explicit construction"
399     parm=ESySParameters()
400     parm.parm1=ESySParameters()
401     parm.parm1.gamma=0.
402     parm.parm1.dim=2
403     parm.parm1.tol_v=0.001
404     parm.parm1.output_file="/tmp/u.%3.3d.dx"
405     parm.parm1.runFlag=True
406     parm.parm1.T=1.
407     parm.parm1.x1=[-1.,2]
408     parm.parm1.x2=(10,11.)
409     parm.parm1.x3=(-10.,)
410     parm.parm1.parm11=ESySParameters()
411     parm.parm1.parm11.gamma1=1.
412     parm.parm1.parm11.gamma2=2.
413     parm.parm1.parm11.gamma3=3.
414     parm.parm2=ESySParameters()
415     parm.parm2.alpha=814.
416     print parm
417     test(parm)
418     print "@@@ read and write:"
419     parm.writeESySXML(file("/tmp/test.xml",mode="w"))
420     parm2=readESySXMLFile("/tmp/test.xml")
421     print parm2
422     test(parm2)
423     print "@@@ file"
424     file("/tmp/test2.xml","w").write("""<?xml version="1.0"?>
425     <ESyS>
426     <Component type="Geodynamics">
427     <Name>parm1</Name>
428     <Description>
429     a few examples of parameters
430     </Description>
431     <Parameter><Item>gamma</Item><Value>0.</Value></Parameter>
432     <Parameter type="int"><Item>dim</Item><Value>2</Value></Parameter>
433     <Parameter type="real"><Item>tol_v</Item><Value>0.001</Value></Parameter>
434     <Parameter type="string"><Item>output_file</Item><Value>/tmp/u.%3.3d.dx</Value></Parameter>
435     <Parameter type="bool"><Item>runFlag</Item><Value>true</Value></Parameter>
436     <Parameter type="real" sequence="single"><Item>T</Item><Value>1.</Value><Value>2</Value></Parameter>
437     <Parameter type="real" sequence="list"><Item>x1</Item><Value>-1.</Value><Value>2</Value></Parameter>
438     <Parameter type="real" sequence="tuple"><Item>x2</Item><Value>10</Value><Value>11</Value></Parameter>
439     <Parameter sequence="tuple"><Item>x3</Item><Value>-10</Value></Parameter>
440     <Component>
441     <Name>parm11</Name>
442     <Description>
443     a sub compoment
444     </Description>
445     <Parameter><Item>gamma1</Item><Value>1.</Value></Parameter>
446     <Parameter><Item>gamma2</Item><Value>2.</Value></Parameter>
447     <Parameter><Item>gamma3</Item><Value>3.</Value></Parameter>
448     </Component>
449     </Component>
450     <Component type="Geodynamics">
451     <Name>parm2</Name>
452     <Description>
453     another component
454     </Description>
455     <Parameter><Item>alpha</Item><Value>0814</Value></Parameter>
456     </Component>
457     </ESyS>
458     """)
459     parm3=readESySXMLFile("/tmp/test2.xml")
460     print parm3
461     test(parm3)

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.26