-
Notifications
You must be signed in to change notification settings - Fork 26
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Raster writing via ArchGDAL.copy suddenly broken? #123
Comments
I'll also note that writing as ASCII, (with |
Could this be the same issue as evetion/GeoArrays.jl#26? What versions of GDAL and it's dependencies are you using? |
It seems unrelated AFAICT. Here's the manifest. |
Were you able to reproduce the issue with the code I posted? |
Hmm yeah that manifest just has recent versions. And if I run your code I also get all missings. But isn't the problem with how the raster is written? I don't have a fix now, but if I run it interactively ds = write_raster(fn_prefix,
array,
wkt,
transform,
file_format)
AG.read(ds, 1) I read out the same values that are put in. Is the problem perhaps that you don't close the dataset so the values are never flushed to disk? Returning an open dataset is probably not what you want |
Interesting. I had assumed that the connection would be closed upon exiting the do block, similar to how: open(file) do f
# do some stuff
end will automatically close the connection. Do I need to add a line in write_raster to force that? |
But the open files issue would make sense given some other issues I've been having with trying to implement these functions in another related package. There are tons of tests, and I had been getting |
You had it right!! I needed to do My new function is below and it seems to be working. Thank you so much for the help! You're a life saver. As I said above, this will also likely resolve an issue that I was having in another package! Still seems strange that it was working okay with the AAIGrid driver? Either way, glad that it's working now! function write_raster(fn_prefix::AbstractString,
array,
wkt::AbstractString,
transform,
file_format::String)
# transponse array back to columns by rows
array_t = permutedims(array, [2, 1])
width, height = size(array_t)
# Define extension and driver based in file_format
file_format == "tif" ? (ext = ".tif"; driver = "GTiff") :
(ext = ".asc"; driver = "AAIGrid")
file_format == "tif" ? (options = ["COMPRESS=LZW"]) :
(options = [])
# Append file extention to filename
fn = string(fn_prefix, ext)
# Create raster in memory
ArchGDAL.create(fn_prefix,
driver = ArchGDAL.getdriver("MEM"),
width = width,
height = height,
nbands = 1,
dtype = eltype(array_t),
options = options) do ds
# Copy memory object to disk (necessary because ArchGDAL.create
# does not support creation of ASCII rasters)
ArchGDAL.copy(ds,
filename = fn,
driver = ArchGDAL.getdriver(driver),
options = options) do dataset
band = ArchGDAL.getband(dataset, 1)
# Write data to band
ArchGDAL.write!(band, array_t)
# Write nodata and projection info
ArchGDAL.setnodatavalue!(band, -9999.0)
ArchGDAL.setgeotransform!(dataset, transform)
ArchGDAL.setproj!(dataset, wkt)
end
end
end |
Ah great that it's working now. We definitely need more examples like this in the documentation.
That's right, but the |
Great! Thanks again for the help! Presumably as it is now all of the datasets should be closed properly? |
Hm, now it is working when I run it as in the code above, but when running it inside my package, I'm getting another error: Any ideas for a quick fix? Thanks again. |
Hmm are you sure that in your package it is not still dealing with an old read only opened dataset? What if you change the filename for instance? |
Yeah, the failure is actually occurring with ERROR: LoadError: GDALError (CE_Failure, code 1):
test3/cum_currmap.asc, band 1: Write operation not permitted on dataset opened in read-only mode
Stacktrace:
[1] gdaljl_errorhandler(::GDAL.CPLErr, ::Int32, ::Cstring) at /root/.julia/packages/GDAL/cghbO/src/error.jl:36
[2] rasterio! at /root/.julia/packages/ArchGDAL/JhHWz/src/raster/rasterio.jl:457 [inlined]
[3] rasterio! at /root/.julia/packages/ArchGDAL/JhHWz/src/raster/rasterio.jl:455 [inlined]
[4] rasterio!(::ArchGDAL.IRasterBand, ::Array{Float64,2}, ::GDAL.GDALRWFlag, ::Int64, ::Int64) at /root/.julia/packages/ArchGDAL/JhHWz/src/raster/rasterio.jl:103 (repeats 2 times)
[5] write! at /root/.julia/packages/ArchGDAL/JhHWz/src/raster/rasterio.jl:175 [inlined]
[6] (::Omniscape.var"#10#12"{String,Array{Float64,1},Array{Float64,2}})(::ArchGDAL.Dataset) at /home/omniscape/src/io.jl:72
[7] copy(::Omniscape.var"#10#12"{String,Array{Float64,1},Array{Float64,2}}, ::ArchGDAL.Dataset; kwargs::Base.Iterators.Pairs{Symbol,Any,Tuple{Symbol,Symbol,Symbol},NamedTuple{(:filename, :driver, :options),Tuple{String,ArchGDAL.Driver,Array{Any,1}}}}) at /root/.julia/packages/ArchGDAL/JhHWz/src/context.jl:215
[8] (::Omniscape.var"#9#11"{String,Array{Float64,1},Array{Float64,2},String})(::ArchGDAL.Dataset) at /home/omniscape/src/io.jl:66
[9] create(::Omniscape.var"#9#11"{String,Array{Float64,1},Array{Float64,2},String}, ::String; kwargs::Base.Iterators.Pairs{Symbol,Any,NTuple{6,Symbol},NamedTuple{(:driver, :width, :height, :nbands, :dtype, :options),Tuple{ArchGDAL.Driver,Int64,Int64,Int64,DataType,Array{Any,1}}}}) at /root/.julia/packages/ArchGDAL/JhHWz/src/context.jl:215
[10] write_raster(::String, ::Array{Float64,2}, ::String, ::Array{Float64,1}, ::String) at /home/omniscape/src/io.jl:56
[11] run_omniscape(::String) at /home/omniscape/src/run_omniscape.jl:376
[12] top-level scope at /home/omniscape/test/runtests.jl:86
[13] include(::String) at ./client.jl:439
[14] top-level scope at none:6 |
Wait so for the GTiff it is fine to |
It does appear to work with GTiff. Only the tests that attempt to write with AAIGrid trigger the error. I confirmed by adjusting all tests to write with GTiff, and the error wasn't triggered that time. I think this might be the sweet spot? It seems to be working. function write_raster(fn_prefix::AbstractString,
array,
wkt::AbstractString,
transform,
file_format::String)
# transponse array back to columns by rows
array_t = permutedims(array, [2, 1])
width, height = size(array_t)
# Define extension and driver based in file_format
file_format == "tif" ? (ext = ".tif"; driver = "GTiff") :
(ext = ".asc"; driver = "AAIGrid")
file_format == "tif" ? (options = ["COMPRESS=LZW"]) :
(options = [])
# Append file extention to filename
fn = string(fn_prefix, ext)
# Create raster in memory
ArchGDAL.create(fn_prefix,
driver = ArchGDAL.getdriver("MEM"),
width = width,
height = height,
nbands = 1,
dtype = eltype(array_t),
options = options) do dataset
band = ArchGDAL.getband(dataset, 1)
# Write data to band
ArchGDAL.write!(band, array_t)
# Write nodata and projection info
ArchGDAL.setnodatavalue!(band, -9999.0)
ArchGDAL.setgeotransform!(dataset, transform)
ArchGDAL.setproj!(dataset, wkt)
# Copy memory object to disk (necessary because ArchGDAL.create
# does not support creation of ASCII rasters)
ArchGDAL.destroy(ArchGDAL.copy(dataset,
filename = fn,
driver = ArchGDAL.getdriver(driver),
options = options))
end
nothing
end |
Please feel free to copy any of the code above to use in examples if/as you see fit.
|
@vlandau thanks for posting these, I'm setting up GeoData.jl to write all formats based on extension, and this is perfect. |
BTW do you know if there is much overhead to using this for tif, as compared to just writing to disk? |
Not sure about overhead -- it seems pretty efficient for the most part, but I suppose there could be overhead from using GDAL as a middleman. |
I'm noticing that raster writing is not working for my package, Omniscape.jl, when using ArchGDAL. I think it has something to do with a dependency of ArchGDAL being updated? I'm not 100% sure. It was working fine before, and it also seems to work when running from a top-level function in my package using a specific manifest.toml; however, when I try to run
write_raster
directly (see below, and also here), or use my package with a fresh install of ArchGDAL, it fails then too (even in the docker image with the specific manifest.toml).I'm trying to write a tif raster (by copying an in-memory raster) using LZW compression. Instead of writing the values as it was before, it is writing an empty raster (all of it is "NoData")
Code to reproduce the issue is below. Anything that you notice right away that seems wrong?
Thanks very much for any assistance.
The text was updated successfully, but these errors were encountered: