/[escript]/trunk-mpi-branch/escript/py_src/esysXML.py
ViewVC logotype

Annotation of /trunk-mpi-branch/escript/py_src/esysXML.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1306 - (hide annotations)
Tue Sep 18 05:51:09 2007 UTC (12 years ago) by ksteube
File MIME type: text/x-python
File size: 20510 byte(s)
New Copyright in each .c .h .cpp and .py file

1 ksteube 1306 #
2 jgs 122 # $Id$
3 ksteube 1306 #
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 jgs 149 """
18     A simple tool to handle parameters for a simulation in easy way.
19 jgs 122
20 jgs 149 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 jgs 122 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 jgs 149 This structure can be stored/defined through an XML file parm.xml::
39 jgs 122
40 jgs 149 <?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 jgs 122 """
74    
75 elspeth 609 __copyright__=""" Copyright (c) 2006 by ACcESS MNRF
76     http://www.access.edu.au
77     Primary Business: Queensland, Australia"""
78 elspeth 614 __license__="""Licensed under the Open Software License version 3.0
79     http://www.opensource.org/licenses/osl-3.0.php"""
80 elspeth 609
81 jgs 122 import types
82     from xml.dom import minidom
83     from string import atoi,atof
84    
85     class ESySParameters:
86 jgs 149 """
87     Is an object to store simulation parameters in the form of a tree and
88     access their values in an easy form
89 jgs 122
90 jgs 149 Leaves of an ESySParameters object can be:
91 jgs 122
92 jgs 149 - 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 jgs 122
99 jgs 149 Example how to create an ESySParameters object::
100 jgs 122
101 jgs 149 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 jgs 122
119 jgs 149 print parm
120 jgs 122
121 jgs 149 Output is::
122 jgs 122
123 jgs 149 (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 jgs 122
126 jgs 149 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 jgs 122
131 jgs 149 def __init__(self,description="none",type=None):
132     self.setDescription(description)
133     self.setType(type)
134 jgs 122
135 jgs 149 def getTypeName(self):
136 jgs 122 if self.__type==None:
137     return None
138     else:
139     return self.__type.__str__()
140    
141 jgs 149 def getDescription(self):
142 jgs 122 return self.__description
143    
144 jgs 149 def setType(self,type=None):
145 jgs 122 self.__type=type
146    
147 jgs 149 def setDescription(self,description="none"):
148 jgs 122 self.__description=description
149    
150 jgs 149 def __str__(self):
151     """
152     Returns a string representation.
153     """
154 jgs 122 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 jgs 149 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 jgs 122 self.__dict__[name]=value
192    
193 jgs 149 def writeXML(self,iostream):
194     """
195     Writes the object as an XML object into an IO stream.
196     """
197 jgs 122 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 jgs 149 def writeProperties(self, iostream, nameSpace = None):
231     """
232     Writes the object as a property list to an IO stream.
233     """
234 jgs 122 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 jgs 149 def writeESySXML(self,iostream):
253     """
254     Writes an ESyS XML file.
255     """
256 jgs 122 iostream.write("<?xml version=\"1.0\"?><ESyS>")
257     self.writeXML(iostream)
258     iostream.write("</ESyS>")
259    
260     def readESySXMLFile(filename):
261 jgs 149 """
262     Reads an ESyS XML file and returns it as a ESySParameter object.
263     """
264 jgs 122 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 jgs 149 """
290     Returns list where all items in the list have the same type.
291     """
292 jgs 122 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 jgs 149 """
335     Returns the type of the parameters in list values.
336     """
337 jgs 122 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 jgs 149 """
345     Returns the type of the parameter value.
346     """
347 jgs 122 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 jgs 149 """
362     Exracts a string from a DOM node.
363     """
364 jgs 122 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 jgs 149 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 jgs 122
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 jgs 149
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