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