Skip to content

Commit

Permalink
Merge pull request #317 from daniel-thom/fix-printing
Browse files Browse the repository at this point in the history
Fix issues with printing of the system
  • Loading branch information
jd-lara authored Jan 2, 2024
2 parents 2f8a2dc + 600bfc2 commit c6b7f1b
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 34 deletions.
2 changes: 1 addition & 1 deletion src/components.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ struct Components <: InfrastructureSystemsContainer
validation_descriptors::Vector
end

get_display_string(::Components) = "components"
get_member_string(::Components) = "components"

function Components(
time_series_storage::TimeSeriesStorage,
Expand Down
2 changes: 2 additions & 0 deletions src/containers.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
abstract type InfrastructureSystemsContainer end

get_display_string(x::InfrastructureSystemsContainer) = string(nameof(typeof(x)))

function serialize(container::InfrastructureSystemsContainer)
# time_series_storage and validation_descriptors are serialized elsewhere.
return [serialize(x) for y in values(container.data) for x in values(y)]
Expand Down
2 changes: 1 addition & 1 deletion src/supplemental_attributes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ struct SupplementalAttributes <: InfrastructureSystemsContainer
time_series_storage::TimeSeriesStorage
end

get_display_string(::SupplementalAttributes) = "SupplementalAttributes"
get_member_string(::SupplementalAttributes) = "supplemental attributes"

function SupplementalAttributes(time_series_storage::TimeSeriesStorage)
return SupplementalAttributes(SupplementalAttributesByType(), time_series_storage)
Expand Down
58 changes: 51 additions & 7 deletions src/system_data.jl
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,10 @@ function iterate_components_with_time_series(data::SystemData)
))
end

function iterate_supplemental_attributes_with_time_series(data::SystemData)
iterate_supplemental_attributes_with_time_series(data.attributes)
end

