yeesian / ArchGDAL.jl

A high level API for GDAL - Geospatial Data Abstraction Library
https://yeesian.github.io/ArchGDAL.jl/stable/
Other
141 stars 27 forks source link

Question about `dest` input to `unsafe_gdalbuildvrt` #358

Open alex-s-gardner opened 1 year ago

alex-s-gardner commented 1 year ago

When supplying dest kwarg to ArchGDAL.unsafe_gdalbuildvrt i would expect the .vrt file to be written to dest but this is not the case. Is this the expected behavior?

using ArchGDAL
in_tifs = vector list of tif files
vrt_sep = ArchGDAL.unsafe_gdalbuildvrt(in_tifs, []; dest = "/path/to/file.vrt")
isfile( "/path/to/file.vrt") is false
visr commented 1 year ago

Can you try ArchGDAL.gdalbuildvrt? See also #142. It could be that the file is only written to disk when the finalizer gets called.

alex-s-gardner commented 1 year ago

I'm a little unclear on how to use gdalbuildvrt as the first input needs to be a Function

gdalbuildvrt(::Function, ::Any...; kwargs...)

visr commented 1 year ago

That is the signature of the do block syntax, like in https://docs.julialang.org/en/v1/manual/functions/#Do-Block-Syntax-for-Function-Arguments.

But I believe the same arguments as you used for the unsafe version are also supported. It just doesn't appear in the docstring.

alex-s-gardner commented 1 year ago

unfortunately 'gdalbuildvrt' does not accept the same inputs as unsafe_gdalbuildvrt

MethodError: no method matching gdalbuildvrt(::Vector{String}, ::Vector{Any}; dest="/mnt/devon-r2/shared_data/arcticdem/mosaics/v3.0/10m/arcticdem_v3.0_10m.vrt")
Closest candidates are:
  gdalbuildvrt(::Function, ::Any...; kwargs...) at ~/.julia/packages/ArchGDAL/AZONk/src/context.jl:264
visr commented 1 year ago

Ah you're right there is a difference between the two. Note that it does not take a vector of paths, but a vector of opened datasets. Here are two examples:

ds = ArchGDAL.read("LC08_L2SP_196026_20180101_20200902_02_T1_SR_B2.TIF")
vrt = ArchGDAL.unsafe_gdalbuildvrt([ds]; dest="a.vrt")
ArchGDAL.destroy(vrt)

And using do-blocks to directly clean up:

ArchGDAL.read("LC08_L2SP_196026_20180101_20200902_02_T1_SR_B2.TIF") do ds
    ArchGDAL.gdalbuildvrt([ds]; dest="b.vrt") do vrt
        # do something with vrt dataset if needed
    end
end

In the first example, the VRT is only written on the call to destroy.

alex-s-gardner commented 1 year ago

I previously had

in_tifs_str = ["data1.tif", "data2.tif","data3.tif","data4.tif"]
in_tifs = ArchGDAL.read.(in_tifs_str)
vrt_sep = ArchGDAL.unsafe_gdalbuildvrt(in_tifs, []; dest = out_vrt)
ArchGDAL.write(vrt_sep, out_vrt)

and ArchGDAL.write(vrt_sep, out_vrt) should be replaced with ArchGDAL.destroy(vrt)

To get the same functionality with gdalbuildvrt i need:

ArchGDAL.gdalbuildvrt(in_tifs; dest="b.vrt") do vrt
    ArchGDAL.write(vrt,out_vrt)
end

Is that right? If so it seems a bit counterintuitive to have to wrap this in a do block

alex-s-gardner commented 1 year ago

I guess this is related issue #164 that was partially resolved by allowing gdalbuildvrt to accept multiple datasets but the do block requirement persists.

looking at Working with Files it seems that gdalbuildvrt should also be callable without the do block

visr commented 1 year ago

gdalbuildvrt should also be callable without the do block

Yeah I think so as well. Let's keep this issue open to track that.

yeesian commented 1 year ago

If so it seems a bit counterintuitive to have to wrap this in a do block

Yeah it is, thank you for filing and explaining!