@@ -18,30 +18,54 @@ struct ConcatDiskArray{T,N,P,C,HC} <: AbstractDiskArray{T,N}
18
18
chunks:: C
19
19
haschunks:: HC
20
20
end
21
- function ConcatDiskArray (arrays:: AbstractArray{<:AbstractArray{<:Any,N},M} ) where {N,M}
22
- T = mapreduce (eltype, promote_type, init= eltype (first (arrays)), arrays)
23
21
22
+ function ConcatDiskArray (arrays:: AbstractArray{Union{<:AbstractArray,Missing}} )
23
+ et = Base. nonmissingtype (eltype (arrays))
24
+ T = Union{Missing,eltype (et)}
25
+ N = ndims (arrays)
26
+ M = ndims (et)
27
+ _ConcatDiskArray (arrays, T, Val (N), Val (M))
28
+ end
29
+ function ConcatDiskArray (arrays:: AbstractArray{<:AbstractArray} )
30
+ T = eltype (eltype (arrays))
31
+ N = ndims (arrays)
32
+ M = ndims (eltype (arrays))
33
+ _ConcatDiskArray (arrays, T, Val (N), Val (M))
34
+ end
35
+ function ConcatDiskArray (arrays:: AbstractArray )
36
+ N = ndims (arrays)
37
+ M, T = foldl (arrays, init= (- 1 , Union{})) do (M, T), a
38
+ if ismissing (a)
39
+ (M, promote_type (Missing, T))
40
+ else
41
+ M == - 1 || ndims (a) == M || throw (ArgumentError (" All arrays to concatenate must have equal ndims" ))
42
+ (ndims (a), promote_type (eltype (a), T))
43
+ end
44
+ end
45
+ _ConcatDiskArray (arrays, T, Val (N), Val (M))
46
+ end
47
+
48
+
49
+ function _ConcatDiskArray (arrays, T, :: Val{N} , :: Val{M} ) where {N,M}
24
50
if N > M
25
- newshape = extenddims (size (arrays), size ( first (arrays) ), 1 )
51
+ newshape = extenddims (size (arrays), ntuple (_ -> 1 , N ), 1 )
26
52
arrays1 = reshape (arrays, newshape)
27
53
D = N
28
54
else
29
55
arrays1 = arrays
30
56
D = M
31
57
end
58
+ _ConcatDiskArray (arrays1:: AbstractArray , T, Val (D))
59
+ end
60
+ function _ConcatDiskArray (arrays1:: AbstractArray , T, :: Val{D} ) where {D}
32
61
startinds, sizes = arraysize_and_startinds (arrays1)
33
62
34
63
chunks = concat_chunksize (arrays1)
35
64
hc = Chunked (batchstrategy (chunks))
36
65
37
66
return ConcatDiskArray {T,D,typeof(arrays1),typeof(chunks),typeof(hc)} (arrays1, startinds, sizes, chunks, hc)
38
67
end
39
- function ConcatDiskArray (arrays:: AbstractArray )
40
- # Validate array eltype and dimensionality
41
- all (a -> ndims (a) == ndims (first (arrays)), arrays) ||
42
- error (" Arrays don't have the same dimensions" )
43
- return error (" Should not be reached" )
44
- end
68
+
45
69
extenddims (a:: Tuple{Vararg{Any,N}} , b:: Tuple{Vararg{Any,M}} , fillval) where {N,M} = extenddims ((a... , fillval), b, fillval)
46
70
extenddims (a:: Tuple{Vararg{Any,N}} , _:: Tuple{Vararg{Any,N}} , _) where {N} = a
47
71
@@ -51,6 +75,7 @@ function arraysize_and_startinds(arrays1)
51
75
sizes = map (i -> zeros (Int, i), size (arrays1))
52
76
for i in CartesianIndices (arrays1)
53
77
ai = arrays1[i]
78
+ ismissing (ai) && continue
54
79
sizecur = extenddims (size (ai), size (arrays1), 1 )
55
80
foreach (sizecur, i. I, sizes) do si, ind, sizeall
56
81
if sizeall[ind] == 0
@@ -62,6 +87,9 @@ function arraysize_and_startinds(arrays1)
62
87
end
63
88
end
64
89
r = map (sizes) do sizeall
90
+ # Replace missing sizes with size 1
91
+ replace! (sizeall, 0 => 1 )
92
+ # Add starting 1
65
93
pushfirst! (sizeall, 1 )
66
94
for i in 2 : length (sizeall)
67
95
sizeall[i] = sizeall[i- 1 ] + sizeall[i]
@@ -80,13 +108,24 @@ function readblock!(a::ConcatDiskArray, aout, inds::AbstractUnitRange...)
80
108
# Find affected blocks and indices in blocks
81
109
_concat_diskarray_block_io (a, inds... ) do outer_range, array_range, I
82
110
vout = view (aout, outer_range... )
83
- readblock! (a. parents[I], vout, array_range... )
111
+ if ismissing (I)
112
+ vout .= missing
113
+ else
114
+ readblock! (a. parents[I], vout, array_range... )
115
+ end
84
116
end
85
117
end
86
118
function writeblock! (a:: ConcatDiskArray , aout, inds:: AbstractUnitRange... )
87
119
_concat_diskarray_block_io (a, inds... ) do outer_range, array_range, I
88
120
data = view (aout, outer_range... )
89
- writeblock! (a. parents[I], data, array_range... )
121
+ if ismissing (I)
122
+ if ! all (ismissing, data)
123
+ @warn " Trying to write data to missing array tile, skipping write"
124
+ end
125
+ return
126
+ else
127
+ writeblock! (a. parents[I], data, array_range... )
128
+ end
90
129
end
91
130
end
92
131
@@ -101,17 +140,24 @@ function _concat_diskarray_block_io(f, a::ConcatDiskArray, inds...)
101
140
end
102
141
map (CartesianIndices (blockinds)) do cI
103
142
myar = a. parents[cI]
104
- mysize = extenddims (size (myar), cI. I, 1 )
143
+ size_inferred = map (a. startinds, size (a), cI. I) do si, sa, ii
144
+ ii == length (si) ? sa - si[ii] + 1 : si[ii+ 1 ] - si[ii]
145
+ end
146
+ mysize = extenddims (size_inferred, cI. I, 1 )
105
147
array_range = map (cI. I, a. startinds, mysize, inds) do ii, si, ms, indstoread
106
148
max (first (indstoread) - si[ii] + 1 , 1 ): min (last (indstoread) - si[ii] + 1 , ms)
107
149
end
108
150
outer_range = map (cI. I, a. startinds, array_range, inds) do ii, si, ar, indstoread
109
151
(first (ar)+ si[ii]- first (indstoread)): (last (ar)+ si[ii]- first (indstoread))
110
152
end
111
153
# Shorten array range to shape of actual array
112
- array_range = map ((i, j) -> j, size (myar) , array_range)
154
+ array_range = map ((i, j) -> j, size_inferred , array_range)
113
155
outer_range = fix_outerrangeshape (outer_range, array_range)
114
- f (outer_range, array_range, cI)
156
+ if ismissing (myar)
157
+ f (outer_range, array_range, missing )
158
+ else
159
+ f (outer_range, array_range, cI)
160
+ end
115
161
end
116
162
end
117
163
fix_outerrangeshape (outer_range, array_range) = fix_outerrangeshape ((), outer_range, array_range)
@@ -126,6 +172,7 @@ function concat_chunksize(parents)
126
172
newchunks = map (s -> Vector {Union{RegularChunks,IrregularChunks}} (undef, s), size (parents))
127
173
for i in CartesianIndices (parents)
128
174
array = parents[i]
175
+ ismissing (array) && continue
129
176
chunks = eachchunk (array)
130
177
foreach (chunks. chunks, i. I, newchunks) do c, ind, newc
131
178
if ! isassigned (newc, ind)
0 commit comments