NREL-reV 0.8.7__py3-none-any.whl → 0.8.9__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.
Files changed (38) hide show
  1. {NREL_reV-0.8.7.dist-info → NREL_reV-0.8.9.dist-info}/METADATA +12 -10
  2. {NREL_reV-0.8.7.dist-info → NREL_reV-0.8.9.dist-info}/RECORD +38 -38
  3. {NREL_reV-0.8.7.dist-info → NREL_reV-0.8.9.dist-info}/WHEEL +1 -1
  4. reV/SAM/SAM.py +182 -133
  5. reV/SAM/econ.py +18 -14
  6. reV/SAM/generation.py +608 -419
  7. reV/SAM/windbos.py +93 -79
  8. reV/bespoke/bespoke.py +690 -445
  9. reV/bespoke/place_turbines.py +6 -6
  10. reV/config/project_points.py +220 -140
  11. reV/econ/econ.py +165 -113
  12. reV/econ/economies_of_scale.py +57 -34
  13. reV/generation/base.py +310 -183
  14. reV/generation/generation.py +298 -190
  15. reV/handlers/exclusions.py +16 -15
  16. reV/handlers/multi_year.py +12 -9
  17. reV/handlers/outputs.py +6 -5
  18. reV/hybrids/hybrid_methods.py +28 -30
  19. reV/hybrids/hybrids.py +304 -188
  20. reV/nrwal/nrwal.py +262 -168
  21. reV/qa_qc/cli_qa_qc.py +14 -10
  22. reV/qa_qc/qa_qc.py +217 -119
  23. reV/qa_qc/summary.py +228 -146
  24. reV/rep_profiles/rep_profiles.py +349 -230
  25. reV/supply_curve/aggregation.py +349 -188
  26. reV/supply_curve/competitive_wind_farms.py +90 -48
  27. reV/supply_curve/exclusions.py +138 -85
  28. reV/supply_curve/extent.py +75 -50
  29. reV/supply_curve/points.py +536 -309
  30. reV/supply_curve/sc_aggregation.py +366 -225
  31. reV/supply_curve/supply_curve.py +505 -308
  32. reV/supply_curve/tech_mapping.py +144 -82
  33. reV/utilities/__init__.py +199 -16
  34. reV/utilities/pytest_utils.py +8 -4
  35. reV/version.py +1 -1
  36. {NREL_reV-0.8.7.dist-info → NREL_reV-0.8.9.dist-info}/LICENSE +0 -0
  37. {NREL_reV-0.8.7.dist-info → NREL_reV-0.8.9.dist-info}/entry_points.txt +0 -0
  38. {NREL_reV-0.8.7.dist-info → NREL_reV-0.8.9.dist-info}/top_level.txt +0 -0
@@ -2,17 +2,18 @@
2
2
  """
3
3
  Exclusion layers handler
4
4
  """
5
- import logging
6
5
  import json
6
+ import logging
7
+
7
8
  import numpy as np
9
+ from rex.multi_file_resource import MultiFileResource
10
+ from rex.resource import Resource
11
+ from rex.utilities.parse_keys import parse_keys
8
12
 
9
13
  from reV.utilities.exceptions import HandlerKeyError, MultiFileExclusionError
10
14
 
11
- from rex.utilities.parse_keys import parse_keys
12
- from rex.resource import Resource
13
- from rex.multi_file_resource import MultiFileResource
14
-
15
15
  logger = logging.getLogger(__name__)
16
+ LATITUDE, LONGITUDE = "latitude", "longitude"
16
17
 
17
18
 
18
19
  class ExclusionLayers:
@@ -81,8 +82,8 @@ class ExclusionLayers:
81
82
 
82
83
  def _preflight_multi_file(self):
83
84
  """Run simple multi-file exclusion checks."""
84
- lat_shape = self.h5.shapes['latitude']
85
- lon_shape = self.h5.shapes['longitude']
85
+ lat_shape = self.h5.shapes[LATITUDE]
86
+ lon_shape = self.h5.shapes[LONGITUDE]
86
87
  for layer in self.layers:
87
88
  lshape = self.h5.shapes[layer]
88
89
  lshape = lshape[1:] if len(lshape) > 2 else lshape
@@ -231,7 +232,7 @@ class ExclusionLayers:
231
232
  """
232
233
  shape = self.h5.attrs.get('shape', None)
233
234
  if shape is None:
234
- shape = self.h5.shapes['latitude']
235
+ shape = self.h5.shapes[LATITUDE]
235
236
 
236
237
  return tuple(shape)
237
238
 
@@ -247,7 +248,7 @@ class ExclusionLayers:
247
248
  """
248
249
  chunks = self.h5.attrs.get('chunks', None)
249
250
  if chunks is None:
250
- chunks = self.h5.chunks['latitude']
251
+ chunks = self.h5.chunks[LATITUDE]
251
252
 
252
253
  return chunks
253
254
 
@@ -260,7 +261,7 @@ class ExclusionLayers:
260
261
  -------
261
262
  ndarray
