Skip to content
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

add CHELSA V2 #62

Merged
merged 22 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f218721
download chelsa v2 bioclim
tiemvanderdeure Jan 30, 2024
8c66818
add version keyword, implement bioclim+
tiemvanderdeure Feb 27, 2024
74bb1c2
avoid Val(version), use if-else instead
tiemvanderdeure Feb 28, 2024
09a4e4a
make constants UPPERCASE
tiemvanderdeure Feb 28, 2024
37a1ada
display info when downloading new data
tiemvanderdeure Feb 28, 2024
9a4c9c6
specify version and patch are keywords
tiemvanderdeure Mar 1, 2024
591586d
fix some types in documentation
tiemvanderdeure Mar 1, 2024
083703f
add future bioclimplus
tiemvanderdeure Mar 3, 2024
f5c1324
add koppen-geiger to bioclimplus layers
tiemvanderdeure Mar 3, 2024
07c913d
add documentation for getraster with bioclimplus
tiemvanderdeure Mar 3, 2024
2aa7de5
swb (soil water balance) is not monthly
tiemvanderdeure Mar 3, 2024
ff0fb3f
correct bioclimplus layers for future
tiemvanderdeure Mar 12, 2024
71bd858
pet is called pet_penman
tiemvanderdeure Mar 12, 2024
cedae5c
add chelsa current climate
tiemvanderdeure Apr 15, 2024
05f97cc
add tests for chelsa bioclimplus and chelsa climate
tiemvanderdeure Apr 15, 2024
5612f58
delete aqua toml formatting, test chelsa climate
tiemvanderdeure Apr 16, 2024
c1de8cc
fix tests
tiemvanderdeure Apr 16, 2024
edda690
fix and test chelsa_warn_version
tiemvanderdeure Apr 16, 2024
1800477
rastername for pet uses pet_penman
tiemvanderdeure May 8, 2024
1f56a14
move a line away from docs
tiemvanderdeure May 10, 2024
aa994a4
update readme and chelsa docs
tiemvanderdeure May 19, 2024
4339dd5
Merge branch 'EcoJulia:master' into chelsa_v2
tiemvanderdeure Jun 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Currently sources include:

| Source | URL | Status |
| --------- | ---------------------------------------- | ---------------------------------------- |
| CHELSA | https://chelsa-climate.org | BioClim, Future BioClim and Climate |
| CHELSA | https://chelsa-climate.org | BioClim, BioClimPlus, and Climate |
| WorldClim | https://www.worldclim.org | Climate, Weather, BioClim, and Elevation |
| EarthEnv | http://www.earthenv.org | LandCover and HabitatHeterogeneity |
| AWAP | http://www.bom.gov.au/jsp/awap/index.jsp | Complete |
Expand Down
5 changes: 4 additions & 1 deletion src/RasterDataSources.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import JSON.Parser as JP

export WorldClim, CHELSA, EarthEnv, AWAP, ALWB, SRTM, MODIS

export BioClim, Climate, Weather, Elevation, LandCover, HabitatHeterogeneity
export BioClim, BioClimPlus, Climate, Weather, Elevation, LandCover, HabitatHeterogeneity

export Future, CMIP5, CMIP6

Expand Down Expand Up @@ -47,6 +47,8 @@ export ACCESS1, BNUESM, CCSM4, CESM1BGC, CESM1CAM5, CMCCCMS, CMCCCM, CNRMCM5,
# Climate models from CMIP6 (used in WorldClim)
export BCCCSM2MR, CNRMCM61, CNRMESM21, CanESM5, GFDLESM4, IPSLCM6ALR, MIROCES2L, MIROC6, MRIESM2

# Climate models from CMIP6 (CHELSA)
export UKESM, MPIESMHR

export Values, Deciles

Expand All @@ -63,6 +65,7 @@ include("worldclim/weather.jl")
include("worldclim/elevation.jl")

include("chelsa/shared.jl")
include("chelsa/climate.jl")
include("chelsa/bioclim.jl")
include("chelsa/future.jl")

