NREL-reV 0.14.0__py3-none-any.whl → 0.14.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nrel_rev-0.14.0.dist-info → nrel_rev-0.14.2.dist-info}/METADATA +2 -2
- {nrel_rev-0.14.0.dist-info → nrel_rev-0.14.2.dist-info}/RECORD +16 -16
- {nrel_rev-0.14.0.dist-info → nrel_rev-0.14.2.dist-info}/WHEEL +1 -1
- reV/SAM/version_checker.py +3 -2
- reV/bespoke/bespoke.py +13 -6
- reV/config/project_points.py +8 -5
- reV/supply_curve/aggregation.py +15 -6
- reV/supply_curve/cli_sc_aggregation.py +28 -22
- reV/supply_curve/cli_tech_mapping.py +2 -2
- reV/supply_curve/points.py +7 -4
- reV/supply_curve/sc_aggregation.py +14 -9
- reV/supply_curve/tech_mapping.py +29 -44
- reV/version.py +1 -1
- {nrel_rev-0.14.0.dist-info → nrel_rev-0.14.2.dist-info}/entry_points.txt +0 -0
- {nrel_rev-0.14.0.dist-info → nrel_rev-0.14.2.dist-info}/licenses/LICENSE +0 -0
- {nrel_rev-0.14.0.dist-info → nrel_rev-0.14.2.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: NREL-reV
|
3
|
-
Version: 0.14.
|
3
|
+
Version: 0.14.2
|
4
4
|
Summary: National Renewable Energy Laboratory's (NREL's) Renewable Energy Potential(V) Model: reV
|
5
5
|
Author-email: Galen Maclaurin <galen.maclaurin@nrel.gov>
|
6
6
|
Maintainer-email: Grant Buster <gbuster@nrel.gov>, Paul Pinchuk <ppinchuk@nrel.gov>
|
@@ -23,7 +23,7 @@ License-File: LICENSE
|
|
23
23
|
Requires-Dist: NREL-gaps<0.9,>=0.8.0
|
24
24
|
Requires-Dist: NREL-NRWAL<0.1,>=0.0.11
|
25
25
|
Requires-Dist: NREL-PySAM~=7.0.0
|
26
|
-
Requires-Dist: NREL-rex<0.4,>=0.3.
|
26
|
+
Requires-Dist: NREL-rex<0.4,>=0.3.5
|
27
27
|
Requires-Dist: numpy<3,>=2.0.2
|
28
28
|
Requires-Dist: packaging<25,>=24.2
|
29
29
|
Requires-Dist: plotly<7,>=6.0.1
|
@@ -1,13 +1,13 @@
|
|
1
|
-
nrel_rev-0.14.
|
1
|
+
nrel_rev-0.14.2.dist-info/licenses/LICENSE,sha256=hDwoTANtan2ZpufBlXm5C3W_PJ-mCqItvlcobgjxL7k,1526
|
2
2
|
reV/__init__.py,sha256=tXTpWu_qVo3uotfSw_TJ-gNbidGaIPPfUTwBlpCMJ-g,856
|
3
3
|
reV/cli.py,sha256=u7G5M5moA7q8fCgC_1MB30Z7R14GNcngVf6eVNkfQU8,1682
|
4
|
-
reV/version.py,sha256=
|
4
|
+
reV/version.py,sha256=iZ2NEm6j_ZMkwjscuehf0I9OUwsEHrSS3xbfjV9LCbM,51
|
5
5
|
reV/SAM/SAM.py,sha256=3NK9rRaJzqH6wz7CU_5XguKCRhmoilOpDdFFsFgOaxQ,33163
|
6
6
|
reV/SAM/__init__.py,sha256=LJqoncyKDY5ZP5WA4kboh561bce11F9Ge645Izah0EY,240
|
7
7
|
reV/SAM/defaults.py,sha256=JQMJomX7wsbMzxKjx_IMnA_9QFsV2yWCyl_JToDVSJo,6703
|
8
8
|
reV/SAM/econ.py,sha256=dFhtUXp5eozSsPyk0XXji0HGexKJnxoct8cwE1ApHVg,20704
|
9
9
|
reV/SAM/generation.py,sha256=kbDiQ0a0VCrfPi6P1RSMKdjlbxuO3rgiR0-YSM1pyU8,85653
|
10
|
-
reV/SAM/version_checker.py,sha256=
|
10
|
+
reV/SAM/version_checker.py,sha256=MBSPqHYmTyjXJLi1ziJ1sGS18AH9an-PZRcl-6IPJGw,3963
|
11
11
|
reV/SAM/windbos.py,sha256=fnq1uxtSl-vtJth0gTlHkCSsmvDbRROCo9RGdqA7hK4,7504
|
12
12
|
reV/SAM/defaults/USA AZ Phoenix Sky Harbor Intl Ap (TMY3).csv,sha256=8QorTX0ACjgPgNV7kLSpTHOqfY4E17gkkpKB-qseiFk,406896
|
13
13
|
reV/SAM/defaults/USA CA Daggett (TMY2).csv,sha256=vVP-mk_cXj1GRHMbqsyZ60fTVMywTappzwp5-ILurFs,410050
|
@@ -16,7 +16,7 @@ reV/SAM/defaults/WY Southern-Flat Lands.srw,sha256=oSlFI7nnycW7SMnTXEXBXYkoh8rhV
|
|
16
16
|
reV/SAM/defaults/geothermal.json,sha256=gnlxOBxxkbDDacIw6B9yP9iRkfmwj0WTWs8Zb71ytCo,7119
|
17
17
|
reV/SAM/defaults/i_pvwattsv5.json,sha256=sF8rSe1bcqsKLXchvRxlp25dXOVe_q7rPJTf_vWR20Y,312
|
18
18
|
reV/bespoke/__init__.py,sha256=vpXbyBUrUsTgK8UP_LafMjLiDg2CRG9WZLHPsOJoxek,109
|
19
|
-
reV/bespoke/bespoke.py,sha256=
|
19
|
+
reV/bespoke/bespoke.py,sha256=ZMl4kz9oAaXpZaNa5EgiD43RvKiKl3xymRv-z4lDYmQ,113169
|
20
20
|
reV/bespoke/cli_bespoke.py,sha256=b6Xu0GKpXqPX3qVJ6-z0FrO97uCsH_1dVOa4r6IvesQ,2911
|
21
21
|
reV/bespoke/gradient_free.py,sha256=URWV1yiO2jyWk3_GOpfpLV_wlgJhXXGmTUwCB3WTV0Y,12015
|
22
22
|
reV/bespoke/pack_turbs.py,sha256=Dcd9F8obF8LPztzeycB5kxa5hXKSCiz3jC1WeAFUx28,3508
|
@@ -28,7 +28,7 @@ reV/config/cli_project_points.py,sha256=6edOlLNOG-ZEbcpNS2MPfu-DXjcOTEh_MEvKOvQS
|
|
28
28
|
reV/config/curtailment.py,sha256=1bH7xzxOmD4PwLKcXFNotMAa9iCfGBUm2DKTOXViCJg,5548
|
29
29
|
reV/config/execution.py,sha256=hyf8W7XYUXE6tXBXs-4En7h_aDTYu8FzbslgBsKLJkQ,5046
|
30
30
|
reV/config/output_request.py,sha256=Sj3L5hcypLTCtLnKAqS7GSaI4_Hpb28QLuWT9IMCvrc,4520
|
31
|
-
reV/config/project_points.py,sha256=
|
31
|
+
reV/config/project_points.py,sha256=CSq7lHgWfJ1pq1XlWJ5eykmGGhumkxVcg__Ln9RR4-Y,41886
|
32
32
|
reV/config/sam_config.py,sha256=xvvx2FTuliq0Sk-BjRE3I9zdDmIdwHVBnWtXCcsoc40,7998
|
33
33
|
reV/econ/__init__.py,sha256=UId1LNaAP9lErCEXVce6JZf0qVRUvwNFOPrajdRevGo,130
|
34
34
|
reV/econ/cli_econ.py,sha256=2KNy3JQD0EKjStaoD2r6nv3ELFw88h2E_up-UKj_sfE,4286
|
@@ -74,17 +74,17 @@ reV/rep_profiles/__init__.py,sha256=v6YZk7tGLpw5gnSckjOn22xazTnv10siCFfWQl9H_fQ,
|
|
74
74
|
reV/rep_profiles/cli_rep_profiles.py,sha256=i3fRolT7HTzTQePXpNLDyxwgpRa7FEfHO1mOqiSufK4,4613
|
75
75
|
reV/rep_profiles/rep_profiles.py,sha256=dJ2jcklbelYYNS3IUXIYHg8E0poXLOWrwdqeBBnqYIE,48271
|
76
76
|
reV/supply_curve/__init__.py,sha256=dbf0cO0qmt1VhV8dnDddztrcpnwua9T2HBhM6tLKaP8,274
|
77
|
-
reV/supply_curve/aggregation.py,sha256=
|
78
|
-
reV/supply_curve/cli_sc_aggregation.py,sha256=
|
77
|
+
reV/supply_curve/aggregation.py,sha256=DvIUmj0PbZ8NxgOSmpXvzn9wJnOiQO2Xm2w_WCRVK-U,40908
|
78
|
+
reV/supply_curve/cli_sc_aggregation.py,sha256=iDBHlUUPg-Ce4N4Rqb4scn8A_Ygq2q4i9v_ypbH-krs,3387
|
79
79
|
reV/supply_curve/cli_supply_curve.py,sha256=e-XrHQIe4OqWTL6u-TUAyHrw7Alk7vkXQ2HoLbE3zTM,2163
|
80
|
-
reV/supply_curve/cli_tech_mapping.py,sha256=
|
80
|
+
reV/supply_curve/cli_tech_mapping.py,sha256=Dirn4JOmu_3BIP7WgcRLAepsreKqmDhChHLPEUqcDAo,1735
|
81
81
|
reV/supply_curve/competitive_wind_farms.py,sha256=eOjM72-4oWtsqxB7Wh2gnB2zVAt4LY3iPE_DqWdXbQ4,15795
|
82
82
|
reV/supply_curve/exclusions.py,sha256=4-ZxTO5Vlu03vie0V_74uvdajQfCuC8FE96Pg8I4U_c,42950
|
83
83
|
reV/supply_curve/extent.py,sha256=a31po753hXSxQ8lfcCvpE8hoKc4bY7MmYq0NO0jtdqA,17414
|
84
|
-
reV/supply_curve/points.py,sha256=
|
85
|
-
reV/supply_curve/sc_aggregation.py,sha256=
|
84
|
+
reV/supply_curve/points.py,sha256=p9Kqzas1jX8uCXcvYX7o6mdUVsgeHCC_F9pjBaEypPI,93548
|
85
|
+
reV/supply_curve/sc_aggregation.py,sha256=l7uXs-grLb0enblPNsEDKccSP11WZ2Pah5baWtgtvzE,68067
|
86
86
|
reV/supply_curve/supply_curve.py,sha256=9zhAA_9XSxE18j1Z9FuC71Wr3I0VuakfR5mt1_gHYuU,69931
|
87
|
-
reV/supply_curve/tech_mapping.py,sha256=
|
87
|
+
reV/supply_curve/tech_mapping.py,sha256=WP-o5Sk5q1Jz_F9Rpe77_fvTYGH8R4GnYDfRMSTuHB8,17804
|
88
88
|
reV/utilities/__init__.py,sha256=HVb1P-ee-z2P6UTjyc0s0gYFK7XYM71BQLEMxj26apA,10834
|
89
89
|
reV/utilities/_clean_readme.py,sha256=IFI9wGPX5nnLTNVLJzH8IOHq9unQlAlHRu4Namib0LA,709
|
90
90
|
reV/utilities/cli_functions.py,sha256=1_T_sXz0Ct8lW-vOk3mMRcpD6NYsc9cGI7dEujIi9z4,3864
|
@@ -92,8 +92,8 @@ reV/utilities/curtailment.py,sha256=As902-2aLGnCiVEutYfAFIOwuV--_rCQhxGNOY9RB-4,
|
|
92
92
|
reV/utilities/exceptions.py,sha256=f7sRGsbFLpmL6Caq_H1cD4GfVhnLMyvYUsLPA1UVDDE,3974
|
93
93
|
reV/utilities/pytest_utils.py,sha256=spCw9yQ8KEYOkQZpCi9IEmaWIvIqHqbUPDXXNQJJ68U,3241
|
94
94
|
reV/utilities/slots.py,sha256=xsw-JuUVZ0YeoCNuwP_HxGNxFMA4xRs1tuImXHIJqaU,2618
|
95
|
-
nrel_rev-0.14.
|
96
|
-
nrel_rev-0.14.
|
97
|
-
nrel_rev-0.14.
|
98
|
-
nrel_rev-0.14.
|
99
|
-
nrel_rev-0.14.
|
95
|
+
nrel_rev-0.14.2.dist-info/METADATA,sha256=lIgkZ3PQLu5YOtLYAP62nRtNVAhxkwRuHGqS_2mSwDY,10733
|
96
|
+
nrel_rev-0.14.2.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
|
97
|
+
nrel_rev-0.14.2.dist-info/entry_points.txt,sha256=4IfJtZm2iMJwrbC8J0Or7VjZWnFpvCaHYVpvSWfIwDA,616
|
98
|
+
nrel_rev-0.14.2.dist-info/top_level.txt,sha256=S6YF2ZYgXUB6n28SY0K2H8YB9tMJdXQ9CyQbo6VC89M,4
|
99
|
+
nrel_rev-0.14.2.dist-info/RECORD,,
|
reV/SAM/version_checker.py
CHANGED
@@ -6,8 +6,9 @@ Created on Mon Feb 3 14:40:42 2020
|
|
6
6
|
@author: gbuster
|
7
7
|
"""
|
8
8
|
import logging
|
9
|
+
import importlib
|
9
10
|
from warnings import warn
|
10
|
-
|
11
|
+
|
11
12
|
from packaging import version
|
12
13
|
from reV.utilities.exceptions import PySAMVersionError, PySAMVersionWarning
|
13
14
|
|
@@ -105,7 +106,7 @@ class PySamVersionChecker:
|
|
105
106
|
@property
|
106
107
|
def pysam_version(self):
|
107
108
|
"""Get the PySAM distribution version"""
|
108
|
-
return
|
109
|
+
return importlib.metadata.version("nrel-pysam")
|
109
110
|
|
110
111
|
@classmethod
|
111
112
|
def run(cls, tech, parameters):
|
reV/bespoke/bespoke.py
CHANGED
@@ -23,7 +23,7 @@ from rex.multi_year_resource import MultiYearWindResource
|
|
23
23
|
from rex.utilities.bc_parse_table import parse_bc_table
|
24
24
|
from rex.utilities.execution import SpawnProcessPool
|
25
25
|
from rex.utilities.loggers import create_dirs, log_mem
|
26
|
-
from rex.utilities.utilities import parse_year
|
26
|
+
from rex.utilities.utilities import parse_year, check_res_file
|
27
27
|
|
28
28
|
from reV.config.output_request import SAMOutputRequest
|
29
29
|
from reV.econ.utilities import lcoe_fcr
|
@@ -80,7 +80,8 @@ class BespokeMultiPlantData:
|
|
80
80
|
Option to pre-load relative humidity data (useful for icing
|
81
81
|
runs). If ``False``, relative humidities are not loaded.
|
82
82
|
"""
|
83
|
-
self.res_fpath = res_fpath
|
83
|
+
self.res_fpath = ([res_fpath]
|
84
|
+
if isinstance(res_fpath, str) else res_fpath)
|
84
85
|
self.sc_gid_to_hh = sc_gid_to_hh
|
85
86
|
self.sc_gid_to_res_gid = sc_gid_to_res_gid
|
86
87
|
self.hh_to_res_gids = {}
|
@@ -104,8 +105,9 @@ class BespokeMultiPlantData:
|
|
104
105
|
hh: sorted(gids) for hh, gids in self.hh_to_res_gids.items()
|
105
106
|
}
|
106
107
|
|
108
|
+
hsds = all(check_res_file(fp)[1] for fp in self.res_fpath)
|
107
109
|
start_time = time.time()
|
108
|
-
with MultiYearWindResource(self.res_fpath) as res:
|
110
|
+
with MultiYearWindResource(self.res_fpath, hsds=hsds) as res:
|
109
111
|
self._wind_dirs = {
|
110
112
|
hh: res[f"winddirection_{hh}m", :, gids]
|
111
113
|
for hh, gids in self.hh_to_res_gids.items()
|
@@ -488,7 +490,9 @@ class BespokeSinglePlant:
|
|
488
490
|
self._pre_loaded_data = pre_loaded_data
|
489
491
|
self._outputs = {}
|
490
492
|
|
491
|
-
|
493
|
+
if isinstance(res, str):
|
494
|
+
__, hsds = check_res_file(res)
|
495
|
+
res = MultiYearWindResource(res, hsds=hsds)
|
492
496
|
|
493
497
|
self._sc_point = AggSCPoint(
|
494
498
|
gid,
|
@@ -1972,7 +1976,8 @@ class BespokeWindPlants(BaseAggregation):
|
|
1972
1976
|
pre_extract_inclusions=pre_extract_inclusions,
|
1973
1977
|
)
|
1974
1978
|
|
1975
|
-
self._res_fpath = res_fpath
|
1979
|
+
self._res_fpath = ([res_fpath]
|
1980
|
+
if isinstance(res_fpath, str) else res_fpath)
|
1976
1981
|
self._obj_fun = objective_function
|
1977
1982
|
self._cap_cost_fun = capital_cost_function
|
1978
1983
|
self._foc_fun = fixed_operating_cost_function
|
@@ -2123,8 +2128,9 @@ class BespokeWindPlants(BaseAggregation):
|
|
2123
2128
|
)
|
2124
2129
|
)
|
2125
2130
|
|
2131
|
+
hsds = all(check_res_file(fp)[1] for fp in self._res_fpath)
|
2126
2132
|
# just check that this file exists, cannot check res_fpath if *glob
|
2127
|
-
with MultiYearWindResource(self._res_fpath) as f:
|
2133
|
+
with MultiYearWindResource(self._res_fpath, hsds=hsds) as f:
|
2128
2134
|
assert any(f.dsets)
|
2129
2135
|
|
2130
2136
|
def _pre_load_data(self, pre_load_data):
|
@@ -2494,6 +2500,7 @@ class BespokeWindPlants(BaseAggregation):
|
|
2494
2500
|
"area_filter_kernel": area_filter_kernel,
|
2495
2501
|
"min_area": min_area,
|
2496
2502
|
"h5_handler": MultiYearWindResource,
|
2503
|
+
"hsds": all(check_res_file(fp)[1] for fp in res_fpath),
|
2497
2504
|
}
|
2498
2505
|
|
2499
2506
|
with AggFileHandler(excl_fpath, res_fpath, **file_kwargs) as fh:
|
reV/config/project_points.py
CHANGED
@@ -464,8 +464,10 @@ class ProjectPoints:
|
|
464
464
|
h_var = "wind_turbine_hub_ht"
|
465
465
|
if self._h is None:
|
466
466
|
if "wind" in self.tech:
|
467
|
-
|
468
|
-
|
467
|
+
if h_var in self.df.columns:
|
468
|
+
self._h = self.df[h_var].values.tolist()
|
469
|
+
else:
|
470
|
+
self._h = [self[site][1][h_var] for site in self.sites]
|
469
471
|
|
470
472
|
return self._h
|
471
473
|
|
@@ -837,7 +839,6 @@ class ProjectPoints:
|
|
837
839
|
logger.error(msg)
|
838
840
|
raise ConfigError(msg)
|
839
841
|
|
840
|
-
|
841
842
|
unused_configs = set(curtail_configs) - set(df_configs)
|
842
843
|
if unused_configs:
|
843
844
|
msg = ("One or more curtailment configurations not found in "
|
@@ -1164,12 +1165,14 @@ class ProjectPoints:
|
|
1164
1165
|
multi_h5_res, hsds = check_res_file(res_file)
|
1165
1166
|
if multi_h5_res:
|
1166
1167
|
res_cls = MultiFileResourceX
|
1168
|
+
res_kwargs = {}
|
1167
1169
|
else:
|
1168
1170
|
res_cls = ResourceX
|
1171
|
+
res_kwargs = {"hsds": hsds}
|
1169
1172
|
|
1170
1173
|
logger.info("Extracting ProjectPoints for desired regions")
|
1171
1174
|
points = []
|
1172
|
-
with res_cls(res_file,
|
1175
|
+
with res_cls(res_file, **res_kwargs) as f:
|
1173
1176
|
meta = f.meta
|
1174
1177
|
for region, region_col in regions.items():
|
1175
1178
|
logger.debug("- {}: {}".format(region_col, region))
|
@@ -1181,7 +1184,7 @@ class ProjectPoints:
|
|
1181
1184
|
if duplicates:
|
1182
1185
|
msg = (
|
1183
1186
|
"reV Cannot currently handle duplicate "
|
1184
|
-
"Resource gids! The given regions
|
1187
|
+
"Resource gids! The given regions containing the "
|
1185
1188
|
"same gids:\n{}".format(duplicates)
|
1186
1189
|
)
|
1187
1190
|
logger.error(msg)
|
reV/supply_curve/aggregation.py
CHANGED
@@ -9,6 +9,7 @@ import h5py
|
|
9
9
|
import numpy as np
|
10
10
|
import pandas as pd
|
11
11
|
from rex.resource import Resource
|
12
|
+
from rex.utilities import check_res_file
|
12
13
|
from rex.utilities.execution import SpawnProcessPool
|
13
14
|
from rex.utilities.loggers import log_mem
|
14
15
|
|
@@ -113,6 +114,7 @@ class AggFileHandler(AbstractAggFileHandler):
|
|
113
114
|
area_filter_kernel="queen",
|
114
115
|
min_area=None,
|
115
116
|
h5_handler=None,
|
117
|
+
**h5_handler_kwargs,
|
116
118
|
):
|
117
119
|
"""
|
118
120
|
Parameters
|
@@ -136,6 +138,8 @@ class AggFileHandler(AbstractAggFileHandler):
|
|
136
138
|
h5_handler : rex.Resource | None
|
137
139
|
Optional special handler similar to the rex.Resource handler which
|
138
140
|
is default.
|
141
|
+
**h5_handler_kwargs
|
142
|
+
Optional keyword-value pairs to pass to the h5 handler.
|
139
143
|
"""
|
140
144
|
super().__init__(
|
141
145
|
excl_fpath,
|
@@ -145,9 +149,9 @@ class AggFileHandler(AbstractAggFileHandler):
|
|
145
149
|
)
|
146
150
|
|
147
151
|
if h5_handler is None:
|
148
|
-
self._h5 = Resource(h5_fpath)
|
152
|
+
self._h5 = Resource(h5_fpath, **h5_handler_kwargs)
|
149
153
|
else:
|
150
|
-
self._h5 = h5_handler(h5_fpath)
|
154
|
+
self._h5 = h5_handler(h5_fpath, **h5_handler_kwargs)
|
151
155
|
|
152
156
|
@property
|
153
157
|
def h5(self):
|
@@ -504,8 +508,9 @@ class BaseAggregation(ABC):
|
|
504
508
|
generation run.
|
505
509
|
"""
|
506
510
|
|
511
|
+
__, hsds = check_res_file(gen_fpath)
|
507
512
|
if gen_fpath.endswith(".h5"):
|
508
|
-
with Resource(gen_fpath) as f:
|
513
|
+
with Resource(gen_fpath, hsds=hsds) as f:
|
509
514
|
gen_index = f.meta
|
510
515
|
elif gen_fpath.endswith(".csv"):
|
511
516
|
gen_index = pd.read_csv(gen_fpath)
|
@@ -631,7 +636,8 @@ class Aggregation(BaseAggregation):
|
|
631
636
|
)
|
632
637
|
)
|
633
638
|
|
634
|
-
|
639
|
+
__, hsds = check_res_file(h5_fpath)
|
640
|
+
if not hsds and not os.path.exists(h5_fpath):
|
635
641
|
raise FileNotFoundError(
|
636
642
|
"Could not find required h5 file: " "{}".format(h5_fpath)
|
637
643
|
)
|
@@ -645,7 +651,7 @@ class Aggregation(BaseAggregation):
|
|
645
651
|
)
|
646
652
|
)
|
647
653
|
|
648
|
-
with Resource(h5_fpath) as f:
|
654
|
+
with Resource(h5_fpath, hsds=hsds) as f:
|
649
655
|
for dset in self._agg_dsets:
|
650
656
|
if dset not in f:
|
651
657
|
raise FileInputError(
|
@@ -744,6 +750,7 @@ class Aggregation(BaseAggregation):
|
|
744
750
|
"excl_dict": excl_dict,
|
745
751
|
"area_filter_kernel": area_filter_kernel,
|
746
752
|
"min_area": min_area,
|
753
|
+
"hsds": check_res_file(h5_fpath)[1],
|
747
754
|
}
|
748
755
|
dsets = (
|
749
756
|
*agg_dset,
|
@@ -1011,7 +1018,9 @@ class Aggregation(BaseAggregation):
|
|
1011
1018
|
chunks = {}
|
1012
1019
|
dtypes = {}
|
1013
1020
|
time_index = None
|
1014
|
-
|
1021
|
+
|
1022
|
+
__, hsds = check_res_file(h5_fpath)
|
1023
|
+
with Resource(h5_fpath, hsds=hsds) as f:
|
1015
1024
|
for dset, data in agg_out.items():
|
1016
1025
|
dsets.append(dset)
|
1017
1026
|
shape = data.shape
|
@@ -6,6 +6,7 @@ import os
|
|
6
6
|
import logging
|
7
7
|
|
8
8
|
from rex.multi_file_resource import MultiFileResource
|
9
|
+
from rex.utilities.utilities import check_res_file
|
9
10
|
from gaps.cli import as_click_command, CLICommandFromClass
|
10
11
|
|
11
12
|
from reV.supply_curve.sc_aggregation import SupplyCurveAggregation
|
@@ -32,7 +33,7 @@ def _preprocessor(config, out_dir):
|
|
32
33
|
dict
|
33
34
|
Updated config file.
|
34
35
|
"""
|
35
|
-
config =
|
36
|
+
config = _validate_res_fpath(config)
|
36
37
|
_validate_tm(config)
|
37
38
|
|
38
39
|
key_to_modules = {"gen_fpath": [ModuleName.MULTI_YEAR,
|
@@ -47,32 +48,37 @@ def _preprocessor(config, out_dir):
|
|
47
48
|
return config
|
48
49
|
|
49
50
|
|
50
|
-
def
|
51
|
-
"""Format res_fpath with year
|
51
|
+
def _validate_res_fpath(config):
|
52
|
+
"""Format res_fpath with year (if needed) and check for file existence"""
|
52
53
|
res_fpath = config.setdefault("res_fpath", None)
|
53
|
-
if isinstance(res_fpath, str):
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
"{!r}".format(res_fpath.format("<year>")))
|
61
|
-
logger.error(msg)
|
62
|
-
raise FileNotFoundError(msg)
|
63
|
-
|
64
|
-
res_fpath = res_fpath.format(year)
|
65
|
-
|
66
|
-
elif not os.path.exists(res_fpath):
|
67
|
-
msg = "Could not find resource file: {!r}".format(res_fpath)
|
68
|
-
logger.error(msg)
|
69
|
-
raise FileNotFoundError(msg)
|
70
|
-
|
71
|
-
config["res_fpath"] = res_fpath
|
54
|
+
if not isinstance(res_fpath, str):
|
55
|
+
return config
|
56
|
+
|
57
|
+
if '{}' in res_fpath:
|
58
|
+
config["res_fpath"] = _get_filepath_with_year(res_fpath)
|
59
|
+
else:
|
60
|
+
check_res_file(res_fpath)
|
72
61
|
|
73
62
|
return config
|
74
63
|
|
75
64
|
|
65
|
+
def _get_filepath_with_year(res_fpath):
|
66
|
+
"""Find first file that exists on disk with year filled in"""
|
67
|
+
|
68
|
+
for year in range(1950, 2100):
|
69
|
+
fp = res_fpath.format(year)
|
70
|
+
try:
|
71
|
+
check_res_file(fp)
|
72
|
+
except FileNotFoundError:
|
73
|
+
continue
|
74
|
+
return fp
|
75
|
+
|
76
|
+
msg = ("Could not find any files that match the pattern"
|
77
|
+
"{!r}".format(res_fpath.format("<year>")))
|
78
|
+
logger.error(msg)
|
79
|
+
raise FileNotFoundError(msg)
|
80
|
+
|
81
|
+
|
76
82
|
def _validate_tm(config):
|
77
83
|
"""Check that tm_dset exists or that res_fpath is given (to generate tm)"""
|
78
84
|
paths = config["excl_fpath"]
|
@@ -9,7 +9,7 @@ from gaps.cli import as_click_command, CLICommandFromClass
|
|
9
9
|
from reV.supply_curve.tech_mapping import TechMapping
|
10
10
|
from reV.utilities import ModuleName
|
11
11
|
from reV.utilities.exceptions import ConfigError
|
12
|
-
from reV.supply_curve.cli_sc_aggregation import
|
12
|
+
from reV.supply_curve.cli_sc_aggregation import _validate_res_fpath
|
13
13
|
|
14
14
|
logger = logging.getLogger(__name__)
|
15
15
|
|
@@ -28,7 +28,7 @@ def _preprocessor(config):
|
|
28
28
|
Updated config file.
|
29
29
|
"""
|
30
30
|
_validate_excl_fpath(config)
|
31
|
-
config =
|
31
|
+
config = _validate_res_fpath(config)
|
32
32
|
_validate_dset(config)
|
33
33
|
|
34
34
|
return config
|
reV/supply_curve/points.py
CHANGED
@@ -11,7 +11,7 @@ import numpy as np
|
|
11
11
|
import pandas as pd
|
12
12
|
from rex.multi_time_resource import MultiTimeResource
|
13
13
|
from rex.resource import BaseResource, Resource
|
14
|
-
from rex.utilities.utilities import jsonify_dict
|
14
|
+
from rex.utilities.utilities import jsonify_dict, check_res_file
|
15
15
|
|
16
16
|
from reV.econ.economies_of_scale import EconomiesOfScale
|
17
17
|
from reV.econ.utilities import lcoe_fcr
|
@@ -1169,9 +1169,11 @@ class AggregationSupplyCurvePoint(SupplyCurvePoint):
|
|
1169
1169
|
Resource h5 handler object.
|
1170
1170
|
"""
|
1171
1171
|
if self._h5 is None and "*" in self._h5_fpath:
|
1172
|
-
|
1172
|
+
__, hsds = check_res_file(self._h5_fpath)
|
1173
|
+
self._h5 = MultiTimeResource(self._h5_fpath, hsds=hsds)
|
1173
1174
|
elif self._h5 is None:
|
1174
|
-
|
1175
|
+
__, hsds = check_res_file(self._h5_fpath)
|
1176
|
+
self._h5 = Resource(self._h5_fpath, hsds=hsds)
|
1175
1177
|
|
1176
1178
|
return self._h5
|
1177
1179
|
|
@@ -1643,7 +1645,8 @@ class GenerationSupplyCurvePoint(AggregationSupplyCurvePoint):
|
|
1643
1645
|
reV generation Resource object
|
1644
1646
|
"""
|
1645
1647
|
if self._gen is None:
|
1646
|
-
|
1648
|
+
__, hsds = check_res_file(self._gen_fpath)
|
1649
|
+
self._gen = Resource(self._gen_fpath, str_decode=False, hsds=hsds)
|
1647
1650
|
|
1648
1651
|
return self._gen
|
1649
1652
|
|
@@ -569,15 +569,20 @@ class SupplyCurveAggregation(BaseAggregation):
|
|
569
569
|
generation HDF5 output, or if `recalc_lcoe` is set to
|
570
570
|
``False``, the mean LCOE will be computed from the data
|
571
571
|
stored under the `lcoe_dset` instead. By default, ``True``.
|
572
|
-
zones_dset: str, optional
|
573
|
-
Dataset name in `excl_fpath` containing the zones to be
|
574
|
-
If specified, supply curve aggregation will be
|
575
|
-
for each discrete zone within each
|
576
|
-
can be used for uses cases
|
577
|
-
such
|
578
|
-
|
579
|
-
|
580
|
-
areas.
|
572
|
+
zones_dset : str, optional
|
573
|
+
Dataset name in `excl_fpath` containing the zones to be
|
574
|
+
applied. If specified, supply curve aggregation will be
|
575
|
+
performed separately for each discrete zone within each
|
576
|
+
supply curve site. This option can be used for uses cases
|
577
|
+
such as subdividing sites by parcel, such that each parcel
|
578
|
+
within each site is output to a separate ``sc_gid``. The
|
579
|
+
input data layer should consist of unique integer values for
|
580
|
+
each zone. Values of zero will be treated as excluded areas.
|
581
|
+
This functionality works best of you have on the order of
|
582
|
+
~100,000 zones or less. If you have significantly more zones
|
583
|
+
than that, the supply curve aggregation computation may take
|
584
|
+
too long to run; consider performing an alternative
|
585
|
+
analysis. By default, ``None``.
|
581
586
|
|
582
587
|
Examples
|
583
588
|
--------
|
reV/supply_curve/tech_mapping.py
CHANGED
@@ -16,10 +16,10 @@ from warnings import warn
|
|
16
16
|
|
17
17
|
import h5py
|
18
18
|
import numpy as np
|
19
|
+
from scipy.spatial import cKDTree
|
19
20
|
from rex.resource import Resource
|
20
21
|
from rex.utilities.execution import SpawnProcessPool
|
21
|
-
from rex.utilities.utilities import res_dist_threshold
|
22
|
-
from scipy.spatial import cKDTree
|
22
|
+
from rex.utilities.utilities import check_res_file, res_dist_threshold
|
23
23
|
|
24
24
|
from reV.supply_curve.extent import SupplyCurveExtent, LATITUDE, LONGITUDE
|
25
25
|
from reV.utilities.exceptions import FileInputError, FileInputWarning
|
@@ -30,17 +30,13 @@ logger = logging.getLogger(__name__)
|
|
30
30
|
class TechMapping:
|
31
31
|
"""Framework to create map between tech layer (exclusions), res, and gen"""
|
32
32
|
|
33
|
-
def __init__(
|
34
|
-
self, excl_fpath, res_fpath, sc_resolution=1200, dist_margin=1.05
|
35
|
-
):
|
33
|
+
def __init__(self, excl_fpath, sc_resolution=1200):
|
36
34
|
"""
|
37
35
|
Parameters
|
38
36
|
----------
|
39
37
|
excl_fpath : str
|
40
38
|
Filepath to exclusions h5 file, must contain latitude and longitude
|
41
39
|
arrays to allow for mapping to resource points
|
42
|
-
res_fpath : str
|
43
|
-
Filepath to .h5 resource file that we're mapping to.
|
44
40
|
sc_resolution : int | None, optional
|
45
41
|
Defines how many exclusion pixels are mapped at a time. Units
|
46
42
|
indicate the length of one dimension, in pixels, of each square
|
@@ -52,22 +48,13 @@ class TechMapping:
|
|
52
48
|
``sc_resolution`` parameter works in other functionality within
|
53
49
|
``reV``.
|
54
50
|
|
55
|
-
dist_margin : float, optional
|
56
|
-
Extra margin to multiply times the computed distance between
|
57
|
-
neighboring resource points, by default 1.05
|
58
51
|
"""
|
59
52
|
self._excl_fpath = excl_fpath
|
60
|
-
self._res_fpath = res_fpath
|
61
53
|
self._check_fout()
|
62
54
|
|
63
|
-
self._tree, self._dist_thresh = self._build_tree(
|
64
|
-
self._res_fpath, dist_margin=dist_margin
|
65
|
-
)
|
66
|
-
|
67
55
|
with SupplyCurveExtent(
|
68
56
|
self._excl_fpath, resolution=sc_resolution
|
69
57
|
) as sc:
|
70
|
-
self._sc_resolution = sc.resolution
|
71
58
|
self._gids = np.array(list(range(len(sc))), dtype=np.uint32)
|
72
59
|
self._excl_shape = sc.exclusions.shape
|
73
60
|
self._n_excl = np.prod(self._excl_shape)
|
@@ -82,19 +69,6 @@ class TechMapping:
|
|
82
69
|
)
|
83
70
|
)
|
84
71
|
|
85
|
-
@property
|
86
|
-
def distance_threshold(self):
|
87
|
-
"""Get the upper bound on NN distance between excl and res points.
|
88
|
-
|
89
|
-
Returns
|
90
|
-
-------
|
91
|
-
float
|
92
|
-
Estimate the distance between resource points. Calculated as half
|
93
|
-
of the diagonal between closest resource points, with desired
|
94
|
-
extra margin
|
95
|
-
"""
|
96
|
-
return self._dist_thresh
|
97
|
-
|
98
72
|
@staticmethod
|
99
73
|
def _build_tree(res_fpath, dist_margin=1.05):
|
100
74
|
"""
|
@@ -118,7 +92,8 @@ class TechMapping:
|
|
118
92
|
of the diagonal between closest resource points, with desired
|
119
93
|
extra margin
|
120
94
|
"""
|
121
|
-
|
95
|
+
__, hsds = check_res_file(res_fpath)
|
96
|
+
with Resource(res_fpath, hsds=hsds) as f:
|
122
97
|
lat_lons = f.lat_lon
|
123
98
|
|
124
99
|
# pylint: disable=not-callable
|
@@ -320,12 +295,6 @@ class TechMapping:
|
|
320
295
|
fillvalue=-1
|
321
296
|
)
|
322
297
|
|
323
|
-
if self._dist_thresh:
|
324
|
-
f[dset].attrs["distance_threshold"] = self._dist_thresh
|
325
|
-
|
326
|
-
if self._res_fpath:
|
327
|
-
f[dset].attrs["src_res_fpath"] = self._res_fpath
|
328
|
-
|
329
298
|
def _check_fout(self):
|
330
299
|
"""Check the TechMapping output file for cached data."""
|
331
300
|
with h5py.File(self._excl_fpath, 'r') as f:
|
@@ -337,9 +306,8 @@ class TechMapping:
|
|
337
306
|
logger.exception(emsg)
|
338
307
|
raise FileInputError(emsg)
|
339
308
|
|
340
|
-
def map_resource(
|
341
|
-
|
342
|
-
):
|
309
|
+
def map_resource(self, dset, res_fpath, dist_margin=1.05,
|
310
|
+
max_workers=None, batch_size=100):
|
343
311
|
"""
|
344
312
|
Map all resource gids to exclusion gids. Save results to dset in
|
345
313
|
exclusions h5 file.
|
@@ -349,6 +317,11 @@ class TechMapping:
|
|
349
317
|
dset : str, optional
|
350
318
|
Name of the output dataset in the exclusions H5 file to which the
|
351
319
|
tech map will be saved.
|
320
|
+
res_fpath : str
|
321
|
+
Filepath to .h5 resource file that we're mapping to.
|
322
|
+
dist_margin : float, optional
|
323
|
+
Extra margin to multiply times the computed distance between
|
324
|
+
neighboring resource points, by default 1.05
|
352
325
|
max_workers : int, optional
|
353
326
|
Number of cores to run mapping on. None uses all available cpus,
|
354
327
|
by default None
|
@@ -362,6 +335,17 @@ class TechMapping:
|
|
362
335
|
"""
|
363
336
|
loggers = [__name__, "reV"]
|
364
337
|
|
338
|
+
logger.info(
|
339
|
+
f"Computing cKDtree for tech mapping using {res_fpath=!r} "
|
340
|
+
f"and {dist_margin=!r}"
|
341
|
+
)
|
342
|
+
tree, dist_thresh = self._build_tree(
|
343
|
+
res_fpath, dist_margin=dist_margin
|
344
|
+
)
|
345
|
+
with h5py.File(self._excl_fpath, "a") as f:
|
346
|
+
f[dset].attrs["distance_threshold"] = dist_thresh
|
347
|
+
f[dset].attrs["src_res_fpath"] = res_fpath
|
348
|
+
|
365
349
|
n_jobs = len(self._gids)
|
366
350
|
n_batches = ceil(n_jobs / batch_size)
|
367
351
|
gid_batches = np.array_split(self._gids, n_batches)
|
@@ -389,8 +373,8 @@ class TechMapping:
|
|
389
373
|
exe.submit(
|
390
374
|
self.map_resource_gids,
|
391
375
|
excl_coords,
|
392
|
-
|
393
|
-
|
376
|
+
tree,
|
377
|
+
dist_thresh,
|
394
378
|
)
|
395
379
|
] = i
|
396
380
|
|
@@ -476,11 +460,12 @@ class TechMapping:
|
|
476
460
|
out-of-memory errors. Values less than the number of workers can
|
477
461
|
also lead to slower processing, due to poor load balancing.
|
478
462
|
"""
|
479
|
-
|
480
|
-
mapper = cls(excl_fpath, res_fpath, **kwargs)
|
463
|
+
mapper = cls(excl_fpath, sc_resolution=sc_resolution)
|
481
464
|
mapper.initialize_dataset(dset)
|
482
465
|
mapper.map_resource(
|
483
|
-
max_workers=max_workers,
|
484
466
|
dset=dset,
|
467
|
+
res_fpath=res_fpath,
|
468
|
+
dist_margin=dist_margin,
|
469
|
+
max_workers=max_workers,
|
485
470
|
batch_size=batch_size,
|
486
471
|
)
|
reV/version.py
CHANGED
File without changes
|
File without changes
|
File without changes
|