/[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 155 - (hide annotations)
Wed Nov 9 02:02:19 2005 UTC (13 years, 11 months ago) by jgs
File MIME type: text/x-python
File size: 19800 byte(s)
move all directories from trunk/esys2 into trunk and remove esys2

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