-
Notifications
You must be signed in to change notification settings - Fork 5
Ice velocity integration #97
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
Changes from 14 commits
ed4f0d8
b3b0015
5633df2
05692d4
e2c4f9e
c278657
43e1f55
084f982
4613425
1f5230f
1c326f6
c9b8221
9c1c119
3a50573
a270f5f
c8a1ec4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ using JLD2 | |
using Distributed | ||
using Statistics | ||
using CairoMakie | ||
using Observables | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this for? I've seen it's some sort of improved There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is used in lines like Observables.connect!(cb.height, @lift CairoMakie.Fixed($(viewport(ax.scene)).widths[2])) whose purpose is to make the colobar have the same height as the heatmap we are plotting. |
||
using Downloads | ||
using HDF5 | ||
using ComponentArrays | ||
|
@@ -24,7 +25,6 @@ import NCDatasets | |
using Unitful: m, rad, ° | ||
using CoordRefSystems | ||
using Dates, DateFormats | ||
using NetCDF | ||
using GR | ||
using DataStructures | ||
using ImageInTerminal | ||
|
@@ -50,14 +50,25 @@ end | |
# ############################################## | ||
|
||
include("setup/config.jl") | ||
# All parameters needed for the models | ||
include("parameters/Parameters.jl") | ||
|
||
# Anything related to managing glacier data used for data assimilation | ||
include("glaciers/data/Data.jl") | ||
|
||
# Anything related to managing glacier topographical and climate variables | ||
include("glaciers/glacier/Glacier.jl") | ||
|
||
# All parameters needed for the models | ||
include("parameters/Parameters.jl") | ||
|
||
# The utils of surface velocity data, glaciers and climate need the struct to be already | ||
# defined since they depend on each other. This is why we import them afterwards | ||
include("glaciers/data/SurfaceVelocityData_utils.jl") | ||
include("glaciers/glacier/glacier2D_utils.jl") | ||
include("glaciers/climate/climate2D_utils.jl") | ||
|
||
# All structures and functions related to ODINN models | ||
include("models/Model.jl") | ||
|
||
# Everything related to running simulations in ODINN | ||
include("simulations/Simulation.jl") | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,12 @@ | ||
export AbstractData | ||
|
||
""" | ||
AbstractData | ||
|
||
Abstract type that represents data. Used to implement `ThicknessData` and `SurfaceVelocityData`. | ||
""" | ||
abstract type AbstractData end | ||
|
||
include("ThicknessData.jl") | ||
include("SurfaceVelocityData.jl") | ||
include("SurfaceVelocityMapping.jl") | ||
include("SurfaceVelocityData.jl") |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,36 +7,38 @@ by providing `nothing` as the default value. | |
`SurfaceVelocityData{F <: AbstractFloat} <: AbstractData` | ||
|
||
# Fields | ||
- `x::Union{Vector{F}, Nothing}`: Easting of observation. | ||
- `y::Union{Vector{F}, Nothing}`: Northing of observation. | ||
- `lat::Union{Vector{F}, Nothing}`: Latitude of observation. | ||
- `lon::Union{Vector{F}, Nothing}`: Longitude of observation. | ||
- `vx::Union{Array{F, 3}, Nothing}`: x component of surface velocity. | ||
- `vy::Union{Array{F, 3}, Nothing}`: y component of surface velocity. | ||
- `vabs::Union{Array{F, 3}, Nothing}`: Absolute ice surface velocity. | ||
- `vx_error::Union{Array{F, 1}, Nothing}`: Error in `vx` | ||
- `vy_error::Union{Array{F, 1}, Nothing}`: Error in `vy` | ||
- `vabs_error::Union{Array{F, 1}, Nothing}`: Error in `vabs`. | ||
- `date::Union{Vector{DateTime}, Nothing}`: Date of observation (mean of `date1` and `date2`) | ||
- `date1::Union{Vector{DateTime}, Nothing}`: First date of adquisition. | ||
- `date2::Union{Vector{DateTime}, Nothing}`: Second date of adquisition. | ||
- `date_error::Union{Vector{Day}, Vector{Millisecond}, Nothing}`: Error in `date`. | ||
- `x::Union{Vector{F}, Nothing}`: Easting of observation. | ||
- `y::Union{Vector{F}, Nothing}`: Northing of observation. | ||
- `lat::Union{Vector{F}, Nothing}`: Latitude of observation. | ||
- `lon::Union{Vector{F}, Nothing}`: Longitude of observation. | ||
- `vx::Union{Vector{Matrix{F}}, Nothing}`: x component of surface velocity. | ||
- `vy::Union{Vector{Matrix{F}}, Nothing}`: y component of surface velocity. | ||
- `vabs::Union{Vector{Matrix{F}}, Nothing}`: Absolute ice surface velocity. | ||
- `vx_error::Union{Vector{F}, Nothing}`: Error in `vx` | ||
- `vy_error::Union{Vector{F}, Nothing}`: Error in `vy` | ||
- `vabs_error::Union{Vector{F}, Nothing}`: Error in `vabs`. | ||
- `date::Union{Vector{DateTime}, Nothing}`: Date of observation (mean of `date1` and `date2`) | ||
- `date1::Union{Vector{DateTime}, Nothing}`: First date of adquisition. | ||
- `date2::Union{Vector{DateTime}, Nothing}`: Second date of adquisition. | ||
- `date_error::Union{Vector{Day}, Vector{Millisecond}, Nothing}`: Error in `date`. | ||
- `glacierGridded::Bool`: Whether the data have been gridded to the glacier grid or not. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not entirely clear what you mean by this. Is there a case where the date is not gridded to the glacier grid? Like, do you use the same struct to store the original raw data and the final data in the glacier grid? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes we use the same struct to store the original raw data and the gridded ones. I don't think we need a specific struct to store the original raw data. Doing so will even come with many memory issues as here we load the data in a lazy mode only when we need them and many of the points in the original data aren't useful since they are outside of the glacier grid. I changed the name to |
||
""" | ||
mutable struct SurfaceVelocityData{F <: AbstractFloat} <: AbstractData | ||
x::Union{Vector{F}, Nothing} | ||
y::Union{Vector{F}, Nothing} | ||
lat::Union{Vector{F}, Nothing} | ||
lon::Union{Vector{F}, Nothing} | ||
vx::Union{Array{F, 3}, Nothing} | ||
vy::Union{Array{F, 3}, Nothing} | ||
vabs::Union{Array{F, 3}, Nothing} | ||
vx_error::Union{Array{F, 1}, Nothing} | ||
vy_error::Union{Array{F, 1}, Nothing} | ||
vabs_error::Union{Array{F, 1}, Nothing} | ||
vx::Union{Vector{Matrix{F}}, Nothing} | ||
vy::Union{Vector{Matrix{F}}, Nothing} | ||
vabs::Union{Vector{Matrix{F}}, Nothing} | ||
Comment on lines
+31
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks good to me! Just curious: any reason why a vector of matrices is better than just a 3D tensor? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's nicer to handle. Since two dimensions are spatial and one is temporal, I feel it's much nicer to iterate through time and get back spatial grids. Otherwise the user needs to know which of the 3 dimensions is time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At the origin it was because the plotting functions assume that spatio-temporal data are a vector of matrix. I don't have a strong opinion except that it should be uniform across the different structs. |
||
vx_error::Union{Vector{F}, Nothing} | ||
vy_error::Union{Vector{F}, Nothing} | ||
vabs_error::Union{Vector{F}, Nothing} | ||
date::Union{Vector{DateTime}, Nothing} | ||
date1::Union{Vector{DateTime}, Nothing} | ||
date2::Union{Vector{DateTime}, Nothing} | ||
date_error::Union{Vector{Day}, Vector{Millisecond}, Nothing} | ||
glacierGridded::Bool | ||
end | ||
|
||
""" | ||
|
@@ -48,24 +50,23 @@ function SurfaceVelocityData(; | |
y::Union{Vector{F}, Nothing} = nothing, | ||
lat::Union{Vector{F}, Nothing} = nothing, | ||
lon::Union{Vector{F}, Nothing} = nothing, | ||
vx::Union{Array{F, 3}, Nothing} = nothing, | ||
vy::Union{Array{F, 3}, Nothing} = nothing, | ||
vabs::Union{Array{F, 3}, Nothing} = nothing, | ||
vx_error::Union{Array{F, 1}, Nothing} = nothing, | ||
vy_error::Union{Array{F, 1}, Nothing} = nothing, | ||
vabs_error::Union{Array{F, 1}, Nothing} = nothing, | ||
vx::Union{Vector{Matrix{F}}, Nothing} = nothing, | ||
vy::Union{Vector{Matrix{F}}, Nothing} = nothing, | ||
vabs::Union{Vector{Matrix{F}}, Nothing} = nothing, | ||
vx_error::Union{Vector{F}, Nothing} = nothing, | ||
vy_error::Union{Vector{F}, Nothing} = nothing, | ||
vabs_error::Union{Vector{F}, Nothing} = nothing, | ||
date::Union{Vector{DateTime}, Nothing} = nothing, | ||
date1::Union{Vector{DateTime}, Nothing} = nothing, | ||
date2::Union{Vector{DateTime}, Nothing} = nothing, | ||
date_error::Union{Vector{Day}, Vector{Millisecond}, Nothing} = nothing, | ||
) where {F <: AbstractFloat} | ||
glacierGridded::Bool = false, | ||
) where {F <: AbstractFloat} | ||
|
||
Constructor for ice surface velocity data based on Rabatel et. al (2023). | ||
|
||
|
||
Important remarks: | ||
- Projections in longitude and latitude assume we are working in the north hemisphere. | ||
If working with south hemisphere glaciers, this needs to be changed. | ||
- The error in velocity is unique per timestamp, rather than being pixel distributed. | ||
- The error in the absolute velocities `vabs_error` is overestimated. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this? Does this come from the paper(s)? And by oversestimated you mean that the error is larger than reported or lower than reported? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, this agreement about the northern hemisphere is quite strong. At the very least I would give a warning somehow (e.g. in case there is a way to infer that we are not in the northern hemisphere) and clearly document this in the docs. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Concerning the errors, this is something that @facusapienza21 implemented, so I'm not 100% sure of the answer. I guess this is because for every point of the grid, we don't have the velocities for every time and we use an upper bound by taking for every grid point the maximum speed over time. In the end the error is overestimated. @facusapienza21 am I right? As for the northern hemisphere restriction, actually this is something that I removed in this PR and the code now supports data in the southern hemisphere too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't remember exactly what was the problem, but as long as you can specify if the projection is done in the north or south hemisphere it should be fine! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think right now we can just do north hemisphere unless we change this code:
Right now this is done for north hemisphere. I think this was also something from the dataset: since the dataset for now is just for the north hemisphere, it is not as clear what will be the argument in the future from the dataset to determine if the datacube is north or south hemisphere. This is a good question for Romain/Antoine, but for now I will keep the comment until we are sure the preprocessing will work with South data. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I suggest we open an issue to keep track of this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In fact, I already changed that line in the PR. The code is now: hemisphere = (y[end]+y[begin])/2 >= 0 ? :north : :south
transform(X,Y) = Sleipnir.UTMercator(X, Y; zone=Int(params_projection["zone"]), hemisphere=hemisphere) Since in the UTM coordinate system, If you think there can be bugs, we can add an assert, put back the remark in the documentation and create an issue for that, but I think that this code will work with dataset in the south hemisphere. |
||
|
||
|
@@ -80,26 +81,39 @@ function SurfaceVelocityData(; | |
y::Union{Vector{F}, Nothing} = nothing, | ||
lat::Union{Vector{F}, Nothing} = nothing, | ||
lon::Union{Vector{F}, Nothing} = nothing, | ||
vx::Union{Array{F, 3}, Nothing} = nothing, | ||
vy::Union{Array{F, 3}, Nothing} = nothing, | ||
vabs::Union{Array{F, 3}, Nothing} = nothing, | ||
vx_error::Union{Array{F, 1}, Nothing} = nothing, | ||
vy_error::Union{Array{F, 1}, Nothing} = nothing, | ||
vabs_error::Union{Array{F, 1}, Nothing} = nothing, | ||
vx::Union{Vector{Matrix{F}}, Nothing} = nothing, | ||
vy::Union{Vector{Matrix{F}}, Nothing} = nothing, | ||
vabs::Union{Vector{Matrix{F}}, Nothing} = nothing, | ||
vx_error::Union{Vector{F}, Nothing} = nothing, | ||
vy_error::Union{Vector{F}, Nothing} = nothing, | ||
vabs_error::Union{Vector{F}, Nothing} = nothing, | ||
date::Union{Vector{DateTime}, Nothing} = nothing, | ||
date1::Union{Vector{DateTime}, Nothing} = nothing, | ||
date2::Union{Vector{DateTime}, Nothing} = nothing, | ||
date_error::Union{Vector{Day}, Vector{Millisecond}, Nothing} = nothing, | ||
) where {F <: AbstractFloat} | ||
glacierGridded::Bool = false, | ||
) where {F <: AbstractFloat} | ||
|
||
ft = Sleipnir.Float | ||
|
||
return SurfaceVelocityData{ft}( | ||
x, y, lat, lon, | ||
vx, vy, vabs, vx_error, vy_error, vabs_error, | ||
date, date1, date2, date_error | ||
date, date1, date2, date_error, glacierGridded | ||
) | ||
end | ||
|
||
|
||
include("surfacevelocitydata_utils.jl") | ||
Base.:(==)(a::SurfaceVelocityData, b::SurfaceVelocityData) = | ||
a.x == b.x && a.y == b.y && a.lat == b.lat && a.lon == b.lon && | ||
a.vx == b.vx && a.vy == b.vy && a.vabs == b.vabs && | ||
a.vx_error == b.vx_error && a.vy_error == b.vy_error && a.vabs_error == b.vabs_error && | ||
a.date == b.date && a.date1 == b.date1 && a.date2 == b.date2 && a.date_error == b.date_error && | ||
a.glacierGridded == b.glacierGridded | ||
|
||
|
||
Base.:(≈)(a::SurfaceVelocityData, b::SurfaceVelocityData) = | ||
safe_approx(a.x, b.x) && safe_approx(a.y, b.y) && safe_approx(a.lat, b.lat) && safe_approx(a.lon, b.lon) && | ||
safe_approx(a.vx, b.vx) && safe_approx(a.vy, b.vy) && safe_approx(a.vabs, b.vabs) && | ||
safe_approx(a.vx_error, b.vx_error) && safe_approx(a.vy_error, b.vy_error) && safe_approx(a.vabs_error, b.vabs_error) && | ||
safe_approx(a.date, b.date) && safe_approx(a.date1, b.date1) && safe_approx(a.date2, b.date2) && safe_approx(a.date_error, b.date_error) && | ||
a.glacierGridded == b.glacierGridded |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is already available from
Rasters.jl
. Did you add it just to have the necessary exported namespaces?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this is just to access
Dim
inSleipnir/test/surface_velocity.jl
for example. If that bothers you we can probably doRasters.Dim
instead.