4 # Copyright (C) 2002 Jörg Lehmann <joergl@users.sourceforge.net>
5 # Copyright (C) 2002 André Wobst <wobsta@users.sourceforge.net>
7 # This file is part of PyX (http://pyx.sourceforge.net/).
9 # PyX is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
14 # PyX is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with PyX; if not, write to the Free Software
21 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 import re
, ConfigParser
25 import helper
, mathtree
28 class ColumnError(Exception): pass
31 ColPattern
= re
.compile(r
"\$-?[0-9]+")
33 class MathTreeValCol(mathtree
.MathTreeValVar
):
35 def InitByParser(self
, arg
):
36 Match
= arg
.MatchPattern(ColPattern
)
42 MathTreeValsWithCol
= (mathtree
.MathTreeValConst
,
43 mathtree
.MathTreeValVar
,
49 def __init__(self
, titles
, data
, parser
=mathtree
.parser(MathTreeVals
=MathTreeValsWithCol
)):
54 def getcolumnno(self
, column
):
55 if self
.titles
.count(column
) == 1:
56 return self
.titles
.index(column
)
59 except (TypeError, IndexError, ValueError):
63 def getcolumn(self
, column
):
64 columnno
= self
.getcolumnno(column
)
65 return [x
[columnno
] for x
in self
.data
]
67 def addcolumn(self
, expression
, context
={}):
69 split
= expression
.rindex("=")
71 self
.titles
.append(None)
73 self
.titles
.append(expression
[:split
])
74 expression
= expression
[split
+1:]
75 tree
= self
.parser
.parse(expression
)
77 for key
in tree
.VarList():
84 columnlist
[key
] = column
87 columnlist
[key
] = self
.getcolumnno(key
)
88 except ColumnError
, e
:
89 if key
not in context
.keys():
92 varlist
= context
.copy()
93 for data
in self
.data
:
95 for key
in columnlist
.keys():
96 varlist
[key
] = float(data
[columnlist
[key
]])
97 except (TypeError, ValueError):
100 data
.append(tree
.Calc(**varlist
))
105 def __init__(self
, titles
=[], data
=[], maxcolumns
=helper
.nodefault
, **kwargs
):
107 if maxcolumns
is helper
.nodefault
:
108 maxcolumns
= len(data
[0])
109 for line
in data
[1:]:
110 if len(line
) > maxcolumns
:
111 maxcolumns
= len(line
)
112 titles
= titles
[:maxcolumns
]
113 titles
+= [None] * (maxcolumns
- len(titles
))
115 line
+= [None] * (maxcolumns
- len(line
))
118 _data
.__init
__(self
, titles
, data
, **kwargs
)
121 class datafile(data
):
123 defaultcommentpattern
= re
.compile(r
"(#+|!+|%+)\s*")
124 defaultstringpattern
= re
.compile(r
"\"(.*?
)\"(\s
+|$
)")
125 defaultcolumnpattern = re.compile(r"(.*?
)(\s
+|$
)")
127 def splitline(self, line, stringpattern, columnpattern, tofloat=1):
129 if line.find('"')!=-1 or \
130 stringpattern is not self.defaultstringpattern or \
131 columnpattern is not self.defaultcolumnpattern:
133 match = stringpattern.match(line)
135 result.append(match.groups()[0])
136 line = line[match.end():]
138 match = columnpattern.match(line)
141 result.append(float(match.groups()[0]))
142 except (TypeError, ValueError):
143 result.append(match.groups()[0])
145 result.append(match.groups()[0])
146 line = line[match.end():]
150 return map(float, line.split())
151 except (TypeError, ValueError):
153 for r in line.split():
155 result.append(float(r))
156 except (TypeError, ValueError):
163 def __init__(self, file, commentpattern=defaultcommentpattern,
164 stringpattern=defaultstringpattern,
165 columnpattern=defaultcolumnpattern,
166 skiphead=0, skiptail=0, every=1,**kwargs):
167 if helper.isstring(file):
168 file = open(file, "r")
173 for line in file.readlines():
175 match = commentpattern.match(line)
178 newtitles = self.splitline(line[match.end():], stringpattern, columnpattern, tofloat=0)
180 usetitles = newtitles
183 for value in self.splitline(line, stringpattern, columnpattern, tofloat=1):
184 linedata.append(value)
186 if linenumber >= skiphead and not ((linenumber - skiphead) % every):
187 linedata = [linenumber + 1] + linedata
188 if len(linedata) > maxcolumns:
189 maxcolumns = len(linedata)
190 usedata.append(linedata)
193 del usedata[-skiptail:]
194 data.__init__(self, titles=[None] + usetitles, data=usedata, maxcolumns=maxcolumns, **kwargs)
198 class sectionfile(_data):
200 def __init__(self, file, sectionstr = "section", **kwargs):
201 config = ConfigParser.ConfigParser()
202 config.optionxform = str
208 config.readfp(open(file, "r"))
210 usetitles = [sectionstr]
211 sections = config.sections()
213 for section in sections:
214 usedata.append([section] + [None for x in range(len(usetitles) - 1)])
215 for option in config.options(section):
216 if option == sectionstr:
217 raise ValueError("'%s' is already used as the section identifier" % sectionstr)
219 index = usetitles.index(option)
221 index = len(usetitles)
222 usetitles.append(option)
225 value = config.get(section, option)
227 usedata[-1][index] = float(value)
228 except (TypeError, ValueError):
229 usedata[-1][index] = value
230 _data.__init__(self, usetitles, usedata, **kwargs)