-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ComponentSelector
feature: IS portion
#342
base: main
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #342 +/- ##
==========================================
+ Coverage 78.28% 78.30% +0.02%
==========================================
Files 71 71
Lines 5484 5596 +112
==========================================
+ Hits 4293 4382 +89
- Misses 1191 1214 +23
Flags with carried forward coverage won't be shown. Click here to find out more.
|
We need working implementations of |
1732638
to
83ea408
Compare
Rebased onto |
f4e395d
to
d4c3aff
Compare
0344a74
to
915d247
Compare
915d247
to
b11ccf6
Compare
src/component_selector.jl
Outdated
""" | ||
make_selector( | ||
component_type::Type{<:InfrastructureSystemsComponent}, | ||
filter_func::Function; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be first?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a signature (line 386) where it is first. Is this compromise where I have both signatures acceptable? It just seems really inconsistent to me to have the user specify the component type first in every case except the filter function case. This way the do
block is supported but I also get my consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My concern is consistency in our API. Currently, there is only one way to call get_components
with a filter function. That function has to be first. This PR is introducing a second pattern where you can call get_components
and specify the filter function or scope limiter as a keyword argument. If people see this pattern being used they may try to use it with the existing get_components
and then complain that it doesn't work. I don't want to have to then go back and change that method to support this new pattern. My suggestion is that we continue to provide a single way to specify filter functions - and that it follow the Julia convention.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the record, @daniel-thom, @jd-lara, @sourabhdalvi, @akrivi and I discussed this synchronously and came to the following resolution:
- Eliminate the
scope_limiter
feature. Instead:- When the user calls
get_components(selector, system)
, return all components that satisfy the selector (no availability filtering) - When the user calls
get_components(selector, results)
, return only the available components - When the user calls
get_available_components(selector, system)
, return only the available components
- When the user calls
- Follow the Julia convention of always putting the function first; remove the methods where the function is not first (I was outvoted)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the user's point of view, this is done; all function parameters should only appear in first position. There is a hidden scope_limiter
kwarg to aid in implementation and extension.
This reverts commit 15b3f31.
abstract type ComponentContainer <: InfrastructureSystemsContainer end | ||
|
||
# For each of these functions, `ComponentContainer` concrete subtypes MUST either implement | ||
# appropriate methods or accept the default if it exists. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@daniel-thom these methods are necessary and sufficient for the ComponentSelector
design and I'm trying to avoid further scope creep. But maybe we also want iterate_components
, etc. here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mabye. I'm definitely OK leaving it out.
@@ -17,7 +17,7 @@ const SERIALIZATION_METADATA_KEY = "__serialization_metadata__" | |||
|
|||
Container for system components and time series data | |||
""" | |||
mutable struct SystemData <: InfrastructureSystemsType | |||
mutable struct SystemData <: ComponentContainer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ComponentContainer <: InfrastructureSystemsType
so this is backwards compatible
@daniel-thom Ready for another review. The main changes since last review are:
|
function get_components(selector::FilterComponentSelector, sys; kwargs...) | ||
# Short-circuit-evaluate the `scope_limiter` first so `filter_func` may refer to | ||
# component attributes that do not exist in components outside the scope | ||
scope_limiter = get(kwargs, :scope_limiter, nothing) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like you want scope_limiter
to be part of the public interface, or at least you may be setting it in PowerAnalytics. Is that correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want it to be part of the public interface, but it's used in the implementation of get_available_components
, so I tried to strike a middle ground here with the undocumented kwarg (similar to your use_system_fallback
kwarg)
Get the available components of the collection that make up the `ComponentSelector`. | ||
""" | ||
get_available_components(selector::ComponentSelector, sys) = | ||
get_components(selector, sys; scope_limiter = x -> get_available(sys, x)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a bit concerned that people will use this as example code. And then eventually ask why scope_limiter isn't a kwarg in the System get_components method. Wouldn't it be better to follow the Julia convention and pass the "scope_limiter" as the first argument?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The goals with this design are to (a) keep scope_limiter
completely out of the public interface, as we resolved earlier, while (b) keeping it in a sort of "developer interface" so that it can be used for get_available_components
. Absent another layer of indirection (have each ComponentSelector
subtype implement _get_components
with a scope_limiter
and have get_components
and get_available_components
call that), putting scope_limiter
as the first argument would more or less force it be part of the public interface: it would explicitly appear in method lists and such. Do you think it's worth it to add that layer of indirection, or is the current solution (perhaps with a comment added here that users are not to take this source code as example code?) good enough?
This draft PR will get filled in as @tengis-nrl and I move the ComponentSelector features from PowerAnalytics to InfrastructureSystems.Ready for review! Adds an immutable, lazy, system-independent representation of a grouped set of components. For more details and a demonstration, see https://github.nrel.gov/gkonars/PowerAnalytics-demos/blob/main/component_selector_pr_demo.ipynb.