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 ComponentSelector
s.
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, ornothing
to load all the subdirectoriespopulate_system::Bool = false
: whether to automatically load and attach the system; errors iftrue
and the system has not been saved with the results. This keyword argument isfalse
by 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 Metric
s.
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 Metric
s require a ComponentSelector
to specify which available components of the system the quantity should be computed on, and many but not all Metric
s 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 — Metric
s encapsulate default component-wise and time-wise aggregation behaviors. Metrics can be "called" like functions.
PowerAnalytics provides a library of pre-built Metric
s, 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
— TypeMetric
s that return time series.
PowerAnalytics.TimelessMetric
— TypeMetric
s 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, PowerSystems.Component, Vector};
...
) -> Any
compute_all(
results::InfrastructureSystems.Results,
metrics::Vector{<:TimelessMetric},
selectors::Union{Nothing, ComponentSelector, PowerSystems.Component, Vector},
col_names::Union{Nothing, Vector{<:Union{Nothing, AbstractString}}};
kwargs...
) -> Any
Methods of compute_all
for TimelessMetric
s. 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 ofnothing
default to the result ofmetric_selector_to_string
;names = nothing
is equivalent to an entire vector ofnothing
kwargs...
: pass through to eachcompute
call
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(
results::InfrastructureSystems.Results,
metrics::Vector{<:TimedMetric};
...
) -> Any
compute_all(
results::InfrastructureSystems.Results,
metrics::Vector{<:TimedMetric},
selectors::Union{Nothing, ComponentSelector, PowerSystems.Component, Vector};
...
) -> Any
compute_all(
results::InfrastructureSystems.Results,
metrics::Vector{<:TimedMetric},
selectors::Union{Nothing, ComponentSelector, PowerSystems.Component, Vector},
col_names::Union{Nothing, Vector{<:Union{Nothing, AbstractString}}};
kwargs...
) -> Any
Methods of compute_all
for TimedMetric
s. 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 ofnothing
default to the result ofmetric_selector_to_string
;names = nothing
is equivalent to an entire vector ofnothing
kwargs...
: pass through to eachcompute
call
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
— Functioncompute_all
takes several metrics, single-group ComponentSelector
s 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
— 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)
wheremetric
is the metric to compute,selector
is theComponentSelector
on which to compute the metric ornothing
if not relevant, andcol_name
is the name for the output column of data or nothing to use the defaultkwargs...
: pass through to eachcompute
call
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 Metric
s. 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 prefix
PowerAnalytics.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
Component
s 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 ComponentSelector
s, excluding categories in the 'non_generators' list in metadata.
Arguments
filename
: the path to thegenerator_mapping.yaml
fileroot_type::Type{<:Component} = PSY.StaticInjection
: theComponent
type 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 ComponentSelector
s and a dictionary of metadata if present.
Arguments
filename
: the path to thegenerator_mapping.yaml
fileroot_type::Type{<:Component} = PSY.StaticInjection
: theComponent
type 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 ComponentSelector
s.
Arguments
filename
: the path to thegenerator_mapping.yaml
fileroot_type::Type{<:Component} = PSY.StaticInjection
: theComponent
type 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 ComponentSelector
s. 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 prefix
PowerAnalytics.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 ComponentSelector
s, 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 ComponentSelector
s, each of which corresponds to one of the static injector categories in generator_mapping.yaml
Post-Metric Utilities
Post-processing on the specially formatted DataFrame
s that Metric
s 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 = month
puts January 2024 and January 2025 into the same group whereasgroupby_fn = (x -> (year(x), month(x)))
does not. Passingnothing
groups all rows in theDataFrame
together.groupby_col::Union{Nothing, AbstractString, Symbol} = nothing
: specify a column name to report the result ofgroupby_fn
in the output DataFrame, ornothing
to 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 likesum
here; 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 DataFrame
s that Metric
s 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
— TypeTimedMetric
s 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 theMetric
eval_fn
: a function with signature(::IS.Results, ::Component; start_time::Union{Nothing, DateTime}, len::Union{Int, Nothing})
that returns aDataFrame
representing the results for thatComponent
component_agg_fn
: optional, a function to aggregate results betweenComponent
s/ComponentSelector
s, defaults tosum
time_agg_fn
: optional, a function to aggregate results across time, defaults tosum
component_meta_agg_fn
: optional, a function to aggregate metadata across components, defaults tosum
time_meta_agg_fn
: optional, a function to aggregate metadata across time, defaults tosum
eval_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 Component
s, just calls the eval_fn
directly on the ComponentSelector
.
Arguments
name::String
: the name of theMetric
eval_fn
: a function with signature(::IS.Results, ::Union{ComponentSelector, Component}; start_time::Union{Nothing, DateTime}, len::Union{Int, Nothing})
that returns aDataFrame
representing the results for thatComponent
time_agg_fn
: optional, a function to aggregate results across time, defaults tosum
time_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 theMetric
eval_fn
: a function with signature(::IS.Results,)
that returns aDataFrame
representing 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 theMetric
eval_fn
: a function with signature(::IS.Results; start_time::Union{Nothing, DateTime}, len::Union{Int, Nothing})
that returns aDataFrame
representing the resultstime_agg_fn
: optional, a function to aggregate results across time, defaults tosum
time_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 newMetric
reduce_fn
: a function that takes one value from each of the inputMetric
s and returns a single value that will be the result of thisMetric
. "Value" means a vector (not aDataFrame
) in the case ofTimedMetric
s and a scalar forTimelessMetric
s.metrics
: the inputMetric
s. It is currently not possible to combineTimedMetric
s withTimelessMetric
s, though it is possible to combineComponentSelectorTimedMetric
s withSystemTimedMetric
s.
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
: theComponentSelector
on 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::PowerSystems.Component;
kwargs...
) -> Any
Like compute(metric::ComponentTimedMetric, results::IS.Results, selector::ComponentSelector; kwargs...)
but for Component
s rather than ComponentSelector
s, 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, PowerSystems.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, PowerSystems.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::PowerSystems.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)