Skip to content

Commit 204325c

Browse files
authored
Merge pull request #373 from anthofflab/patch
Support `missing` backup data
2 parents 9a9aeb9 + 228a736 commit 204325c

File tree

4 files changed

+50
-47
lines changed

4 files changed

+50
-47
lines changed

src/components/connector.jl

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ using Mimi
1010

1111
function run_timestep(p, v, d, ts)
1212
if gettime(ts) >= p.first && gettime(ts) <= p.last
13-
v.output[ts] = p.input1[ts]
13+
input = p.input1
1414
else
15-
v.output[ts] = p.input2[ts]
15+
input = p.input2
1616
end
17+
18+
v.output[ts] = @allow_missing(input[ts])
19+
1720
end
1821
end
1922

@@ -28,10 +31,15 @@ end
2831
last = Parameter() # last year to use the shorter data
2932

3033
function run_timestep(p, v, d, ts)
31-
if gettime(ts) >= p.first && gettime(ts) <= p.last
32-
v.output[ts, :] = p.input1[ts, :]
34+
35+
if gettime(ts) >= p.first && gettime(ts) <= p.last
36+
input = p.input1
3337
else
34-
v.output[ts, :] = p.input2[ts, :]
38+
input = p.input2
39+
end
40+
41+
for r in d.regions
42+
v.output[ts, r] = @allow_missing(input[ts, r])
3543
end
3644
end
3745
end

src/core/connections.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ function connect_param!(md::ModelDef,
125125
dst_param = parameter(dst_comp_def, dst_par_name)
126126
dst_dims = dimensions(dst_param)
127127

128-
backup = convert(Array{number_type(md)}, backup) # converts number type and, if it's a NamedArray, it's converted to Array
128+
backup = convert(Array{Union{Missing, number_type(md)}}, backup) # converts number type and, if it's a NamedArray, it's converted to Array
129129
first = first_period(md, dst_comp_def)
130130
T = eltype(backup)
131131

src/core/time.jl

Lines changed: 35 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -180,46 +180,57 @@ const AnyIndex = Union{Int, Vector{Int}, Tuple, Colon, OrdinalRange}
180180
# TBD: can it be reduced to this?
181181
# const AnyIndex = Union{Int, AbstractRange}
182182

183+
# Helper function for getindex; throws a MissingException if data is missing, otherwise returns data
184+
function _missing_data_check(data)
185+
if data === missing
186+
throw(MissingException("Cannot get index; data is missing. You may have tried to access a value that has not yet been computed."))
187+
else
188+
return data
189+
end
190+
end
191+
192+
# Helper macro used by connector
193+
macro allow_missing(expr)
194+
let e = gensym("e")
195+
retexpr = quote
196+
try
197+
$expr
198+
catch $e
199+
if $e isa MissingException
200+
missing
201+
else
202+
rethrow($e)
203+
end
204+
end
205+
end
206+
return esc(retexpr)
207+
end
208+
end
209+
183210
#
184211
# 3b. TimestepVector
185212
#
186213

187214
function Base.getindex(v::TimestepVector{FixedTimestep{FIRST, STEP}, T}, ts::FixedTimestep{FIRST, STEP, LAST}) where {T, FIRST, STEP, LAST}
188215
data = v.data[ts.t]
189-
if data === missing
190-
error("Cannot get index; data is missing. You may have tried to access a value that has not yet been computed.")
191-
else
192-
return data
193-
end
216+
_missing_data_check(data)
194217
end
195218

196219
function Base.getindex(v::TimestepVector{VariableTimestep{TIMES}, T}, ts::VariableTimestep{TIMES}) where {T, TIMES}
197220
data = v.data[ts.t]
198-
if data === missing
199-
error("Cannot get index; data is missing. You may have tried to access a value that has not yet been computed.")
200-
else
201-
return data
202-
end
221+
_missing_data_check(data)
203222
end
204223

205224
function Base.getindex(v::TimestepVector{FixedTimestep{D_FIRST, STEP}, T}, ts::FixedTimestep{T_FIRST, STEP, LAST}) where {T, D_FIRST, T_FIRST, STEP, LAST}
206225
t = Int(ts.t + (T_FIRST - D_FIRST) / STEP)
207226
data = v.data[t]
208-
if data === missing
209-
error("Cannot get index; data is missing. You may have tried to access a value that has not yet been computed.")
210-
else
211-
return data
212-
end
227+
_missing_data_check(data)
213228
end
214229

215230
function Base.getindex(v::TimestepVector{VariableTimestep{D_FIRST}, T}, ts::VariableTimestep{T_FIRST}) where {T, D_FIRST, T_FIRST}
216231
t = ts.t + findfirst(isequal(T_FIRST[1]), D_FIRST) - 1
217232
data = v.data[t]
218-
if data === missing
219-
error("Cannot get index; data is missing. You may have tried to access a value that has not yet been computed.")
220-
else
221-
return data
222-
end
233+
_missing_data_check(data)
223234
end
224235

225236
# int indexing version supports old-style components and internal functions, not
@@ -274,40 +285,24 @@ Base.lastindex(v::TimestepVector) = length(v)
274285

275286
function Base.getindex(mat::TimestepMatrix{FixedTimestep{FIRST, STEP}, T}, ts::FixedTimestep{FIRST, STEP, LAST}, i::AnyIndex) where {T, FIRST, STEP, LAST}
276287
data = mat.data[ts.t, i]
277-
if data === missing
278-
error("Cannot get index; data is missing. You may have tried to access a value that has not yet been computed.")
279-
else
280-
return data
281-
end
288+
_missing_data_check(data)
282289
end
283290

284291
function Base.getindex(mat::TimestepMatrix{VariableTimestep{TIMES}, T}, ts::VariableTimestep{TIMES}, i::AnyIndex) where {T, TIMES}
285292
data = mat.data[ts.t, i]
286-
if data === missing
287-
error("Cannot get index; data is missing. You may have tried to access a value that has not yet been computed.")
288-
else
289-
return data
290-
end
293+
_missing_data_check(data)
291294
end
292295

293296
function Base.getindex(mat::TimestepMatrix{FixedTimestep{D_FIRST, STEP}, T}, ts::FixedTimestep{T_FIRST, STEP, LAST}, i::AnyIndex) where {T, D_FIRST, T_FIRST, STEP, LAST}
294297
t = Int(ts.t + (T_FIRST - D_FIRST) / STEP)
295298
data = mat.data[t, i]
296-
if data === missing
297-
error("Cannot get index; data is missing. You may have tried to access a value that has not yet been computed.")
298-
else
299-
return data
300-
end
299+
_missing_data_check(data)
301300
end
302301

303302
function Base.getindex(mat::TimestepMatrix{VariableTimestep{D_FIRST}, T}, ts::VariableTimestep{T_FIRST}, i::AnyIndex) where {T, D_FIRST, T_FIRST}
304303
t = ts.t + findfirst(isequal(T_FIRST[1]), D_FIRST) - 1
305304
data = mat.data[t, i]
306-
if data === missing
307-
error("Cannot get index; data is missing. You may have tried to access a value that has not yet been computed.")
308-
else
309-
return data
310-
end
305+
_missing_data_check(data)
311306
end
312307

313308
# int indexing version supports old-style components and internal functions, not

test/test_timesteparrays.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ add_comp!(m, foo, :second)
243243
connect_param!(m, :second=>:par, :first=>:var)
244244
set_param!(m, :first, :par, 1:length(years))
245245

246-
@test_throws ErrorException run(m)
246+
@test_throws MissingException run(m)
247247

248248

249249
end #module

0 commit comments

Comments
 (0)