Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues with printing of the system #317

Merged
merged 1 commit into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
))
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 @@
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 @@
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

Check warning on line 538 in src/system_data.jl

View check run for this annotation

Codecov / codecov/patch

src/system_data.jl#L536-L538

Added lines #L536 - L538 were not covered by tests

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 @@
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)

Check warning on line 45 in src/utils/print.jl

View check run for this annotation

Codecov / codecov/patch

src/utils/print.jl#L39-L45

Added lines #L39 - L45 were not covered by tests
end
end

Expand Down Expand Up @@ -71,34 +74,40 @@
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")

Check warning on line 87 in src/utils/print.jl

View check run for this annotation

Codecov / codecov/patch

src/utils/print.jl#L86-L87

Added lines #L86 - L87 were not covered by tests
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

Check warning on line 95 in src/utils/print.jl

View check run for this annotation

Codecov / codecov/patch

src/utils/print.jl#L95

Added line #L95 was not covered by tests
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 @@

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 @@
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
Loading