From 0eea112f1e4119f91f88fb814fbcaebd2a0b0a8e Mon Sep 17 00:00:00 2001 From: kdayday Date: Thu, 4 Jun 2026 20:49:40 -0600 Subject: [PATCH 1/4] Flesh out 1-line docstrings for key types --- src/InfrastructureSystems.jl | 75 ++++++++++----- src/abstract_time_series.jl | 40 ++++++-- src/component_container.jl | 13 +-- src/component_uuids.jl | 6 ++ src/components.jl | 22 ++++- src/containers.jl | 7 ++ src/internal.jl | 15 ++- src/serialization.jl | 44 +++++++-- src/supplemental_attribute_associations.jl | 11 +++ src/supplemental_attribute_manager.jl | 22 +++-- src/system_data.jl | 104 ++++++++++++++++++--- src/time_series_manager.jl | 19 ++++ src/time_series_structs.jl | 10 ++ 13 files changed, 316 insertions(+), 72 deletions(-) diff --git a/src/InfrastructureSystems.jl b/src/InfrastructureSystems.jl index a1aa65255..8cb756b82 100644 --- a/src/InfrastructureSystems.jl +++ b/src/InfrastructureSystems.jl @@ -40,66 +40,91 @@ using DocStringExtensions # Do not add export statements. """ -Base type for any struct in the Sienna packages. -All structs must implement a kwarg-only constructor to allow deserializing from a Dict. +Root abstract type for all structs defined in Sienna packages. + +All concrete subtypes must implement a keyword-argument-only constructor so they can be +deserialized from a `Dict` via [`deserialize`](@ref) and [`serialize`](@ref). + +See also: [`InfrastructureSystemsComponent`](@ref), [`DeviceParameter`](@ref), +[`SupplementalAttribute`](@ref) """ abstract type InfrastructureSystemsType end """ -Base type for structs that are stored in a system. +Base type for structs that are stored in a system as top-level members. + +Components are added with [`add_component!`](@ref) and retrieved with +[`get_component`](@ref) and [`get_components`](@ref). Each component carries an +[`InfrastructureSystemsInternal`](@ref) instance for identity and optional extension data. Required interface functions for subtypes: Note: InfrastructureSystems provides default implementations for these methods that depend on the struct field names `name` and `internal`. If subtypes have different field names, they must implement these methods. - - get_name() - - set_name_internal!() - - get_internal() + - [`get_name`](@ref) + - [`set_name_internal!`](@ref) + - [`get_internal`](@ref) -Warning: Subtypes should not implement the function - set_name!(::InfrastructureSystemsComponent, name). - InfrastructureSystems uses the component name in internal data structures, so it is not - safe to change the name of a component after it has been added to a system. - InfrastructureSystems provides set_name!(data::SystemData, component, name) for this - purpose. +Warning: Subtypes should not implement [`set_name!`](@ref) on the component type directly. +InfrastructureSystems uses the component name in internal data structures, so it is not +safe to change the name of a component after it has been added to a system. +Rename attached components through [`SystemData`](@ref) instead. Optional interface functions: Subtypes must implement this method. The default throws a `NotImplementedError`. - - get_available() + - [`get_available`](@ref) Subtypes must implement this method. The default throws a `NotImplementedError`. - - set_available!() + - [`set_available!`](@ref) Subtypes may contain time series and be associated with supplemental attributes. Those behaviors can be modified with these methods: - - supports_supplemental_attributes() - - supports_time_series() + - [`supports_supplemental_attributes`](@ref) + - [`supports_time_series`](@ref) + +See also: [`DeviceParameter`](@ref), [`SupplementalAttribute`](@ref), +[`ComponentContainer`](@ref) """ abstract type InfrastructureSystemsComponent <: InfrastructureSystemsType end """ -Base type for auxillary structs. These should not be stored in a system. +Base type for auxiliary structs that describe the dynamic, economic, or financial +characteristics of an [`InfrastructureSystemsComponent`](@ref). + +Unlike components, `DeviceParameter` subtypes are not added to a system with +[`add_component!`](@ref). They are stored as nested fields on components or on other +`DeviceParameter` subtypes. This decoupling lets the same physical component carry +different parameter sets depending on the modeling context. + +Downstream packages define concrete subtypes for domain-specific data, such as +operational cost representations, dynamic machine sub-models, and inverter control schemes. + +See also: [`InfrastructureSystemsType`](@ref), [`InfrastructureSystemsComponent`](@ref) """ abstract type DeviceParameter <: InfrastructureSystemsType end """ -Base type for structs that store supplemental attributes +Base type for structs that store supplemental attributes attached to components. + +Unlike [`InfrastructureSystemsComponent`](@ref)s, supplemental attributes are not stored in +[`SystemData`](@ref) component containers. They are owned by +[`SupplementalAttributeManager`](@ref) and linked to components through +[`SupplementalAttributeAssociations`](@ref). Required interface functions for subtypes: - - get_internal() + - [`get_internal`](@ref) Optional interface functions: - - get_uuid() - -Subtypes may contain time series. Which requires + - [`get_uuid`](@ref) + - [`supports_time_series`](@ref) - - `supports_time_series(::SupplementalAttribute)` - -All subtypes must include an instance of ComponentUUIDs in order to track +All subtypes must include an instance of [`ComponentUUIDs`](@ref) in order to track components attached to each attribute. + +See also: [`SupplementalAttributeManager`](@ref), [`add_supplemental_attribute!`](@ref) """ abstract type SupplementalAttribute <: InfrastructureSystemsType end diff --git a/src/abstract_time_series.jl b/src/abstract_time_series.jl index 4a6029d4f..8a95f85dd 100644 --- a/src/abstract_time_series.jl +++ b/src/abstract_time_series.jl @@ -1,7 +1,10 @@ """ -Abstract type for time_series that are stored in a system. -Users never create them or get access to them. -Stores references to TimeSeriesData. +Metadata describing a time series attached to a [`TimeSeriesOwners`](@ref) instance. + +Users do not construct metadata directly. It is created by [`add_time_series!`](@ref) and +used internally to locate [`TimeSeriesData`](@ref) in [`TimeSeriesStorage`](@ref). + +See also: [`ForecastMetadata`](@ref), [`StaticTimeSeriesMetadata`](@ref) """ abstract type TimeSeriesMetadata <: InfrastructureSystemsType end @@ -26,8 +29,22 @@ function make_features_string(; features...) return JSON3.write(data) end +""" +Metadata for forecast (multi-window) time series. + +Concrete subtypes are generated from descriptors (for example, +[`DeterministicMetadata`](@ref), [`ScenariosMetadata`](@ref)). + +See also: [`TimeSeriesMetadata`](@ref), [`Forecast`](@ref) +""" abstract type ForecastMetadata <: TimeSeriesMetadata end +""" +Metadata for static (single-window) time series. + +See also: [`TimeSeriesMetadata`](@ref), [`StaticTimeSeries`](@ref), +[`SingleTimeSeriesMetadata`](@ref) +""" abstract type StaticTimeSeriesMetadata <: TimeSeriesMetadata end get_interval(::StaticTimeSeriesMetadata) = nothing @@ -41,9 +58,20 @@ function get_horizon_count(metadata::ForecastMetadata) end """ -Abstract type for time series stored in the system. -Components store references to these through TimeSeriesMetadata values so that data can -reside on storage media instead of memory. +Abstract type for time series arrays stored outside component structs. + +Components and [`SupplementalAttribute`](@ref)s hold [`TimeSeriesMetadata`](@ref) +references so large arrays can live in [`TimeSeriesStorage`](@ref) instead of memory. + +Required interface for subtypes: + - `Base.length` + - `check_time_series_data` + - `get_resolution` + - `make_time_array` + - `eltype_data` + +See also: [`TimeSeriesManager`](@ref), [`get_time_series`](@ref), [`Forecast`](@ref), +[`StaticTimeSeries`](@ref) """ abstract type TimeSeriesData <: InfrastructureSystemsType end diff --git a/src/component_container.jl b/src/component_container.jl index 7bebb9d29..d42c6ed8e 100644 --- a/src/component_container.jl +++ b/src/component_container.jl @@ -1,10 +1,11 @@ """ -A data structure that acts like a container of components. The `ComponentContainer` -interface consists of: - - `get_components` - - `get_component` - - `get_available_components` - - `get_available_component` +Abstract type for containers of [`InfrastructureSystemsComponent`](@ref)s. + +The `ComponentContainer` interface consists of: + - [`get_components`](@ref) + - [`get_component`](@ref) + - [`get_available_components`](@ref) + - [`get_available_component`](@ref) Notable subtypes include [`Components`](@ref), [`SystemData`](@ref), and [`PowerSystems.System`](@extref). diff --git a/src/component_uuids.jl b/src/component_uuids.jl index fbcfdb54c..1f4895b52 100644 --- a/src/component_uuids.jl +++ b/src/component_uuids.jl @@ -1,6 +1,12 @@ # This is an abstraction of a Set in order to enable de-serialization of supplemental # attributes. +""" +Set-like storage of component UUIDs attached to a [`SupplementalAttribute`](@ref). + +Supplemental attribute subtypes include a `ComponentUUIDs` field so associations can be +tracked and serialized without storing full component references. +""" struct ComponentUUIDs <: InfrastructureSystemsType uuids::Set{Base.UUID} diff --git a/src/components.jl b/src/components.jl index d3328d9fc..43641818d 100644 --- a/src/components.jl +++ b/src/components.jl @@ -1,6 +1,12 @@ const ComponentsByType = Dict{DataType, Dict{String, <:InfrastructureSystemsComponent}} -"A simple container for components and time series data." +""" +Concrete [`ComponentContainer`](@ref) backing regular and masked component storage in +[`SystemData`](@ref). + +Components are indexed by concrete type and name. Name uniqueness is enforced per type +when adding with [`add_component!`](@ref). +""" struct Components <: ComponentContainer data::ComponentsByType time_series_manager::TimeSeriesManager @@ -55,12 +61,18 @@ function _add_component!( end """ -Add a component. +Add a component to a [`Components`](@ref) container. + +Validates field ranges when validation descriptors are configured and rejects components +that already carry time series unless `allow_existing_time_series` is set. + +# Throws -Throws ArgumentError if the component's name is already stored for its concrete type. + - `ArgumentError` if the component name is already stored for its concrete type, if the + type is not concrete, or if the component already has time series. + - `InvalidValue` if field validation fails. -Throws InvalidRange if any of the component's field values are outside of defined valid -range. +See also: [`add_component!`](@ref) on [`SystemData`](@ref) """ function add_component!( components::Components, diff --git a/src/containers.jl b/src/containers.jl index bb97f9f30..0f1a08c8f 100644 --- a/src/containers.jl +++ b/src/containers.jl @@ -1,3 +1,10 @@ +""" +Parent abstract type for top-level containers stored in a [`SystemData`](@ref) instance. + +Concrete subtypes include [`ComponentContainer`](@ref) (for components) and +[`SupplementalAttributeManager`](@ref) (for supplemental attributes). Containers expose +their members through package-specific query methods rather than direct field access. +""" abstract type InfrastructureSystemsContainer <: InfrastructureSystemsType end get_display_string(x::InfrastructureSystemsContainer) = string(nameof(typeof(x))) diff --git a/src/internal.jl b/src/internal.jl index 412fbe99f..d6a087bb3 100644 --- a/src/internal.jl +++ b/src/internal.jl @@ -22,13 +22,26 @@ end serialize(val::SystemUnitsSettings) = serialize_struct(val) deserialize(T::Type{<:SystemUnitsSettings}, val::Dict) = deserialize_struct(T, val) +""" +References to system-level managers wired into attached components and attributes. + +When a component or [`SupplementalAttribute`](@ref) is attached to a [`SystemData`](@ref) +instance, [`add_component!`](@ref) and [`add_supplemental_attribute!`](@ref) store a +`SharedSystemReferences` in its [`InfrastructureSystemsInternal`](@ref) so time series and +supplemental-attribute operations can reach the owning [`TimeSeriesManager`](@ref) and +[`SupplementalAttributeManager`](@ref) without passing the system explicitly. +""" @kwdef struct SharedSystemReferences <: InfrastructureSystemsType supplemental_attribute_manager::Any = nothing time_series_manager::Any = nothing end """ -Internal storage common to InfrastructureSystems types. +Internal storage common to [`InfrastructureSystemsType`](@ref)s. + +Every component and supplemental attribute carries a UUID, optional +[`SharedSystemReferences`](@ref) when attached to a system, optional unit metadata, and an +optional user extension dictionary accessed through [`get_ext`](@ref). """ mutable struct InfrastructureSystemsInternal <: InfrastructureSystemsType uuid::Base.UUID diff --git a/src/serialization.jl b/src/serialization.jl index f9999a905..2bf357deb 100644 --- a/src/serialization.jl +++ b/src/serialization.jl @@ -7,7 +7,14 @@ const CONSTRUCT_WITH_PARAMETERS_KEY = "construct_with_parameters" const FUNCTION_KEY = "function" """ -Serializes a InfrastructureSystemsType to a JSON file. +Write an [`InfrastructureSystemsType`](@ref) to a JSON file. + +This is a convenience wrapper around [`serialize`](@ref) and JSON encoding. For +[`SystemData`](@ref), call [`prepare_for_serialization_to_file!`](@ref) first so time series +sidecar paths are recorded. + +See also: [`to_json`](@ref to_json(obj::T; pretty = false, indent = 2) where T <: InfrastructureSystemsType), +[`from_json`](@ref) """ function to_json( obj::T, @@ -27,7 +34,10 @@ function to_json( end """ -Serializes a InfrastructureSystemsType to a JSON string. +Return a JSON string for an [`InfrastructureSystemsType`](@ref). + +See also: [`to_json`](@ref to_json(obj::T, filename::AbstractString; force = false, pretty = false) where T <: InfrastructureSystemsType), +[`serialize`](@ref), [`from_json`](@ref) """ function to_json(obj::T; pretty = false, indent = 2) where {T <: InfrastructureSystemsType} try @@ -61,7 +71,10 @@ function to_json( end """ -Deserializes a InfrastructureSystemsType from a JSON filename. +Read an [`InfrastructureSystemsType`](@ref) from a JSON file. + +See also: [`from_json`](@ref from_json(io::Union{IO, String}, ::Type{T}) where T <: InfrastructureSystemsType), +[`deserialize`](@ref), [`to_json`](@ref) """ function from_json(::Type{T}, filename::String) where {T <: InfrastructureSystemsType} return open(filename) do io @@ -70,16 +83,24 @@ function from_json(::Type{T}, filename::String) where {T <: InfrastructureSystem end """ -Deserializes a InfrastructureSystemsType from String or IO. +Read an [`InfrastructureSystemsType`](@ref) from a JSON string or IO stream. + +See also: [`from_json`](@ref from_json(::Type{T}, filename::String) where T <: InfrastructureSystemsType), +[`deserialize`](@ref) """ function from_json(io::Union{IO, String}, ::Type{T}) where {T <: InfrastructureSystemsType} return deserialize(T, JSON3.read(io, Dict)) end """ -Serialize the Julia value into standard types that can be converted to non-Julia formats, -such as JSON. In cases where val is an instance of a struct, return a Dict. In cases where -val is a scalar value, return that value. +Convert an [`InfrastructureSystemsType`](@ref) into JSON-compatible `Dict`s and scalars. + +Generic structs are encoded as `Dict`s with [`add_serialization_metadata!`](@ref) type +information so [`deserialize`](@ref) can reconstruct them. For [`SystemData`](@ref), +[`serialize(::SystemData)`](@ref) additionally writes time series sidecar files when +[`prepare_for_serialization_to_file!`](@ref) has been called. + +See also: [`to_dict`](@ref), [`to_json`](@ref) """ function serialize(val::T) where {T <: InfrastructureSystemsType} @debug "serialize InfrastructureSystemsType" _group = LOG_GROUP_SERIALIZATION val T @@ -156,8 +177,13 @@ serialize(val::Base.RefValue{T}) where {T} = serialize(val[]) serialize(val::T) where {T} = deepcopy(val) """ -Deserialize an object from standard types stored in non-Julia formats, such as JSON, into -Julia types. +Reconstruct an [`InfrastructureSystemsType`](@ref) from serialized `Dict` data. + +For [`SystemData`](@ref), downstream packages must deserialize individual components +separately after the container is loaded because component types are defined outside +InfrastructureSystems. + +See also: [`serialize`](@ref), [`from_json`](@ref) """ function deserialize(::Type{T}, data::Dict) where {T <: InfrastructureSystemsType} @debug "deserialize InfrastructureSystemsType" _group = LOG_GROUP_SERIALIZATION T data diff --git a/src/supplemental_attribute_associations.jl b/src/supplemental_attribute_associations.jl index 3321c1f72..754210ca7 100644 --- a/src/supplemental_attribute_associations.jl +++ b/src/supplemental_attribute_associations.jl @@ -28,6 +28,17 @@ mutable struct SupplementalAttributeAssociations # If you add any fields, ensure they are managed in deepcopy_internal below. end +""" +SQLite-backed store linking [`SupplementalAttribute`](@ref)s to +[`InfrastructureSystemsComponent`](@ref)s. + +Owned by [`SupplementalAttributeManager`](@ref). Associations are serialized into the +system JSON file rather than a separate sidecar database. + +See also: [`add_supplemental_attribute!`](@ref), [`list_associated_component_uuids`](@ref) +""" +SupplementalAttributeAssociations + """ Construct a new SupplementalAttributeAssociations with an in-memory database. """ diff --git a/src/supplemental_attribute_manager.jl b/src/supplemental_attribute_manager.jl index 9cbfb12d6..4a3df1a61 100644 --- a/src/supplemental_attribute_manager.jl +++ b/src/supplemental_attribute_manager.jl @@ -1,6 +1,16 @@ const SupplementalAttributesByType = Dict{DataType, Dict{Base.UUID, <:SupplementalAttribute}} +""" +Owns supplemental attributes and their associations to components in a [`SystemData`](@ref). + +Attributes are stored by type and UUID. Component links are tracked in +[`SupplementalAttributeAssociations`](@ref). User code typically calls +[`add_supplemental_attribute!`](@ref) on [`SystemData`](@ref) rather than on the manager +directly. + +See also: [`SupplementalAttribute`](@ref), [`iterate_supplemental_attributes`](@ref) +""" mutable struct SupplementalAttributeManager <: InfrastructureSystemsContainer data::SupplementalAttributesByType associations::SupplementalAttributeAssociations @@ -204,16 +214,16 @@ function remove_supplemental_attributes!( end """ -Returns an iterator of supplemental_attributes. T can be concrete or abstract. +Returns an iterator of supplemental attributes. T can be concrete or abstract. Call collect on the result if an array is desired. # Arguments - - `T`: supplemental_attribute type - - `mgr::SupplementalAttributeManager`: SupplementalAttributeManager in the system - - `filter_func::Union{Nothing, Function} = nothing`: Optional function that accepts a component - of type T and returns a Bool. Apply this function to each component and only return components - where the result is true. + - `T`: supplemental attribute type + - `mgr::SupplementalAttributeManager`: manager in the system + - `filter_func::Union{Nothing, Function} = nothing`: Optional function that accepts a + supplemental attribute of type `T` and returns a `Bool`. Only attributes for which + the function returns true are included. """ function get_supplemental_attributes( filter_func::Function, diff --git a/src/system_data.jl b/src/system_data.jl index 554325348..122fac089 100644 --- a/src/system_data.jl +++ b/src/system_data.jl @@ -5,20 +5,24 @@ const VALIDATION_DESCRIPTOR_FILE = "validation_descriptors.json" const SERIALIZATION_METADATA_KEY = "__serialization_metadata__" """ - mutable struct SystemData <: ComponentContainer - components::Components - "Masked components are attached to the system for overall management purposes but - are not exposed in the standard library calls like [`get_components`](@ref). - Examples are components in a subsystem." - masked_components::Components - validation_descriptors::Vector - internal::InfrastructureSystemsInternal - end +Top-level container for [`InfrastructureSystemsComponent`](@ref)s, time series, and +supplemental attributes in a Sienna system. + +Downstream packages typically embed a `SystemData` instance in their own system struct +and redirect container methods such as [`add_component!`](@ref) and +[`get_components`](@ref) to it. + +Regular components live in [`Components`](@ref) and are returned by default +[`get_components`](@ref) calls. Masked components remain attached for bookkeeping (for +example, subsystem membership) but are excluded from those default queries. -Container for system components and time series data +See also: [`ComponentContainer`](@ref), [`TimeSeriesManager`](@ref), +[`SupplementalAttributeManager`](@ref), [`prepare_for_serialization_to_file!`](@ref) """ mutable struct SystemData <: ComponentContainer + "Primary component storage." components::Components + "Masked components are attached to the system for overall management purposes but are not exposed in the standard library calls like [`get_components`](@ref). Examples are components in a subsystem." masked_components::Components "Contains all attached component UUIDs, regular and masked." component_uuids::Dict{Base.UUID, <:InfrastructureSystemsComponent} @@ -43,6 +47,7 @@ Construct SystemData to store components and time series data. in. Default is the environment variable `SIENNA_TIME_SERIES_DIRECTORY` or `tempdir()` if that isn't set. - `compression = CompressionSettings()`: Controls compression of time series data. + See [`CompressionSettings`](@ref). """ function SystemData(; validation_descriptor_file = nothing, @@ -437,7 +442,15 @@ function _handle_component_removal!(data::SystemData, component) end """ -Removes the component from the main container and adds it to the masked container. +Move a component from the main container to the masked container. + +Masked components stay attached to the [`SystemData`](@ref) instance (for example, for +subsystem bookkeeping) but are excluded from default [`get_components`](@ref) calls. + +# Arguments + + - `remove_time_series`: When true, remove time series owned by the component before masking. + - `remove_supplemental_attributes`: When true, detach supplemental attributes before masking. """ function mask_component!( data::SystemData, @@ -882,8 +895,16 @@ function set_component!(metadata::TimeSeriesFileMetadata, data::SystemData, mod: end """ -Parent object should call this prior to serialization so that SystemData can store the -appropriate path information for the time series data. +Prepare a [`SystemData`](@ref) instance for file serialization. + +Records the target directory and basename in the system [`get_ext`](@ref) dictionary so +[`serialize(::SystemData)`](@ref) can write the time series HDF5 sidecar alongside the JSON +system file. + +Typical workflow: `prepare_for_serialization_to_file!` → [`serialize`](@ref) or +[`to_json`](@ref) → read back with [`deserialize`](@ref) or [`from_json`](@ref). + +See also: [`to_dict`](@ref) """ function prepare_for_serialization_to_file!( data::SystemData, @@ -918,7 +939,13 @@ function prepare_for_serialization_to_file!( end """ -Serialize all system and component data to a dictionary. +Serialize all [`SystemData`](@ref) fields except time series arrays into a dictionary. + +Time series metadata and arrays are written to a sidecar file when +[`prepare_for_serialization_to_file!`](@ref) has been called. Use [`serialize`](@ref) on +the full system to obtain the JSON-ready dict including sidecar references. + +See also: [`serialize(::SystemData)`](@ref), [`deserialize`](@ref) """ function to_dict(data::SystemData) TimerOutputs.@timeit_debug SYSTEM_TIMERS "SystemData to_dict" begin @@ -985,6 +1012,14 @@ function serialize(data::SystemData) return json_data end +""" +Reconstruct a [`SystemData`](@ref) container from serialized dictionary data. + +Component instances in `components` and `masked_components` must be deserialized by the +owning package because their concrete types are defined downstream of InfrastructureSystems. + +See also: [`serialize(::SystemData)`](@ref), [`to_dict`](@ref), [`from_json`](@ref) +""" function deserialize( ::Type{SystemData}, raw::Dict; @@ -1085,6 +1120,15 @@ end # Redirect functions to Components +""" +Add a component to a [`SystemData`](@ref) instance. + +Registers the component UUID, wires [`SharedSystemReferences`](@ref) for time series and +supplemental attributes, and delegates storage to the underlying [`Components`](@ref) +container. + +See also: [`add_component!`](@ref) on [`Components`](@ref) +""" function add_component!(data::SystemData, component; kwargs...) _check_add_component(data, component) add_component!(data.components, component; kwargs...) @@ -1380,6 +1424,19 @@ check_component(data::SystemData, component) = check_component(data.components, get_compression_settings(data::SystemData) = get_compression_settings(data.time_series_manager.data_store) +""" +Rename a component that is already stored in the system. + +This is the safe way to change a component name after [`add_component!`](@ref). Updates +the name index in the underlying [`Components`](@ref) container. + +# Throws + + - `ArgumentError` if the component is not attached, the new name is already in use, or + the passed component does not match the stored instance. + +See also: [`set_name!`](@ref) on [`Components`](@ref) +""" set_name!(data::SystemData, component, name) = set_name!(data.components, component, name) function get_component_counts_by_type(data::SystemData) @@ -1416,6 +1473,16 @@ get_forecast_summary_table(data::SystemData) = _get_system_basename(system_file) = splitext(basename(system_file))[1] _get_secondary_basename(system_basename, name) = system_basename * "_" * name +""" +Attach a supplemental attribute to a component in a [`SystemData`](@ref) instance. + +The attribute is stored in [`SupplementalAttributeManager`](@ref) and linked to the +component through [`SupplementalAttributeAssociations`](@ref). Shared system references +are wired so the attribute can use the system [`TimeSeriesManager`](@ref). + +See also: [`add_supplemental_attribute!`](@ref) on +[`SupplementalAttributeManager`](@ref), [`remove_supplemental_attribute!`](@ref) +""" function add_supplemental_attribute!(data::SystemData, component, attribute; kwargs...) # Note that we do not support adding attributes to masked components # and this check doesn't look at those. @@ -1459,6 +1526,15 @@ function iterate_supplemental_attributes(data::SystemData) return iterate_supplemental_attributes(data.supplemental_attribute_manager) end +""" +Detach a supplemental attribute from a component in a [`SystemData`](@ref) instance. + +Removes the association. The attribute itself is deleted from the manager only when no +components remain attached. + +See also: [`remove_supplemental_attribute!`](@ref) on +[`SupplementalAttributeManager`](@ref) +""" remove_supplemental_attribute!( data::SystemData, component::InfrastructureSystemsComponent, diff --git a/src/time_series_manager.jl b/src/time_series_manager.jl index 1ebb7d541..ff06f5ed7 100644 --- a/src/time_series_manager.jl +++ b/src/time_series_manager.jl @@ -6,6 +6,16 @@ mutable struct BulkUpdateTSCache forecast_params::Dict{Tuple{Dates.Period, Dates.Period}, ForecastParameters} end +""" +Owns time series storage and metadata for a [`SystemData`](@ref) instance. + +The manager coordinates [`TimeSeriesStorage`](@ref) (array data) and +[`TimeSeriesMetadataStore`](@ref) (ownership and lookup). Components reach the manager +through [`SharedSystemReferences`](@ref) after [`add_component!`](@ref). + +See also: [`add_time_series!`](@ref), [`clear_time_series!`](@ref), +[`TimeSeriesOwners`](@ref) +""" mutable struct TimeSeriesManager <: InfrastructureSystemsType data_store::TimeSeriesStorage metadata_store::TimeSeriesMetadataStore @@ -173,6 +183,15 @@ function add_time_series!( return ts_key end +""" +Remove all time series metadata and stored arrays managed by a [`TimeSeriesManager`](@ref). + +When called with a [`TimeSeriesOwners`](@ref) argument, only that owner's series are +removed. + +See also: [`clear_time_series!(::TimeSeriesOwners)`](@ref clear_time_series!(owner::TimeSeriesOwners)), +[`prepare_for_removal!`](@ref) +""" function clear_time_series!(mgr::TimeSeriesManager) _throw_if_read_only(mgr) clear_metadata!(mgr.metadata_store) diff --git a/src/time_series_structs.jl b/src/time_series_structs.jl index 49cfd907b..8ab20a54a 100644 --- a/src/time_series_structs.jl +++ b/src/time_series_structs.jl @@ -1,5 +1,15 @@ const TimeSeriesOwners = Union{InfrastructureSystemsComponent, SupplementalAttribute} +""" +Union of types that can own time series metadata and data. + +Both [`InfrastructureSystemsComponent`](@ref)s and [`SupplementalAttribute`](@ref)s may +support time series when [`supports_time_series`](@ref) returns true. Read APIs such as +[`get_time_series`](@ref) and [`has_time_series`](@ref) accept any `TimeSeriesOwners` +value. +""" +TimeSeriesOwners + """ Supertype for keys that can be used to access a desired time series dataset From 21f6b3bd7173be977e6c94119648f9d6c3106557 Mon Sep 17 00:00:00 2001 From: kdayday Date: Fri, 5 Jun 2026 11:28:14 -0600 Subject: [PATCH 2/4] Fix brittle links --- src/serialization.jl | 12 ++++-------- src/time_series_manager.jl | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/serialization.jl b/src/serialization.jl index 2bf357deb..dbac5eedb 100644 --- a/src/serialization.jl +++ b/src/serialization.jl @@ -13,8 +13,7 @@ This is a convenience wrapper around [`serialize`](@ref) and JSON encoding. For [`SystemData`](@ref), call [`prepare_for_serialization_to_file!`](@ref) first so time series sidecar paths are recorded. -See also: [`to_json`](@ref to_json(obj::T; pretty = false, indent = 2) where T <: InfrastructureSystemsType), -[`from_json`](@ref) +See also: [`from_json`](@ref), [`serialize`](@ref) """ function to_json( obj::T, @@ -36,8 +35,7 @@ end """ Return a JSON string for an [`InfrastructureSystemsType`](@ref). -See also: [`to_json`](@ref to_json(obj::T, filename::AbstractString; force = false, pretty = false) where T <: InfrastructureSystemsType), -[`serialize`](@ref), [`from_json`](@ref) +See also: [`serialize`](@ref), [`from_json`](@ref) """ function to_json(obj::T; pretty = false, indent = 2) where {T <: InfrastructureSystemsType} try @@ -73,8 +71,7 @@ end """ Read an [`InfrastructureSystemsType`](@ref) from a JSON file. -See also: [`from_json`](@ref from_json(io::Union{IO, String}, ::Type{T}) where T <: InfrastructureSystemsType), -[`deserialize`](@ref), [`to_json`](@ref) +See also: [`deserialize`](@ref), [`to_json`](@ref) """ function from_json(::Type{T}, filename::String) where {T <: InfrastructureSystemsType} return open(filename) do io @@ -85,8 +82,7 @@ end """ Read an [`InfrastructureSystemsType`](@ref) from a JSON string or IO stream. -See also: [`from_json`](@ref from_json(::Type{T}, filename::String) where T <: InfrastructureSystemsType), -[`deserialize`](@ref) +See also: [`deserialize`](@ref) """ function from_json(io::Union{IO, String}, ::Type{T}) where {T <: InfrastructureSystemsType} return deserialize(T, JSON3.read(io, Dict)) diff --git a/src/time_series_manager.jl b/src/time_series_manager.jl index ff06f5ed7..609c12525 100644 --- a/src/time_series_manager.jl +++ b/src/time_series_manager.jl @@ -189,7 +189,7 @@ Remove all time series metadata and stored arrays managed by a [`TimeSeriesManag When called with a [`TimeSeriesOwners`](@ref) argument, only that owner's series are removed. -See also: [`clear_time_series!(::TimeSeriesOwners)`](@ref clear_time_series!(owner::TimeSeriesOwners)), +See also: [`clear_time_series!(::TimeSeriesOwners)`](@ref clear_time_series!(::TimeSeriesOwners)), [`prepare_for_removal!`](@ref) """ function clear_time_series!(mgr::TimeSeriesManager) From 282c19a7145b0022e73307a691544f736b6cad3a Mon Sep 17 00:00:00 2001 From: kdayday Date: Fri, 5 Jun 2026 11:28:43 -0600 Subject: [PATCH 3/4] Reword InfrastructureSystemsContainer --- src/containers.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/containers.jl b/src/containers.jl index 0f1a08c8f..78bbd11a4 100644 --- a/src/containers.jl +++ b/src/containers.jl @@ -1,9 +1,10 @@ """ Parent abstract type for top-level containers stored in a [`SystemData`](@ref) instance. -Concrete subtypes include [`ComponentContainer`](@ref) (for components) and -[`SupplementalAttributeManager`](@ref) (for supplemental attributes). Containers expose -their members through package-specific query methods rather than direct field access. +Notable specializations include [`Components`](@ref), [`SystemData`](@ref), and +[`SupplementalAttributeManager`](@ref). Component storage uses the [`ComponentContainer`](@ref) +interface. Containers expose their members through package-specific query methods rather +than direct field access. """ abstract type InfrastructureSystemsContainer <: InfrastructureSystemsType end From 2b313054d055ce09d60adfbdbdf341d838e5b6ca Mon Sep 17 00:00:00 2001 From: kdayday Date: Fri, 5 Jun 2026 11:29:10 -0600 Subject: [PATCH 4/4] Reword InfrastructureSystemsComponent --- src/InfrastructureSystems.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/InfrastructureSystems.jl b/src/InfrastructureSystems.jl index 8cb756b82..93a96dc0c 100644 --- a/src/InfrastructureSystems.jl +++ b/src/InfrastructureSystems.jl @@ -73,9 +73,9 @@ Rename attached components through [`SystemData`](@ref) instead. Optional interface functions: - Subtypes must implement this method. The default throws a `NotImplementedError`. + Required only if callers use [`get_available_components`](@ref) or + [`get_available_component`](@ref); otherwise the defaults throw `NotImplementedError`. - [`get_available`](@ref) - Subtypes must implement this method. The default throws a `NotImplementedError`. - [`set_available!`](@ref) Subtypes may contain time series and be associated with supplemental attributes.