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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 # $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