Expand Down
89 changes: 78 additions & 11 deletions src/chelsa/bioclim.jl
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
layers(::Type{CHELSA{BioClim}}) = layers(BioClim)
layers(::Type{CHELSA{BioClimPlus}}) = layers(BioClimPlus)
layerkeys(::Type{CHELSA{BioClim}}, args...) = layerkeys(BioClim, args...)
layerkeys(::Type{CHELSA{BioClimPlus}}, args...) = layerkeys(BioClimPlus, args...)

"""
getraster(source::Type{CHELSA{BioClim}}, [layer]) => Union{Tuple,String}
getraster(source::Type{CHELSA{BioClim}}, [layer]; version = 2, [patch]) => Union{Tuple,String}

Download [`CHELSA`](@ref) [`BioClim`](@ref) data from [chelsa-climate.org](https://chelsa-climate.org/).

Expand All @@ -11,23 +13,88 @@ Download [`CHELSA`](@ref) [`BioClim`](@ref) data from [chelsa-climate.org](https
or `Symbol`s form `$(layerkeys(BioClim))`. Without a `layer` argument, all layers
will be downloaded, and a `NamedTuple` of paths returned.

# Keyword arguments
$CHELSA_KEYWORDS

Returns the filepath/s of the downloaded or pre-existing files.
"""
getraster(T::Type{CHELSA{BioClim}}, layer::Union{Tuple,Int,Symbol}) = _getraster(T, layer)
getraster(
T::Type{CHELSA{BioClim}},
layer::Union{Tuple,Int,Symbol};
version::Int = 2,
patch::Int = latest_patch(T, version)) = _getraster(T, layer, version, patch)

_getraster(T::Type{CHELSA{BioClim}}, layers::Tuple) = _map_layers(T, layers)
_getraster(T::Type{CHELSA{BioClim}}, layer::Symbol) = _getraster(T, bioclim_int(layer))
function _getraster(T::Type{CHELSA{BioClim}}, layer::Integer)
_getraster(T::Type{CHELSA{BioClim}}, layers::Tuple, version, patch) = _map_layers(T, layers, version, patch)
_getraster(T::Type{CHELSA{BioClim}}, layer::Symbol, version, patch) = _getraster(T, bioclim_int(layer), version, patch)
function _getraster(T::Type{CHELSA{BioClim}}, layer::Integer, version, patch)
_check_layer(T, layer)
path = rasterpath(T, layer)
url = rasterurl(T, layer)
path = rasterpath(T, layer; version, patch)
url = rasterurl(T, layer; version, patch)
CHELSA_warn_version(T, layer, version, patch, path)
return _maybe_download(url, path)
end
getraster_keywords(::Type{<:CHELSA{BioClim}}) = (:version,:patch)

rastername(::Type{CHELSA{BioClim}}, layer::Integer) = "CHELSA_bio10_$(lpad(layer, 2, "0")).tif"
function rastername(::Type{CHELSA{BioClim}}, layer::Integer; version::Int = 2, patch = latest_patch(CHELSA, version))
if version == 1
"CHELSA_bio10_$(lpad(layer, 2, "0")).tif"
elseif version == 2
"CHELSA_bio$(layer)_1981-2010_V.2.$patch.tif"
else
CHELSA_invalid_version(version)
end
end

rasterpath(::Type{CHELSA{BioClim}}) = joinpath(rasterpath(CHELSA), "BioClim")
rasterpath(T::Type{CHELSA{BioClim}}, layer::Integer) = joinpath(rasterpath(T), rastername(T, layer))
rasterpath(T::Type{CHELSA{BioClim}}, layer::Integer; version = 2, patch = latest_patch(CHELSA, version)) = joinpath(rasterpath(T), rastername(T, layer; version, patch))

function rasterurl(::Type{CHELSA{BioClim}}; version)
if version == 1
joinpath(rasterurl(CHELSA, version), "climatologies/")
elseif version == 2
joinpath(rasterurl(CHELSA, version), "climatologies/1981-2010/")
else
CHELSA_invalid_version(version)
end
end

rasterurl(T::Type{CHELSA{BioClim}}, layer::Integer; version = 2, patch = latest_patch(CHELSA, version)) =
joinpath(rasterurl(T; version), "bio", rastername(T, layer; version, patch))