"""
Removes all time series of a particular type from a System.
Expand All @@ -403,13 +407,15 @@ function remove_time_series!(data::SystemData, ::Type{T}) where {T <: TimeSeries
end
end
counts = get_time_series_counts(data)
if counts[3] == 0 # no more forecast objects
if counts[2] == 0 # no more static time series objects
if counts.forecast_count == 0
if counts.static_time_series_count == 0
reset_info!(data.time_series_params)
else
reset_info!(data.time_series_params.forecast_params)
end
end

return
end

"""
Expand Down Expand Up @@ -484,21 +490,59 @@ function check_time_series_consistency(data::SystemData, ::Type{SingleTimeSeries
return first_initial_timestamp, first_len
end

struct TimeSeriesCounts
components_with_time_series::Int
supplemental_attributes_with_time_series::Int
static_time_series_count::Int
forecast_count::Int
end

"""
Return a tuple of counts of components with time series and total time series and forecasts.
Build an instance of TimeSeriesCounts by scanning the system.
"""
function get_time_series_counts(data::SystemData)
component_count = 0
attribute_count = 0
static_time_series_count = 0
forecast_count = 0
# Note that the same time series UUID can exist in in multiple types, such as with
# SingleTimeSeries and DeterministicSingleTimeSeries.
uuids_by_type = Dict{DataType, Set{Base.UUID}}()

function update_time_series_counts(object)
for metadata in iterate_time_series_metadata(get_time_series_container(object))
ts_type = time_series_metadata_to_data(metadata)
if !haskey(uuids_by_type, ts_type)
uuids_by_type[ts_type] = Set{Base.UUID}()
end
uuid = get_time_series_uuid(metadata)
if !in(uuid, uuids_by_type[ts_type])
if ts_type <: StaticTimeSeries
static_time_series_count += 1
elseif ts_type <: Forecast
forecast_count += 1
end
push!(uuids_by_type[ts_type], uuid)
end
end
end

for component in iterate_components_with_time_series(data)
component_count += 1
_ts_count, _forecast_count = get_num_time_series(component)
static_time_series_count += _ts_count
forecast_count += _forecast_count
update_time_series_counts(component)
end

return (component_count, static_time_series_count, forecast_count)
for attr in iterate_supplemental_attributes_with_time_series(data)
attribute_count += 1
update_time_series_counts(attr)
end

return TimeSeriesCounts(
component_count,
attribute_count,
static_time_series_count,
forecast_count,
)
end

"""
Expand Down
2 changes: 2 additions & 0 deletions src/time_series_container.jl
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,5 @@ function deserialize(::Type{TimeSeriesContainer}, data::Vector)

return container
end

iterate_time_series_metadata(container::TimeSeriesContainer) = values(container.data)
59 changes: 34 additions & 25 deletions src/utils/print.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,25 @@ function Base.show(io::IO, container::InfrastructureSystemsContainer)
end

function Base.show(io::IO, ::MIME"text/plain", container::InfrastructureSystemsContainer)
num_components = get_num_members(container)
println(io, "$(get_display_string(container))")
println(io, "==========")
println(io, "Num components: $num_components")
if num_components > 0
num_members = get_num_members(container)
title = get_display_string(container)
member_str = get_member_string(container)
println(io, title)
println(io, "="^length(title))
println(io, "Num $member_str: $num_members")
if num_members > 0
println(io)
show_components_table(io, container; backend = Val(:auto))
show_container_table(io, container; backend = Val(:auto))
end
end

function Base.show(io::IO, ::MIME"text/html", components::Components)
num_components = get_num_components(components)
println(io, "<h2>Components</h2>")
println(io, "<p><b>Num components</b>: $num_components</p>")
if num_components > 0
show_components_table(io, components; backend = Val(:html), standalone = false)
function Base.show(io::IO, ::MIME"text/html", container::InfrastructureSystemsContainer)
num_members = get_num_members(container)
member_str = get_member_string(container)
println(io, "<h2>Members</h2>")
println(io, "<p><b>Num $member_str</b>: $num_members</p>")
if num_members > 0
show_container_table(io, container; backend = Val(:html), standalone = false)
end
end

Expand Down Expand Up @@ -71,34 +74,40 @@ end
function Base.show(io::IO, ::MIME"text/plain", data::SystemData)
show(io, MIME"text/plain"(), data.components)
println(io, "\n")
show(io, MIME"text/plain"(), data.attributes)
println(io, "\n")
show_time_series_data(io, data; backend = Val(:auto))
show(io, data.time_series_params)
end

function Base.show(io::IO, ::MIME"text/html", data::SystemData)
show(io, MIME"text/html"(), data.components)
println(io, "\n")
show(io, MIME"text/html"(), data.attributes)
println(io, "\n")
show_time_series_data(io, data; backend = Val(:html), standalone = false)
show(io, data.time_series_params)
end

function show_time_series_data(io::IO, data::SystemData; kwargs...)
component_count, ts_count, forecast_count = get_time_series_counts(data)
counts = get_time_series_counts(data)
if counts.static_time_series_count == 0 && counts.forecast_count == 0
return
end

res = get_time_series_resolution(data)
res = res <= Dates.Minute(1) ? Dates.Second(res) : Dates.Minute(res)

header = ["Property", "Value"]
table = [
"Components with time series data" string(component_count)
"Total StaticTimeSeries" string(ts_count)
"Total Forecasts" string(forecast_count)
"Components with time series data" string(counts.components_with_time_series)
"Supplemental attributes with time series data" string(counts.supplemental_attributes_with_time_series)
"Total StaticTimeSeries" string(counts.static_time_series_count)
"Total Forecasts" string(counts.forecast_count)
"Resolution" string(res)
]
if component_count == 0
return
end

if forecast_count > 0
if counts.forecast_count > 0
initial_times = get_forecast_initial_times(data)
table2 = [
"First initial time" string(first(initial_times))
Expand Down Expand Up @@ -137,7 +146,7 @@ end

function Base.show(io::IO, ::MIME"text/plain", ist::InfrastructureSystemsComponent)
print(io, summary(ist), ":")
for (name, field_type) in zip(fieldnames(typeof(ist)), fieldtypes(typeof(ist)))
for name in fieldnames(typeof(ist))
obj = getfield(ist, name)
if obj isa InfrastructureSystemsInternal
continue
Expand Down Expand Up @@ -197,14 +206,14 @@ function _get_type_counts(it::FlattenIteratorWrapper)
return data
end

function show_components_table(io::IO, components::Components; kwargs...)
function show_container_table(io::IO, container::InfrastructureSystemsContainer; kwargs...)
header = ["Type", "Count", "Has Static Time Series", "Has Forecasts"]
data = Array{Any, 2}(undef, length(components.data), length(header))
data = Array{Any, 2}(undef, length(container.data), length(header))

type_names = [(strip_module_name(string(x)), x) for x in keys(components.data)]
type_names = [(strip_module_name(string(x)), x) for x in keys(container.data)]
sort!(type_names; by = x -> x[1])
for (i, (type_name, type)) in enumerate(type_names)
vals = components.data[type]
vals = container.data[type]
has_sts = false
has_forecasts = false
for val in values(vals)
Expand Down
12 changes: 12 additions & 0 deletions test/test_time_series.jl
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,12 @@ end
IS.Deterministic(; data = fdata, name = "bystander", resolution = resolution)
IS.add_time_series!(sys, component, bystander)

counts = IS.get_time_series_counts(sys)
@test counts.components_with_time_series == 1
@test counts.supplemental_attributes_with_time_series == 0
@test counts.static_time_series_count == 1
@test counts.forecast_count == 1

# This interval is greater than the max possible.
@test_throws IS.ConflictingInputsError IS.transform_single_time_series!(
sys,
Expand All @@ -365,6 +371,12 @@ end
)
verify_show(sys)

counts = IS.get_time_series_counts(sys)
@test counts.components_with_time_series == 1
@test counts.supplemental_attributes_with_time_series == 0
@test counts.static_time_series_count == 1
@test counts.forecast_count == 2

# The original should still be readable.
single_vals = IS.get_time_series_values(IS.SingleTimeSeries, component, name)
@test single_vals == data
Expand Down

0 comments on commit c6b7f1b

Please sign in to comment.