1
+ """
2
+ PaddedDiskArray <: AbstractDiskArray
3
+
4
+ PaddedDiskArray(A, padding; fill=zero(eltype(A)))
5
+
6
+ An `AbstractDiskArray` that adds padding to the edges of the parent array.
7
+ This can help changing chunk offsets or padding a larger than memory array
8
+ before windowing operations.
9
+
10
+ # Arguments
11
+
12
+ - `A`: The parent disk array.
13
+ - `padding`: A tuple of `Int` lower and upper padding tuples, one for each dimension.
14
+
15
+ # Keywords
16
+
17
+ - `fill=zero(eltype(A))`: The value to pad the array with.
18
+ """
19
+ struct PaddedDiskArray{T,N,A<: AbstractArray{T,N} ,C,F<: T } <: AbstractDiskArray{T,N}
20
+ parent:: A
21
+ padding:: NTuple{N,Tuple{Int,Int}}
22
+ fill:: F
23
+ chunks:: C
24
+ end
25
+ function PaddedDiskArray (A:: AbstractArray{T,N} , padding:: NTuple{N,Tuple{Int,Int}} ;
26
+ fill= zero (eltype (A)),
27
+ ) where {T,N}
28
+ map (padding) do (l, u)
29
+ (l < 0 || u < 0 ) && throw (ArgumentError (" Padding must be non-negative" ))
30
+ end
31
+ chunks = GridChunks (map (_pad_offset, eachchunk (A). chunks, padding))
32
+ PaddedDiskArray (A, padding, fill, chunks)
33
+ end
34
+
35
+ function _pad_offset (c:: RegularChunks , (low, high))
36
+ chunksize = c. chunksize
37
+ # Handle lower padding larger than chunksize
38
+ offset = if low == 0
39
+ c. offset
40
+ else
41
+ c. offset - low + chunksize * (div (low - 1 , chunksize) + 1 )
42
+ end
43
+ size = c. arraysize + low + high
44
+ return RegularChunks (chunksize, offset, size)
45
+ end
46
+ function _pad_offset (c:: IrregularChunks , (low, high))
47
+ nlowchunks = Int (low > 0 )
48
+ nhighchunks = Int (high > 0 )
49
+ offsets = Vector {Int} (undef, length (c. offsets) + nlowchunks + nhighchunks)
50
+ # First offset is always zero
51
+ offsets[begin ] = 0
52
+ # Increase original offsets by lower padding
53
+ for (i, o) in enumerate (c. offsets)
54
+ offsets[i + nlowchunks] = o + low
55
+ end
56
+ # Add offset for start of upper padding
57
+ if nhighchunks > 0
58
+ offsets[end ] = offsets[end - 1 ] + high
59
+ end
60
+ return IrregularChunks (offsets)
61
+ end
62
+
63
+ Base. parent (A:: PaddedDiskArray ) = A. parent
64
+ function Base. size (A:: PaddedDiskArray )
65
+ map (size (parent (A)), A. padding) do s, (low, high)
66
+ s + low + high
67
+ end
68
+ end
69
+
70
+ haschunks (A:: PaddedDiskArray ) = haschunks (parent (A))
71
+ eachchunk (A:: PaddedDiskArray ) = A. chunks
72
+
73
+ readblock! (A:: PaddedDiskArray , data, I:: AbstractRange... ) =
74
+ _readblock_padded (A, data, I... )
75
+ writeblock! (A:: PaddedDiskArray , data, I... ) =
76
+ throw (ArgumentError (" Cannot write to a PaddedDiskArray" ))
77
+
78
+ function _readblock_padded (A, data, I:: AbstractRange... )
79
+ data .= A. fill
80
+ Ipadded = map (I, A. padding) do i, (low, high)
81
+ i .- low
82
+ end
83
+ fs = map (axes (parent (A)), Ipadded) do a, ip
84
+ searchsortedfirst (ip, first (a))
85
+ end
86
+ ls = map (axes (parent (A)), Ipadded) do a, ip
87
+ searchsortedlast (ip, last (a))
88
+ end
89
+ return if all (map (<= , fs, ls))
90
+ Idata = map (:, fs, ls)
91
+ Iparent = map (getindex, Ipadded, Idata)
92
+ data[Idata... ] .= parent (A)[Iparent... ]
93
+ else
94
+ # No overlap, don't read
95
+ data
96
+ end
97
+ end
98
+
99
+ """
100
+
101
+ pad(A, padding; fill=zero(eltype(A)))
102
+
103
+ Pad any `AbstractArray` with fill values, updating chunk patterns.
104
+
105
+ # Arguments
106
+
107
+ - `A`: The parent disk array.
108
+ - `padding`: A tuple of `Int` lower and upper padding tuples, one for each dimension.
109
+
110
+ # Keywords
111
+
112
+ - `fill=zero(eltype(A))`: The value to pad the array with.
113
+ """
114
+ pad (A:: AbstractArray{<:Any,N} , padding:: NTuple{N,Tuple{Int,Int}} ; kw... ) where N =
115
+ PaddedDiskArray (A, padding; kw... )
0 commit comments