2

I have a test GDB file-folder that I have been able to verify that it does contain features through using some of ESRI's tools.

The code I have seems simple enough, but it keeps crashing when I try to call the next() function to get the first feature. If I comment that function call out and just simply look through the gdb file for features, the program doesn't crash but prints no features. What am I doing wrong? Below is my code snippet:

gdb = fiona.open(GDB_Path)
gdb.driver # OpenFileGDB
gdb.schema # {'geometry': '3D MultiLineString', 'properties': OrderedDict([(u'FCSubtype', 'int'), ...
gdb.crs # {'init': u'epsg:4326'}

print "Getting first feature..."
gdb.next()

print "going to print all features..."
for feature in gdb:
   print feature
print "finished parsing GDB file" 

Traceback shows that line 318 on fiona's collection.py file is crashing within the next call. Other than trying another GDB file, is there anything else I should consider doing?

1

Nothing new since your post How to do a Spatial Join after opening a GDB file with Fiona?

If Fiona is configured to open .gdb files (via FileGDB or OpenFileGDB), it is the same as opening shapefiles (and others) and your approach is correct.

1) First, information about the file using the command ogrinfo

ogrinfo -al "test.gdb"
INFO: Open of `test.gdb'
  using driver `FileGDB' successful # or using driver `OpenFileGDB' successful 
Layer name: test
Geometry: Multi Line String
Feature Count: 100
Extent: (-1,276087, -0,380435) - (0,306522, 0,889130)
Layer SRS WKT:
....
FID Column = OBJECTID
Geometry Column = SHAPE
id: Integer (0.0)
OGRFeature(test):1
id (Integer) = (1)
MULTILINESTRING ((-1.254300117492676 0.223900079727173,-1.05430006980896 0.663000106811523,-0.69350004196167 0.628400087356567,-0.306600093841553 0.726200103759766,0.30649995803833 0.889100074768066))
OGRFeature(test):2
id (Integer) = (null)
MULTILINESTRING ((-0.384799957275391 0.145699977874756,-0.166699886322021 -0.128900051116943,0.093499898910522 -0.380399942398071))
...

2) Confirmation with Fiona

import fiona
layer = fiona.open("test.gdb")
# number of features (layer is now an iterator)
len(layer)
100
layer.bounds # = Extent
(-1.276086956521739, -0.3804347826086957, 0.3065217391304347, 0.8891304347826088)

All these elements (schema, crs, driver,...) are metadata and do not depend on the mechanism of reading the records.

To understand this process, look at Iterables vs. Iterators vs. Generators.

Fiona does not read the entire file into memory but use a generator (one feature by one feature with the command next())

layer.next()
{'geometry': {'type': 'MultiLineString', 'coordinates':   [[(-1.2543001174926758, 0.22390007972717285), (-1.05430006980896, 0.6630001068115234), (-0.6935000419616699, 0.6284000873565674), (-0.30660009384155273, 0.7262001037597656), (0.3064999580383301, 0.8891000747680664)]]}, 'type': 'Feature', 'id': '1', 'properties': OrderedDict([(u'DIP', 42), (u'DIP_DIR', 140)])}
layer.next()
{'geometry': {'type': 'MultiLineString', 'coordinates': [[(-0.3847999572753906, 0.14569997787475586), (-0.16669988632202148, -0.12890005111694336), (0.09349989891052246, -0.3803999423980713)]]}, 'type': 'Feature', 'id': '2', 'properties': OrderedDict([((u'DIP', 35), (u'DIP_DIR', 156))])}
....

It is the same thing that

# first two elements
for features in layer[:2]:
    print feature
{'geometry': {'type': 'MultiLineString', 'coordinates': [[(-1.2543001174926758, 0.22390007972717285), (-1.05430006980896, 0.6630001068115234), (-0.6935000419616699, 0.6284000873565674),     (-0.30660009384155273, 0.7262001037597656), (0.3064999580383301, 0.8891000747680664)]]}, 'type': 'Feature', 'id': '1', 'properties': OrderedDict([(u'id', None)])}
{'geometry': {'type': 'MultiLineString', 'coordinates': [[(-0.3847999572753906, 0.14569997787475586), (-0.16669988632202148, -0.12890005111694336), (0.09349989891052246, -0.3803999423980713)]]}, 'type': 'Feature', 'id': '2', 'properties': OrderedDict([(u'id', None)])}

If you want the entire file into memory, use

features = list(layer)
len(list(features))
100

Therefore, in your case, Fiona can read the metadata of your file but not the records (problem of GDAL/OGR, of the driver, of the file, of the geomtries, of...?)

  • Gene, I think I see why the next() command is crashing the app. I used the ogrinfo you suggested and grepped out anywhere "Feature Count: " exists... Feature counts as they are encountered: 0,0, 22, 35, 0, 157, 0, 0, 5, 0, 0, 1, 62, 0, 0, 0, 14, 2, 17, 3088, 320, 0, 14, 17, 952, 35, 0, 18906, 435, 14, 4, 19, 1, 108, 1139, 2, 0, 0, 80, 0, 0. Is there a preferred way to handle the Next function call crashing whenever it encounters a 0 feature count? – George May 16 '16 at 16:13
  • Or is there a way to open a GDB file with Fiona but filter out all layers with a feature count of 0? – George May 16 '16 at 16:46
  • Gene, sorry for being so dense... your last statement is sinking in... you're telling me something is hosed up... I just need to dig further. I've shuffled things around and have essentially created a for feature in gdb loop immediately after opening my gdb file.... and for whatever reason, I never enter the loop. Not sure why that is given how there should be multiple feature layers to iterate through. The GDB file is created by ArcGIS. – George May 16 '16 at 17:28
1

For what it's worth, I have found a way to traverse through the GDB file but was never able to resolve why the next() function call would crash on my ESRI generated GDB file. Many thanks to Gene for his time, patience, and willingness to help. In essence, this is what I had to do in order to be able to parse through the GDB file:

    for i, name in enumerate(fiona.listlayers(sourceDatabaseFile)):
       with fiona.open(sourceDatabaseFile, layer=1) as gdb:
          print "Current layer's feature count is: ", len(gdb)
          featureCounter = 0 # to verify len(gdb)
          for feature in gdb:
             print "Current feature's size is: ", len(feature) # Is always 4
             print "Feature ", name, " contents are: ", feature # Seems to show more than 4
             featureCounter = featureCounter + 1
          print "Feature Count counter is: ", featureCounter
          print "Finished parsing layer! \n\n"
          featureCounter = 0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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