### Bioclim+
"""
getraster(source::Type{CHELSA{BioClim}}, [layer]; version = 2, [patch]) => Union{Tuple,String}

Download [`CHELSA`](@ref) [`BioClim`](@ref) data from [chelsa-climate.org](https://chelsa-climate.org/).

# Arguments
- `layer`: iterable of `Symbol`s from `$(layerkeys(BioClimPlus))`. Without a `layer` argument, all layers
will be downloaded, and a `NamedTuple` of paths returned.

# Keyword arguments
$CHELSA_KEYWORDS

Returns the filepath/s of the downloaded or pre-existing files.
"""
getraster(
T::Type{CHELSA{BioClimPlus}},
layer::Union{Tuple,Int,Symbol};
version::Int = 2,
patch::Int = latest_patch(T, version)) = _getraster(T, layer, version, patch)

_getraster(T::Type{CHELSA{BioClimPlus}}, layers::Tuple, version, patch) = _map_layers(T, layers, version, patch)
function _getraster(T::Type{CHELSA{BioClimPlus}}, layer::Symbol, version, patch)
version == 2 || CHELSA_invalid_version(version, 2)
_check_layer(T, layer)
path = rasterpath(T, layer; version, patch)
url = rasterurl(T, layer; version, patch)
return _maybe_download(url, path)
end
getraster_keywords(::Type{<:CHELSA{BioClimPlus}}) = (:version,:patch)


rasterurl(::Type{CHELSA{BioClim}}) = joinpath(rasterurl(CHELSA), "chelsa_V1/climatologies/bio/")
rasterurl(T::Type{CHELSA{BioClim}}, layer::Integer) = joinpath(rasterurl(T), rastername(T, layer))
rastername(T::Type{CHELSA{BioClimPlus}}, layer::Symbol; version = 2, patch = latest_patch(T, version)) = "CHELSA_$(layer)_1981-2010_V.2.$patch.tif"
rasterpath(::Type{CHELSA{BioClimPlus}}) = rasterpath(CHELSA{BioClim})
rasterpath(T::Type{CHELSA{BioClimPlus}}, layer::Symbol; version = 2, patch = latest_patch(T, version)) = joinpath(rasterpath(T), rastername(T, layer; version, patch))
rasterurl(T::Type{CHELSA{BioClimPlus}}, layer::Symbol; version = 2, patch = latest_patch(T, version)) =
joinpath(rasterurl(CHELSA{BioClim}; version), "bio", rastername(T, layer; version, patch))
44 changes: 44 additions & 0 deletions src/chelsa/climate.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
layers(::Type{CHELSA{Climate}}) = (:clt, :cmi, :hurs, :ncdf, :pet, :pr, :rsds, :sfcWind, :tas, :tasmax, :tasmin, :vpd)

"""
getraster(T::Type{CHELSA{Climate}}, [layer::Union{Tuple,Symbol}]; month) => Vector{String}

Download [`CHELSA`](@ref) [`Climate`](@ref) data.

# Arguments
- `layer` `Symbol` or `Tuple` of `Symbol` from `$(layers(CHELSA{Climate}))`.

# Keywords
- `month`: `Integer` or `AbstractArray` of `Integer`. Chosen from `1:12`.

Returns the filepath/s of the downloaded or pre-existing files.
"""
function getraster(T::Type{CHELSA{Climate}}, layers::Union{Tuple,Symbol}; month)
_getraster(T, layers, month)
end

getraster_keywords(::Type{CHELSA{Climate}}) = (:month,)

function _getraster(T::Type{CHELSA{Climate}}, layers, month::AbstractArray)
_getraster.(T, Ref(layers), month)
end
function _getraster(T::Type{CHELSA{Climate}}, layers::Tuple, month::Integer)
_map_layers(T, layers, month)
end
function _getraster(T::Type{CHELSA{Climate}}, layer::Symbol, month::Integer)
_check_layer(T, layer)
path = rasterpath(T, layer; month)
url = rasterurl(T, layer; month)
return _maybe_download(url, path)
end