262
263
  """
263
- return self['latitude']
264
+ return self[LATITUDE]
264
265
 
265
266
  @property
266
267
  def longitude(self):
@@ -271,7 +272,7 @@ class ExclusionLayers:
271
272
  -------
272
273
  ndarray
273
274
  """
274
- return self['longitude']
275
+ return self[LONGITUDE]
275
276
 
276
277
  def get_layer_profile(self, layer):
277
278
  """
@@ -384,13 +385,13 @@ class ExclusionLayers:
384
385
  lat : ndarray
385
386
  Latitude coordinates
386
387
  """
387
- if 'latitude' not in self.h5:
388
+ if LATITUDE not in self.h5:
388
389
  msg = ('"latitude" is missing from {}'
389
390
  .format(self.h5_file))
390
391
  logger.error(msg)
391
392
  raise HandlerKeyError(msg)
392
393
 
393
- ds_slice = ('latitude', ) + ds_slice
394
+ ds_slice = (LATITUDE, ) + ds_slice
394
395
 
395
396
  lat = self.h5[ds_slice]
396
397
 
@@ -410,13 +411,13 @@ class ExclusionLayers:
410
411
  lon : ndarray
411
412
  Longitude coordinates
412
413
  """
413
- if 'longitude' not in self.h5:
414
+ if LONGITUDE not in self.h5:
414
415
  msg = ('"longitude" is missing from {}'
415
416
  .format(self.h5_file))
416
417
  logger.error(msg)
417
418
  raise HandlerKeyError(msg)
418
419
 
419
- ds_slice = ('longitude', ) + ds_slice
420
+ ds_slice = (LONGITUDE, ) + ds_slice
420
421
 
421
422
  lon = self.h5[ds_slice]
422
423
 
@@ -3,22 +3,25 @@
3
3
  Classes to collect reV outputs from multiple annual files.
4
4
  """
5
5
  import glob
6
- import time
7
6
  import logging
8
- import numpy as np
9
7
  import os
10
- import pandas as pd
8
+ import time
11
9
  from warnings import warn
12
10
 
13
- from rex import Resource
14
- from rex.utilities.utilities import (get_class_properties, parse_year,
15
- get_lat_lon_cols)
11
+ import numpy as np
12
+ import pandas as pd
16
13
  from gaps.pipeline import parse_previous_status
14
+ from rex import Resource
15
+ from rex.utilities.utilities import (
16
+ get_class_properties,
17
+ get_lat_lon_cols,
18
+ parse_year,
19
+ )
17
20
 
18
- from reV.handlers.outputs import Outputs
19
21
  from reV.config.output_request import SAMOutputRequest
20
- from reV.utilities.exceptions import HandlerRuntimeError, ConfigError
21
- from reV.utilities import log_versions, ModuleName
22
+ from reV.handlers.outputs import Outputs
23
+ from reV.utilities import ModuleName, log_versions
24
+ from reV.utilities.exceptions import ConfigError, HandlerRuntimeError
22
25
 
23
26
  logger = logging.getLogger(__name__)
24
27
 
reV/handlers/outputs.py CHANGED
@@ -2,15 +2,16 @@
2
2
  """
3
3
  Classes to handle reV h5 output files.
4
4
  """
5
+ import json
5
6
  import logging
7
+ import sys
8
+
6
9
  import NRWAL
7
10
  import PySAM
8
11
  import rex
9
- import sys
10
- import json
12
+ from rex.outputs import Outputs as rexOutputs
11
13
 
12
14
  from reV.version import __version__
13
- from rex.outputs import Outputs as rexOutputs
14
15
 
15
16
  logger = logging.getLogger(__name__)
16
17
 
@@ -28,8 +29,8 @@ class Outputs(rexOutputs):
28
29
  >>> import pandas as pd
29
30
  >>> import numpy as np
30
31
  >>>
31
- >>> meta = pd.DataFrame({'latitude': np.ones(100),
32
- >>> 'longitude': np.ones(100)})
32
+ >>> meta = pd.DataFrame({SupplyCurveField.LATITUDE: np.ones(100),
33
+ >>> SupplyCurveField.LONGITUDE: np.ones(100)})
33
34
  >>>
34
35
  >>> time_index = pd.date_range('20210101', '20220101', freq='1h',
35
36
  >>> closed='right')
@@ -3,18 +3,12 @@
3
3
 
4
4
  @author: ppinchuk
5
5
  """
6
+ from reV.utilities import SupplyCurveField
6
7
 
7
8
 
8
9
  def aggregate_solar_capacity(h):
9
10
  """Compute the total solar capcity allowed in hybridization.
10
11
 
11
- Note
12
- ----
13
- No limiting is done on the ratio of wind to solar. This method
14
- checks for an existing 'hybrid_solar_capacity'. If one does not exist,
15
- it is assumed that there is no limit on the solar to wind capacity
16
- ratio and the solar capacity is copied into this new column.
17
-
18
12
  Parameters
19
13
  ----------
20
14
  h : `reV.hybrids.Hybridization`
@@ -26,27 +20,25 @@ def aggregate_solar_capacity(h):
26
20
  -------
27
21
  data : Series | None
28
22
  A series of data containing the capacity allowed in the hybrid
