evetion / GeoDataFrames.jl

Simple geographical vector interaction built on top of ArchGDAL
https://www.evetion.nl/GeoDataFrames.jl/dev/
MIT License
68 stars 6 forks source link

Odd subset of vector types can not be written to disk #89

Open alex-s-gardner opened 2 days ago

alex-s-gardner commented 2 days ago

These types all error: Vector{Int8}, Vector{UInt16}, Vector{Int16}, Vector{Float32}

These types do not: UInt8(), Int8(), UInt16(), Int16(), Float32(), Float64(), Vector{UInt8}, Vector{Float64}

This is likely an ArchGDAL issue but thought I'd start the discussion here.

import GeoInterface as GI
using DataFrames
using GeoDataFrames

outfile = joinpath(tempdir(), "test.geojson");
pt = GI.Point(1,1, crs=GFT.EPSG(4326))
colvals = [UInt8(1), Int8(1), UInt16(1), Int16(1), Float32(1), Float64(1), [UInt8.([1,2])], [Int8.([1,2])], [UInt16.([1,2])], [Int16.([1,2])], [Float32.([1,2])], [Float64.([1,2])]]

for cv in colvals
    df = DataFrame(geometry=pt, test=cv)
    try
        GeoDataFrames.write(outfile, df)
    catch e
        println("causes write error: $cv")
    end
end
causes write error: Vector{Int8}[[1, 2]]
causes write error: Vector{UInt16}[[0x0001, 0x0002]]
causes write error: Vector{Int16}[[1, 2]]
causes write error: Vector{Float32}[[1.0, 2.0]]

Typical error message looks like this:

ERROR: MethodError: no method matching setfield!(::ArchGDAL.Feature, ::Int64, ::Vector{Int8})
You may have intended to import Base.setfield!
The function `setfield!` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  setfield!(::ArchGDAL.AbstractFeature, ::Integer, ::DateTime, ::Int64)
   @ ArchGDAL ~/.julia/packages/ArchGDAL/aXTAq/src/ogr/feature.jl:713
  setfield!(::ArchGDAL.AbstractFeature, ::Integer, ::DateTime)
   @ ArchGDAL ~/.julia/packages/ArchGDAL/aXTAq/src/ogr/feature.jl:713
  setfield!(::ArchGDAL.AbstractFeature, ::Integer, ::Vector{UInt8})
   @ ArchGDAL ~/.julia/packages/ArchGDAL/aXTAq/src/ogr/feature.jl:704
  ...

Stacktrace:
  [1] (::GeoDataFrames.var"#22#27"{Vector{…}, DataFrameRow{…}, Vector{…}})(feature::ArchGDAL.Feature)
    @ GeoDataFrames ~/.julia/packages/GeoDataFrames/eP9Sg/src/io.jl:224
  [2] addfeature(f::GeoDataFrames.var"#22#27"{Vector{…}, DataFrameRow{…}, Vector{…}}, layer::ArchGDAL.FeatureLayer)
    @ ArchGDAL ~/.julia/packages/ArchGDAL/aXTAq/src/ogr/featurelayer.jl:490
  [3] (::GeoDataFrames.var"#20#25"{…})(layer::ArchGDAL.FeatureLayer)
    @ GeoDataFrames ~/.julia/packages/GeoDataFrames/eP9Sg/src/io.jl:210
  [4] createlayer(::GeoDataFrames.var"#20#25"{…}; kwargs::@Kwargs{…})
    @ ArchGDAL ~/.julia/packages/ArchGDAL/aXTAq/src/context.jl:268
  [5] (::GeoDataFrames.var"#19#24"{…})(spatialref::ArchGDAL.SpatialRef)
    @ GeoDataFrames ~/.julia/packages/GeoDataFrames/eP9Sg/src/io.jl:183
  [6] newspatialref(::GeoDataFrames.var"#19#24"{…}; kwargs::@Kwargs{})
    @ ArchGDAL ~/.julia/packages/ArchGDAL/aXTAq/src/context.jl:268
  [7] newspatialref
    @ ~/.julia/packages/ArchGDAL/aXTAq/src/context.jl:265 [inlined]
  [8] #18
    @ ~/.julia/packages/GeoDataFrames/eP9Sg/src/io.jl:177 [inlined]
  [9] create(f::GeoDataFrames.var"#18#23"{…}, args::String; kwargs::@Kwargs{…})
    @ ArchGDAL ~/.julia/packages/ArchGDAL/aXTAq/src/context.jl:268
 [10] create
    @ ~/.julia/packages/ArchGDAL/aXTAq/src/context.jl:265 [inlined]
 [11] write(fn::String, table::DataFrame; layer_name::String, crs::Nothing, driver::Nothing, options::Dict{…}, geom_columns::Tuple{…}, chunksize::Int64, kwargs::@Kwargs{})
    @ GeoDataFrames ~/.julia/packages/GeoDataFrames/eP9Sg/src/io.jl:176
 [12] write(fn::String, table::DataFrame)
    @ GeoDataFrames ~/.julia/packages/GeoDataFrames/eP9Sg/src/io.jl:112
 [13] top-level scope
    @ ./Untitled-1:12
Some type information was truncated. Use `show(err)` to see complete types.
evetion commented 1 day ago

This is indeed a limitation by GDAL. Would you expect a better error, or an automatic conversion?

alex-s-gardner commented 1 day ago

Are you sure about Vector{Float32} that seems like a pretty basic type... looking through the GDAL docs I can't readily determine what types are supported. I see that GeoTiff these types are supported.

I would automatic conversion with a warning?

evetion commented 1 day ago

Yeah, gdal defines a list of doubles (float64) only. https://gdal.org/en/latest/doxygen/ogr__api_8h.html#a83a56d01128bf247016c139faed157be. ArchGDAL follows it to the letter, but should probably be more lenient and just convert. All your other types can also be converted without data loss. You just won't get them back as the same type.