# Climate layers don't get their own folder
rasterpath(T::Type{<:CHELSA{Climate}}, layer; month) =
joinpath(_rasterpath(T, layer), rastername(T, layer; month))
_rasterpath(T::Type{<:CHELSA{Climate}}, layer) = joinpath(rasterpath(T), string(layer))
rasterpath(T::Type{<:CHELSA{Climate}}) = joinpath(rasterpath(CHELSA), "Climate")
function rastername(T::Type{<:CHELSA{Climate}}, layer; month)
_layer = layer == :pet ? :pet_penman : layer
"CHELSA_$(_layer)_$(_pad2(month))_1981-2010_V.2.1.tif"
end
rasterurl(T::Type{CHELSA{Climate}}, layer::Symbol; month) = joinpath(rasterurl(CHELSA, 2), "climatologies/1981-2010", string(layer), rastername(T, layer; month))
61 changes: 59 additions & 2 deletions src/chelsa/future.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

layers(::Type{<:CHELSA{<:Future{BioClim}}}) = layers(BioClim)
layers(::Type{<:CHELSA{T}}) where T <:Future{BioClimPlus} = layers(T)
layerkeys(T::Type{<:CHELSA{<:Future{BioClim}}}, args...) = layerkeys(BioClim, args...)

layers(::Type{<:CHELSA{<:Future{Climate}}}) = (:prec, :temp, :tmin, :tmax)
Expand All @@ -24,7 +25,15 @@ returned.

- `date`: a `Date` or `DateTime` object, a Vector, or Tuple of start/end dates.
Note that CHELSA CMIP5 only has two datasets, for the periods 2041-2060 and
2061-2080. Dates must fall within these ranges.
2061-2080. CMIP6 has datasets for the periods 2011-2040, 2041-2070, and 2071-2100.
Dates must fall within these ranges.

## Example
```julia
using RasterDataSources, Dates
getraster(CHELSA{Future{BioClim, CMIP6, GFDLESM4, SSP370}}, 1, date = Date(2050))
```

"""
function getraster(
T::Type{<:CHELSA{<:Future{BioClim}}}, layers::Union{Tuple,Int,Symbol}; date
Expand All @@ -34,6 +43,34 @@ end

getraster_keywords(::Type{<:CHELSA{<:Future{BioClim}}}) = (:date,)

"""
getraster(T::Type{CHELSA{Future{BioClimPlus}}}, [layer]; date) => String

Download CHELSA [`BioClimPlus`](@ref) data, choosing layers from: `$(layers(CHELSA{BioClimPlus}))`.

See the docs for [`Future`](@ref) for model choices.

Without a layer argument, all layers will be downloaded, and a `NamedTuple` of paths
returned.

## Keywords

- `date`: a `Date` or `DateTime` object, a Vector, or Tuple of start/end dates.
Note that CHELSA CMIP5 only has two datasets, for the periods 2041-2060 and
2061-2080. CMIP6 has datasets for the periods 2011-2040, 2041-2070, and 2071-2100.
Dates must fall within these ranges.

## Example
"""
function getraster(
T::Type{<:CHELSA{<:Future{BioClimPlus}}}, layers::Union{Tuple,Int,Symbol}; date
)
_getraster(T, layers, date)
end

getraster_keywords(::Type{<:CHELSA{<:Future{BioClimPlus}}}) = (:date,)


"""
getraster(T::Type{CHELSA{Future{Climate}}}, [layer]; date, month) => String

Expand All @@ -47,8 +84,15 @@ Without a layer argument, all layers will be downloaded, and a `NamedTuple` of p

- `date`: a `Date` or `DateTime` object, a Vector, or Tuple of start/end dates.
Note that CHELSA CMIP5 only has two datasets, for the periods 2041-2060 and
2061-2080. Dates must fall within these ranges.
2061-2080. CMIP6 has datasets for the periods 2011-2040, 2041-2070, and 2071-2100.
Dates must fall within these ranges.
- `month`: the month of the year, from 1 to 12, or a array or range of months like `1:12`.

