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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 122 - (show annotations)
Thu Jun 9 05:38:05 2005 UTC (14 years, 4 months ago) by jgs
File MIME type: text/x-python
File size: 19634 byte(s)
Merge of development branch back to main trunk on 2005-06-09

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 writeProperties(self, iostream, nameSpace = None):
202 """writes the object as a property list to an IO stream"""
203 if nameSpace != None and nameSpace != "":
204 nameSpace += ".";
205 for name,value in self.__dict__.iteritems():
206 if name[0]!="_":
207 if isinstance(value,ESySParameters):
208 value.writeProperties(iostream, name)
209 else:
210 if isinstance(value,types.ListType):
211 sequence=_PARAMETER_SEQUENCE_LIST
212 type=_getTypeNameOfList(value)
213 elif isinstance(value,types.TupleType):
214 sequence=_PARAMETER_SEQUENCE_TUPLE
215 type=_getTypeNameOfList(value)
216 else:
217 sequence=_PARAMETER_SEQUENCE_SINGLE
218 type=_getTypeName(value)
219 iostream.write("%s = %s\n" % (nameSpace + name, value.__str__()))
220
221 def writeESySXML(self,iostream):
222 """writes an ESyS XML file"""
223 iostream.write("<?xml version=\"1.0\"?><ESyS>")
224 self.writeXML(iostream)
225 iostream.write("</ESyS>")
226
227 def readESySXMLFile(filename):
228 """reads an ESyS XML file and returns it as a ESySParameter object"""
229 return _readParametersFromDOM(minidom.parse(filename).getElementsByTagName(_ESYS)[0])
230
231
232 _ESYS="ESyS"
233 _COMPONENT="Component"
234 _COMPONENT_TYPE_ATTRIBUTE="type"
235 _NAME="Name"
236 _DESCRIPTION="Description"
237 _PARAMETER="Parameter"
238 _PARAMETER_ITEM="Item"
239 _PARAMETER_VALUE="Value"
240 _PARAMETER_TYPE_ATTRIBUTE="type"
241 _PARAMETER_TYPE_REAL="real"
242 _PARAMETER_TYPE_INT="int"
243 _PARAMETER_TYPE_STRING="string"
244 _PARAMETER_TYPE_BOOL="bool"
245 _PARAMETER_TYPE_UNKNOWN="unknown"
246 _PARAMETER_SEQUENCE_ATTRIBUTE="sequence"
247 _PARAMETER_SEQUENCE_UNKNOWN="unknown"
248 _PARAMETER_SEQUENCE_SINGLE="single"
249 _PARAMETER_SEQUENCE_LIST="list"
250 _PARAMETER_SEQUENCE_TUPLE="tuple"
251
252
253 def _mkSameType(list):
254 """returns list where all items in the list have the same type"""
255 out=[]
256 if len(list)>0:
257 type=0
258 for i in list:
259 if isinstance(i,types.BooleanType):
260 type=max(type,0)
261 elif isinstance(i,types.IntType):
262 type=max(type,1)
263 elif isinstance(i,types.FloatType):
264 type=max(type,2)
265 elif isinstance(i,types.StringType):
266 type=max(type,3)
267 else:
268 raise TypeError,"illegal item type"
269
270 for i in list:
271 if isinstance(i,types.BooleanType):
272 if type==0:
273 out.append(i)
274 elif type==1:
275 out.append(int(i))
276 elif type==2:
277 out.append(float(i))
278 else:
279 out.append(i.__str__())
280 elif isinstance(i,types.IntType):
281 if type==1:
282 out.append(i)
283 elif type==2:
284 out.append(float(i))
285 else:
286 out.append(i.__str__())
287 elif isinstance(i,types.FloatType):
288 if type==2:
289 out.append(i)
290 else:
291 out.append(i.__str__())
292 else:
293 out.append(i)
294 return out
295
296 def _getTypeNameOfList(values):
297 """returns the type of the parameters in list values"""
298 if len(values)==0:
299 type=_PARAMETER_TYPE_UNKNOWN
300 else:
301 type=_getTypeName(values[0])
302 return type
303
304 def _getTypeName(value):
305 """returns the type of the parameter value"""
306 if isinstance(value,types.FloatType):
307 type=_PARAMETER_TYPE_REAL
308 elif isinstance(value,types.BooleanType):
309 type=_PARAMETER_TYPE_BOOL
310 elif isinstance(value,types.IntType):
311 type=_PARAMETER_TYPE_INT
312 elif isinstance(value,types.StringType):
313 type=_PARAMETER_TYPE_STRING
314 else:
315 type=_PARAMETER_TYPE_UNKNOWN
316 return type
317
318
319 def _extractStrippedValue(dom):
320 """exracts a string from a DOM node"""
321 out=""
322 for i in dom.childNodes:
323 s=i.nodeValue.strip()
324 if s!="\n": out+=s
325 return str(out)
326
327 def _readParametersFromDOM(dom):
328 out=ESySParameters()
329 for node in dom.childNodes:
330 if node.nodeType==node.ELEMENT_NODE:
331 if node.nodeName==_COMPONENT:
332 name=None
333 description="none"
334 type=None
335 if node.hasAttribute(_COMPONENT_TYPE_ATTRIBUTE): type=node.getAttribute(_COMPONENT_TYPE_ATTRIBUTE)
336 # find description and name:
337 for c_dom in node.childNodes:
338 if c_dom.nodeType==c_dom.ELEMENT_NODE:
339 if c_dom.tagName==_NAME: name=_extractStrippedValue(c_dom)
340 if c_dom.tagName==_DESCRIPTION: description=_extractStrippedValue(c_dom)
341 if name==None:
342 raise IOError,"name of component missing"
343 p=_readParametersFromDOM(node)
344 p.setDescription(description)
345 p.setType(type)
346 out.__setattr__(name,p)
347 elif node.nodeName==_PARAMETER:
348 if node.hasAttribute(_PARAMETER_TYPE_ATTRIBUTE):
349 type=node.getAttribute(_PARAMETER_TYPE_ATTRIBUTE)
350 if type==_PARAMETER_TYPE_UNKNOWN: type=_PARAMETER_TYPE_REAL
351 else:
352 type=_PARAMETER_TYPE_REAL
353 if node.hasAttribute(_PARAMETER_SEQUENCE_ATTRIBUTE):
354 sequence=node.getAttribute(_PARAMETER_SEQUENCE_ATTRIBUTE)
355 if sequence==_PARAMETER_SEQUENCE_UNKNOWN: sequence=_PARAMETER_SEQUENCE_SINGLE
356 else:
357 sequence=_PARAMETER_SEQUENCE_SINGLE
358 # get the name and values as list:
359 name=None
360 p=[]
361 for c_dom in node.childNodes:
362 if c_dom.nodeType==c_dom.ELEMENT_NODE:
363 if c_dom.nodeName==_PARAMETER_ITEM: name=_extractStrippedValue(c_dom)
364 if c_dom.nodeName==_PARAMETER_VALUE:
365 value=_extractStrippedValue(c_dom)
366 if type==_PARAMETER_TYPE_REAL:
367 p.append(atof(value))
368 elif type==_PARAMETER_TYPE_INT:
369 p.append(atoi(value))
370 elif type==_PARAMETER_TYPE_BOOL:
371 if value=="true" or value=="True" or value=="TRUE":
372 p.append(True)
373 elif value=="false" or value=="FALSE" or value=="False":
374 p.append(False)
375 else:
376 raise IOError,"cannot convert %s to bool"%value
377 elif type==_PARAMETER_TYPE_STRING:
378 p.append(value)
379 else:
380 raise IOError,"unknown parameter type %s"%type
381 if name==None: raise IOError,"Item tag missing"
382 if sequence==_PARAMETER_SEQUENCE_SINGLE:
383 if len(p)==0:
384 p=None
385 else:
386 p=p[0]
387 elif sequence==_PARAMETER_SEQUENCE_TUPLE:
388 if len(p)==0:
389 p=tuple()
390 else:
391 p=tuple(p)
392 elif sequence==_PARAMETER_SEQUENCE_LIST:
393 pass
394 else:
395 raise IOError,"unknown sequence attribute %s"%sequence
396 out.__setattr__(name,p)
397 return out
398
399 # test section:
400 if (__name__=="__main__"):
401 def test(parm):
402 if parm.parm1.gamma!=0. : raise IOError,"unexpected value for parm.parm1.gamma"
403 if parm.parm1.dim!=2: raise IOError,"unexpected value for parm.parm1.dim"
404 if parm.parm1.tol_v!=0.001: raise IOError,"unexpected value for parm.parm1.tol_v"
405 if parm.parm1.output_file!="/tmp/u.%3.3d.dx": raise IOError,"unexpected value for parm.parm1.output_file"
406 if parm.parm1.runFlag!=True: raise IOError,"unexpected value for parm.parm1.runFlag"
407 if parm.parm1.T!=1.: raise IOError,"unexpected value for parm.parm1.T"
408 if parm.parm1.x1[0]!=-1.: raise IOError,"unexpected value for parm.parm1.x1[0]"
409 if parm.parm1.x1[1]!=2.: raise IOError,"unexpected value for parm.parm1.x1[1]"
410 if parm.parm1.x2[0]!=10.: raise IOError,"unexpected value for parm.parm1.x2[0]"
411 if parm.parm1.x2[1]!=11.: raise IOError,"unexpected value for parm.parm1.x2[1]"
412 if parm.parm1.x3[0]!=-10: raise IOError,"unexpected value for parm.parm1.x3[0]"
413 if parm.parm1.parm11.gamma1!=1.: raise IOError,"unexpected value for parm.parm1.parm11.gamma1"
414 if parm.parm1.parm11.gamma2!=2.: raise IOError,"unexpected value for parm.parm1.parm11.gamma2"
415 if parm.parm1.parm11.gamma3!=3.: raise IOError,"unexpected value for parm.parm1.parm11.gamma3"
416 if parm.parm2.alpha!=814.: raise IOError,"unexpected value for parm.parm2.alpha"
417
418 print "@@@ explicit construction"
419 parm=ESySParameters()
420 parm.parm1=ESySParameters()
421 parm.parm1.gamma=0.
422 parm.parm1.dim=2
423 parm.parm1.tol_v=0.001
424 parm.parm1.output_file="/tmp/u.%3.3d.dx"
425 parm.parm1.runFlag=True
426 parm.parm1.T=1.
427 parm.parm1.x1=[-1.,2]
428 parm.parm1.x2=(10,11.)
429 parm.parm1.x3=(-10.,)
430 parm.parm1.parm11=ESySParameters()
431 parm.parm1.parm11.gamma1=1.
432 parm.parm1.parm11.gamma2=2.
433 parm.parm1.parm11.gamma3=3.
434 parm.parm2=ESySParameters()
435 parm.parm2.alpha=814.
436 print parm
437 test(parm)
438 print "@@@ read and write:"
439 parm.writeESySXML(file("/tmp/test.xml",mode="w"))
440 parm.writeProperties(file("/tmp/test.dat",mode="w"))
441 parm2=readESySXMLFile("/tmp/test.xml")
442 print parm2
443 test(parm2)
444 print "@@@ file"
445 file("/tmp/test2.xml","w").write("""<?xml version="1.0"?>
446 <ESyS>
447 <Component type="Geodynamics">
448 <Name>parm1</Name>
449 <Description>
450 a few examples of parameters
451 </Description>
452 <Parameter><Item>gamma</Item><Value>0.</Value></Parameter>
453 <Parameter type="int"><Item>dim</Item><Value>2</Value></Parameter>
454 <Parameter type="real"><Item>tol_v</Item><Value>0.001</Value></Parameter>
455 <Parameter type="string"><Item>output_file</Item><Value>/tmp/u.%3.3d.dx</Value></Parameter>
456 <Parameter type="bool"><Item>runFlag</Item><Value>true</Value></Parameter>
457 <Parameter type="real" sequence="single"><Item>T</Item><Value>1.</Value><Value>2</Value></Parameter>
458 <Parameter type="real" sequence="list"><Item>x1</Item><Value>-1.</Value><Value>2</Value></Parameter>
459 <Parameter type="real" sequence="tuple"><Item>x2</Item><Value>10</Value><Value>11</Value></Parameter>
460 <Parameter sequence="tuple"><Item>x3</Item><Value>-10</Value></Parameter>
461 <Component>
462 <Name>parm11</Name>
463 <Description>
464 a sub compoment
465 </Description>
466 <Parameter><Item>gamma1</Item><Value>1.</Value></Parameter>
467 <Parameter><Item>gamma2</Item><Value>2.</Value></Parameter>
468 <Parameter><Item>gamma3</Item><Value>3.</Value></Parameter>
469 </Component>
470 </Component>
471 <Component type="Geodynamics">
472 <Name>parm2</Name>
473 <Description>
474 another component
475 </Description>
476 <Parameter><Item>alpha</Item><Value>0814</Value></Parameter>
477 </Component>
478 </ESyS>
479 """)
480 parm3=readESySXMLFile("/tmp/test2.xml")
481 print parm3
482 test(parm3)

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26