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
reV/qa_qc/summary.py CHANGED
@@ -3,15 +3,17 @@
3
3
  Compute and plot summary data
4
4
  """
5
5
  import logging
6
- import numpy as np
7
6
  import os
7
+
8
+ import numpy as np
8
9
  import pandas as pd
9
- import plotting as mplt
10
10
  import plotly.express as px
11
-
11
+ import plotting as mplt
12
12
  from rex import Resource
13
13
  from rex.utilities import SpawnProcessPool, parse_table
14
14
 
15
+ from reV.utilities import SupplyCurveField, ResourceMetaField
16
+
15
17
  logger = logging.getLogger(__name__)
16
18
 
17
19
 
@@ -19,6 +21,7 @@ class SummarizeH5:
19
21
  """
20
22
  reV Summary data for QA/QC
21
23
  """
24
+
22
25
  def __init__(self, h5_file, group=None):
23
26
  """
24
27
  Parameters
@@ -28,7 +31,7 @@ class SummarizeH5:
28
31
  group : str, optional
29
32
  Group within h5_file to summarize datasets for, by default None
30
33
  """
31
- logger.info('QAQC Summarize initializing on: {}'.format(h5_file))
34
+ logger.info("QAQC Summarize initializing on: {}".format(h5_file))
32
35
  self._h5_file = h5_file
33
36
  self._group = group
34
37
 
@@ -73,12 +76,12 @@ class SummarizeH5:
73
76
  sites = slice(None)
74
77
 
75
78
  with Resource(h5_file, group=group) as f:
76
- sites_meta = f['meta', sites]
79
+ sites_meta = f["meta", sites]
77
80
  sites_data = f[ds_name, :, sites]
78
81
 
79
82
  sites_summary = pd.DataFrame(sites_data, columns=sites_meta.index)
80
- sites_summary = sites_summary.describe().T.drop(columns=['count'])
81
- sites_summary['sum'] = sites_data.sum(axis=0)
83
+ sites_summary = sites_summary.describe().T.drop(columns=["count"])
84
+ sites_summary["sum"] = sites_data.sum(axis=0)
82
85
 
83
86
  return sites_summary
84
87
 
@@ -105,13 +108,14 @@ class SummarizeH5:
105
108
  ds_data = f[ds_name, :]
106
109
 
107
110
  ds_summary = pd.DataFrame(ds_data, columns=[ds_name])
108
- ds_summary = ds_summary.describe().drop(['count'])
109
- ds_summary.at['sum', ds_name] = ds_data.sum()
111
+ ds_summary = ds_summary.describe().drop(["count"])
112
+ ds_summary.at["sum", ds_name] = ds_data.sum()
110
113
 
111
114
  return ds_summary
112
115
 
113
- def summarize_dset(self, ds_name, process_size=None, max_workers=None,
114
- out_path=None):
116
+ def summarize_dset(
117
+ self, ds_name, process_size=None, max_workers=None, out_path=None
118
+ ):
115
119
  """
116
120
  Compute dataset summary. If dataset is 2D compute temporal statistics
117
121
  for each site
@@ -144,46 +148,52 @@ class SummarizeH5:
144
148
  if process_size is None:
145
149
  process_size = ds_shape[-1]
146
150
 
147
- sites = \
148
- np.array_split(sites,
149
- int(np.ceil(len(sites) / process_size)))
150
- loggers = [__name__, 'reV']
151
- with SpawnProcessPool(max_workers=max_workers,
152
- loggers=loggers) as ex:
151
+ sites = np.array_split(
152
+ sites, int(np.ceil(len(sites) / process_size))
153
+ )
154
+ loggers = [__name__, "reV"]
155
+ with SpawnProcessPool(
156
+ max_workers=max_workers, loggers=loggers
157
+ ) as ex:
153
158
  futures = []
154
159
  for site_slice in sites:
