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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 122 - (hide annotations)
Thu Jun 9 05:38:05 2005 UTC (14 years, 4 months ago) by jgs
File MIME type: text/x-python
File size: 19634 byte(s)
Merge of development branch back to main trunk on 2005-06-09

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

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.26