On 13/12/11 12:38, Jason Gofford wrote:

Unfortunately, I'm using the OS X binary install. I tried to avoid using
the binary but had several compatibility/architecture issues when I
upgraded to Lion (I upgraded early..). Can i use the updated file with
the binary install, perhaps as a separate independent plugin just for
contour plots? I'm not too familiar with Python (yet) so I'm not too
sure how to write a plugin myself.

I don't think I'll be working with any datasets which combine 2D and 1D
data (unless xspec spectra or contour plots do that, I'm not too sure)
so I doubt I'll miss that functionality if it doesn't work.

Hope its not too much trouble, and cheers for your help..

I've attached a hacked plugin to replace the qdp plugin with a new one. Add this to the list of plugins in the preferences dialog box (for this release).

It would be nice to get some sort of daily binary builds, but it's quite a bit of work.

Jeremy

import os.path
from veusz.plugins import *

class QdpFile2(object):
    """Handle reading of a Qdp file."""

    def __init__(self, colnames):
        self.colmodes = {}
        self.skipmode = 'none'
        self.retndata = []

        # store read in data here
        self.data = []
        # index of max vector
        self.dataindex = 1
        self.colnames = colnames

        # list of data groups for 2d objects
        self.datagroup2d = []
        # axis ranges for 2d objects
        self.axis2d = [None, None]

    def handleRead(self, p):
        """Handle read command."""
        try:
            mode = {'t': 'terr', 's': 'serr'}[p[1][:1]]
        except (IndexError, KeyError):
            raise ImportPluginException("read command takes terr/serr")
        try:
            cols = [int(x) for x in p[2:]]
        except ValueError:
            raise ImportPluginException("read command takes list of columns 
separated by spaces")
        for c in cols:
            self.colmodes[c] = mode

    def handleSkip(self, p):
        """Handle skip command."""
        try:
            self.skipmode = {'o': 'off', 's': 'single', 'd': 'double'}[p[1][:1]]
        except (IndexError, KeyError):
            raise ImportPluginException("skip command takes single/double/off")

    def handleNO(self, p, lastp):
        """Handle no command, meaning no data."""
        if self.skipmode == 'none':
            self.addNans( len(p) )
        elif self.skipmode == 'single':
            self.pushData()
            del self.data[:]
            self.dataindex += 1
        elif self.skipmode == 'double':
            if lastp[0] == 'no':
                self.pushData()
                del self.data[:]
                self.dataindex += 1
            else:
                self.addNans( len(p) )

    def addNans(self, num):
        """Add a blank set of data to output."""
        col = 0
        ds = 0
        while col < num or ds < len(self.data):
            if ds >= len(self.data):
                self.data.append([])
            m = self.colmodes.get(ds+1)
            if m == 'serr':
                self.data[ds].append( (N.nan, N.nan) )
                col += 2
            elif m == 'terr':
                self.data[ds].append( (N.nan, N.nan, N.nan) )
                col += 3
            else:
                self.data[ds].append( N.nan )
                col += 1
            ds += 1

    def pushData2D(self):
        """Handle 2D data groups."""

        for num, r1, c1, r2, c2 in self.datagroup2d:
            arr = []
            for c in xrange(c1-1,c2-1+1):
                arr.append( self.data[c][r1-1:r2-1+1] )
                # make data as "used"
                self.data[c] = None
            arr = N.array(arr)
            if num-1 < len(self.colnames):
                name = self.colnames[num-1]
            else:
                name = 'vec2d%i' % num

            rangex = rangey = None
            if self.axis2d[0] is not None:
                minval, pixsize = self.axis2d[0]
                rangex = (minval - pixsize*0.5,
                          minval+(arr.shape[1]-0.5)*pixsize )
            if self.axis2d[1] is not None:
                minval, pixsize = self.axis2d[1]
                rangey = (minval - pixsize*0.5,
                          minval+(arr.shape[0]-0.5)*pixsize )

            ds = datasetplugin.Dataset2D(name, data=arr,
                                         rangex=rangex, rangey=rangey)
            self.retndata.append(ds)

    def pushData(self):
        """Add data to output array.
        """

        for i in xrange(len(self.data)):
            if self.data[i] is None:
                continue

            # get dataset name
            if i < len(self.colnames):
                name = self.colnames[i]
            else:
                name = 'vec%i' % (i+1)
            if self.skipmode == 'single' or self.skipmode == 'double':
                name = name + '_' + str(self.dataindex)

            # convert data
            a = N.array(self.data[i])
            if len(a.shape) == 1:
                # no error bars
                ds = datasetplugin.Dataset1D(name, data=a)
            elif a.shape[1] == 2:
                # serr
                ds = datasetplugin.Dataset1D(name, data=a[:,0], serr=a[:,1])
            elif a.shape[1] == 3:
                # perr/nerr
                p = N.where(a[:,1] < a[:,2], a[:,2], a[:,1])
                n = N.where(a[:,1] < a[:,2], a[:,1], a[:,2])

                ds = datasetplugin.Dataset1D(name, data=a[:,0], perr=p, nerr=n)
            else:
                raise RuntimeError

            self.retndata.append(ds)

    def handleDataGroup(self, p):
        """Handle data groups."""

        if len(p) == 3:
            # we don't support the renaming thing
            pass
        elif len(p) == 6:
            # 2d data
            try:
                pint = [int(x) for x in p[1:]]
            except ValueError:
                raise ImportPluginException("invalid 2d datagroup command")

            self.datagroup2d.append(pint)

    def handleAxis(self, p):
        """Axis command gives range of axes (used for 2d)."""

        try:
            minval, maxval = float(p[2]), float(p[3])
        except ValueError:
            raise ImportPluginException("invalid axis range")
        self.axis2d[ p[0][0] == 'y' ] = (minval, maxval)

    def handleNum(self, p):
        """Handle set of numbers."""

        try:
            nums = [float(x) for x in p]
        except ValueError:
            raise ImportPluginException("Cannot convert '%s' to numbers" %
                                        (' '.join(p)))
        col = 0
        ds = 0
        while col < len(nums):
            if ds >= len(self.data):
                self.data.append([])
            m = self.colmodes.get(ds+1)
            if m == 'serr':
                self.data[ds].append( (nums[col], nums[col+1]) )
                col += 2
            elif m == 'terr':
                self.data[ds].append( (nums[col], nums[col+1], nums[col+2]) )
                col += 3
            else:
                self.data[ds].append( nums[col] )
                col += 1

            ds += 1

    def importFile(self, fileobj, dirname):
        """Read data from file object.
        dirname is the directory in which the file is located
        """

        contline = None
        lastp = []
        for line in fileobj:
            # strip comments
            if line.find("!") >= 0:
                line = line[:line.find("!")]
            if line[:1] == '@':
                # read another file
                fname = os.path.join(dirname, line[1:].strip())
                try:
                    newf = open(fname)
                    self.importFile(newf, dirname)
                except IOError:
                    pass
                continue

            p = [x.lower() for x in line.split()]

            if contline:
                # add on previous continuation if existed
                p = contline + p
                contline = None

            if len(p) > 0 and p[-1][-1] == '-':
                # continuation
                p[-1] = p[-1][:-1]
                contline = p
                continue

            if len(p) == 0:
                # nothing
                continue

            v0 = p[0]
            if v0[0] in '0123456789-.':
                self.handleNum(p)
            elif v0 == 'no':
                self.handleNO(p, lastp)
            elif v0 == 'read':
                self.handleRead(p)
            elif v0[:2] == 'sk':
                self.handleSkip(p)
            elif v0[:2] == 'dg':
                self.handleDataGroup(p)
            elif v0[:1] == 'x' or v0[:2] == 'ya':
                self.handleAxis(p)
            else:
                # skip everything else (for now)
                pass

            lastp = p

class ImportPluginQdp2(ImportPlugin):
    """An example plugin for reading data from QDP files."""

    name = "QDP import"
    author = "Jeremy Sanders"
    description = "Reads datasets from QDP files (fixed)"
    file_extensions = set(['.qdp'])

    def __init__(self):
        self.fields = [
            field.FieldTextMulti("names", descr="Vector name list ",
                                 default=['']),
            ]

    def doImport(self, params):
        """Actually import data
        params is a ImportPluginParams object.
        Return a list of datasetplugin.Dataset1D, datasetplugin.Dataset2D 
objects
        """
        names = [x.strip() for x in params.field_results["names"]
                 if x.strip()]

        f = params.openFileWithEncoding()
        rqdp = QdpFile2(names)
        rqdp.importFile(f, os.path.dirname(params.filename))
        rqdp.pushData2D()
        rqdp.pushData()
        f.close()

        return rqdp.retndata

# delete existing plugin
k = None
for i in xrange(len(importpluginregistry)):
    if importpluginregistry[i] is ImportPluginQdp:
        k = i
if k is not None:
    del importpluginregistry[k]

# add new one
importpluginregistry.append(ImportPluginQdp2)
_______________________________________________
Veusz-discuss mailing list
[email protected]
https://mail.gna.org/listinfo/veusz-discuss

Répondre à