155
- futures.append(ex.submit(
156
- self._compute_sites_summary,
157
- self.h5_file, ds_name, sites=site_slice,
158
- group=self._group))
160
+ futures.append(
161
+ ex.submit(
162
+ self._compute_sites_summary,
163
+ self.h5_file,
164
+ ds_name,
165
+ sites=site_slice,
166
+ group=self._group,
167
+ )
168
+ )
159
169
 
160
170
  summary = [future.result() for future in futures]
161
171
 
162
172
  summary = pd.concat(summary)
173
+ elif process_size is None:
174
+ summary = self._compute_sites_summary(self.h5_file,
175
+ ds_name,
176
+ sites=sites,
177
+ group=self._group)
163
178
  else:
164
- if process_size is None:
165
- summary = self._compute_sites_summary(self.h5_file,
166
- ds_name,
167
- sites=sites,
168
- group=self._group)
169
- else:
170
- sites = np.array_split(
171
- sites, int(np.ceil(len(sites) / process_size)))
172
-
173
- summary = []
174
- for site_slice in sites:
175
- summary.append(self._compute_sites_summary(
176
- self.h5_file, ds_name,
177
- sites=site_slice,
178
- group=self._group))
179
+ sites = np.array_split(
180
+ sites, int(np.ceil(len(sites) / process_size)))
179
181
 
180
- summary = pd.concat(summary)
182
+ summary = []
183
+ for site_slice in sites:
184
+ summary.append(self._compute_sites_summary(
185
+ self.h5_file, ds_name,
186
+ sites=site_slice,
187
+ group=self._group))
181
188
 
182
- summary.index.name = 'gid'
189
+ summary = pd.concat(summary)
190
+
191
+ summary.index.name = ResourceMetaField.GID
183
192
 
184
193
  else:
185
- summary = self._compute_ds_summary(self.h5_file, ds_name,
186
- group=self._group)
194
+ summary = self._compute_ds_summary(
195
+ self.h5_file, ds_name, group=self._group
196
+ )
187
197
 
188
198
  if out_path is not None:
189
199
  summary.to_csv(out_path)
@@ -206,9 +216,9 @@ class SummarizeH5:
206
216
  """
207
217
  with Resource(self.h5_file, group=self._group) as f:
208
218
  meta = f.meta
209
- if 'gid' not in meta:
210
- if meta.index.name != 'gid':
211
- meta.index.name = 'gid'
219
+ if ResourceMetaField.GID not in meta:
220
+ if meta.index.name != ResourceMetaField.GID:
221
+ meta.index.name = ResourceMetaField.GID
212
222
 
213
223
  meta = meta.reset_index()
214
224
 
@@ -223,8 +233,15 @@ class SummarizeH5:
223
233
  return meta
224
234
 
225
235
  @classmethod
226
- def run(cls, h5_file, out_dir, group=None, dsets=None,
227
- process_size=None, max_workers=None):
236
+ def run(
237
+ cls,
238
+ h5_file,
239
+ out_dir,
240
+ group=None,
241
+ dsets=None,
242
+ process_size=None,
243
+ max_workers=None,
244
+ ):
228
245
  """
229
246
  Summarize all datasets in h5_file and dump to out_dir
230
247
 
@@ -249,19 +266,25 @@ class SummarizeH5:
249
266
 
250
267
  if dsets is None:
251
268
  with Resource(h5_file, group=group) as f:
252
- dsets = [dset for dset in f.datasets
253
- if dset not in ['meta', 'time_index']]
269
+ dsets = [
270
+ dset
271
+ for dset in f.datasets
272
+ if dset not in ["meta", "time_index"]
273
+ ]
254
274
  elif isinstance(dsets, str):
255
275
  dsets = [dsets]
256
276
 
257
277
  summary = cls(h5_file)
258
278
  for ds_name in dsets:
