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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 ksteube 1809
2     ########################################################
3 ksteube 1312 #
4 ksteube 1809 # Copyright (c) 2003-2008 by University of Queensland
5     # Earth Systems Science Computational Center (ESSCC)
6     # http://www.uq.edu.au/esscc
7 ksteube 1312 #
8 ksteube 1809 # 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 ksteube 1312 #
12 ksteube 1809 ########################################################
13 ksteube 1312
14 ksteube 1809 __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 jgs 149 """
23     A simple tool to handle parameters for a simulation in easy way.
24 jgs 122
25 jgs 149 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 jgs 122 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 jgs 149 This structure can be stored/defined through an XML file parm.xml::
44 jgs 122
45 jgs 149 <?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 jgs 122 """
79    
80     import types
81     from xml.dom import minidom
82     from string import atoi,atof
83    
84     class ESySParameters:
85 jgs 149 """
86     Is an object to store simulation parameters in the form of a tree and
87     access their values in an easy form
88 jgs 122
89 jgs 149 Leaves of an ESySParameters object can be:
90 jgs 122
91 jgs 149 - 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 jgs 122
98 jgs 149 Example how to create an ESySParameters object::
99 jgs 122
100 jgs 149 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 jgs 122
118 jgs 149 print parm
119 jgs 122
120 jgs 149 Output is::
121 jgs 122
122 jgs 149 (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 jgs 122
125 jgs 149 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 jgs 122
130 jgs 149 def __init__(self,description="none",type=None):
131     self.setDescription(description)
132     self.setType(type)
133 jgs 122
134 jgs 149 def getTypeName(self):
135 jgs 122 if self.__type==None:
136     return None
137     else:
138     return self.__type.__str__()
139    
140 jgs 149 def getDescription(self):
141 jgs 122 return self.__description
142    
143 jgs 149 def setType(self,type=None):
144 jgs 122 self.__type=type
145    
146 jgs 149 def setDescription(self,description="none"):
147 jgs 122 self.__description=description
148    
149 jgs 149 def __str__(self):
150     """
151     Returns a string representation.
152     """
153 jgs 122 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 jgs 149 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 jgs 122 self.__dict__[name]=value
191    
192 jgs 149 def writeXML(self,iostream):
193     """
194     Writes the object as an XML object into an IO stream.
195     """
196 jgs 122 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 jgs 149 def writeProperties(self, iostream, nameSpace = None):
230     """
231     Writes the object as a property list to an IO stream.
232     """
233 jgs 122 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 jgs 149 def writeESySXML(self,iostream):
252     """
253     Writes an ESyS XML file.
254     """
255 jgs 122 iostream.write("<?xml version=\"1.0\"?><ESyS>")
256     self.writeXML(iostream)
257     iostream.write("</ESyS>")
258    
259     def readESySXMLFile(filename):
260 jgs 149 """
261     Reads an ESyS XML file and returns it as a ESySParameter object.
262     """
263 jgs 122 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 jgs 149 """
289     Returns list where all items in the list have the same type.
290     """
291 jgs 122 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 jgs 149 """
334     Returns the type of the parameters in list values.
335     """
336 jgs 122 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 jgs 149 """
344     Returns the type of the parameter value.
345     """
346 jgs 122 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 jgs 149 """
361     Exracts a string from a DOM node.
362     """
363 jgs 122 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 jgs 149 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 jgs 122
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 jgs 149
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