Skip to content
This repository has been archived by the owner on Dec 11, 2022. It is now read-only.

✨ ASCII (Fixes #26) #54

Merged
merged 13 commits into from
Feb 20, 2021
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
assets
test/assets
test/gallery
test/*.asc

# Files generated by invoking Julia with --track-allocation
*.jl.mem
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "SimpleSDMLayers"
uuid = "2c645270-77db-11e9-22c3-0f302a89c64c"
authors = ["Timothée Poisot <[email protected]>", "Gabriel Dansereau <[email protected]>"]
version = "0.3.6"
version = "0.4.0"

[deps]
ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"
Expand Down
6 changes: 6 additions & 0 deletions docs/src/man/data.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ bioclim
```@docs
landcover
```

## ASCII files

```@docs
SimpleSDMLayers.ascii
```
5 changes: 2 additions & 3 deletions src/SimpleSDMLayers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ include(joinpath("datasets", "raster.jl"))
include(joinpath("datasets", "worldclim.jl"))
include(joinpath("datasets", "chelsa.jl"))
include(joinpath("datasets", "landcover.jl"))
export worldclim
export bioclim
export landcover
include(joinpath("datasets", "ascii.jl"))
export worldclim, bioclim, landcover

include(joinpath("operations", "coarsen.jl"))
include(joinpath("operations", "sliding.jl"))
Expand Down
72 changes: 72 additions & 0 deletions src/datasets/ascii.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
function _get_asc_field(lines, field, type)
line_id = findfirst(line -> startswith(line, field), lines)
return parse(type, last(split(lines[line_id], " "))), line_id
end

"""
ascii(file::AbstractString, datatype::Type{T}=Float64) where {T <: Number}

Reads the content of a grid file to a `SimpleSDMPredictor`, the type of which is
given by the `datatype` argument.
"""
function ascii(file::AbstractString, datatype::Type{T}=Float64) where {T <: Number}
lines = lowercase.(readlines(file))
# Get the information
ncols, ncols_line = _get_asc_field(lines, "ncols", Int64)
nrows, nrows_line = _get_asc_field(lines, "nrows", Int64)
xl, xl_line = _get_asc_field(lines, "xllcorner", Float64)
yl, yl_line = _get_asc_field(lines, "yllcorner", Float64)
cs, cs_line = _get_asc_field(lines, "cellsize", Float64)
nodata, nodata_line = _get_asc_field(lines, "nodata", datatype)
# Read the data
M = zeros(datatype, (ncols, nrows))
data_start = nodata_line+1
data_end = length(lines)
for line_id in data_start:data_end
M[:,nrows-(line_id-(data_start))] = parse.(datatype, split(lines[line_id]))
end
println(permutedims(M))
# Put data in the grid
grid = convert(Matrix{Union{datatype,Nothing}}, permutedims(M))
for i in eachindex(M)
if grid[i] == nodata
grid[i] = nothing
end
end
return SimpleSDMPredictor(grid, xl, xl+cs*2ncols, yl, yl+cs*2nrows)
end

"""
ascii(layer::SimpleSDMPredictor{T}, file::AbstractString; nodata::T=convert(T, -9999)) where {T <: Number}

Writes a `layer` to a grid file, with a given `nodata` value. The layer must store numbers.
"""
function ascii(layer::SimpleSDMPredictor{T}, file::AbstractString; nodata::T=convert(T, -9999)) where {T <: Number}
if !(stride(layer)[1] ≈ stride(layer)[2])
throw(DimensionMismatch("The cells of the layer to write must be square (i.e. both values of stride must be equal)"))
end
open(file, "w") do io
write(io, "ncols $(size(layer, 2))\n")
write(io, "nrows $(size(layer, 1))\n")
write(io, "cellsize $(stride(layer)[1])\n")
write(io, "xllcorner $(layer.left)\n")
write(io, "yllcorner $(layer.bottom)\n")
write(io, "yllcorner $(layer.bottom)\n")
write(io, "nodata_value $(nodata)\n")
for row in reverse(1:size(layer.grid, 1))
for el in layer.grid[row,:]
if isnothing(el)
write(io, "$(nodata) ")
else
write(io, "$(el) ")
end
end
write(io, "\n")
end
end
return file
end

function ascii(layer::SimpleSDMResponse{T}, file::AbstractString; nodata::T=convert(T, -9999)) where {T <: Number}
return ascii(convert(SimpleSDMPredictor, layer), file; nodata=nodata)
end
25 changes: 25 additions & 0 deletions test/ascii.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module SSLTestASCII
using SimpleSDMLayers
using Test

M = rand(Float64, 4, 8)
M = convert(Matrix{Union{Nothing,Float64}}, M)
M[rand(Bool, size(M))] .= nothing

S = SimpleSDMPredictor(M, 0.0, 2.0, 0.0, 1.0)

SimpleSDMLayers.ascii(S, "test.asc")
@test isfile("test.asc")

U = SimpleSDMLayers.ascii("test.asc")

@test all(S.grid .== U.grid)
@test S.left == U.left
@test S.bottom == U.bottom
@test S.right == U.right
@test S.top == U.top
@test size(S) == size(U)

rm("test.asc")

end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ global anyerrors = false

tests = [
"construction" => "construction.jl",
"ascii" => "ascii.jl",
"basics" => "basics.jl",
"overloads" => "overloads.jl",
"generated" => "generated.jl",
Expand Down