Mean Seasonal Cycle for a sigle pixel
using CairoMakie
CairoMakie.activate!()
using Dates
using Statistics
We define the data span. For simplicity, three non-leap years were selected.
t = Date("2021-01-01"):Day(1):Date("2023-12-31")
NpY = 3
3
and create some seasonal dummy data
x = repeat(range(0, 2π, length=365), NpY)
var = @. sin(x) + 0.1 * randn()
lines(1:length(t), var; color = :purple, linewidth=1.25,
axis=(; xlabel="Time", ylabel="Variable"),
figure = (; resolution = (600,400))
)
Currently makie doesn't support time axis natively, but the following function can do the work for now.
function time_ticks(dates; frac=8)
tempo = string.(dates)
lentime = length(tempo)
slice_dates = range(1, lentime, step=lentime ÷ frac)
return slice_dates, tempo[slice_dates]
end
xpos, ticks = time_ticks(t; frac=8)
In order to apply the previous output, we split the plotting function into his 3 components, figure
, axis
and plotted object
, namely
fig, ax, obj = lines(1:length(t), var; color = :purple, linewidth=1.25,
axis=(; xlabel="Time", ylabel="Variable"),
figure = (; resolution = (600,400))
)
ax.xticks = (xpos, ticks)
ax.xticklabelrotation = π / 4
ax.xticklabelalign = (:right, :center)
fig
Define the cube
Let's calculate the mean seasonal cycle of our dummy variable 'var'
function mean_seasonal_cycle(c; ndays = 365)
## filterig by month-day
monthday = map(x->Dates.format(x, "u-d"), collect(c.Time))
datesid = unique(monthday)
## number of years
NpY = Int(size(monthday,1)/ndays)
idx = Int.(zeros(ndays, NpY))
## get the day-month indices for data subsetting
for i in 1:ndays
idx[i,:] = Int.(findall(x-> x == datesid[i], monthday))
end
## compute the mean seasonal cycle
mscarray = map(x->var[x], idx)
msc = mapslices(mean, mscarray, dims=2)
return msc
end
msc = mean_seasonal_cycle(c);
365×1 Matrix{Float64}:
-0.026828628171312697
0.04343008524971354
-0.013963376578375446
0.09632602646594195
0.06785911352648893
0.13640560842186403
-0.019247143570796727
0.15365962258524676
0.2042693941687408
0.16278960247700497
⋮
-0.21315062702210044
-0.083148807147485
-0.07288337556769314
-0.09166918551190778
-0.06616128638997433
-0.16221375342858915
-0.020939015931497735
-0.05280213695003191
-0.06690457207246205
TODO: Apply the new groupby funtion from DD
Plot results: mean seasonal cycle
xpos, ticks = time_ticks(t[1:365]; frac=8)
fig, ax, obj = lines(1:365, var[1:365]; label="2021", color=:black,
linewidth=2.0, linestyle=:dot,
axis = (; xlabel="Time", ylabel="Variable"),
figure=(; size = (600,400))
)
lines!(1:365, var[366:730], label="2022", color=:brown,
linewidth=1.5, linestyle=:dash
)
lines!(1:365, msc[:,1]; label="MSC", color=:dodgerblue, linewidth=2.5)
axislegend()
ax.xticks = (xpos, ticks)
ax.xticklabelrotation = π / 4
ax.xticklabelalign = (:right, :center)
fig
current_figure()