## Example
```
using Dates, RasterDataSources
getraster(CHELSA{Future{Climate, CMIP6, GFDLESM4, SSP370}}, :prec; date = Date(2050), month = 1)
```
"""
function getraster(
T::Type{<:CHELSA{<:Future{Climate}}}, layers::Union{Tuple,Symbol}; date, month
Expand Down Expand Up @@ -84,6 +128,12 @@ end
function _getraster(T::Type{<:CHELSA{<:Future{BioClim}}}, layers, date::TimeType)
_getraster(T, layers; date)
end
function _getraster(T::Type{<:CHELSA{<:Future{BioClimPlus}}}, layers, dates::AbstractArray)
map(date -> _getraster(T, layers, date), dates)
end
function _getraster(T::Type{<:CHELSA{<:Future{BioClimPlus}}}, layers, date::TimeType)
_getraster(T, layers; date)
end

# We have the extra args as keywords again to generalise rasterpath/rasterurl
function _getraster(T::Type{<:CHELSA{<:Future}}, layers::Tuple; kw...)
Expand Down Expand Up @@ -124,6 +174,12 @@ function _rastername(::Type{CMIP6}, T::Type{<:CHELSA{<:Future{BioClim}}}, layer:
scen = _format(CHELSA, _scenario(T))
return "CHELSA_bio$(layer)_$(date_string)_$(mod)_$(scen)_V.2.1.tif"
end
function _rastername(::Type{CMIP6}, T::Type{<:CHELSA{<:Future{BioClimPlus}}}, layer::Symbol; date)
date_string = _date_string(_phase(T), date)
mod = _format(CHELSA, _model(T))
scen = _format(CHELSA, _scenario(T))
return "CHELSA_$(layer)_$(date_string)_$(mod)_$(scen)_V.2.1.tif"
end
function _rastername(
::Type{CMIP6}, T::Type{<:CHELSA{<:Future{Climate}}}, layer::Symbol; date, month
)
Expand Down Expand Up @@ -151,6 +207,7 @@ function rasterurl(T::Type{<:CHELSA{<:Future}}, layer; date, kw...)
end

_chelsa_layer(::Type{<:BioClim}, layer) = :bio
_chelsa_layer(::Type{<:BioClimPlus}, layer) = :bio
_chelsa_layer(::Type{<:Climate}, layer) = layer

function _urlpath(::Type{CMIP5}, T::Type{<:CHELSA{<:Future}}, name, date_str)
Expand Down
40 changes: 37 additions & 3 deletions src/chelsa/shared.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,47 @@
"""
CHELSA{Union{BioClim,<:Future}} <: RasterDataSource
CHELSA{Union{BioClim,BioClimPlus,Climate,<:Future}} <: RasterDataSource

Data from CHELSA, currently implements the current `BioClim` and
`Future{BioClim}` variables, and `Future{Climate}`.
Data from CHELSA, currently implements the `BioClim` `BioClimPlus`, and `Climate`
variables for current and future conditions.

See: [chelsa-climate.org](https://chelsa-climate.org/) for the dataset,
and the [`getraster`](@ref) docs for implementation details.
"""
struct CHELSA{X} <: RasterDataSource end

rasterpath(::Type{CHELSA}) = joinpath(rasterpath(), "CHELSA")
function rasterurl(T::Type{CHELSA}, version)
if version == 1
joinpath(rasterurl(T), "chelsa_V1")
elseif version == 2
joinpath(rasterurl(T), "chelsa_V2/GLOBAL")
else
CHELSA_invalid_version(version)
end
end
rasterurl(::Type{CHELSA}) = URI(scheme="https", host="os.zhdk.cloud.switch.ch", path="/envicloud/chelsa/")

function latest_patch(::Type{<:CHELSA}, v)
if v == 1
2
elseif v == 2
1
else
CHELSA_invalid_version(v)
end
end

const CHELSA_KEYWORDS = """
- `version`: `Integer` indicating the CHELSA version, currently either `1` or `2`.
- `patch`: `Integer` indicating the CHELSA patch number. Defaults to the latest patch (V1.2 and V2.1)
"""

CHELSA_invalid_version(v, valid_versions = [1,2]) =
throw(ArgumentError("Version $v is not available for CHELSA. Available versions: $valid_versions."))

function CHELSA_warn_version(T, layer, version, patch, path)
if version == 2 && !isfile(path) && isfile(rasterpath(T, layer; version = 1))
@info "File for CHELSA v1.2 detected, but requested version is CHELSA v$version.$patch.
To load data for CHELSA v1.2 instead, set version keyword to 1"
end
end
Loading
Loading