Skip to content

Commit

Permalink
Merge pull request #373 from anthofflab/patch
Browse files Browse the repository at this point in the history
Support `missing` backup data
  • Loading branch information
davidanthoff authored Dec 19, 2018
2 parents 9a9aeb9 + 228a736 commit 204325c
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 47 deletions.
18 changes: 13 additions & 5 deletions src/components/connector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@ using Mimi

function run_timestep(p, v, d, ts)
if gettime(ts) >= p.first && gettime(ts) <= p.last
v.output[ts] = p.input1[ts]
input = p.input1
else
v.output[ts] = p.input2[ts]
input = p.input2
end

v.output[ts] = @allow_missing(input[ts])

end
end

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

function run_timestep(p, v, d, ts)
if gettime(ts) >= p.first && gettime(ts) <= p.last
v.output[ts, :] = p.input1[ts, :]

if gettime(ts) >= p.first && gettime(ts) <= p.last
input = p.input1
else
v.output[ts, :] = p.input2[ts, :]
input = p.input2
end

for r in d.regions
v.output[ts, r] = @allow_missing(input[ts, r])
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion src/core/connections.jl
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ function connect_param!(md::ModelDef,
dst_param = parameter(dst_comp_def, dst_par_name)
dst_dims = dimensions(dst_param)

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

Expand Down
75 changes: 35 additions & 40 deletions src/core/time.jl
Original file line number Diff line number Diff line change
Expand Up @@ -180,46 +180,57 @@ const AnyIndex = Union{Int, Vector{Int}, Tuple, Colon, OrdinalRange}
# TBD: can it be reduced to this?
# const AnyIndex = Union{Int, AbstractRange}

# Helper function for getindex; throws a MissingException if data is missing, otherwise returns data
function _missing_data_check(data)
if data === missing
throw(MissingException("Cannot get index; data is missing. You may have tried to access a value that has not yet been computed."))
else
return data
end
end

# Helper macro used by connector
macro allow_missing(expr)
let e = gensym("e")
retexpr = quote
try
$expr
catch $e
if $e isa MissingException
missing
else
rethrow($e)
end
end
end
return esc(retexpr)
end
end

#
# 3b. TimestepVector
#

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

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

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

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

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

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

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

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}
t = Int(ts.t + (T_FIRST - D_FIRST) / STEP)
data = mat.data[t, i]
if data === missing
error("Cannot get index; data is missing. You may have tried to access a value that has not yet been computed.")
else
return data
end
_missing_data_check(data)
end

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

# int indexing version supports old-style components and internal functions, not
Expand Down
2 changes: 1 addition & 1 deletion test/test_timesteparrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ add_comp!(m, foo, :second)
connect_param!(m, :second=>:par, :first=>:var)
set_param!(m, :first, :par, 1:length(years))

@test_throws ErrorException run(m)
@test_throws MissingException run(m)


end #module

0 comments on commit 204325c

Please sign in to comment.