Public API Reference
ComponentSelector
PowerAnalytics depends heavily on the ComponentSelector feature of PowerSystems.jl. ComponentSelector documentation can be found here. PowerAnalytics provides some built-in selectors, but much of the power of PowerAnalytics comes from the ability to operate on custom ComponentSelectors.
Input Utilities
PowerAnalytics.create_problem_results_dict — Functioncreate_problem_results_dict(
results_dir::AbstractString,
problem::String;
...
) -> DataStructures.SortedDict{Any, Any, Base.Order.ForwardOrdering}
create_problem_results_dict(
results_dir::AbstractString,
problem::String,
scenarios::Union{Nothing, Vector{<:AbstractString}};
populate_system,
kwargs...
) -> DataStructures.SortedDict{Any, Any, Base.Order.ForwardOrdering}
Accept a directory that contains several results subdirectories (that each contain results, problems, etc. sub-subdirectories) and construct a sorted dictionary from String to PowerSimulations.SimulationProblemResults where the keys are the subdirectory names and the values are loaded results datasets.
Arguments
results_dir::AbstractString: the directory where results subdirectories can be foundproblem::String: the name of the problem to load (e.g.,UC,ED)scenarios::Union{Vector{AbstractString}, Nothing} = nothing: a list of scenario subdirectories to load, ornothingto load all the subdirectoriespopulate_system::Bool = false: whether to automatically load and attach the system; errors iftrueand the system has not been saved with the results. This keyword argument isfalseby default for backwards compatibility, but most PowerAnalytics functionality requires results to have an attached system, so users should typically passpopulate_system = true.kwargs...: further keyword arguments to pass through toget_decision_problem_results
Examples
Suppose we have the directory data_root with subdirectories results1, results2, and results3, where each of these subdirectories contains problems/UC. Then:
# Load results for only `results1` and `results2`:
create_problem_results_dict(data_root, "UC", ["results1", "results2"]; populate_system = true)
# Load results for all three scenarios:
create_problem_results_dict(data_root, "UC"; populate_system = true)See also
create_problem_results_dict is a convenience function that calls public interface in PowerSimulations.jl. To read one results set, or several of them that are not all in the same parent directory, invoke that interface directly as needed:
# Load a single results set
PowerSimulations.get_decision_problem_results(
PowerSimulations.SimulationResults(path_to_individual_results),
problem_name; populate_system = true)Basic Metric Interface
The basic Metric interface consists of calling a Metric itself, for computing one Metric at a time, and the compute_all function for bulk computation. Combined with PowerAnalytics' built-in metrics, this is enough to execute many common computations. See Advanced Metrics Interface for the interface to create custom Metrics.
PowerAnalytics.Metric — TypeA PowerAnalytics Metric specifies how to compute a useful quantity, like active power or curtailment, from a set of results. Many but not all Metrics require a ComponentSelector to specify which available components of the system the quantity should be computed on, and many but not all Metrics return time series results. In addition to how to compute the output — which may be as simple as looking up a variable or parameter in the results but may involve actual computation — Metrics encapsulate default component-wise and time-wise aggregation behaviors. Metrics can be "called" like functions.
PowerAnalytics provides a library of pre-built Metrics, PowerAnalytics.Metrics; users may also build their own. In most cases of custom metric creation, it should suffice to instantiate one of the concrete Metric subtypes PowerAnalytics provides; in special cases, the user can create their own subtype that implements compute.
Examples
Given a PowerSimulations.SimulationProblemResults results:
using PowerAnalytics.Metrics
# Call the built-in `Metric` `calc_active_power` on a `ComponentSelector` to get a
# `DataFrame` of results, where the columns are the groups in the `ComponentSelector` and
# the rows are time:
calc_active_power(make_selector(RenewableDispatch), results)
# Call the built-in `Metric` `calc_system_slack_up`, which refers to the whole system so
# doesn't need a `ComponentSelector`:
calc_system_slack_up(results)PowerAnalytics.TimedMetric — TypeMetrics that return time series.
PowerAnalytics.TimelessMetric — TypeMetrics that do not return time series.
PowerAnalytics.compute_all — Functioncompute_all(
results::InfrastructureSystems.Results,
metrics::Vector{<:TimelessMetric};
...
) -> Any
compute_all(
results::InfrastructureSystems.Results,
metrics::Vector{<:TimelessMetric},
selectors::Union{Nothing, ComponentSelector, Component, Vector};
...
) -> Any
compute_all(
results::InfrastructureSystems.Results,
metrics::Vector{<:TimelessMetric},
selectors::Union{Nothing, ComponentSelector, Component, Vector},
col_names::Union{Nothing, Vector{<:Union{Nothing, AbstractString}}};
kwargs...
) -> Any
Methods of compute_all for TimelessMetrics. For each (metric, selector, col_name) tuple in zip(metrics, selectors, col_names), call compute and collect the results in a DataFrame. All selectors must yield exactly one group.
Arguments
results::IS.Results: the results from which to fetch datametrics::Vector{<:TimelessMetric}: the metrics to computeselectors: either a scalar or vector ofNothing/Component/ComponentSelector: the selectors on which to compute the metrics, or nothing for system/results metrics; broadcast if scalarcol_names::Union{Nothing, Vector{<:Union{Nothing, AbstractString}}} = nothing: a vector of names for the columns of output data. Entries ofnothingdefault to the result ofmetric_selector_to_string;names = nothingis equivalent to an entire vector ofnothingkwargs...: pass through to eachcomputecall
Examples
Given a results with the proper data:
using PowerAnalytics.Metrics
compute_all(results,
[calc_sum_objective_value, calc_sum_solve_time],
[nothing, nothing],
["objective_value", "solve_time"]
) # returns an 1x2 DataFrame with columns `objective_value` and `solve_time`See also: compute_all tuple-based interface
PowerAnalytics.compute_all — Functioncompute_all takes several metrics, single-group ComponentSelectors if relevant, and optionally column names and produces a single table with all the output for a given results set. It can be useful to quickly put together a summary statistics table.
Examples
See the methods.
PowerAnalytics.compute_all — Functioncompute_all(
results::InfrastructureSystems.Results,
metrics::Vector{<:TimedMetric};
...
) -> Any
compute_all(
results::InfrastructureSystems.Results,
metrics::Vector{<:TimedMetric},
selectors::Union{Nothing, ComponentSelector, Component, Vector};
...
) -> Any
compute_all(
results::InfrastructureSystems.Results,
metrics::Vector{<:TimedMetric},
selectors::Union{Nothing, ComponentSelector, Component, Vector},
col_names::Union{Nothing, Vector{<:Union{Nothing, AbstractString}}};
kwargs...
) -> Any
Methods of compute_all for TimedMetrics. For each (metric, selector, col_name) tuple in zip(metrics, selectors, col_names), call compute and collect the results in a DataFrame with a single DateTime column. All selectors must yield exactly one group.
Arguments
results::IS.Results: the results from which to fetch datametrics::Vector{<:TimedMetric}: the metrics to computeselectors: either a scalar or vector ofNothing/Component/ComponentSelector: the selectors on which to compute the metrics, or nothing for system/results metrics; broadcast if scalarcol_names::Union{Nothing, Vector{<:Union{Nothing, AbstractString}}} = nothing: a vector of names for the columns of output data. Entries ofnothingdefault to the result ofmetric_selector_to_string;names = nothingis equivalent to an entire vector ofnothingkwargs...: pass through to eachcomputecall
Examples
Given a results with the proper data:
using PowerAnalytics.Metrics
compute_all(results,
[calc_active_power, calc_curtailment],
[make_selector(ThermalStandard; groupby = :all), make_selector(RenewableDispatch; groupby = :all)],
["thermal_power", "renewable_curtailment"]
) # returns an 8760x3 DataFrame with columns `DateTime`, `thermal_power`, and `renewable_curtailment`See also: compute_all tuple-based interface
PowerAnalytics.compute_all — Methodcompute_all(
results::InfrastructureSystems.Results,
computations::Tuple{Union{TimedMetric, TimelessMetric}, Any, Any}...;
kwargs...
) -> Any
For convenience, a variant signature of compute_all where the metrics, selectors, and column names are specified as a list of tuples rather than three separate lists.
Arguments
results::IS.Results: the results from which to fetch datacomputations::(Tuple{<:T, Any, Any} where T <: Union{TimedMetric, TimelessMetric})...: a list of the computations to perform, where each element is a(metric, selector, col_name)wheremetricis the metric to compute,selectoris theComponentSelectoron which to compute the metric ornothingif not relevant, andcol_nameis the name for the output column of data or nothing to use the defaultkwargs...: pass through to eachcomputecall
Examples
Given a results with the proper data:
my_computations = [
(calc_active_power, make_selector(ThermalStandard; groupby = :all), "thermal_power"),
(calc_curtailment, make_selector(RenewableDispatch; groupby = :all), "renewable_curtailment")
]
compute_all(results, my_computations...)
# The above is equivalent to
compute_all(results,
[calc_active_power, calc_curtailment],
[make_selector(ThermalStandard; groupby = :all), make_selector(RenewableDispatch; groupby = :all)],
["thermal_power", "renewable_curtailment"]
)See also: compute_all non-tuple-based interface
Built-in Metrics
Metrics Submodule
Here is defined a "library" of built-in metrics to execute many common power systems post-processing calculations.
PowerAnalytics.Metrics — ModulePowerAnalytics built-in Metrics. Use names to list what is available.
Examples
using PowerAnalytics
names(PowerAnalytics.Metrics) # lists built-in Metrics
PowerAnalytics.Metrics.calc_active_power # by default, must prefix built-in Metrics with the module name
@isdefined calc_active_power # -> false
using PowerAnalytics.Metrics
@isdefined calc_active_power # -> true, can now refer to built-in Metrics without the prefixPowerAnalytics.Metrics.calc_active_power — ConstantCalculate the active power of the specified ComponentSelector
PowerAnalytics.Metrics.calc_active_power_forecast — ConstantFetch the forecast active power of the specified ComponentSelector
PowerAnalytics.Metrics.calc_active_power_in — ConstantCalculate the active power input to the specified (storage) ComponentSelector
PowerAnalytics.Metrics.calc_active_power_out — ConstantCalculate the active power output of the specified (storage) ComponentSelector
PowerAnalytics.Metrics.calc_capacity_factor — ConstantCalculate the capacity factor (actual production/rated production) of the specified ComponentSelector
PowerAnalytics.Metrics.calc_curtailment — ConstantCalculate the ActivePowerForecast minus the ActivePower of the given ComponentSelector
PowerAnalytics.Metrics.calc_curtailment_frac — ConstantCalculate the curtailment as a fraction of the ActivePowerForecast of the given ComponentSelector
PowerAnalytics.Metrics.calc_discharge_cycles — ConstantCalculate the number of discharge cycles a storage device has gone through in the time period
PowerAnalytics.Metrics.calc_integration — ConstantCalculate the ActivePower of the given ComponentSelector over the sum of the SystemLoadForecast and the SystemLoadFromStorage
PowerAnalytics.Metrics.calc_is_slack_up — ConstantCalculate whether the given time period has system balance slack up of magnitude greater than 0.0001
PowerAnalytics.Metrics.calc_load_forecast — ConstantFetch the forecast active load of the specified ComponentSelector
PowerAnalytics.Metrics.calc_load_from_storage — ConstantCalculate the ActivePowerIn minus the ActivePowerOut of the specified (storage) ComponentSelector
PowerAnalytics.Metrics.calc_net_load_forecast — ConstantSystemLoadForecast minus ActivePowerForecast of the given ComponentSelector
PowerAnalytics.Metrics.calc_production_cost — ConstantCalculate the active power output of the specified ComponentSelector
PowerAnalytics.Metrics.calc_shutdown_cost — ConstantCalculate the shutdown cost of the specified ComponentSelector
PowerAnalytics.Metrics.calc_startup_cost — ConstantCalculate the startup cost of the specified ComponentSelector
PowerAnalytics.Metrics.calc_stored_energy — ConstantCalculate the energy stored in the specified (storage) ComponentSelector
PowerAnalytics.Metrics.calc_sum_bytes_alloc — ConstantSum the bytes allocated to the optimization problems
PowerAnalytics.Metrics.calc_sum_objective_value — ConstantSum the objective values achieved in the optimization problems
PowerAnalytics.Metrics.calc_sum_solve_time — ConstantSum the solve times taken by the optimization problems
PowerAnalytics.Metrics.calc_system_load_forecast — ConstantFetch the forecast active load of all the ElectricLoad Components in the system
PowerAnalytics.Metrics.calc_system_load_from_storage — ConstantFetch the LoadFromStorage of all storage in the system
PowerAnalytics.Metrics.calc_system_slack_up — ConstantCalculate the system balance slack up
PowerAnalytics.Metrics.calc_total_cost — ConstantCalculate the production cost of the specified ComponentSelector, plus the startup and shutdown costs if they are defined
Built-in Selectors
Selector Utilities
PowerAnalytics.parse_generator_categories — Functionparse_generator_categories(
filename;
root_type
) -> Union{Nothing, Dict{String, ComponentSelector}}
Use parse_generator_mapping_file to parse a generator_mapping.yaml file into a dictionary of ComponentSelectors, excluding categories in the 'non_generators' list in metadata.
Arguments
filename: the path to thegenerator_mapping.yamlfileroot_type::Type{<:Component} = PSY.StaticInjection: theComponenttype assumed in cases where there is no more precise information
See also: parse_injector_categories if all injectors are desired
PowerAnalytics.parse_generator_mapping_file — Functionparse_generator_mapping_file(
filename;
root_type
) -> Tuple{Dict{String, ComponentSelector}, Any}
Parse a generator_mapping.yaml file into a dictionary of ComponentSelectors and a dictionary of metadata if present.
Arguments
filename: the path to thegenerator_mapping.yamlfileroot_type::Type{<:Component} = PSY.StaticInjection: theComponenttype assumed in cases where there is no more precise information
PowerAnalytics.parse_injector_categories — Functionparse_injector_categories(
filename;
root_type
) -> Dict{String, ComponentSelector}
Use parse_generator_mapping_file to parse a generator_mapping.yaml file into a dictionary of all ComponentSelectors.
Arguments
filename: the path to thegenerator_mapping.yamlfileroot_type::Type{<:Component} = PSY.StaticInjection: theComponenttype assumed in cases where there is no more precise information
See also: parse_generator_categories if only generators are desired
Selectors Submodule
PowerAnalytics.Selectors — ModulePowerAnalytics built-in ComponentSelectors. Use names to list what is available.
Examples
using PowerAnalytics
names(PowerAnalytics.Selectors) # lists built-in selectors
PowerAnalytics.Selectors.all_loads # by default, must prefix built-in selectors with the module name
@isdefined all_loads # -> false
using PowerAnalytics.Selectors
@isdefined all_loads # -> true, can now refer to built-in selectors without the prefixPowerAnalytics.Selectors.all_loads — ConstantA ComponentSelector representing all the electric load in a System
PowerAnalytics.Selectors.all_storage — ConstantA ComponentSelector representing all the storage in a System
PowerAnalytics.Selectors.categorized_generators — ConstantA single ComponentSelector representing the generators in a System (no storage or load) grouped by the categories in generator_mapping.yaml
PowerAnalytics.Selectors.categorized_injectors — ConstantA single ComponentSelector representing the static injectors in a System grouped by the categories in generator_mapping.yaml
PowerAnalytics.Selectors.generator_categories — ConstantA dictionary of ComponentSelectors, each of which corresponds to one of the categories in generator_mapping.yaml, only considering the components and categories that represent generators (no storage or load)
PowerAnalytics.Selectors.injector_categories — ConstantA dictionary of ComponentSelectors, each of which corresponds to one of the static injector categories in generator_mapping.yaml
Post-Metric Utilities
Post-processing on the specially formatted DataFrames that Metrics produce.
PowerAnalytics.aggregate_time — Functionaggregate_time(
df::DataFrames.AbstractDataFrame;
groupby_fn,
groupby_col,
agg_fn
) -> Any
Given a DataFrame like that produced by a TimedMetric or the timed version of compute_all, group by a function of the time axis, apply a reduction, and report the resulting aggregation indexed by the first timestamp in each group.
Arguments
df::DataFrames.AbstractDataFrame: the DataFrame to operate upongroupby_fn = nothing: a function that can be passed aDateTime; two rows will be in the same group if their timestamps produce the same result undergroupby_fn. Note thatgroupby_fn = monthputs January 2024 and January 2025 into the same group whereasgroupby_fn = (x -> (year(x), month(x)))does not. Passingnothinggroups all rows in theDataFrametogether.groupby_col::Union{Nothing, AbstractString, Symbol} = nothing: specify a column name to report the result ofgroupby_fnin the output DataFrame, ornothingto notagg_fn = nothing: by default, the aggregation function (sum/mean/etc.) is specified by theMetric, which is read from the metadata of each column. If this metadata isn't found, one can specify a default aggregation function likesumhere; if nothing, an error will be thrown.
Examples
using Dates
using PowerAnalytics.Metrics
# Setup: create a `DataFrame` to work with
my_computations = [
(calc_active_power, make_selector(ThermalStandard; groupby = :all), "thermal_power"),
(calc_curtailment, make_selector(RenewableDispatch; groupby = :all), "renewable_curtailment")
]
my_8760 = compute_all(results, my_computations...)
# Now (given a certain simulation setup) `my_8760` is an 8760x3 DataFrame
# with columns `DateTime`, `thermal_power`, and `renewable_curtailment`
# Aggregate across the entire time period; result is 1x3:
aggregate_time(my_8760)
# Aggregate all January results together, all February results together, etc.; result is 12x3:
aggregate_time(my_8760; groupby_fn = Dates.month)
# Same as above but create a column 'month_n' with 1 for January, 2 for February, etc.; result is 12x4:
aggregate_time(my_8760; groupby_fn = Dates.month, groupby_col = "month_n")
# Custom `groupby_fn`: put all weekday timestamps together and all weekend timestamps together; result is 2x4:
aggregate_time(my_8760; groupby_fn = x -> (Dates.dayofweek(x) in [6, 7]) ? "weekend" : "weekday", groupby_col = "day_type")PowerAnalytics.hcat_timed_dfs — Functionhcat_timed_dfs(vals::DataFrames.DataFrame...) -> Any
If the time axes match across all the DataFrames, horizontally concatenate them and remove the duplicate time axes. If not, throw an error.
Post-Metric Accessors
Extract and manipulate information from the specially formatted DataFrames that Metrics produce.
PowerAnalytics.get_agg_meta — Methodget_agg_meta(df, colname) -> Any
Get the column's aggregation metadata; return nothing if there is none.
PowerAnalytics.get_agg_meta — Methodget_agg_meta(df) -> Any
Get the single data column's aggregation metadata; error on multiple data columns.
PowerAnalytics.get_data_cols — Methodget_data_cols(
df::DataFrames.AbstractDataFrame
) -> Vector{String}
Select the names of the data columns of the DataFrame, i.e., those that are not DateTime and not metadata.
PowerAnalytics.get_data_df — Methodget_data_df(df::DataFrames.AbstractDataFrame) -> Any
Select the data columns of the DataFrame as a DataFrame without copying.
PowerAnalytics.get_data_mat — Methodget_data_mat(df::DataFrames.AbstractDataFrame) -> Any
Select the data columns of the DataFrame as a Matrix with copying.
PowerAnalytics.get_data_vec — Methodget_data_vec(df::DataFrames.AbstractDataFrame) -> Any
Select the data column of the DataFrame as a vector without copying, errors if more than one.
PowerAnalytics.get_time_df — Methodget_time_df(df::DataFrames.AbstractDataFrame) -> Any
Select the DateTime column of the DataFrame as a one-column DataFrame without copying.
PowerAnalytics.get_time_vec — Methodget_time_vec(df::DataFrames.AbstractDataFrame) -> Any
Select the DateTime column of the DataFrame as a Vector without copying.
PowerAnalytics.is_col_meta — Methodis_col_meta(df, colname) -> Any
Check whether a column is metadata.
PowerAnalytics.set_agg_meta! — Methodset_agg_meta!(
df,
colname,
val
) -> Union{DataFrames.DataFrame, DataFrames.DataFrameColumns, DataFrames.DataFrameRow, DataFrames.DataFrameRows, DataFrames.SubDataFrame}
Set the column's aggregation metadata.
PowerAnalytics.set_agg_meta! — Methodset_agg_meta!(
df,
val
) -> Union{DataFrames.DataFrame, DataFrames.DataFrameColumns, DataFrames.DataFrameRow, DataFrames.DataFrameRows, DataFrames.SubDataFrame}
Set the single data column's aggregation metadata; error on multiple data columns.
PowerAnalytics.set_col_meta! — Functionset_col_meta!(
df,
colname
) -> Union{DataFrames.DataFrame, DataFrames.DataFrameColumns, DataFrames.DataFrameRow, DataFrames.DataFrameRows, DataFrames.SubDataFrame}
set_col_meta!(
df,
colname,
val
) -> Union{DataFrames.DataFrame, DataFrames.DataFrameColumns, DataFrames.DataFrameRow, DataFrames.DataFrameRows, DataFrames.SubDataFrame}
Mark a column as metadata.
Advanced Metrics Interface
PowerAnalytics.ComponentSelectorTimedMetric — TypeTimedMetrics defined in terms of a ComponentSelector.
PowerAnalytics.ComponentTimedMetric — TypeComponentTimedMetric(name::String, eval_fn::Function, component_agg_fn::Function, time_agg_fn::Function, component_meta_agg_fn::Function, time_meta_agg_fn::Function, eval_zero::Union{Nothing, Function})
ComponentTimedMetric(; name, eval_fn, component_agg_fn, time_agg_fn, component_meta_agg_fn, time_meta_agg_fn, eval_zero)A ComponentSelectorTimedMetric implemented by evaluating a function on each Component.
Arguments
name::String: the name of theMetriceval_fn: a function with signature(::IS.Results, ::Component; start_time::Union{Nothing, DateTime}, len::Union{Int, Nothing})that returns aDataFramerepresenting the results for thatComponentcomponent_agg_fn: optional, a function to aggregate results betweenComponents/ComponentSelectors, defaults tosumtime_agg_fn: optional, a function to aggregate results across time, defaults tosumcomponent_meta_agg_fn: optional, a function to aggregate metadata across components, defaults tosumtime_meta_agg_fn: optional, a function to aggregate metadata across time, defaults tosumeval_zero: optional and rarely filled in, specifies what to do in the case where there are no components to contribute to a particular group; defaults tonothing, in which case the data is filled in from the identity element ofcomponent_agg_fn
PowerAnalytics.CustomTimedMetric — TypeCustomTimedMetric(name::String, eval_fn::Function, time_agg_fn::Function, time_meta_agg_fn::Function)
CustomTimedMetric(; name, eval_fn, time_agg_fn, time_meta_agg_fn)A ComponentSelectorTimedMetric implemented without drilling down to the base Components, just calls the eval_fn directly on the ComponentSelector.
Arguments
name::String: the name of theMetriceval_fn: a function with signature(::IS.Results, ::Union{ComponentSelector, Component}; start_time::Union{Nothing, DateTime}, len::Union{Int, Nothing})that returns aDataFramerepresenting the results for thatComponenttime_agg_fn: optional, a function to aggregate results across time, defaults tosumtime_meta_agg_fn: optional, a function to aggregate metadata across time, defaults tosum
PowerAnalytics.ResultsTimelessMetric — TypeResultsTimelessMetric(name::String, eval_fn::Function)
ResultsTimelessMetric(; name, eval_fn)A TimelessMetric with a single value per IS.Results instance.
Arguments
name::String: the name of theMetriceval_fn: a function with signature(::IS.Results,)that returns aDataFramerepresenting the results
PowerAnalytics.SystemTimedMetric — TypeSystemTimedMetric(name::String, eval_fn::Function, time_agg_fn::Function, time_meta_agg_fn::Function)
SystemTimedMetric(; name, eval_fn, time_agg_fn, time_meta_agg_fn)A TimedMetric that calculates an output for an entire System embedded in a set of results.
Arguments
name::String: the name of theMetriceval_fn: a function with signature(::IS.Results; start_time::Union{Nothing, DateTime}, len::Union{Int, Nothing})that returns aDataFramerepresenting the resultstime_agg_fn: optional, a function to aggregate results across time, defaults tosumtime_meta_agg_fn: optional, a function to aggregate metadata across time, defaults tosum
PowerAnalytics.rebuild_metric — Functionrebuild_metric(metric::Metric; kwargs...) -> Any
Returns a new Metric identical to the input metric except with the changes to its fields specified in the keyword arguments. See the Metric constructors (e.g., ComponentTimedMetric) for available fields to alter.
Examples
Make a variant of calc_active_power that averages across components rather than summing:
using PowerAnalytics.Metrics
const calc_active_power_mean = rebuild_metric(calc_active_power; component_agg_fn = mean)
# Now calc_active_power_mean works as a standalone, callable metric:
calc_active_power_mean(make_selector(RenewableDispatch), results)PowerAnalytics.compose_metrics — FunctionGiven a list of metrics and a function that applies to their results to produce one result, create a new metric that computes the sub-metrics and applies the function to produce its own result.
Arguments
name::String: the name of the newMetricreduce_fn: a function that takes one value from each of the inputMetrics and returns a single value that will be the result of thisMetric. "Value" means a vector (not aDataFrame) in the case ofTimedMetrics and a scalar forTimelessMetrics.metrics: the inputMetrics. It is currently not possible to combineTimedMetrics withTimelessMetrics, though it is possible to combineComponentSelectorTimedMetrics withSystemTimedMetrics.
Examples
This is the implementation of the built-in metric calc_load_from_storage, which computes the preexisting built-in metrics calc_active_power_in and calc_active_power_out and combines them by subtraction:
const calc_load_from_storage = compose_metrics(
"LoadFromStorage",
(-),
calc_active_power_in, calc_active_power_out)PowerAnalytics.compute — FunctionThe compute function is the most important part of the Metric interface. Calling a metric as if it were a function is syntactic sugar for calling compute:
# this:
my_metric1(selector, results; kwargs)
# is the same as this:
compute(my_metric1, results, selector; kwargs)
# and this:
my_metric2(results; kwargs)
# is the same as this:
compute(my_metric2; kwargs)Exact keyword arguments and formatting of the resulting DataFrame are documented for each of the existing methods, below. Custom Metric subtypes must implement this function.
PowerAnalytics.compute — Methodcompute(
metric::ComponentTimedMetric,
results::InfrastructureSystems.Results,
selector::ComponentSelector;
kwargs...
) -> Any
compute method for ComponentTimedMetric. Compute the given metric on the groups of the given ComponentSelector within the given set of results, returning a DataFrame with a DateTime column and a data column for each group. Exclude components marked as not available.
Arguments
metric::ComponentTimedMetric: the metric to computeresults::IS.Results: the results from which to fetch dataselector::ComponentSelector: theComponentSelectoron whose subselectors to compute the metricstart_time::Union{Nothing, DateTime} = nothing: the time at which the resulting time series should beginlen::Union{Int, Nothing} = nothing: the number of steps in the resulting time series
See also: compute unified function documentation
PowerAnalytics.compute — Methodcompute(
metric::ComponentTimedMetric,
results::InfrastructureSystems.Results,
comp::Component;
kwargs...
) -> Any
Like compute(metric::ComponentTimedMetric, results::IS.Results, selector::ComponentSelector; kwargs...) but for Components rather than ComponentSelectors, used in the implementation of that method. Compute the given metric on the given component within the given set of results, returning a DataFrame with a DateTime column and a data column labeled with the component's name.
Arguments
metric::ComponentTimedMetric: the metric to computeresults::IS.Results: the results from which to fetch datacomp::Component: the component on which to compute the metricstart_time::Union{Nothing, DateTime} = nothing: the time at which the resulting time series should beginlen::Union{Int, Nothing} = nothing: the number of steps in the resulting time series
See also: compute unified function documentation
PowerAnalytics.compute — Methodcompute(
metric::CustomTimedMetric,
results::InfrastructureSystems.Results,
comp::Union{ComponentSelector, Component};
kwargs...
) -> Any
compute method for CustomTimedMetric. Compute the given metric on the given component within the given set of results, returning a DataFrame with a DateTime column and a data column labeled with the component's name. Exclude components marked as not available.
Arguments
metric::CustomTimedMetric: the metric to computeresults::IS.Results: the results from which to fetch datacomp::Component: the component on which to compute the metricstart_time::Union{Nothing, DateTime} = nothing: the time at which the resulting time series should beginlen::Union{Int, Nothing} = nothing: the number of steps in the resulting time series
See also: compute unified function documentation
PowerAnalytics.compute — Methodcompute(
metric::ResultsTimelessMetric,
results::InfrastructureSystems.Results,
selector::Nothing
) -> DataFrames.DataFrame
Convenience method that ignores the selector argument and redirects to compute(metric::ResultsTimelessMetric, results::IS.Results; kwargs...) for the purposes of compute_all.
See also: compute unified function documentation
PowerAnalytics.compute — Methodcompute(
metric::ResultsTimelessMetric,
results::InfrastructureSystems.Results
) -> DataFrames.DataFrame
compute method for ResultsTimelessMetric. Compute the given metric on the given set of results, returning a DataFrame with a single cell. Exclude components marked as not available.
Arguments
metric::ResultsTimelessMetric: the metric to computeresults::IS.Results: the results from which to fetch data
See also: compute unified function documentation
PowerAnalytics.compute — Methodcompute(
metric::SystemTimedMetric,
results::InfrastructureSystems.Results,
selector::Nothing;
kwargs...
) -> Any
Convenience method that ignores the selector argument and redirects to compute(metric::SystemTimedMetric, results::IS.Results; kwargs...) for the purposes of compute_all.
See also: compute unified function documentation
PowerAnalytics.compute — Methodcompute(
metric::SystemTimedMetric,
results::InfrastructureSystems.Results;
kwargs...
) -> Any
compute method for SystemTimedMetric. Compute the given metric on the System associated with the given set of results, returning a DataFrame with a DateTime column and a data column.
Arguments
metric::SystemTimedMetric: the metric to computeresults::IS.Results: the results from which to fetch datastart_time::Union{Nothing, DateTime} = nothing: the time at which the resulting time series should beginlen::Union{Int, Nothing} = nothing: the number of steps in the resulting time series
See also: compute unified function documentation
Miscellaneous
PowerAnalytics.unweighted_sum — Functionunweighted_sum(x) -> Any
A version of sum that ignores a second argument, for use where aggregation metadata is at play.
PowerAnalytics.weighted_mean — Functionweighted_mean(vals, weights) -> Any
Compute the mean of values weighted by the corresponding entries of weights. Arguments may be vectors or vectors of vectors. A weight of 0 cancels out a value of NaN.
PowerAnalytics.metric_selector_to_string — Functionmetric_selector_to_string(
m::Metric,
e::Union{ComponentSelector, Component}
) -> Any
Canonical way to represent a (Metric, ComponentSelector) or (Metric, Component) pair as a string.
PowerAnalytics.AGG_META_KEY — ConstantColumn metadata key whose value, if any, is additional information to be passed to aggregation functions. Values of nothing are equivalent to absence of the entry.
PowerAnalytics.DATETIME_COL — ConstantName of the column that represents the time axis in computed DataFrames. Currently equal to "DateTime".
PowerAnalytics.META_COL_KEY — ConstantColumn metadata key whose value signifies whether the column is metadata. Metadata columns are excluded from get_data_cols and similar and can be used to represent things like a time aggregation.
PowerAnalytics.RESULTS_COL — ConstantName of a column that represents whole-of-Results data. Currently equal to "Results".
PowerAnalytics.SYSTEM_COL — ConstantName of a column that represents whole-of-System data. Currently equal to "System".
Old PowerAnalytics
This interface predates the 1.0 version and will eventually be deprecated.
PowerAnalytics.categorize_data — Methodcategorize_data(
data::Dict{Symbol, DataFrames.DataFrame},
aggregation::Dict;
curtailment,
slacks
) -> Dict{String, DataFrames.DataFrame}
Re-categorizes data according to an aggregation dictionary
- makes no guarantee of complete data collection *
Example
aggregation = PA.make_fuel_dictionary(results_uc.system)
categorize_data(gen_uc.data, aggregation)PowerAnalytics.make_fuel_dictionary — Methodmake_fuel_dictionary(
sys::System,
mapping::Dict{NamedTuple, String};
filter_func,
kwargs...
) -> Dict{Any, Any}
generators = make_fuel_dictionary(system::PSY.System, mapping::Dict{NamedTuple, String})This function makes a dictionary of fuel type and the generators associated.
Arguments
sys::PSY.System: the system that is used to create the resultsresults::IS.Results: results
Keyword Arguments
categories::Dict{String, NamedTuple}: if stacking by a different category is desired
Examples
results = solve_op_model!(OpModel)
generators = make_fuel_dictionary(sys)