/[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 149 - (show annotations)
Thu Sep 1 03:31:39 2005 UTC (14 years, 1 month ago) by jgs
File MIME type: text/x-python
File size: 19800 byte(s)
Merge of development branch dev-02 back to main trunk on 2005-09-01

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

Properties

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

  ViewVC Help
Powered by ViewVC 1.1.26