259
- out_path = os.path.join(out_dir,
260
- "{}_summary.csv".format(ds_name))
261
- summary.summarize_dset(ds_name, process_size=process_size,
262
- max_workers=max_workers, out_path=out_path)
263
-
264
- out_path = os.path.basename(h5_file).replace('.h5', '_summary.csv')
279
+ out_path = os.path.join(out_dir, "{}_summary.csv".format(ds_name))
280
+ summary.summarize_dset(
281
+ ds_name,
282
+ process_size=process_size,
283
+ max_workers=max_workers,
284
+ out_path=out_path,
285
+ )
286
+
287
+ out_path = os.path.basename(h5_file).replace(".h5", "_summary.csv")
265
288
  out_path = os.path.join(out_dir, out_path)
266
289
  summary.summarize_means(out_path=out_path)
267
290
 
@@ -270,6 +293,7 @@ class SummarizeSupplyCurve:
270
293
  """
271
294
  Summarize Supply Curve table
272
295
  """
296
+
273
297
  def __init__(self, sc_table):
274
298
  self._sc_table = self._parse_summary(sc_table)
275
299
 
@@ -343,27 +367,27 @@ class SummarizeSupplyCurve:
343
367
 
344
368
  sc_summary = []
345
369
  sc_stat = sc_table.mean(axis=0)
346
- sc_stat.name = 'mean'
370
+ sc_stat.name = "mean"
347
371
  sc_summary.append(sc_stat)
348
372
 
349
373
  sc_stat = sc_table.std(axis=0)
350
- sc_stat.name = 'stdev'
374
+ sc_stat.name = "stdev"
351
375
  sc_summary.append(sc_stat)
352
376
 
353
377
  sc_stat = sc_table.median(axis=0)
354
- sc_stat.name = 'median'
378
+ sc_stat.name = "median"
355
379
  sc_summary.append(sc_stat)
356
380
 
357
381
  sc_stat = sc_table.min(axis=0)
358
- sc_stat.name = 'min'
382
+ sc_stat.name = "min"
359
383
  sc_summary.append(sc_stat)
360
384
 
361
385
  sc_stat = sc_table.max(axis=0)
362
- sc_stat.name = 'max'
386
+ sc_stat.name = "max"
363
387
  sc_summary.append(sc_stat)
364
388
 
365
389
  sc_stat = sc_table.sum(axis=0)
366
- sc_stat.name = 'sum'
390
+ sc_stat.name = "sum"
367
391
  sc_summary.append(sc_stat)
368
392
 
369
393
  sc_summary = pd.concat(sc_summary, axis=1).T
@@ -392,7 +416,7 @@ class SummarizeSupplyCurve:
392
416
  os.makedirs(out_dir, exist_ok=True)
393
417
 
394
418
  summary = cls(sc_table)
395
- out_path = os.path.basename(sc_table).replace('.csv', '_summary.csv')
419
+ out_path = os.path.basename(sc_table).replace(".csv", "_summary.csv")
396
420
  out_path = os.path.join(out_dir, out_path)
397
421
  summary.supply_curve_summary(columns=columns, out_path=out_path)
398
422
 
@@ -401,6 +425,7 @@ class PlotBase:
401
425
  """
402
426
  QA/QC Plotting base class
403
427
  """
428
+
404
429
  def __init__(self, data):
405
430
  """
406
431
  Parameters
@@ -438,7 +463,7 @@ class PlotBase:
438
463
  out_path : str
439
464
  File path to save plot to, can be a .html or static image
440
465
  """
441
- if out_path.endswith('.html'):
466
+ if out_path.endswith(".html"):
442
467
  fig.write_html(out_path)
443
468
  else:
444
469
  fig.write_image(out_path)
@@ -461,12 +486,13 @@ class PlotBase:
461
486
  values = [values]
462
487
 
463
488
  if scatter:
464
- values += ['latitude', 'longitude']
489
+ values += [SupplyCurveField.LATITUDE, SupplyCurveField.LONGITUDE]
465
490
 
466
491
  for value in values:
467
492
  if value not in df:
468
- msg = ("{} is not a valid column in summary table:\n{}"
469
- .format(value, df))
493
+ msg = "{} is not a valid column in summary table:\n{}".format(
494
+ value, df
495
+ )
470
496
  logger.error(msg)
471
497
  raise ValueError(msg)
472
498
 
@@ -475,6 +501,7 @@ class SummaryPlots(PlotBase):
475
501
  """
476
502
  Plot summary data for QA/QC
477
503
  """
504
+
478
505
  def __init__(self, summary):
479
506
  """
480
507
  Parameters
@@ -506,7 +533,7 @@ class SummaryPlots(PlotBase):
506
533
  """
507
534
  return list(self.summary.columns)
508
535
 
509
- def scatter_plot(self, value, cmap='viridis', out_path=None, **kwargs):
536
+ def scatter_plot(self, value, cmap="viridis", out_path=None, **kwargs):
510
537
  """
511
538
  Plot scatter plot of value versus longitude and latitude using
512
539
  pandas.plot.scatter
@@ -523,10 +550,11 @@ class SummaryPlots(PlotBase):
523
550
  Additional kwargs for plotting.dataframes.df_scatter
524
551
  """
525
552
  self._check_value(self.summary, value)
526
- mplt.df_scatter(self.summary, x='longitude', y='latitude', c=value,
527
- colormap=cmap, filename=out_path, **kwargs)
553
+ mplt.df_scatter(self.summary, x=SupplyCurveField.LONGITUDE,
554
+ y=SupplyCurveField.LATITUDE, c=value, colormap=cmap,
555
+ filename=out_path, **kwargs)
528
556
 
529
- def scatter_plotly(self, value, cmap='Viridis', out_path=None, **kwargs):
557
+ def scatter_plotly(self, value, cmap="Viridis", out_path=None, **kwargs):
530
558
  """
531
559
  Plot scatter plot of value versus longitude and latitude using
532
560
  plotly
@@ -544,8 +572,9 @@ class SummaryPlots(PlotBase):
544
572
  Additional kwargs for plotly.express.scatter
545
573
  """
546
574
  self._check_value(self.summary, value)
547
- fig = px.scatter(self.summary, x='longitude', y='latitude',
548
- color=value, color_continuous_scale=cmap, **kwargs)
575
+ fig = px.scatter(self.summary, x=SupplyCurveField.LONGITUDE,
576
+ y=SupplyCurveField.LATITUDE, color=value,
577
+ color_continuous_scale=cmap, **kwargs)
549
578
  fig.update_layout(font=dict(family="Arial", size=18, color="black"))
550
579
 
551
580
  if out_path is not None:
@@ -553,24 +582,27 @@ class SummaryPlots(PlotBase):
553
582
 
554
583
  fig.show()
555
584
 
556
- def _extract_sc_data(self, lcoe='mean_lcoe'):
585
+ def _extract_sc_data(self, lcoe=SupplyCurveField.MEAN_LCOE):
557
586
  """
558
587
  Extract supply curve data
559
588
 
560
589
  Parameters
561
590
  ----------
562
591
  lcoe : str, optional
563
- LCOE value to use for supply curve, by default 'mean_lcoe'
592
+ LCOE value to use for supply curve,
593
+ by default :obj:`SupplyCurveField.MEAN_LCOE`
564
594
 
565
595
  Returns
566
596
  -------
567
597
  sc_df : pandas.DataFrame
568
598
  Supply curve data
569
599
  """
570
- values = ['capacity', lcoe]
600
+ values = [SupplyCurveField.CAPACITY, lcoe]
571
601
  self._check_value(self.summary, values, scatter=False)
572
602
  sc_df = self.summary[values].sort_values(lcoe)
573
- sc_df['cumulative_capacity'] = sc_df['capacity'].cumsum()
603
+ sc_df['cumulative_capacity'] = (
604
+ sc_df[SupplyCurveField.CAPACITY].cumsum()
605
+ )
574
606
 
