foxes 1.1.1__py3-none-any.whl → 1.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.

Potentially problematic release.


This version of foxes might be problematic. Click here for more details.

Files changed (131) hide show
  1. docs/source/conf.py +3 -1
  2. examples/dyn_wakes/run.py +2 -2
  3. examples/timelines/run.py +1 -1
  4. foxes/__init__.py +13 -2
  5. foxes/algorithms/downwind/downwind.py +6 -1
  6. foxes/algorithms/downwind/models/init_farm_data.py +5 -2
  7. foxes/algorithms/downwind/models/point_wakes_calc.py +0 -1
  8. foxes/algorithms/iterative/iterative.py +1 -1
  9. foxes/algorithms/sequential/sequential.py +4 -3
  10. foxes/config/__init__.py +1 -0
  11. foxes/config/config.py +134 -0
  12. foxes/constants.py +15 -6
  13. foxes/core/algorithm.py +22 -10
  14. foxes/core/data.py +2 -1
  15. foxes/core/engine.py +40 -34
  16. foxes/core/farm_controller.py +4 -3
  17. foxes/core/farm_data_model.py +6 -2
  18. foxes/core/model.py +2 -1
  19. foxes/core/point_data_model.py +4 -2
  20. foxes/core/rotor_model.py +8 -4
  21. foxes/core/turbine_type.py +1 -1
  22. foxes/core/wake_frame.py +7 -5
  23. foxes/core/wake_model.py +6 -1
  24. foxes/data/__init__.py +1 -1
  25. foxes/data/static_data.py +0 -7
  26. foxes/engines/dask.py +4 -3
  27. foxes/engines/single.py +1 -1
  28. foxes/input/__init__.py +1 -1
  29. foxes/input/farm_layout/from_csv.py +3 -1
  30. foxes/input/farm_layout/from_file.py +10 -10
  31. foxes/input/farm_layout/from_json.py +4 -3
  32. foxes/input/farm_layout/grid.py +3 -3
  33. foxes/input/states/create/random_abl_states.py +5 -3
  34. foxes/input/states/field_data_nc.py +22 -14
  35. foxes/input/states/multi_height.py +26 -15
  36. foxes/input/states/one_point_flow.py +6 -5
  37. foxes/input/states/scan_ws.py +4 -1
  38. foxes/input/states/single.py +15 -6
  39. foxes/input/states/slice_data_nc.py +18 -12
  40. foxes/input/states/states_table.py +17 -10
  41. foxes/input/yaml/__init__.py +3 -0
  42. foxes/input/yaml/dict.py +210 -0
  43. foxes/input/yaml/windio/__init__.py +4 -0
  44. foxes/input/{windio → yaml/windio}/get_states.py +7 -7
  45. foxes/input/{windio → yaml/windio}/read_attributes.py +61 -40
  46. foxes/input/{windio → yaml/windio}/read_farm.py +34 -43
  47. foxes/input/{windio → yaml/windio}/read_fields.py +11 -10
  48. foxes/input/yaml/windio/read_outputs.py +147 -0
  49. foxes/input/yaml/windio/windio.py +269 -0
  50. foxes/input/yaml/yaml.py +103 -0
  51. foxes/models/partial_wakes/axiwake.py +7 -6
  52. foxes/models/partial_wakes/centre.py +3 -2
  53. foxes/models/partial_wakes/segregated.py +5 -2
  54. foxes/models/point_models/set_uniform_data.py +5 -3
  55. foxes/models/rotor_models/centre.py +2 -2
  56. foxes/models/rotor_models/grid.py +5 -5
  57. foxes/models/rotor_models/levels.py +6 -6
  58. foxes/models/turbine_models/kTI_model.py +3 -1
  59. foxes/models/turbine_models/lookup_table.py +7 -4
  60. foxes/models/turbine_models/power_mask.py +14 -8
  61. foxes/models/turbine_models/sector_management.py +4 -2
  62. foxes/models/turbine_models/set_farm_vars.py +53 -23
  63. foxes/models/turbine_models/table_factors.py +8 -7
  64. foxes/models/turbine_models/yaw2yawm.py +0 -1
  65. foxes/models/turbine_models/yawm2yaw.py +0 -1
  66. foxes/models/turbine_types/CpCt_file.py +6 -3
  67. foxes/models/turbine_types/CpCt_from_two.py +6 -3
  68. foxes/models/turbine_types/PCt_file.py +7 -6
  69. foxes/models/turbine_types/PCt_from_two.py +11 -2
  70. foxes/models/turbine_types/TBL_file.py +3 -4
  71. foxes/models/turbine_types/wsrho2PCt_from_two.py +19 -11
  72. foxes/models/turbine_types/wsti2PCt_from_two.py +19 -11
  73. foxes/models/vertical_profiles/abl_log_neutral_ws.py +1 -1
  74. foxes/models/vertical_profiles/abl_log_stable_ws.py +1 -1
  75. foxes/models/vertical_profiles/abl_log_unstable_ws.py +1 -1
  76. foxes/models/vertical_profiles/abl_log_ws.py +1 -1
  77. foxes/models/wake_frames/dynamic_wakes.py +17 -9
  78. foxes/models/wake_frames/farm_order.py +4 -3
  79. foxes/models/wake_frames/rotor_wd.py +3 -1
  80. foxes/models/wake_frames/seq_dynamic_wakes.py +14 -7
  81. foxes/models/wake_frames/streamlines.py +9 -6
  82. foxes/models/wake_frames/timelines.py +21 -14
  83. foxes/models/wake_frames/yawed_wakes.py +3 -1
  84. foxes/models/wake_models/induction/vortex_sheet.py +0 -1
  85. foxes/models/wake_models/ti/crespo_hernandez.py +2 -1
  86. foxes/models/wake_models/wind/bastankhah14.py +3 -2
  87. foxes/models/wake_models/wind/bastankhah16.py +2 -1
  88. foxes/models/wake_models/wind/turbopark.py +9 -7
  89. foxes/models/wake_superpositions/ws_product.py +0 -1
  90. foxes/output/calc_points.py +7 -4
  91. foxes/output/farm_layout.py +30 -18
  92. foxes/output/farm_results_eval.py +4 -3
  93. foxes/output/grids.py +8 -7
  94. foxes/output/output.py +7 -2
  95. foxes/output/results_writer.py +10 -11
  96. foxes/output/rose_plot.py +38 -20
  97. foxes/output/rotor_point_plots.py +7 -3
  98. foxes/output/slice_data.py +1 -1
  99. foxes/output/state_turbine_map.py +5 -1
  100. foxes/output/state_turbine_table.py +7 -3
  101. foxes/output/turbine_type_curves.py +7 -2
  102. foxes/utils/dict.py +107 -3
  103. foxes/utils/geopandas_utils.py +3 -2
  104. {foxes-1.1.1.dist-info → foxes-1.2.dist-info}/METADATA +18 -17
  105. {foxes-1.1.1.dist-info → foxes-1.2.dist-info}/RECORD +122 -122
  106. {foxes-1.1.1.dist-info → foxes-1.2.dist-info}/WHEEL +1 -1
  107. foxes-1.2.dist-info/entry_points.txt +3 -0
  108. tests/0_consistency/iterative/test_iterative.py +65 -67
  109. tests/0_consistency/partial_wakes/test_partial_wakes.py +58 -61
  110. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +56 -53
  111. tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +41 -41
  112. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +34 -34
  113. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +50 -50
  114. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +51 -52
  115. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +73 -74
  116. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +73 -74
  117. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +51 -49
  118. tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +101 -103
  119. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +61 -62
  120. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +51 -52
  121. examples/windio/run.py +0 -29
  122. foxes/data/states/windio_timeseries_5000.nc +0 -0
  123. foxes/data/windio/DTU_10MW_turbine.yaml +0 -10
  124. foxes/data/windio/__init__.py +0 -0
  125. foxes/data/windio/windio_5turbines_timeseries.yaml +0 -79
  126. foxes/input/windio/__init__.py +0 -11
  127. foxes/input/windio/read_outputs.py +0 -172
  128. foxes/input/windio/runner.py +0 -183
  129. foxes/input/windio/windio.py +0 -193
  130. {foxes-1.1.1.dist-info → foxes-1.2.dist-info}/LICENSE +0 -0
  131. {foxes-1.1.1.dist-info → foxes-1.2.dist-info}/top_level.txt +0 -0
