[gdal-dev] Fwd: NotImplementedError: Wrong number of arguments for overloaded function 'Feature_SetField'.

Ole Nielsen ole.moller.nielsen at gmail.com
Mon Sep 5 23:34:54 EDT 2011


Dear Even

Thank you so much for going through the trouble of reproducing this issue.
You have help a lot, but I need one more hint regarding the apparent change
in how field names get truncated (Normalized/laundered).

To summarise:

   - I followed your suggestions and rebuilt from scratch.
   - Your Python example worked perfectly
   - However my code still produced the error in SetField
   (NotImplementedError: Wrong number of arguments for overloaded function)
   - It turned out the reason was that I was passing a singleton
   numpy.ndarray element into it. Casting that to a float fixed the problem in
   ogr 1.8
   - However, I still get the following warning and associated errors of the
   form
   - Warning 6: Normalized/laundered field name: 'CONTENTS_LOSS_AUD' to
      'CONTENTS_L'
      - ERROR 1: No such field: 'CONTENTS_LOSS_AUD'    (not surprisingly, if
      it was truncated :-))


The warning comes from a call to lyr.CreateField(fd) and the error happens
when calling SetField with the full length string.
I have included the routine I wrote to store our layers as reference below,
but my questions are


   - What are the official ogr steps required to store a vector layer
   (represented as e.g. a list of x, y values and associated feature attributes
   (name, value))? In particular, is CreateField perhaps obsoleted by something
   else?
   - Is the truncation to 10 characters hard and fast or driver dependent -
   and how should one deal with this truncation? Your example (which does not
   use CreateField) would suggest names can be longer than 10 characters.
   - Where can i find some documentation of the OGR Python bindings?


I am sorry that my questions are so fundamental, but I am still new to this
library.
Cheers and many thanks
Ole Nielsen




------------ The code that works for version 1.6 but not 1.8
--------------------------------

    def write_to_file(self, filename):
        """Save vector data to file

        Input
            filename: filename with extension .shp or .gml
        """

        # Check file format
        basename, extension = os.path.splitext(filename)

        msg = ('Invalid file type for file %s. Only extensions '
               'shp or gml allowed.' % filename)
        assert extension == '.shp' or extension == '.gml', msg
        driver = DRIVER_MAP[extension]

        # FIXME (Ole): Tempory flagging of GML issue (ticket #18)
        if extension == '.gml':
            msg = ('OGR GML driver does not store geospatial reference.'
                   'This format is disabled for the time being. See '
                   'https://github.com/AIFDR/riab/issues/18')
            raise Exception(msg)

        # Derive layername from filename (excluding preceding dirs)
        layername = os.path.split(basename)[-1]

        # Get vector data
        geometry = self.get_geometry()
        data = self.get_data()
        N = len(geometry)

        # Clear any previous file of this name (ogr does not overwrite)
        try:
            os.remove(filename)
        except:
            pass

        # Create new file with one layer
        drv = ogr.GetDriverByName(driver)
        if drv is None:
            msg = 'OGR driver %s not available' % driver
            raise Exception(msg)

        ds = drv.CreateDataSource(filename)
        if ds is None:
            msg = 'Creation of output file %s failed' % filename
            raise Exception(msg)

        lyr = ds.CreateLayer(layername,
                             self.projection.spatial_reference,
                             self.geometry_type)
        if lyr is None:
            msg = 'Could not create layer %s' % layername
            raise Exception(msg)

        # Define attributes if any
        store_attributes = False
        if data is not None:
            if len(data) > 0:
                try:
                    fields = data[0].keys()
                except:
                    msg = ('Input parameter "attributes" was specified '
                           'but it does not contain dictionaries with '
                           'field information as expected. The first'
                           'element is %s' % data[0])
                    raise Exception(msg)
                else:
                    # Establish OGR types for each element
                    ogrtypes = {}
                    for name in fields:
                        att = data[0][name]
                        py_type = type(att)
                        msg = ('Unknown type for storing vector '
                               'data: %s, %s' % (name, str(py_type)[1:-1]))
                        assert py_type in TYPE_MAP, msg
                        ogrtypes[name] = TYPE_MAP[py_type]

            else:
                msg = ('Input parameter "data" was specified '
                       'but appears to be empty')
                raise Exception(msg)

            # Create attribute fields in layer
            store_attributes = True
            for name in fields:
                print 'Creating', name
                fd = ogr.FieldDefn(name, ogrtypes[name])
                # FIXME (Ole): Trying to address issue #16
                #              But it doesn't work and
                #              somehow changes the values of MMI in test
                #width = max(128, len(name))
                #print name, width
                #fd.SetWidth(width)

                if lyr.CreateField(fd) != 0:
                    msg = 'Could not create field %s' % name
                    raise Exception(msg)

        # Store geometry
        geom = ogr.Geometry(self.geometry_type)
        layer_def = lyr.GetLayerDefn()
        for i in range(N):
            # Create new feature instance
            feature = ogr.Feature(layer_def)

            # Store geometry and check
            if self.geometry_type == ogr.wkbPoint:
                x = float(geometry[i][0])
                y = float(geometry[i][1])
                geom.SetPoint_2D(0, x, y)
            elif self.geometry_type == ogr.wkbPolygon:
                wkt = array2wkt(geometry[i])
                geom = ogr.CreateGeometryFromWkt(wkt)
            else:
                msg = 'Geometry %s not implemented' % self.geometry_type
                raise Exception(msg)

            feature.SetGeometry(geom)

            G = feature.GetGeometryRef()
            if G is None:
                msg = 'Could not create GeometryRef for file %s' % filename
                raise Exception(msg)

            # Store attributes
            if store_attributes:
                for name in fields:
                    val = data[i][name]
                    if type(val) == numpy.ndarray:
                        # A singleton of type <type 'numpy.ndarray'> works