575
607
  return sc_df
576
608
 
@@ -614,8 +646,15 @@ class SummaryPlots(PlotBase):
614
646
  fig.show()
615
647
 
616
648
  @classmethod
617
- def scatter(cls, summary_csv, out_dir, value, plot_type='plotly',
618
- cmap='viridis', **kwargs):
649
+ def scatter(
650
+ cls,
651
+ summary_csv,
652
+ out_dir,
653
+ value,
654
+ plot_type="plotly",
655
+ cmap="viridis",
656
+ **kwargs,
657
+ ):
619
658
  """
620
659
  Create scatter plot for given value in summary table and save to
621
660
  out_dir
@@ -636,25 +675,31 @@ class SummaryPlots(PlotBase):
636
675
  Additional plotting kwargs
637
676
  """
638
677
  splt = cls(summary_csv)
639
- if plot_type == 'plot':
640
- out_path = os.path.basename(summary_csv).replace('.csv', '.png')
678
+ if plot_type == "plot":
679
+ out_path = os.path.basename(summary_csv).replace(".csv", ".png")
641
680
  out_path = os.path.join(out_dir, out_path)
642
- splt.scatter_plot(value, cmap=cmap.lower(), out_path=out_path,
643
- **kwargs)
644
- elif plot_type == 'plotly':
645
- out_path = os.path.basename(summary_csv).replace('.csv', '.html')
681
+ splt.scatter_plot(
682
+ value, cmap=cmap.lower(), out_path=out_path, **kwargs
683
+ )
684
+ elif plot_type == "plotly":
685
+ out_path = os.path.basename(summary_csv).replace(".csv", ".html")
646
686
  out_path = os.path.join(out_dir, out_path)
647
- splt.scatter_plotly(value, cmap=cmap.capitalize(),
648
- out_path=out_path, **kwargs)
687
+ splt.scatter_plotly(
688
+ value, cmap=cmap.capitalize(), out_path=out_path, **kwargs
689
+ )
649
690
  else:
650
- msg = ("plot_type must be 'plot' or 'plotly' but {} was given"
651
- .format(plot_type))
691
+ msg = (
692
+ "plot_type must be 'plot' or 'plotly' but {} was given".format(
693
+ plot_type
694
+ )
695
+ )
652
696
  logger.error(msg)
653
697
  raise ValueError(msg)
654
698
 
655
699
  @classmethod
656
- def scatter_all(cls, summary_csv, out_dir, plot_type='plotly',
657
- cmap='viridis', **kwargs):
700
+ def scatter_all(
701
+ cls, summary_csv, out_dir, plot_type="plotly", cmap="viridis", **kwargs
702
+ ):
658
703
  """
659
704
  Create scatter plot for all summary stats in summary table and save to
660
705
  out_dir
@@ -674,24 +719,29 @@ class SummaryPlots(PlotBase):
674
719
  """
675
720
  splt = cls(summary_csv)
676
721
  splt._data = splt.summary.select_dtypes(include=np.number)
677
- datasets = [c for c in splt.summary.columns
678
- if not c.startswith(('lat', 'lon'))]
722
+ datasets = [
723
+ c for c in splt.summary.columns if not c.startswith(("lat", "lon"))
724
+ ]
679
725
 
680
726
  for value in datasets:
681
- if plot_type == 'plot':
682
- out_path = '_{}.png'.format(value)
683
- out_path = \
684
- os.path.basename(summary_csv).replace('.csv', out_path)
727
+ if plot_type == "plot":
728
+ out_path = "_{}.png".format(value)
729
+ out_path = os.path.basename(summary_csv).replace(
730
+ ".csv", out_path
731
+ )
685
732
  out_path = os.path.join(out_dir, out_path)
