-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
204 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
export parse_metadata | ||
|
||
""" | ||
parse_metadata(in_hdf; metadata_field = "StructMetadata.0") | ||
The `metadata_field` follows from the MODIS MCD64A1.061 specification product. | ||
""" | ||
function parse_metadata(in_hdf; metadata_field = "StructMetadata.0") | ||
attr = in_hdf.attributes(); | ||
metadata_string = string.(attr[metadata_field]) | ||
|
||
result = OrderedDict{String, Any}() | ||
stack = [result] | ||
|
||
for line in eachsplit(metadata_string, '\n') | ||
line = rstrip(line) | ||
level = count(x -> x == '\t', line) | ||
line = strip(line) | ||
|
||
if line == "END" | ||
break # Stop parsing when "END" is encountered | ||
elseif startswith(line, "GROUP=") || startswith(line, "OBJECT=") | ||
key = split(line, '=', limit=2)[2] | ||
new_dict = OrderedDict{String, Any}() | ||
stack[end][key] = new_dict | ||
push!(stack, new_dict) | ||
elseif startswith(line, "END_GROUP=") || startswith(line, "END_OBJECT=") | ||
pop!(stack) | ||
elseif contains(line, "=") | ||
key, value = split(line, '=', limit=2) | ||
value = strip(value, ['"']) # Remove quotation marks | ||
# Try to parse as number if possible | ||
try | ||
if contains(value, ",") # Handle tuples | ||
value = Tuple(parse(Float64, v) for v in split(value[2:end-1], ',')) | ||
else | ||
value = parse(Float64, value) | ||
end | ||
catch | ||
# If parsing fails, keep it as a string | ||
end | ||
stack[end][key] = value | ||
end | ||
end | ||
return result | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
function getPixelDay(ba, doy) | ||
day_b = ba .== doy # get indices for day d | ||
day_mask = ba .< 1 # get indices for water, unmmaped and unburned pixels | ||
bmask = ba .* day_mask # compute mask | ||
return ba .* day_b .+ bmask # combine burnt pixels for day d, plus mask | ||
end | ||
|
||
# this one is just for fire or not fire, Bool, true -> 1, false -> 0 | ||
function getPixelDayRaw(ba, doy) | ||
day_b = ba .== doy # get indices for day d | ||
return day_b # ba .* day_b # ouput only 0 or 1 for that day | ||
end | ||
|
||
function monthIntervals(year) | ||
days = Date(year):Day(1):Date("$(year)-12-31") | ||
doy = dayofyear.(days) | ||
meses = Dates.month.(days) | ||
return Pair.(doy, meses) | ||
end | ||
|
||
function initMonthsArray(year) | ||
return ["$(year).$(m).01" for m in ["0".* string.(1:9)..., "10", "11", "12"]] | ||
end | ||
|
||
function getPixelTime(bSpaceTime, i,j) | ||
return [bSpaceTime[k][i,j] for k in eachindex(bSpaceTime)] | ||
end | ||
|
||
function cluster_entries(vec::Vector{T}, gap_length::Int) where T<:Number | ||
result = Vector{Vector{Int}}() | ||
n = length(vec) | ||
current_group = Int[] | ||
zero_count = 0 | ||
for i in 1:n | ||
if vec[i] != zero(T) | ||
if zero_count >= gap_length && !isempty(current_group) | ||
push!(result, current_group) | ||
current_group = Int[] | ||
end | ||
push!(current_group, i) | ||
zero_count = 0 | ||
else | ||
zero_count += 1 | ||
end | ||
end | ||
if !isempty(current_group) | ||
push!(result, current_group) | ||
end | ||
return result | ||
end | ||
|
||
function normalize_groups(groups::Vector{Vector{Int}}) | ||
normPairs = map(groups) do group | ||
group_length = length(group) | ||
normalized_value = 1 ./ group_length # 1 .// group_length | ||
Pair.(group, normalized_value) | ||
end | ||
return vcat(normPairs...) | ||
end | ||
|
||
function updateCounts!(afterBurn, nPairs, i, j) | ||
for (k, v) in nPairs | ||
afterBurn[k][i,j] = v | ||
end | ||
return nothing | ||
end | ||
|
||
function updateAfterBurn!(beforeBurn, afterBurn; burnWindow = 30) | ||
@showprogress for i in 1:size(beforeBurn[1], 1) | ||
for j in 1:size(beforeBurn[1], 2) | ||
onePix = getPixelTime(beforeBurn, i, j) | ||
gBurn = cluster_entries(onePix, burnWindow) | ||
normedPairs = normalize_groups(gBurn) | ||
updateCounts!(afterBurn, normedPairs, i, j) | ||
end | ||
end | ||
return nothing | ||
end | ||
|
||
function averageWindows(sMatrix, n::Int) | ||
rows, cols = size(sMatrix) | ||
# Check if the matrix dimensions are divisible by n | ||
if rows % n != 0 || cols % n != 0 | ||
error("Matrix dimensions must be divisible by n") | ||
end | ||
# Calculate the size of the output matrix | ||
new_rows, new_cols = rows ÷ n, cols ÷ n | ||
# Initialize the output matrix | ||
result = fill(NaN32, new_rows, new_cols) | ||
# Iterate over the windows and calculate averages | ||
for i in 1:new_rows | ||
for j in 1:new_cols | ||
window = @view sMatrix[(i-1)*n+1:i*n, (j-1)*n+1:j*n] | ||
μ = mean(window) | ||
result[i, j] = iszero(μ) ? NaN32 : μ | ||
end | ||
end | ||
return result | ||
end | ||
|
||
function agg(μBurn, afterBurn, tsteps; res = 60) | ||
@showprogress for t_step in 1:tsteps | ||
μBurn[:,:,t_step] = averageWindows(afterBurn[t_step], res) | ||
end | ||
return μBurn | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
|
||
# maybe start first with a complete empty zarr store and then modify in-place instead of creating YAXArrays on the fly | ||
|
||
function appendTile(tile, agg_μBurn, xdim, ydim, tdim, zarrPath) | ||
axlist = ( | ||
Dim{:x}(xdim), | ||
Dim{:y}(ydim), | ||
Dim{:time}(tdim), | ||
) | ||
yax = YAXArray(axlist, agg_μBurn) | ||
ds = YAXArrays.Dataset(; (Symbol(tile) => yax,)...) | ||
# append to file | ||
savedataset(ds, path=zarrPath, driver=:zarr, append=true) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters