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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1809 - (show annotations)
Thu Sep 25 06:43:44 2008 UTC (11 years ago) by ksteube
File MIME type: text/x-python
File size: 20558 byte(s)
Copyright updated in all python files

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