686
- splt.scatter_plot(value, cmap=cmap.lower(), out_path=out_path,
687
- **kwargs)
688
- elif plot_type == 'plotly':
689
- out_path = '_{}.html'.format(value)
690
- out_path = \
691
- os.path.basename(summary_csv).replace('.csv', out_path)
733
+ splt.scatter_plot(
734
+ value, cmap=cmap.lower(), out_path=out_path, **kwargs
735
+ )
736
+ elif plot_type == "plotly":
737
+ out_path = "_{}.html".format(value)
738
+ out_path = os.path.basename(summary_csv).replace(
739
+ ".csv", out_path
740
+ )
692
741
  out_path = os.path.join(out_dir, out_path)
693
- splt.scatter_plotly(value, cmap=cmap.capitalize(),
694
- out_path=out_path, **kwargs)
742
+ splt.scatter_plotly(
743
+ value, cmap=cmap.capitalize(), out_path=out_path, **kwargs
744
+ )
695
745
  else:
696
746
  msg = ("plot_type must be 'plot' or 'plotly' but {} was given"
697
747
  .format(plot_type))
@@ -735,52 +785,58 @@ class SupplyCurvePlot(PlotBase):
735
785
  """
736
786
  return list(self.sc_table.columns)
737
787
 
738
- def _extract_sc_data(self, lcoe='mean_lcoe'):
788
+ def _extract_sc_data(self, lcoe=SupplyCurveField.MEAN_LCOE):
739
789
  """
740
790
  Extract supply curve data
741
791
 
742
792
  Parameters
743
793
  ----------
744
794
  lcoe : str, optional
745
- LCOE value to use for supply curve, by default 'mean_lcoe'
795
+ LCOE value to use for supply curve,
796
+ by default :obj:`SupplyCurveField.MEAN_LCOE`
746
797
 
747
798
  Returns
748
799
  -------
749
800
  sc_df : pandas.DataFrame
750
801
  Supply curve data
751
802
  """
752
- values = ['capacity', lcoe]
803
+ values = [SupplyCurveField.CAPACITY, lcoe]
753
804
  self._check_value(self.sc_table, values, scatter=False)
754
805
  sc_df = self.sc_table[values].sort_values(lcoe)
755
- sc_df['cumulative_capacity'] = sc_df['capacity'].cumsum()
806
+ sc_df['cumulative_capacity'] = (
807
+ sc_df[SupplyCurveField.CAPACITY].cumsum()
808
+ )
756
809
 
757
810
  return sc_df
758
811
 
759
- def supply_curve_plot(self, lcoe='mean_lcoe', out_path=None, **kwargs):
812
+ def supply_curve_plot(self, lcoe=SupplyCurveField.MEAN_LCOE, out_path=None,
813
+ **kwargs):
760
814
  """
761
815
  Plot supply curve (cumulative capacity vs lcoe) using seaborn.scatter
762
816
 
763
817
  Parameters
764
818
  ----------
765
819
  lcoe : str, optional
766
- LCOE value to plot, by default 'mean_lcoe'
820
+ LCOE value to plot, by default :obj:`SupplyCurveField.MEAN_LCOE`
767
821
  out_path : str, optional
768
822
  File path to save plot to, by default None
769
823
  kwargs : dict
770
824
  Additional kwargs for plotting.dataframes.df_scatter
771
825
  """
772
826
  sc_df = self._extract_sc_data(lcoe=lcoe)
773
- mplt.df_scatter(sc_df, x='cumulative_capacity', y=lcoe,
774
- filename=out_path, **kwargs)
827
+ mplt.df_scatter(
828
+ sc_df, x="cumulative_capacity", y=lcoe, filename=out_path, **kwargs
829
+ )
775
830
 
776
- def supply_curve_plotly(self, lcoe='mean_lcoe', out_path=None, **kwargs):
831
+ def supply_curve_plotly(self, lcoe=SupplyCurveField.MEAN_LCOE,
832
+ out_path=None, **kwargs):
777
833
  """
778
834
  Plot supply curve (cumulative capacity vs lcoe) using plotly
779
835
 
