/[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 609 - (hide annotations)
Tue Mar 21 09:46:39 2006 UTC (13 years, 7 months ago) by elspeth
File MIME type: text/x-python
File size: 20089 byte(s)
Updated copyright and licence notices.

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