@@ -4,6 +4,7 @@ from cycler import cycler
4
4
  import matplotlib.pyplot as plt
5
5
 
6
6
  from .output import Output
7
+ from foxes.config import config
7
8
  import foxes.variables as FV
8
9
  import foxes.constants as FC
9
10
 
@@ -409,7 +410,7 @@ class FarmResultsEval(Output):
409
410
  if algo is not None and P_unit_W is None:
410
411
  P_unit_W = np.array(
411
412
  [FC.P_UNITS[t.P_unit] for t in algo.farm_controller.turbine_types],
412
- dtype=FC.DTYPE,
413
+ dtype=config.dtype_double,
413
414
  )[:, None]
414
415
  elif algo is None and P_unit_W is not None:
415
416
  pass
@@ -472,10 +473,10 @@ class FarmResultsEval(Output):
472
473
  if algo is not None and P_nom is None:
473
474
  P_nom = np.array(
474
475
  [t.P_nominal for t in algo.farm_controller.turbine_types],
475
- dtype=FC.DTYPE,
476
+ dtype=config.dtype_double,
476
477
  )
477
478
  elif algo is None and P_nom is not None:
478
- P_nom = np.array(P_nom, dtype=FC.DTYPE)
479
+ P_nom = np.array(P_nom, dtype=config.dtype_double)
479
480
  else:
480
481
  raise KeyError("Expecting either 'algo' or 'P_nom'")
481
482
 
foxes/output/grids.py CHANGED
@@ -3,6 +3,7 @@ import pandas as pd
3
3
  from xarray import Dataset
4
4
 
5
5
  from foxes.utils import wd2uv, write_nc
6
+ from foxes.config import config
6
7
  import foxes.variables as FV
7
8
  import foxes.constants as FC
8
9
 
@@ -151,7 +152,7 @@ def get_grid_xy(
151
152
  N_x, N_y = len(x_pos), len(y_pos)
152
153
  n_pts = len(x_pos) * len(y_pos)
153
154
  z_pos = 0.5 * (z_min + z_max)
154
- g_pts = np.zeros((n_states, N_x, N_y, 3), dtype=FC.DTYPE)
155
+ g_pts = np.zeros((n_states, N_x, N_y, 3), dtype=config.dtype_double)
155
156
  g_pts[:, :, :, 0] = x_pos[None, :, None]
156
157
  g_pts[:, :, :, 1] = y_pos[None, None, :]
157
158
  g_pts[:, :, :, 2] = z_pos
@@ -248,7 +249,7 @@ def get_grid_xz(
248
249
  n_y = np.cross(n_z, n_x)
249
250
 
250
251
  # project to axes:
251
- xyz = np.zeros((n_states, n_turbines, 3), dtype=FC.DTYPE)
252
+ xyz = np.zeros((n_states, n_turbines, 3), dtype=config.dtype_double)
252
253
  xyz[:, :, 0] = farm_results[FV.X]
253
254
  xyz[:, :, 1] = farm_results[FV.Y]
254
255
  xyz[:, :, 2] = farm_results[FV.H]
@@ -297,7 +298,7 @@ def get_grid_xz(
297
298
  N_x, N_z = len(x_pos), len(z_pos)
298
299
  n_pts = len(x_pos) * len(z_pos)
299
300
  y_pos = 0.5 * (y_min + y_max)
300
- g_pts = np.zeros((n_states, N_x, N_z, 3), dtype=FC.DTYPE)
301
+ g_pts = np.zeros((n_states, N_x, N_z, 3), dtype=config.dtype_double)
301
302
  g_pts[:] += x_pos[None, :, None, None] * n_x[None, None, None, :]
302
303
  g_pts[:] += y_pos * n_y[None, None, None, :]
303
304
  g_pts[:] += z_pos[None, None, :, None] * n_z[None, None, None, :]
@@ -394,7 +395,7 @@ def get_grid_yz(
394
395
  n_y = np.cross(n_z, n_x)
395
396
 
396
397
  # project to axes:
397
- xyz = np.zeros((n_states, n_turbines, 3), dtype=FC.DTYPE)
398
+ xyz = np.zeros((n_states, n_turbines, 3), dtype=config.dtype_double)
398
399
  xyz[:, :, 0] = farm_results[FV.X]
399
400
  xyz[:, :, 1] = farm_results[FV.Y]
400
401
  xyz[:, :, 2] = farm_results[FV.H]
@@ -443,7 +444,7 @@ def get_grid_yz(
443
444
  N_y, N_z = len(y_pos), len(z_pos)
444
445
  n_pts = len(y_pos) * len(z_pos)
445
446
  x_pos = 0.5 * (x_min + x_max)
446
- g_pts = np.zeros((n_states, N_y, N_z, 3), dtype=FC.DTYPE)
447
+ g_pts = np.zeros((n_states, N_y, N_z, 3), dtype=config.dtype_double)
447
448
  g_pts[:] += x_pos * n_x[None, None, None, :]
448
449
  g_pts[:] += y_pos[None, :, None, None] * n_y[None, None, None, :]
449
450
  g_pts[:] += z_pos[None, None, :, None] * n_z[None, None, None, :]
@@ -491,7 +492,7 @@ def np2np_p(data, a_pos, b_pos):
491
492
  n_a = len(a_pos)
492
493
  n_b = len(b_pos)
493
494
  n_v = len(data)
494
- out = np.zeros((n_a, n_b, n_v), dtype=FC.DTYPE)
495
+ out = np.zeros((n_a, n_b, n_v), dtype=config.dtype_double)
495
496
  for vi, (v, d) in enumerate(data.items()):
496
497
  out[:, :, vi] = d.reshape(n_a, n_b)
497
498
  return out
@@ -526,7 +527,7 @@ def np2np_sp(data, states, a_pos, b_pos):
526
527
  n_a = len(a_pos)
527
528
  n_b = len(b_pos)
528
529
  n_v = len(data)
529
- out = np.zeros((n_s, n_a, n_b, n_v), dtype=FC.DTYPE)
530
+ out = np.zeros((n_s, n_a, n_b, n_v), dtype=config.dtype_double)
530
531
  for vi, (v, d) in enumerate(data.items()):
531
532
  out[:, :, :, vi] = d.reshape(n_s, n_a, n_b)
532
533
  return out
foxes/output/output.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from pathlib import Path
2
2
 
3
+ from foxes.config import config, get_path
3
4
  from foxes.utils import PandasFileHelper, all_subclasses
4
5
 
5
6
 
@@ -33,9 +34,13 @@ class Output:
33
34
  Modifies file names by f(fname)
34
35
 
35
36
  """
36
- self.out_dir = Path(out_dir) if out_dir is not None else None
37
+ self.out_dir = get_path(out_dir) if out_dir is not None else config.out_dir
37
38
  self.out_fname_fun = out_fname_fun
38
39
 
40
+ if not self.out_dir.is_dir():
41
+ print(f"{type(self).__name__}: Creating output dir {self.out_dir}")
42
+ self.out_dir.mkdir(parents=True)
43
+
39
44
  def get_fpath(self, fname):
40
45
  """
41
46
  Gets the total file path
@@ -54,7 +59,7 @@ class Output:
54
59
  fnm = Path(fname)
55
60
  if self.out_fname_fun is not None:
56
61
  fnm = self.out_fname_fun(fnm)
57
- return self.out_dir / fnm if self.out_dir is not None else fnm
62
+ return self.out_dir / fnm if self.out_dir is not None else get_path(fnm)
58
63
 
59
64
  def write(self, file_name, data, format_col2var={}, format_dict={}, **kwargs):
60
65
  """
@@ -1,8 +1,8 @@
1
1
  import pandas as pd
2
2
  from xarray import Dataset
3
3
 
4
- import foxes.constants as FC
5
4
  from foxes.utils import write_nc
5
+ import foxes.constants as FC
6
6
 
7
7
  from .output import Output
8
8
 
@@ -70,7 +70,7 @@ class ResultsWriter(Output):
70
70
 
71
71
  def write_csv(
72
72
  self,
73
- file_path,
73
+ file_name,
74
74
  variables=None,
75
75
  turbine_names=False,
76
76
  state_turbine_table=False,
@@ -82,8 +82,8 @@ class ResultsWriter(Output):
82
82
 
83
83
  Parameters
84
84
  ----------
85
- file_path: str
86
- Path for the csv file
85
+ file_name: str
86
+ Name of the csv file
87
87
  variables: dict or list of str, optional
88
88
  The variables to be written. If a dict, then
89
89
  the keys are the foxes variables and the values
@@ -101,7 +101,7 @@ class ResultsWriter(Output):
101
101
 
102
102
  """
103
103
  if verbosity:
104
- print(f"ResultsWriter: Writing file '{file_path}'")
104
+ print(f"ResultsWriter: Writing file '{file_name}'")
105
105
 
106
106
  data, variables = self._get_data_vars(variables)
107
107
  data.reset_index(inplace=True)
@@ -133,12 +133,11 @@ class ResultsWriter(Output):
133
133
  else:
134
134
  data.set_index([FC.STATE, tix], inplace=True)
135
135
 
136
- fpath = self.get_fpath(file_path)
137
- super().write(fpath, data, format_col2var=fc2v, **kwargs)
136
+ super().write(file_name, data, format_col2var=fc2v, **kwargs)
138
137
 
139
138
  def write_nc(
140
139
  self,
141
- file_path,
140
+ file_name,
142
141
  variables=None,
143
142
  turbine_names=False,
144
143
  verbosity=1,
@@ -149,8 +148,8 @@ class ResultsWriter(Output):
149
148
 
150
149
  Parameters
151
150
  ----------
152
- file_path: str
153
- Path for the nc file
151
+ file_name: str
152
+ The nc file name
154
153
  variables: dict or list of str, optional
155
154
  The variables to be written. If a dict, then
156
155
  the keys are the foxes variables and the values
@@ -185,5 +184,5 @@ class ResultsWriter(Output):
185
184
  },
186
185
  )
187
186
 
188
- fpath = self.get_fpath(file_path)
187
+ fpath = self.get_fpath(file_name)
189
188
  write_nc(ds, fpath, verbosity=verbosity, **kwargs)
foxes/output/rose_plot.py CHANGED
@@ -1,12 +1,13 @@
1
1
  import numpy as np
2
2
  import pandas as pd
3
3
 
4
- import foxes.variables as FV
5
- import foxes.constants as FC
6
4
  from foxes.utils import wd2uv, uv2wd, TabWindroseAxes
7
5
  from foxes.algorithms import Downwind
8
6
  from foxes.core import WindFarm, Turbine
9
7
  from foxes.models import ModelBook
8
+ import foxes.variables as FV
9
+ import foxes.constants as FC
10
+
10
11
  from .output import Output
11
12
 
12
13
 
@@ -23,7 +24,7 @@ class RosePlotOutput(Output):
23
24
 
24
25
  """
25
26
 
26
- def __init__(self, results):
27
+ def __init__(self, results, **kwargs):
27
28
  """
28
29
  Constructor.
29
30
 
@@ -31,8 +32,11 @@ class RosePlotOutput(Output):
31
32
  ----------
32
33
  results: xarray.Dataset
33
34
  The calculation results (farm or points)
35
+ kwargs: dict, optional
36
+ Additional parameters for the base class
34
37
 
35
38
  """
39
+ super().__init__(**kwargs)
36
40
  dims = list(results.sizes.keys())
37
41
  if dims[1] == FC.TURBINE:
38
42
  self._rtype = FC.TURBINE
@@ -324,7 +328,7 @@ class RosePlotOutput(Output):
324
328
  Parameters
325
329
  ----------
326
330
  file_name: str
327
- Path to the output file
331
+ Name of the output file
328
332
  sectors: int
329
333
  The number of wind direction sectors
330
334
  var: str
@@ -350,31 +354,45 @@ class RosePlotOutput(Output):
350
354
  ret_data=ret_data,
351
355
  **kwargs,
352
356
  )
357
+ fpath = self.get_fpath(file_name)
353
358
  if ret_data:
354
- r[0].write_image(file_name)
359
+ r[0].write_image(fpath)
355
360
  return r[1]
356
361
  else:
357
- r.write_image(file_name)
362
+ r.write_image(fpath)
358
363
 
359
364
 
360
365
  class StatesRosePlotOutput(RosePlotOutput):
361
366
  """
362
- Class for rose plot creation directly from states
363
-
364
- Parameters
365
- ----------
366
- states: foxes.core.States
367
- The states from which to compute the wind rose
368
- point: numpy.ndarray
369
- The evaluation point, shape: (3,)
370
- mbook: foxes.models.ModelBook, optional
371
- The model book
372
-
367
+ Class for rose plot creation directly from states
373
368
  :group: output
374
-
375
369
  """
376
370
 
377
- def __init__(self, states, point, mbook=None, ws_var=FV.AMB_REWS):
371
+ def __init__(
372
+ self,
373
+ states,
374
+ point,
375
+ mbook=None,
376
+ ws_var=FV.AMB_REWS,
377
+ **kwargs,
378
+ ):
379
+ """
380
+ Constructor.
381
+
382
+ Parameters
383
+ ----------
384
+ states: foxes.core.States
385
+ The states from which to compute the wind rose
386
+ point: numpy.ndarray
387
+ The evaluation point, shape: (3,)
388
+ mbook: foxes.models.ModelBook, optional
389
+ The model book
390
+ ws_var: str
391
+ The wind speed variable name
392
+ kwargs: dict, optional
393
+ Additional parameters for the base class
394
+
395
+ """
378
396
  farm = WindFarm()
379
397
  farm.add_turbine(
380
398
  Turbine(
@@ -390,4 +408,4 @@ class StatesRosePlotOutput(RosePlotOutput):
390
408
 
391
409
  results = algo.calc_farm(ambient=True).rename_vars({ws_var: FV.AMB_WS})
392
410
 
393
- super().__init__(results)
411
+ super().__init__(results, **kwargs)
@@ -1,14 +1,15 @@
1
1
  import numpy as np
2
2
  import matplotlib.pyplot as plt
3
3
  from matplotlib import colormaps
4
- from matplotlib.colors import LinearSegmentedColormap
5
4
 
6
5
  from foxes.input.states import SingleStateStates
7
6
  from foxes.core import WindFarm
8
7
  from foxes.algorithms import Downwind
9
8
 
9
+ from .output import Output
10
10
 
11
- class RotorPointPlot:
11
+
12
+ class RotorPointPlot(Output):
12
13
  """
13
14
  Visualizes rotor points and their weights.
14
15
 
@@ -23,7 +24,7 @@ class RotorPointPlot:
23
24
 
24
25
  """
25
26
 
26
- def __init__(self, rotor_model, algo=None):
27
+ def __init__(self, rotor_model, algo=None, **kwargs):
27
28
  """
28
29
  Constructor.
29
30
 
@@ -33,8 +34,11 @@ class RotorPointPlot:
33
34
  The rotor model
34
35
  algo: foxes.core.Algorithm, optional
35
36
  The algorithm
37
+ kwargs: dict, optional
38
+ Additional parameters for the base class
36
39
 
37
40
  """
41
+ super().__init__(**kwargs)
38
42
  self.rotor_model = rotor_model
39
43
  self.algo = algo
40
44
 
@@ -2,8 +2,8 @@ import numpy as np
2
2
 
3
3
  from foxes.output import Output
4
4
  from foxes.utils import write_nc
5
- import foxes.constants as FC
6
5
  import foxes.variables as FV
6
+ import foxes.constants as FC
7
7
 
8
8
  from . import grids
9
9
 
@@ -2,6 +2,7 @@ import matplotlib.pyplot as plt
2
2
  import numpy as np
3
3
 
4
4
  import foxes.constants as FC
5
+
5
6
  from .output import Output
6
7
 
7
8
 
@@ -19,7 +20,7 @@ class StateTurbineMap(Output):
19
20
 
20
21
  """
21
22
 
22
- def __init__(self, farm_results):
23
+ def __init__(self, farm_results, **kwargs):
23
24
  """
24
25
  Constructor.
25
26
 
@@ -27,8 +28,11 @@ class StateTurbineMap(Output):
27
28
  ----------
28
29
  farm_results: xarray.Dataset
29
30
  The farm results
31
+ kwargs: dict, optional
32
+ Additional parameters for the base class
30
33
 
31
34
  """
35
+ super().__init__(**kwargs)
32
36
  self.results = farm_results
33
37
 
34
38
  def plot_map(
@@ -19,7 +19,7 @@ class StateTurbineTable(Output):
19
19
 
20
20
  """
21
21
 
22
- def __init__(self, farm_results):
22
+ def __init__(self, farm_results, **kwargs):
23
23
  """
24
24
  Constructor.
25
25
 
@@ -27,8 +27,11 @@ class StateTurbineTable(Output):
27
27
  ----------
28
28
  farm_results: xarray.Dataset
29
29
  The farm results
30
+ kwargs: dict, optional
31
+ Additional parameters for the base class
30
32
 
31
33
  """
34
+ super().__init__(**kwargs)
32
35
  self.farm_results = farm_results
33
36
 
34
37
  def get_dataset(
@@ -48,7 +51,7 @@ class StateTurbineTable(Output):
48
51
  name_map: dict
49
52
  Map from foxes to output names
50
53
  to_file: str, optional
51
- The output file path, if writing is desired
54
+ Name of the output file, if writing is desired
52
55
  kwargs: dict, optional
53
56
  Additional parameters for write_nc
54
57
 
@@ -73,6 +76,7 @@ class StateTurbineTable(Output):
73
76
  )
74
77
 
75
78
  if to_file is not None:
76
- write_nc(ds=ds, fpath=to_file, **kwargs)
79
+ fpath = self.get_fpath(to_file)
80
+ write_nc(ds=ds, fpath=fpath, **kwargs)
77
81
 
78
82
  return ds
@@ -7,8 +7,10 @@ from foxes.input.states import StatesTable
7
7
  from foxes.core import WindFarm, Turbine
8
8
  from foxes.algorithms import Downwind
9
9
  from foxes.models.turbine_models import SetFarmVars
10
+ from foxes.config import config
10
11
  import foxes.variables as FV
11
12
  import foxes.constants as FC
13
+
12
14
  from .output import Output
13
15
 
14
16
 
@@ -26,7 +28,7 @@ class TurbineTypeCurves(Output):
26
28
 
27
29
  """
28
30
 
29
- def __init__(self, mbook):
31
+ def __init__(self, mbook, **kwargs):
30
32
  """
31
33
  Constructor.
32
34
 
@@ -34,8 +36,11 @@ class TurbineTypeCurves(Output):
34
36
  ----------
35
37
  mbook: foxes.models.ModelBook
36
38
  The model book
39
+ kwargs: dict, optional
40
+ Additional parameters for the base class
37
41
 
38
42
  """
43
+ super().__init__(**kwargs)
39
44
  self.mbook = mbook
40
45
 
41
46
  def plot_curves(
@@ -113,7 +118,7 @@ class TurbineTypeCurves(Output):
113
118
  if not isinstance(axs, (list, tuple, np.ndarray)):
114
119
  axs = [axs]
115
120
 
116
- ws = np.arange(ws_min, ws_max + ws_step, ws_step, dtype=FC.DTYPE)
121
+ ws = np.arange(ws_min, ws_max + ws_step, ws_step, dtype=config.dtype_double)
117
122
  n_states = len(ws)
118
123
  sdata = pd.DataFrame(index=range(n_states))
119
124
  sdata.index.name = FC.STATE
foxes/utils/dict.py CHANGED
@@ -1,3 +1,7 @@
1
+ from yaml import safe_load
2
+ from pathlib import Path
3
+
4
+
1
5
  class Dict(dict):
2
6
  """
3
7
  A slightly enhanced dictionary.
@@ -25,10 +29,34 @@ class Dict(dict):
25
29
  Arguments passed to `dict`
26
30
 
27
31
  """
28
- super().__init__(*args, **kwargs)
32
+ tmp = dict()
33
+ for a in args:
34
+ tmp.update(
35
+ {
36
+ k: (
37
+ Dict(d, name=f"{name}.{k}")
38
+ if isinstance(d, dict) and not isinstance(d, Dict)
39
+ else d
40
+ )
41
+ for k, d in a.items()
42
+ }
43
+ )
44
+
45
+ super().__init__(
46
+ **tmp,
47
+ **{
48
+ k: (
49
+ Dict(d, name=k)
50
+ if isinstance(d, dict) and not isinstance(d, Dict)
51
+ else d
52
+ )
53
+ for k, d in kwargs.items()
54
+ },
55
+ )
56
+
29
57
  self.name = name if name is not None else type(self).__name__
30
58
 
31
- def get_item(self, key, prnt=True):
59
+ def get_item(self, key, *deflt, prnt=True):
32
60
  """
33
61
  Gets an item, prints readable error if not found
34
62
 
@@ -36,12 +64,25 @@ class Dict(dict):
36
64
  ----------
37
65
  key: immutable object
38
66
  The key
67
+ deflt: tuple, optional
68
+ Tuple of length 1, containing the default
39
69
  prnt: bool
40
70
  Flag for message printing
41
71
 
72
+ Returns
73
+ -------
74
+ data: object
75
+ The data
76
+
42
77
  """
43
78
  try:
44
- return self[key]
79
+ if len(deflt):
80
+ assert (
81
+ len(deflt) == 1
82
+ ), f"Expecting a single default entry, got {len(deflt)}"
83
+ data = self.get(key, deflt[0])
84
+ else:
85
+ data = self[key]
45
86
  except KeyError as e:
46
87
  if prnt:
47
88
  print(f"\n{self.name}: Cannot find key '{key}'.\n")
@@ -51,6 +92,35 @@ class Dict(dict):
51
92
  print()
52
93
  raise e
53
94
 
95
+ if isinstance(data, dict) and not isinstance(data, Dict):
96
+ data = Dict(data, name=f"{self.name}.{key}")
97
+
98
+ return data
99
+
100
+ def pop_item(self, key, *deflt, prnt=True):
101
+ """
102
+ Pops an item, prints readable error if not found
103
+
104
+ Parameters
105
+ ----------
106
+ key: immutable object
107
+ The key
108
+ deflt: tuple, optional
109
+ Tuple of length 1, containing the default
110
+ prnt: bool
111
+ Flag for message printing
112
+
113
+ Returns
114
+ -------
115
+ data: object
116
+ The data
117
+
118
+ """
119
+ data = self.get_item(key, *deflt, prnt=prnt)
120
+ if key in self:
121
+ del self[key]
122
+ return data
123
+
54
124
  def __getitem__(self, key):
55
125
  try:
56
126
  return super().__getitem__(key)
@@ -58,3 +128,37 @@ class Dict(dict):
58
128
  k = ", ".join(sorted([f"{s}" for s in self.keys()]))
59
129
  e = f"{self.name}: Cannot find key '{key}'. Known keys: {k}"
60
130
  raise KeyError(e)
131
+
132
+ @classmethod
133
+ def from_yaml(self, yml_file, verbosity=1):
134
+ """
135
+ Reads a yaml file
136
+
137
+ Parameters
138
+ ----------
139
+ yml_file: str
140
+ Path to the yaml file
141
+ verbosity: int
142
+ The verbosity level, 0 = silent
143
+
144
+ Returns
145
+ -------
146
+ dct: Dict
147
+ The data
148
+
149
+ """
150
+
151
+ def _print(*args, level=1, **kwargs):
152
+ if verbosity >= level:
153
+ print(*args, **kwargs)
154
+
155
+ fpath = Path(yml_file)
156
+ _print("Reading file", fpath)
157
+ with open(fpath) as stream:
158
+ data = safe_load(stream)
159
+ if data is None:
160
+ data = {}
161
+ dct = Dict(data, name=fpath.stem)
162
+ _print(dct, level=2)
163
+
164
+ return dct
@@ -1,7 +1,8 @@
1
1
  import numpy as np
2
2
  import argparse
3
3
 
4
- import foxes.constants as FC
4
+ from foxes.config import config
5
+
5
6
  from .dict import Dict
6
7
  from .geom2d import AreaUnion, ClosedPolygon
7
8
 
@@ -212,7 +213,7 @@ def read_shp_polygons(
212
213
  if not len(data):
213
214
  return []
214
215
  if isinstance(data[0], tuple):
215
- out = np.array(data, dtype=FC.DTYPE)
216
+ out = np.array(data, dtype=config.dtype_double)
216
217
  return _to_utm(out) if apply_utm else out
217
218
  return [_to_numpy(d) for d in data]
218
219