780
836
  Parameters
781
837
  ----------
782
838
  lcoe : str, optional
783
- LCOE value to plot, by default 'mean_lcoe'
839
+ LCOE value to plot, by default SupplyCurveField.MEAN_LCOE
784
840
  out_path : str, optional
785
841
  File path to save plot to, can be a .html or static image,
786
842
  by default None
@@ -788,7 +844,7 @@ class SupplyCurvePlot(PlotBase):
788
844
  Additional kwargs for plotly.express.scatter
789
845
  """
790
846
  sc_df = self._extract_sc_data(lcoe=lcoe)
791
- fig = px.scatter(sc_df, x='cumulative_capacity', y=lcoe, **kwargs)
847
+ fig = px.scatter(sc_df, x="cumulative_capacity", y=lcoe, **kwargs)
792
848
  fig.update_layout(font=dict(family="Arial", size=18, color="black"))
793
849
 
794
850
  if out_path is not None:
@@ -797,8 +853,8 @@ class SupplyCurvePlot(PlotBase):
797
853
  fig.show()
798
854
 
799
855
  @classmethod
800
- def plot(cls, sc_table, out_dir, plot_type='plotly', lcoe='mean_lcoe',
801
- **kwargs):
856
+ def plot(cls, sc_table, out_dir, plot_type='plotly',
857
+ lcoe=SupplyCurveField.MEAN_LCOE, **kwargs):
802
858
  """
803
859
  Create supply curve plot from supply curve table using lcoe value
804
860
  and save to out_dir
@@ -812,22 +868,25 @@ class SupplyCurvePlot(PlotBase):
812
868
  plot_type : str, optional
813
869
  plot_type of plot to create 'plot' or 'plotly', by default 'plotly'
814
870
  lcoe : str, optional
815
- LCOE value to plot, by default 'mean_lcoe'
871
+ LCOE value to plot, by default :obj:`SupplyCurveField.MEAN_LCOE`
816
872
  kwargs : dict
817
873
  Additional plotting kwargs
818
874
  """
819
875
  splt = cls(sc_table)
820
- if plot_type == 'plot':
821
- out_path = os.path.basename(sc_table).replace('.csv', '.png')
876
+ if plot_type == "plot":
877
+ out_path = os.path.basename(sc_table).replace(".csv", ".png")
822
878
  out_path = os.path.join(out_dir, out_path)
823
879
  splt.supply_curve_plot(lcoe=lcoe, out_path=out_path, **kwargs)
824
- elif plot_type == 'plotly':
825
- out_path = os.path.basename(sc_table).replace('.csv', '.html')
880
+ elif plot_type == "plotly":
881
+ out_path = os.path.basename(sc_table).replace(".csv", ".html")
826
882
  out_path = os.path.join(out_dir, out_path)
827
883
  splt.supply_curve_plotly(lcoe=lcoe, out_path=out_path, **kwargs)
828
884
  else:
829
- msg = ("plot_type must be 'plot' or 'plotly' but {} was given"
830
- .format(plot_type))
885
+ msg = (
886
+ "plot_type must be 'plot' or 'plotly' but {} was given".format(
887
+ plot_type
888
+ )
889
+ )
831
890
  logger.error(msg)
832
891
  raise ValueError(msg)
833
892
 
@@ -879,8 +938,9 @@ class ExclusionsMask(PlotBase):
879
938
 
880
939
  return excl_mask
881
940
 
882
- def exclusions_plot(self, cmap='Viridis', plot_step=100, out_path=None,
883
- **kwargs):
941
+ def exclusions_plot(
942
+ self, cmap="Viridis", plot_step=100, out_path=None, **kwargs
943
+ ):
884
944
  """
885
945
  Plot exclusions mask as a seaborn heatmap
886
946
 
@@ -896,11 +956,16 @@ class ExclusionsMask(PlotBase):
896
956
  kwargs : dict
897
957
  Additional kwargs for plotting.colormaps.heatmap_plot