for gdal version 1.6
                        # but fails for version 1.8 in SetField with error:
                        # NotImplementedError: Wrong number of arguments for
overloaded function
                        val = float(val)

                    feature.SetField(name, val)

            # Save this feature
            if lyr.CreateFeature(feature) != 0:
                msg = 'Failed to create feature %i in file %s' % (i,
filename)
                raise Exception(msg)

            feature.Destroy()

        # Write keywords if any
        write_keywords(self.keywords, basename + '.keywords')




On Sun, Sep 4, 2011 at 4:16 PM, Even Rouault
<even.rouault at mines-paris.org>wrote:

> Le dimanche 04 septembre 2011 05:54:34, Ole Nielsen a écrit :
> > Hi again and sorry for nagging, but do you have any hints as to what this
> > error means
> >
> > >    return _ogr.Feature_SetField(self, *args)
> > >
> > > NotImplementedError: Wrong number of arguments for overloaded function
> > > 'Feature_SetField'.
> > >
> > >   Possible C/C++ prototypes are:
> > >     SetField(OGRFeatureShadow *,int,char const *)
> > >     SetField(OGRFeatureShadow *,char const *,char const *)
> > >     SetField(OGRFeatureShadow *,int,int)
> > >     SetField(OGRFeatureShadow *,char const *,int)
> > >     SetField(OGRFeatureShadow *,int,double)
> > >     SetField(OGRFeatureShadow *,char const *,double)
> > >     SetField(OGRFeatureShadow *,int,int,int,int,int,int,int,int)
> > >     SetField(OGRFeatureShadow *,char const
> *,int,int,int,int,int,int,int)
> >
> > The input to the Python bindings is of the form
> > SetField('STRUCT_DAMAGE_fraction', 0.346734256639)
> >
> > i.e. one string argument (char*) followed by a float (double) which I
> > thought would be matched by the third last header above. It works fine on
> > version 1.6 but not version 1.8.
> >
> > Can anyone tell me what has changed, what it means and how to work around
> > it - please?
> >
> Ole,
>
> Unfortunately, I cannot explain your error, but I'm convinced it must be
> something particular with your installation. So I'd advise you to test on a
> fresh machine and/or clean a bit the packages you've installed on the one
> where you have problems.
>
> Below a test I've just done to show you that SetField(string, double)
> definitely works with GDAL 1.8.0 under normal conditions. I've installed
> Ubuntu
> 11.04 amd64 in a virtual machine, installed first python-gdal (1.6), then
> added
> ubuntugis-unstable PPA, installed qgis (1.7) :
>
> even at even-virtual-machine:~$ dpkg -l | grep gdal
> ii  gdal-bin                              1.8.0-2~natty2
> Geospatial Data Abstraction Library - Utility programs
> ii  libgdal1-1.6.0                        1.6.3-4build4
> Geospatial Data Abstraction Library
> ii  libgdal1-1.8.0                        1.8.0-2~natty2
> Geospatial Data Abstraction Library
> ii  python-gdal                           1.8.0-2~natty2
> Python bindings to the Geospatial Data Abstraction Library
>
> even at even-virtual-machine:~$ python
> Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53)
> [GCC 4.5.2] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
> >>> from osgeo import gdal
> >>> from osgeo import ogr
> >>> gdal.VersionInfo('')
> 'GDAL 1.8.0, released 2011/01/12'
> >>> fielddefn = ogr.FieldDefn('STRUCT_DAMAGE_fraction', ogr.OFTReal)
> >>> featuredefn = ogr.FeatureDefn()
> >>> featuredefn.AddFieldDefn(fielddefn)
> >>> feat = ogr.Feature(featuredefn)
> >>> feat.SetField('STRUCT_DAMAGE_fraction', 0.346734256639)
> >>> feat.DumpReadable()
> OGRFeature():-1
>  STRUCT_DAMAGE_fraction (Real) = 0.346734256639
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.osgeo.org/pipermail/gdal-dev/attachments/20110906/9aaf248d/attachment-0001.html


More information about the gdal-dev mailing list