11using YAXArrayBase: backendlist, get_var_handle
22using DiskArrayTools
33using DiskArrays: DiskArrays, GridChunks
4+ using DiskArrayEngine: DiskArrayEngine as DAE
45using DimensionalData: DimensionalData as DD, X, Y
56using GeoFormatTypes
67# using PyramidScheme: PyramidScheme as PS
78using Rasters: Raster
9+ import DiskArrays: readblock!, IrregularChunks, AbstractDiskArray
10+ using StatsBase: rle
11+ using Statistics: mean
12+
13+ # DiskArrays.readblock!(a::AbstractArray,aout,i::AbstractUnitRange...) = copyto!(aout,view(a,i...))
14+
15+ struct LazyAggDiskArray{T,F,A} <: AbstractDiskArray{T,3}
16+ f:: F
17+ arrays:: A
18+ inds:: IrregularChunks
19+ s:: Tuple{Int,Int,Int}
20+ end
21+ function LazyAggDiskArray (f,arrays,groups)
22+ allequal (size,arrays) || error (" All Arrays must have same size" )
23+ allequal (eltype,arrays) || error (" All Arrays must have same element type" )
24+ inds = IrregularChunks (;chunksizes= last (rle (groups)))
25+ s = (size (first (arrays))... ,length (inds))
26+ T = Base. promote_op (f,Vector{eltype (first (arrays))})
27+ LazyAggDiskArray {T,typeof(f),typeof(arrays)} (f,arrays,inds,s)
28+ end
29+ Base. size (a:: LazyAggDiskArray ) = a. s
30+ DiskArrays. haschunks (a:: LazyAggDiskArray ) = DiskArrays. haschunks (first (a. arrays))
31+ function DiskArrays. readblock! (a:: LazyAggDiskArray ,aout,i:: UnitRange{Int} ...)
32+ i1,i2,itime = i
33+ max_n_array = maximum (it-> length (a. inds[it]),itime)
34+ buf = zeros (eltype (first (a. arrays)),length (i1),length (i2),max_n_array)
35+ for (j, it) in enumerate (itime)
36+ arrays_now = a. arrays[a. inds[it]]
37+ for ia in 1 : length (arrays_now)
38+ DiskArrays. readblock! (arrays_now[ia],view (buf,:,:,ia),i1,i2)
39+ end
40+ vbuf = view (buf,:,:,1 : length (arrays_now))
41+ map! (a. f,view (aout,:,:,j),eachslice (vbuf,dims= (1 ,2 )))
42+ end
43+ end
44+
845
946struct BufferGDALBand{T} <: AG.DiskArrays.AbstractDiskArray{T,2}
1047 filename:: String
@@ -56,7 +93,7 @@ where the difference between neighbouring elements are less than `timediff` mill
5693This returns the indices of the subgroups as a vector of vectors.
5794"""
5895function grouptimes (times, timediff= 200000 )
59- @assert sort (times) == times
96+ @assert issorted (times)
6097 group = [1 ]
6198 groups = [group]
6299
@@ -73,6 +110,24 @@ function grouptimes(times, timediff=200000)
73110 return groups
74111end
75112
113+ function stackindices (times, timediff= 200000 )
114+ @assert issorted (times)
115+ groups = zero (eachindex (times))
116+ group = 1
117+ groups[1 ] = group
118+
119+ for i in 2 : length (times)
120+ period = times[i] - times[i- 1 ]
121+ if period. value < timediff
122+ groups[i] = group
123+ else
124+ group += 1
125+ groups[i] = group
126+ end
127+ end
128+ return groups
129+ end
130+
76131#=
77132function DiskArrays.readblock!(b::GDALBand, aout, r::AbstractUnitRange...)
78133 if !isa(aout,Matrix)
@@ -93,19 +148,52 @@ function DiskArrays.readblock!(b::GDALBand, aout, r::AbstractUnitRange...)
93148end
94149=#
95150
96- function gdalcube (filenames:: AbstractVector{<:AbstractString} )
151+ function gdalcube (filenames:: AbstractVector{<:AbstractString} , stackgroups = :dae )
97152 dates = getdate .(filenames)
153+ @show length (dates)
98154 # Sort the dates and files by DateTime
99155 p = sortperm (dates)
100156 sdates = dates[p]
101157 sfiles = filenames[p]
102- taxis = DD. Ti (sdates)
103158
104159 # @show sdates
105160 # Put the dates which are 200 seconds apart into groups
106- # groupinds = grouptimes(sdates, 200000)
161+ if stackgroups in [:dae , :lazyagg ]
162+ groupinds = grouptimes (sdates, 200000 )
163+ onefile = first (sfiles)
164+ gd = backendlist[:gdal ]
165+ yax1 = gd (onefile)
166+ # gdb = yax1["Gray"]
167+ # onecube = Cube(onefile)
168+ # @show onecube.axes
169+ gdb = get_var_handle (yax1, " Gray" )
170+ gdbband = gdb. band
171+ gdbsize = gdb. size
172+ gdbattrs = gdb. attrs
173+ gdbcs = gdb. cs
174+ group_gdbs = map (sfiles) do f
175+ BufferGDALBand {eltype(gdb)} (f, gdbband, gdbsize, gdbattrs, gdbcs, Dict {Int,AG.IRasterBand} ())
176+ end
177+
178+ cubelist = CFDiskArray .(group_gdbs, (gdbattrs,))
179+ stackinds = stackindices (sdates)
180+ aggdata = if stackgroups == :dae
181+ gcube = diskstack (cubelist)
182+ aggdata = DAE. aggregate_diskarray (gcube, mean ∘ skipmissing, (3 => stackinds,); strategy= :direct )
183+ else
184+ println (" Construct lazy diskarray" )
185+ LazyAggDiskArray (mean ∘ skipmissing, cubelist, stackinds)
186+ end
187+ # data = DiskArrays.ConcatDiskArray(reshape(groupcubes, (1,1,length(groupcubes))))
188+ dates_grouped = [sdates[group[begin ]] for group in groupinds]
107189
190+ taxis = DD. Ti (dates_grouped)
191+ gcube = Cube (sfiles[1 ])
192+ return YAXArray ((DD. dims (gcube)[1 : 2 ]. .. , taxis), aggdata, gcube. properties,)
193+ else
108194 # datasets = AG.readraster.(sfiles)
195+ taxis = DD. Ti (sdates)
196+
109197 onefile = first (sfiles)
110198 gd = backendlist[:gdal ]
111199 yax1 = gd (onefile)
@@ -125,6 +213,7 @@ function gdalcube(filenames::AbstractVector{<:AbstractString})
125213 end
126214 all_cfs = CFDiskArray (stacked_gdbs, attrs)
127215 return YAXArray ((onecube. axes... , taxis), all_cfs, onecube. properties)
216+ end
128217 # datasetgroups = [datasets[group] for group in groupinds]
129218 # We have to save the vrts because the usage of nested vrts is not working as a rasterdataset
130219 # temp = tempdir()
0 commit comments