898
958
  """
899
- mplt.heatmap_plot(self.mask[::plot_step, ::plot_step], cmap=cmap,
900
- filename=out_path, **kwargs)
959
+ mplt.heatmap_plot(
960
+ self.mask[::plot_step, ::plot_step],
961
+ cmap=cmap,
962
+ filename=out_path,
963
+ **kwargs,
964
+ )
901
965
 
902
- def exclusions_plotly(self, cmap='Viridis', plot_step=100, out_path=None,
903
- **kwargs):
966
+ def exclusions_plotly(
967
+ self, cmap="Viridis", plot_step=100, out_path=None, **kwargs
968
+ ):
904
969
  """
905
970
  Plot exclusions mask as a plotly heatmap
906
971
 
@@ -916,8 +981,11 @@ class ExclusionsMask(PlotBase):
916
981
  kwargs : dict
917
982
  Additional kwargs for plotly.express.imshow
918
983
  """
919
- fig = px.imshow(self.mask[::plot_step, ::plot_step],
920
- color_continuous_scale=cmap, **kwargs)
984
+ fig = px.imshow(
985
+ self.mask[::plot_step, ::plot_step],
986
+ color_continuous_scale=cmap,
987
+ **kwargs,
988
+ )
921
989
  fig.update_layout(font=dict(family="Arial", size=18, color="black"))
922
990
 
923
991
  if out_path is not None:
@@ -926,8 +994,15 @@ class ExclusionsMask(PlotBase):
926
994
  fig.show()
927
995
 
928
996
  @classmethod
929
- def plot(cls, mask, out_dir, plot_type='plotly', cmap='Viridis',
930
- plot_step=100, **kwargs):
997
+ def plot(
998
+ cls,
999
+ mask,
1000
+ out_dir,
1001
+ plot_type="plotly",
1002
+ cmap="Viridis",
1003
+ plot_step=100,
1004
+ **kwargs,
1005
+ ):
931
1006
  """
932
1007
  Plot exclusions mask and save to out_dir
933
1008
 
@@ -947,22 +1022,29 @@ class ExclusionsMask(PlotBase):
947
1022
  Additional plotting kwargs
948
1023
  """
949
1024
  excl_mask = cls(mask)
950
- if plot_type == 'plot':
951
- out_path = 'exclusions_mask.png'
1025
+ if plot_type == "plot":
1026
+ out_path = "exclusions_mask.png"
952
1027
  out_path = os.path.join(out_dir, out_path)
953
- excl_mask.exclusions_plot(cmap=cmap.lower(),
954
- plot_step=plot_step,
955
- out_path=out_path,
956
- **kwargs)
957
- elif plot_type == 'plotly':
958
- out_path = 'exclusions_mask.html'
1028
+ excl_mask.exclusions_plot(
1029
+ cmap=cmap.lower(),
1030
+ plot_step=plot_step,
1031
+ out_path=out_path,
1032
+ **kwargs,
1033
+ )
1034
+ elif plot_type == "plotly":
1035
+ out_path = "exclusions_mask.html"
959
1036
  out_path = os.path.join(out_dir, out_path)
960
- excl_mask.exclusions_plotly(cmap=cmap.capitalize(),
961
- plot_step=plot_step,
962
- out_path=out_path,
963
- **kwargs)
1037
+ excl_mask.exclusions_plotly(
1038
+ cmap=cmap.capitalize(),
1039
+ plot_step=plot_step,
1040
+ out_path=out_path,
1041
+ **kwargs,
1042
+ )
964
1043
  else:
965
- msg = ("plot_type must be 'plot' or 'plotly' but {} was given"
966
- .format(plot_type))
1044
+ msg = (
1045
+ "plot_type must be 'plot' or 'plotly' but {} was given".format(
1046
+ plot_type
1047
+ )
1048
+ )
967
1049
  logger.error(msg)
968
1050
  raise ValueError(msg)