Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Supply Curve Aggregation by Zone within GIDs #503

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
714e81b
switching to use flake8 from github instead of gitlab and updating re…
mjgleason Jan 16, 2025
31f032b
updating max arguments to 25, removing deprecated options from disabl…
mjgleason Jan 16, 2025
4cc2795
reverting increase of max-args and adding new setting for max-positio…
mjgleason Jan 16, 2025
fd7e488
adding zone masking to supply curve points
mjgleason Jan 16, 2025
063ab4f
adding functionality to load zones array for a specified gid
mjgleason Jan 16, 2025
d1178e7
bumping max-positional-arguments to 30
mjgleason Jan 16, 2025
d7b6123
adding input arguments and logic for aggregating within zones of gids
mjgleason Jan 16, 2025
e36980c
adding zone_id to output fields for supply curve aggregation
mjgleason Jan 17, 2025
5de7124
adding basic test for aggregation with zones
mjgleason Jan 17, 2025
ae8a911
removing separate zones_fpath input, other minor cleanup
mjgleason Jan 20, 2025
369a4e4
trailing change from prior commit switching zones_fpath to excl_fpath
mjgleason Jan 20, 2025
ef05599
removing check of zones_mask for values of 0 and 1 since input is typ…
mjgleason Jan 20, 2025
9d36e5f
adding new test case for test_agg_zones, related fixes
mjgleason Jan 20, 2025
7fe9236
adding more test cases to test_agg_zones
mjgleason Jan 20, 2025
8de4a90
adding more test cases for test_agg_zones
mjgleason Jan 20, 2025
ef9db35
fixing zone_mask copy issue when zone_mask is None, removing _check_z…
mjgleason Jan 20, 2025
0424beb
adding test for sc aggregation with zones via the CLI
mjgleason Jan 20, 2025
99368b2
removing out_of_extent logic from zone_mask(); changing dummy zones a…
mjgleason Jan 21, 2025
b46d724
cleaning up docstrings related to zones_dset and zone_mask
mjgleason Jan 21, 2025
381a7b9
bumping version
mjgleason Jan 21, 2025
1ecd5e8
Add zone ID to logger message
ppinchuk Jan 24, 2025
ca4e8c4
Logger message now only talks about zones
ppinchuk Jan 24, 2025
a68e4f6
Add logger message about points
ppinchuk Jan 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
rev: v5.0.0
hooks:
- id: check-json
- id: check-yaml
Expand All @@ -13,11 +13,11 @@ repos:
- id: requirements-txt-fixer
- id: pretty-format-json
args: [--autofix]
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.4
- repo: https://github.com/PyCQA/flake8
rev: 7.1.1
hooks:
- id: flake8
- repo: https://github.com/PyCQA/pylint
rev: pylint-2.6.0
rev: v3.3.3
hooks:
- id: pylint
64 changes: 3 additions & 61 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -58,73 +58,13 @@ disable=
unspecified-encoding,
consider-using-f-string,
# Defaults
print-statement,
parameter-unpacking,
unpacking-in-except,
old-raise-syntax,
backtick,
import-star-module-level,
raw-checker-failed,
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
apply-builtin,
basestring-builtin,
buffer-builtin,
cmp-builtin,
coerce-builtin,
execfile-builtin,
file-builtin,
long-builtin,
raw_input-builtin,
reduce-builtin,
standarderror-builtin,
unicode-builtin,
xrange-builtin,
coerce-method,
delslice-method,
getslice-method,
setslice-method,
no-absolute-import,
old-division,
dict-iter-method,
dict-view-method,
next-method-called,
metaclass-assignment,
indexing-exception,
raising-string,
reload-builtin,
oct-method,
hex-method,
nonzero-method,
cmp-method,
input-builtin,
round-builtin,
intern-builtin,
unichr-builtin,
map-builtin-not-iterating,
zip-builtin-not-iterating,
range-builtin-not-iterating,
filter-builtin-not-iterating,
using-cmp-argument,
div-method,
idiv-method,
rdiv-method,
exception-message-attribute,
invalid-str-codec,
sys-max-int,
bad-python3-import,
deprecated-string-function,
deprecated-str-translate-call,
deprecated-itertools-function,
deprecated-types-field,
next-method-defined,
dict-items-not-iterating,
dict-keys-not-iterating,
dict-values-not-iterating,
# Custom
protected-access,
fixme,
Expand All @@ -145,7 +85,6 @@ disable=
too-many-nested-blocks,
invalid-name,
import-error,
bad-continuation,
try-except-raise,
no-else-raise,
no-else-return,
Expand Down Expand Up @@ -493,6 +432,9 @@ valid-metaclass-classmethod-first-arg=mcs
# Maximum number of arguments for function / method
max-args=5

