1

I'm running through a UTM grid in geojson format with fiona, attempting to add/populate a field based on other field values and then write out to a new file. It appears to successfully build the record but not write it out. An input record looks like this:

{
      "type" : "Feature", 
      "id" : 1201, 
      "geometry" : 
      {
        "type" : "Polygon", 
        "coordinates" : 
        [
          [
            [-47.9999998938292, -63.9999999562278], 
            [-47.9999998938292, -64.9999998998828],... 
          ]
        ]
      }, 
      "properties" : {
        "FID" : 1201, 
        "ZONE" : 22, 
        "ROW_" : "D", 
        "WEST_VALUE" : " 54W", 
        "CM_VALUE" : " 51W", 
        "EAST_VALUE" : " 48W"
      }
    }

Here is my code:

from collections import OrderedDict
import fiona


gj_file = "/home/me/Downloads/utmzones.geojson"
recs = []  # list of new records that will be written

with fiona.open(gj_file) as source:
    source_driver = source.driver
    source_crs = source.crs

    for f in source:
        props = f['properties']
        geom = f['geometry']
        if props['ROW_'] in ['N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X']:
            r = {
                'type': 'Feature',
                'id': f['id'],
                'geometry': geom,
                'properties': OrderedDict([
                    ('FID', props['FID']),
                    ('ZONE', props['ZONE']),
                    ('ROW_', props['ROW_']),
                    ('UTMZONE', str(props['ZONE']) + 'N'),  # make a ZONE[N/S] value
                    ('WEST_VALUE', props['WEST_VALUE']),
                    ('CM_VALUE', props['CM_VALUE']),
                    ('EAST_VALUE', props['EAST_VALUE'])
                ])
            }
            print(r)
            recs.append(r)
        elif props['ROW_'] in ['M', 'L', 'K', 'J', 'H', 'G', 'F', 'E', 'D', 'C']:
            r = {
                'type': 'Feature',
                'id': f['id'],
                'geometry': geom,
                'properties': OrderedDict([
                    ('FID', props['FID']),
                    ('ZONE', props['ZONE']),
                    ('ROW_', props['ROW_']),
                    ('UTMZONE', str(props['ZONE']) + 'N'),
                    ('WEST_VALUE', props['WEST_VALUE']),
                    ('CM_VALUE', props['CM_VALUE']),
                    ('EAST_VALUE', props['EAST_VALUE'])
                ])
            }
            recs.append(r)

The record generated looks like this:

{
  'type': 'Feature',
  'id': '1201',
  'geometry': {
    'type': 'Polygon',
    'coordinates': [
      [
        (-47.9999998938292, -63.9999999562278),
        (-47.9999998938292, -64.9999998998828),...
      ]
    ]
  },
  'properties': OrderedDict([
    ('FID', 1201),
    ('ZONE', 22),
    ('ROW_', 'D'),
    ('UTMZONE', '22N'),
    ('WEST_VALUE', ' 54W'),
    ('CM_VALUE', ' 51W'),
    ('EAST_VALUE', ' 48W')
  ])
}

My schema looks like this:

schema = {
    'geometry': 'Polygon',
    'properties': OrderedDict([
        ('FID', int),
        ('ZONE', int),
        ('ROW_', str),
        ('UTMZONE', str),
        ('WEST_VALUE', str),
        ('CM_VALUE', str),
        ('EAST_VALUE', str)
    ])
}

And the write action looks like this, based on my (probably incorrect) interpretation of the fiona docs:

with fiona.open(
    '/home/me/Downloads/utm_out.geojson',
    'w',
    driver=source_driver,
    crs=source_crs,
    schema=schema) as c:
    
    for rec in recs:
        c.write(rec) 

This raises an AttributeError: type object 'int' has no attribute 'split'. When I coerce the two values FID and ZONE to str and update the schema, it then raises a TypeError: argument of type 'type' is not iterable.

UPDATE: entire stack trace as requested

Traceback (most recent call last):
  File "/home/me/PycharmProjects/UTM/join_utm_zones.py", line 63, in <module>
    with fiona.open(
  File "/home/me/anaconda3/envs/foss4g/lib/python3.9/site-packages/fiona/env.py", line 417, in wrapper
    return f(*args, **kwargs)
  File "/home/me/anaconda3/envs/foss4g/lib/python3.9/site-packages/fiona/__init__.py", line 272, in open
    c = Collection(path, mode, crs=crs, driver=driver, schema=this_schema,
  File "/home/me/anaconda3/envs/foss4g/lib/python3.9/site-packages/fiona/collection.py", line 151, in __init__
    self._check_schema_driver_support()
  File "/home/me/anaconda3/envs/foss4g/lib/python3.9/site-packages/fiona/collection.py", line 424, in _check_schema_driver_support
    field_type = field.split(":")[0]
AttributeError: type object 'int' has no attribute 'split'
2
  • Can you provide the actual stack trace? It is kind of hard to figure out is happening, where the actual error is being triggered.
    – RomaH
    Dec 17, 2021 at 21:16
  • Updated with stack trace.
    – auslander
    Dec 17, 2021 at 21:36

1 Answer 1

2

Your schema is defined incorrectly. The types need to be defined using strings. You are trying to pass the actual Python object types to the functions, which is causing issues.

Your first error is caused because the library's write utility is trying to call the .split() function on the object int; it can't because int does have have .split() method. The second error is different because a str object does have .split() method, but then it trips when, presumably, the write utility tries to iterate over a Python type object; a Python type has the type of 'type', hence the weird error.

TypeError: argument of type 'type' is not iterable

Instead try defining your schema as:

schema = {
    'geometry': 'Polygon',
    'properties': OrderedDict([
        ('FID', 'int'),
        ('ZONE', 'int'),
        ('ROW_', 'str'),
        ('UTMZONE', 'str'),
        ('WEST_VALUE', 'str'),
        ('CM_VALUE', 'str'),
        ('EAST_VALUE', 'str')
    ])
}

See this section of the documents.

1
  • That worked. Just tired eyes on the fiona documentation I guess! Thanks.
    – auslander
    Dec 17, 2021 at 21:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.