29
- capacity sum, or `None` if 'hybrid_solar_capacity' already exists.
23
+ capacity sum, or `None` if 'hybrid_solar_capacity' already
24
+ exists.
30
25
 
31
26
  Notes
32
27
  -----
33
-
28
+ No limiting is done on the ratio of wind to solar. This method
29
+ checks for an existing 'hybrid_solar_capacity'. If one does not
30
+ exist, it is assumed that there is no limit on the solar to wind
31
+ capacity ratio and the solar capacity is copied into this new
32
+ column.
34
33
  """
35
- if 'hybrid_solar_capacity' in h.hybrid_meta:
34
+ if f'hybrid_solar_{SupplyCurveField.CAPACITY}' in h.hybrid_meta:
36
35
  return None
37
- return h.hybrid_meta['solar_capacity']
36
+ return h.hybrid_meta[f'solar_{SupplyCurveField.CAPACITY}']
38
37
 
39
38
 
40
39
  def aggregate_wind_capacity(h):
41
40
  """Compute the total wind capcity allowed in hybridization.
42
41
 
43
- Note
44
- ----
45
- No limiting is done on the ratio of wind to solar. This method
46
- checks for an existing 'hybrid_wind_capacity'. If one does not exist,
47
- it is assumed that there is no limit on the solar to wind capacity
48
- ratio and the wind capacity is copied into this new column.
49
-
50
42
  Parameters
51
43
  ----------
52
44
  h : `reV.hybrids.Hybridization`
@@ -58,15 +50,19 @@ def aggregate_wind_capacity(h):
58
50
  -------
59
51
  data : Series | None
60
52
  A series of data containing the capacity allowed in the hybrid
61
- capacity sum, or `None` if 'hybrid_solar_capacity' already exists.
53
+ capacity sum, or `None` if 'hybrid_solar_capacity' already
54
+ exists.
62
55
 
63
56
  Notes
64
57
  -----
65
-
58
+ No limiting is done on the ratio of wind to solar. This method
59
+ checks for an existing 'hybrid_wind_capacity'. If one does not
60
+ exist, it is assumed that there is no limit on the solar to wind
61
+ capacity ratio and the wind capacity is copied into this new column.
66
62
  """
67
- if 'hybrid_wind_capacity' in h.hybrid_meta:
63
+ if f'hybrid_wind_{SupplyCurveField.CAPACITY}' in h.hybrid_meta:
68
64
  return None
69
- return h.hybrid_meta['wind_capacity']
65
+ return h.hybrid_meta[f'wind_{SupplyCurveField.CAPACITY}']
70
66
 
71
67
 
72
68
  def aggregate_capacity(h):
@@ -85,8 +81,8 @@ def aggregate_capacity(h):
85
81
  A series of data containing the aggregated capacity, or `None`
86
82
  if the capacity columns are missing.
87
83
  """
88
-
89
- sc, wc = 'hybrid_solar_capacity', 'hybrid_wind_capacity'
84
+ sc = f'hybrid_solar_{SupplyCurveField.CAPACITY}'
85
+ wc = f'hybrid_wind_{SupplyCurveField.CAPACITY}'
90
86
  missing_solar_cap = sc not in h.hybrid_meta.columns
91
87
  missing_wind_cap = wc not in h.hybrid_meta.columns
92
88
  if missing_solar_cap or missing_wind_cap:
@@ -113,8 +109,10 @@ def aggregate_capacity_factor(h):
113
109
  if the capacity and/or mean_cf columns are missing.
114
110
  """
115
111
 
116
- sc, wc = 'hybrid_solar_capacity', 'hybrid_wind_capacity'
117
- scf, wcf = 'solar_mean_cf', 'wind_mean_cf'
112
+ sc = f'hybrid_solar_{SupplyCurveField.CAPACITY}'
113
+ wc = f'hybrid_wind_{SupplyCurveField.CAPACITY}'
114
+ scf = f'solar_{SupplyCurveField.MEAN_CF}'
115
+ wcf = f'wind_{SupplyCurveField.MEAN_CF}'
118
116
  missing_solar_cap = sc not in h.hybrid_meta.columns
119
117
  missing_wind_cap = wc not in h.hybrid_meta.columns
120
118
  missing_solar_mean_cf = scf not in h.hybrid_meta.columns
@@ -132,8 +130,8 @@ def aggregate_capacity_factor(h):
132
130
 
133
131
 
134
132
  HYBRID_METHODS = {
135
- 'hybrid_solar_capacity': aggregate_solar_capacity,
136
- 'hybrid_wind_capacity': aggregate_wind_capacity,
137
- 'hybrid_capacity': aggregate_capacity,
138
- 'hybrid_mean_cf': aggregate_capacity_factor
133
+ f'hybrid_solar_{SupplyCurveField.CAPACITY}': aggregate_solar_capacity,
134
+ f'hybrid_wind_{SupplyCurveField.CAPACITY}': aggregate_wind_capacity,
135
+ f'hybrid_{SupplyCurveField.CAPACITY}': aggregate_capacity,
136
+ f'hybrid_{SupplyCurveField.MEAN_CF}': aggregate_capacity_factor
139
137
  }