# Maximum number of position arguments for function / method
max-positional-arguments=30

# Maximum number of attributes for a class (see R0902).
max-attributes=7

Expand Down
47 changes: 47 additions & 0 deletions reV/supply_curve/aggregation.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,53 @@ def _get_gid_inclusion_mask(

return gid_inclusions

@staticmethod
def _get_gid_zones(zones_fpath, zones_dset, gid, slice_lookup):
"""
Get zones 2D array for desired gid.

Parameters
----------
zones_fpath : str | None, optional
Filepath to HDF5 file containing `zones_dset`. If not specified,
output of function will be an array containing all values equal to
1.
zones_dset : str | None, optional
Dataset name in the `zones_fpath` file containing the zones to be
loaded. If not specified, output of function will be an array
containing all values equal to 1.
gid : int
sc_point_gid value, used to extract the applicable subset of zones.
slice_lookup : dict
Mapping of sc_point_gids to exclusion/inclusion row and column
slices

Returns
-------
zones : ndarray | None
2D array of zones for desired gid.
"""

row_slice, col_slice = slice_lookup[gid]
if zones_fpath is not None and zones_dset is not None:
with ExclusionLayers(zones_fpath) as fh:
if zones_dset not in fh:
msg = (
f"Could not find zones_dset {zones_dset} in "
f"zones_fpath {zones_fpath}."
)
logger.error(msg)
raise FileInputError(msg)
zones = fh[zones_dset, row_slice, col_slice]
else:
shape = (
row_slice.stop - row_slice.start,
col_slice.stop - col_slice.start
)
zones = np.ones(shape, dtype="uint32")
mjgleason marked this conversation as resolved.
Show resolved Hide resolved

return zones

@staticmethod
def _parse_gen_index(gen_fpath):
"""Parse gen outputs for an array of generation gids corresponding to
Expand Down
74 changes: 74 additions & 0 deletions reV/supply_curve/points.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ def __init__(
excl_area=None,
exclusion_shape=None,
close=True,
zone_mask=None,
):
"""
Parameters
Expand Down Expand Up @@ -254,6 +255,10 @@ def __init__(
will speed things up considerably.
close : bool
Flag to close object file handlers on exit.
zone_mask : np.ndarray | None, optional
2D array defining zone within the supply curve to be evaluated,
where 1 is included and 0 is excluded. The shape of this will be
checked against the input resolution.
"""

self._excl_dict = excl_dict
Expand Down Expand Up @@ -282,6 +287,9 @@ def __init__(
assert inclusion_mask.size == len(self._gids), msg
self._incl_mask = inclusion_mask.copy()

self._zone_mask = zone_mask
self._check_zone_mask()

self._centroid = None
self._excl_area = excl_area
self._check_excl()
Expand Down Expand Up @@ -454,6 +462,24 @@ def n_gids(self):

return n_gids

@property
def zone_mask(self):
"""
Get the 2D zone mask, where 1 is included and 0 is excluded.

Returns
-------
np.ndarray
"""

if self._zone_mask is None:
return None
else:
mjgleason marked this conversation as resolved.
Show resolved Hide resolved
out_of_extent = self._gids.reshape(self._zone_mask.shape) == -1
mjgleason marked this conversation as resolved.
Show resolved Hide resolved
self._zone_mask[out_of_extent] = 0.0

return self._zone_mask

@property
def include_mask(self):
"""Get the 2D inclusion mask (normalized with expected range: [0, 1]
Expand Down Expand Up @@ -481,6 +507,10 @@ def include_mask(self):
logger.warning(w)
warn(w)

if self.zone_mask is not None:
out_of_zone = self.zone_mask == 0
self._incl_mask[out_of_zone] = 0.0

return self._incl_mask

@property
Expand Down Expand Up @@ -548,6 +578,31 @@ def _check_excl(self):
)
raise EmptySupplyCurvePointError(msg)

def _check_zone_mask(self):
"""
Check that the zone mask is the correct size and shape, and that it
contains only values of 0 and 1.
"""
if self._zone_mask is not None:
msg = (
"Bad zone mask input shape of {} with stated "
"resolution of {}".format(
self._zone_mask.shape, self._resolution
)
)
assert len(self._zone_mask.shape) == 2, msg
assert self._zone_mask.shape[0] <= self._resolution, msg
assert self._zone_mask.shape[1] <= self._resolution, msg
assert self._zone_mask.size == len(self._gids), msg

if not np.isin(self._zone_mask, [0, 1]).all():
msg = (
"zone_mask includes unexpected values. All values must be "
"in the domain: [0, 1]"
mjgleason marked this conversation as resolved.
Show resolved Hide resolved
)
logger.error(msg)
raise ValueError(msg)

def exclusion_weighted_mean(self, arr, drop_nan=True):
"""
Calc the exclusions-weighted mean value of an array of resource data.
Expand Down Expand Up @@ -955,6 +1010,7 @@ def __init__(
close=True,
gen_index=None,
apply_exclusions=True,
zone_mask=None,
):
"""
Parameters
Expand Down Expand Up @@ -997,6 +1053,10 @@ def __init__(
apply_exclusions : bool
Flag to apply exclusions to the resource / generation gid's on
initialization.
zone_mask : np.ndarray | None, optional
2D array defining zone within the supply curve to be evaluated,
where 1 is included and 0 is excluded. The shape of this will be
checked against the input resolution.
"""
super().__init__(
gid,
Expand All @@ -1008,6 +1068,7 @@ def __init__(
excl_area=excl_area,
exclusion_shape=exclusion_shape,
close=close,
zone_mask=zone_mask,
)

self._h5_fpath, self._h5 = self._parse_h5_file(agg_h5)
Expand Down Expand Up @@ -1435,6 +1496,7 @@ def __init__(
friction_layer=None,
recalc_lcoe=True,
apply_exclusions=True,
zone_mask=None,
):
"""
Parameters
Expand Down Expand Up @@ -1510,6 +1572,10 @@ def __init__(
apply_exclusions : bool
Flag to apply exclusions to the resource / generation gid's on
initialization.
zone_mask : np.ndarray | None, optional
2D array defining zone within the supply curve to be summarized,
where 1 is included and 0 is excluded. The shape of this will be
checked against the input resolution.
"""

self._res_class_dset = res_class_dset
Expand Down Expand Up @@ -1540,6 +1606,7 @@ def __init__(
exclusion_shape=exclusion_shape,
close=close,
apply_exclusions=False,
zone_mask=zone_mask,
)

self._res_gid_set = None
Expand Down Expand Up @@ -2423,6 +2490,7 @@ def summarize(
data_layers=None,
cap_cost_scale=None,
recalc_lcoe=True,
zone_mask=None,
):
"""Get a summary dictionary of a single supply curve point.

Expand Down Expand Up @@ -2504,6 +2572,11 @@ def summarize(
datasets to be aggregated in the gen input: system_capacity,
fixed_charge_rate, capital_cost, fixed_operating_cost,
and variable_operating_cost.
zone_mask : np.ndarray | None, optional
2D array defining zone within the supply curve to be summarized,
where 1 is included and 0 is excluded. The shape of this will be
checked against the input resolution. If not specified, no zone
mask will be applied.

Returns
-------
Expand All @@ -2525,6 +2598,7 @@ def summarize(
"close": close,
"friction_layer": friction_layer,
"recalc_lcoe": recalc_lcoe,
"zone_mask": zone_mask,
}

with cls(
Expand Down
Loading
Loading