foxes 1.1.1__py3-none-any.whl → 1.2.1__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 (155) hide show
  1. docs/source/conf.py +3 -1
  2. examples/abl_states/run.py +5 -5
  3. examples/dyn_wakes/run.py +2 -2
  4. examples/induction/run.py +5 -5
  5. examples/random_timeseries/run.py +13 -13
  6. examples/scan_row/run.py +12 -7
  7. examples/sector_management/run.py +11 -7
  8. examples/single_state/run.py +5 -5
  9. examples/tab_file/run.py +1 -1
  10. examples/timelines/run.py +1 -1
  11. examples/timeseries/run.py +5 -5
  12. examples/timeseries_slurm/run.py +5 -5
  13. examples/wind_rose/run.py +1 -1
  14. examples/yawed_wake/run.py +5 -5
  15. foxes/__init__.py +13 -2
  16. foxes/algorithms/downwind/downwind.py +21 -6
  17. foxes/algorithms/downwind/models/init_farm_data.py +5 -2
  18. foxes/algorithms/downwind/models/point_wakes_calc.py +0 -1
  19. foxes/algorithms/iterative/iterative.py +1 -1
  20. foxes/algorithms/sequential/sequential.py +5 -4
  21. foxes/config/__init__.py +1 -0
  22. foxes/config/config.py +134 -0
  23. foxes/constants.py +15 -6
  24. foxes/core/algorithm.py +46 -30
  25. foxes/core/axial_induction_model.py +18 -0
  26. foxes/core/data.py +2 -1
  27. foxes/core/engine.py +43 -49
  28. foxes/core/farm_controller.py +22 -3
  29. foxes/core/farm_data_model.py +6 -2
  30. foxes/core/ground_model.py +19 -0
  31. foxes/core/model.py +2 -1
  32. foxes/core/partial_wakes_model.py +9 -21
  33. foxes/core/point_data_model.py +22 -2
  34. foxes/core/rotor_model.py +9 -21
  35. foxes/core/states.py +2 -17
  36. foxes/core/turbine_model.py +2 -18
  37. foxes/core/turbine_type.py +2 -18
  38. foxes/core/vertical_profile.py +8 -20
  39. foxes/core/wake_frame.py +9 -25
  40. foxes/core/wake_model.py +24 -20
  41. foxes/core/wake_superposition.py +19 -0
  42. foxes/data/__init__.py +1 -1
  43. foxes/data/static_data.py +0 -7
  44. foxes/engines/dask.py +4 -3
  45. foxes/engines/single.py +1 -1
  46. foxes/input/__init__.py +1 -1
  47. foxes/input/farm_layout/from_csv.py +3 -1
  48. foxes/input/farm_layout/from_file.py +10 -10
  49. foxes/input/farm_layout/from_json.py +4 -3
  50. foxes/input/farm_layout/grid.py +3 -3
  51. foxes/input/states/__init__.py +1 -1
  52. foxes/input/states/create/random_abl_states.py +5 -3
  53. foxes/input/states/field_data_nc.py +36 -15
  54. foxes/input/states/multi_height.py +26 -15
  55. foxes/input/states/one_point_flow.py +6 -5
  56. foxes/input/states/{scan_ws.py → scan.py} +42 -52
  57. foxes/input/states/single.py +15 -6
  58. foxes/input/states/slice_data_nc.py +18 -12
  59. foxes/input/states/states_table.py +17 -10
  60. foxes/input/yaml/__init__.py +3 -0
  61. foxes/input/yaml/dict.py +381 -0
  62. foxes/input/yaml/windio/__init__.py +4 -0
  63. foxes/input/{windio → yaml/windio}/get_states.py +7 -7
  64. foxes/input/{windio → yaml/windio}/read_attributes.py +61 -40
  65. foxes/input/{windio → yaml/windio}/read_farm.py +34 -43
  66. foxes/input/{windio → yaml/windio}/read_fields.py +11 -10
  67. foxes/input/yaml/windio/read_outputs.py +147 -0
  68. foxes/input/yaml/windio/windio.py +269 -0
  69. foxes/input/yaml/yaml.py +103 -0
  70. foxes/models/partial_wakes/axiwake.py +7 -6
  71. foxes/models/partial_wakes/centre.py +3 -2
  72. foxes/models/partial_wakes/segregated.py +5 -2
  73. foxes/models/point_models/set_uniform_data.py +5 -3
  74. foxes/models/rotor_models/centre.py +2 -2
  75. foxes/models/rotor_models/grid.py +5 -5
  76. foxes/models/rotor_models/levels.py +6 -6
  77. foxes/models/turbine_models/kTI_model.py +3 -1
  78. foxes/models/turbine_models/lookup_table.py +7 -4
  79. foxes/models/turbine_models/power_mask.py +14 -8
  80. foxes/models/turbine_models/sector_management.py +4 -2
  81. foxes/models/turbine_models/set_farm_vars.py +53 -23
  82. foxes/models/turbine_models/table_factors.py +8 -7
  83. foxes/models/turbine_models/yaw2yawm.py +0 -1
  84. foxes/models/turbine_models/yawm2yaw.py +0 -1
  85. foxes/models/turbine_types/CpCt_file.py +6 -3
  86. foxes/models/turbine_types/CpCt_from_two.py +6 -3
  87. foxes/models/turbine_types/PCt_file.py +7 -6
  88. foxes/models/turbine_types/PCt_from_two.py +11 -2
  89. foxes/models/turbine_types/TBL_file.py +3 -4
  90. foxes/models/turbine_types/wsrho2PCt_from_two.py +19 -11
  91. foxes/models/turbine_types/wsti2PCt_from_two.py +19 -11
  92. foxes/models/vertical_profiles/abl_log_neutral_ws.py +1 -1
  93. foxes/models/vertical_profiles/abl_log_stable_ws.py +1 -1
  94. foxes/models/vertical_profiles/abl_log_unstable_ws.py +1 -1
  95. foxes/models/vertical_profiles/abl_log_ws.py +1 -1
  96. foxes/models/wake_frames/dynamic_wakes.py +17 -9
  97. foxes/models/wake_frames/farm_order.py +4 -3
  98. foxes/models/wake_frames/rotor_wd.py +3 -1
  99. foxes/models/wake_frames/seq_dynamic_wakes.py +14 -7
  100. foxes/models/wake_frames/streamlines.py +9 -6
  101. foxes/models/wake_frames/timelines.py +21 -14
  102. foxes/models/wake_frames/yawed_wakes.py +3 -1
  103. foxes/models/wake_models/induction/vortex_sheet.py +0 -1
  104. foxes/models/wake_models/ti/crespo_hernandez.py +2 -1
  105. foxes/models/wake_models/wind/bastankhah14.py +3 -2
  106. foxes/models/wake_models/wind/bastankhah16.py +2 -1
  107. foxes/models/wake_models/wind/turbopark.py +9 -7
  108. foxes/models/wake_superpositions/ws_product.py +0 -1
  109. foxes/output/__init__.py +2 -1
  110. foxes/output/calc_points.py +7 -4
  111. foxes/output/farm_layout.py +30 -18
  112. foxes/output/farm_results_eval.py +61 -38
  113. foxes/output/grids.py +8 -7
  114. foxes/output/output.py +9 -20
  115. foxes/output/plt.py +19 -0
  116. foxes/output/results_writer.py +10 -11
  117. foxes/output/rose_plot.py +448 -224
  118. foxes/output/rotor_point_plots.py +7 -3
  119. foxes/output/slice_data.py +1 -1
  120. foxes/output/state_turbine_map.py +5 -1
  121. foxes/output/state_turbine_table.py +7 -3
  122. foxes/output/turbine_type_curves.py +7 -2
  123. foxes/utils/__init__.py +1 -2
  124. foxes/utils/dict.py +107 -3
  125. foxes/utils/geopandas_utils.py +3 -2
  126. foxes/utils/subclasses.py +69 -0
  127. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/METADATA +18 -18
  128. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/RECORD +145 -145
  129. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/WHEEL +1 -1
  130. foxes-1.2.1.dist-info/entry_points.txt +3 -0
  131. tests/0_consistency/iterative/test_iterative.py +65 -67
  132. tests/0_consistency/partial_wakes/test_partial_wakes.py +58 -61
  133. tests/1_verification/flappy_0_6/PCt_files/test_PCt_files.py +56 -53
  134. tests/1_verification/flappy_0_6/abl_states/test_abl_states.py +41 -41
  135. tests/1_verification/flappy_0_6/partial_top_hat/test_partial_top_hat.py +34 -34
  136. tests/1_verification/flappy_0_6/row_Jensen_linear_centre/test_row_Jensen_linear_centre.py +57 -52
  137. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat/test_row_Jensen_linear_tophat.py +58 -54
  138. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2005/test_row_Jensen_linear_tophat_IECTI_2005.py +80 -76
  139. tests/1_verification/flappy_0_6/row_Jensen_linear_tophat_IECTI2019/test_row_Jensen_linear_tophat_IECTI_2019.py +80 -76
  140. tests/1_verification/flappy_0_6/row_Jensen_quadratic_centre/test_row_Jensen_quadratic_centre.py +58 -51
  141. tests/1_verification/flappy_0_6_2/grid_rotors/test_grid_rotors.py +101 -103
  142. tests/1_verification/flappy_0_6_2/row_Bastankhah_Crespo/test_row_Bastankhah_Crespo.py +67 -64
  143. tests/1_verification/flappy_0_6_2/row_Bastankhah_linear_centre/test_row_Bastankhah_linear_centre.py +58 -54
  144. examples/windio/run.py +0 -29
  145. foxes/data/states/windio_timeseries_5000.nc +0 -0
  146. foxes/data/windio/DTU_10MW_turbine.yaml +0 -10
  147. foxes/data/windio/__init__.py +0 -0
  148. foxes/data/windio/windio_5turbines_timeseries.yaml +0 -79
  149. foxes/input/windio/__init__.py +0 -11
  150. foxes/input/windio/read_outputs.py +0 -172
  151. foxes/input/windio/runner.py +0 -183
  152. foxes/input/windio/windio.py +0 -193
  153. foxes/utils/windrose_plot.py +0 -152
  154. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/LICENSE +0 -0
  155. {foxes-1.1.1.dist-info → foxes-1.2.1.dist-info}/top_level.txt +0 -0
@@ -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/__init__.py CHANGED
@@ -5,7 +5,7 @@ General utilities.
5
5
  from .wind_dir import wd2uv, wd2wdvec, wdvec2wd, uv2wd, delta_wd
6
6
  from .pandas_utils import PandasFileHelper
7
7
  from .xarray_utils import write_nc
8
- from .subclasses import all_subclasses
8
+ from .subclasses import all_subclasses, new_cls, new_instance
9
9
  from .dict import Dict
10
10
  from .factory import Factory, FDict, WakeKFactory
11
11
  from .data_book import DataBook
@@ -14,7 +14,6 @@ from .geopandas_utils import read_shp, shp2csv, read_shp_polygons, shp2geom2d
14
14
  from .load import import_module, load_module
15
15
  from .exec_python import exec_python
16
16
  from .regularize import sqrt_reg
17
- from .windrose_plot import TabWindroseAxes
18
17
  from .tab_files import read_tab_file
19
18
  from .random_xy import random_xy_square
20
19
  from .dev_utils import print_mem
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
 
foxes/utils/subclasses.py CHANGED
@@ -19,3 +19,72 @@ def all_subclasses(cls):
19
19
  return set(cls.__subclasses__()).union(
20
20
  [s for c in cls.__subclasses__() for s in all_subclasses(c)]
21
21
  )
22
+
23
+
24
+ def new_cls(base_cls, cls_name):
25
+ """
26
+ Run-time class selector.
27
+
28
+ Parameters
29
+ ----------
30
+ base_cls: object
31
+ The base class
32
+ cls_name: string
33
+ Name of the class
34
+
35
+ Returns
36
+ -------
37
+ cls: object
38
+ The derived class
39
+
40
+ :group: utils
41
+
42
+ """
43
+
44
+ if cls_name is None:
45
+ return None
46
+
47
+ allc = all_subclasses(base_cls)
48
+ found = cls_name in [scls.__name__ for scls in allc]
49
+
50
+ if found:
51
+ for scls in allc:
52
+ if scls.__name__ == cls_name:
53
+ return scls
54
+
55
+ else:
56
+ estr = "Class '{}' not found, available classes derived from '{}' are \n {}".format(
57
+ cls_name, base_cls.__name__, sorted([i.__name__ for i in allc])
58
+ )
59
+ raise KeyError(estr)
60
+
61
+
62
+ def new_instance(base_cls, cls_name, *args, **kwargs):
63
+ """
64
+ Run-time factory.
65
+
66
+ Parameters
67
+ ----------
68
+ base_cls: object
69
+ The base class
70
+ cls_name: string
71
+ Name of the class
72
+ args: tuple, optional
73
+ Additional parameters for the constructor
74
+ kwargs: dict, optional
75
+ Additional parameters for the constructor
76
+
77
+ Returns
78
+ -------
79
+ obj: object
80
+ The instance of the derived class
81
+
82
+ :group: utils
83
+
84
+ """
85
+
86
+ cls = new_cls(base_cls, cls_name)
87
+ if cls is None:
88
+ return None
89
+ else:
90
+ return cls(*args, **kwargs)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: foxes
3
- Version: 1.1.1
3
+ Version: 1.2.1
4
4
  Summary: Farm Optimization and eXtended yield Evaluation Software
5
5
  Author: Jonas Schulte
6
6
  Maintainer: Jonas Schulte
@@ -54,29 +54,16 @@ Requires-Dist: pandas
54
54
  Requires-Dist: xarray
55
55
  Requires-Dist: scipy
56
56
  Requires-Dist: netcdf4
57
- Requires-Dist: windrose
58
57
  Requires-Dist: cycler
59
58
  Requires-Dist: tqdm
60
59
  Requires-Dist: pyyaml
60
+ Provides-Extra: opt
61
+ Requires-Dist: foxes-opt; extra == "opt"
61
62
  Provides-Extra: dask
62
63
  Requires-Dist: dask; extra == "dask"
63
64
  Requires-Dist: distributed; extra == "dask"
64
65
  Requires-Dist: dask-jobqueue; extra == "dask"
65
66
  Requires-Dist: setuptools; extra == "dask"
66
- Provides-Extra: dev
67
- Requires-Dist: flake8; extra == "dev"
68
- Requires-Dist: pytest; extra == "dev"
69
- Requires-Dist: jupyter; extra == "dev"
70
- Requires-Dist: objsize; extra == "dev"
71
- Requires-Dist: black[jupyter]; extra == "dev"
72
- Provides-Extra: doc
73
- Requires-Dist: sphinx; extra == "doc"
74
- Requires-Dist: sphinx-immaterial; extra == "doc"
75
- Requires-Dist: nbsphinx; extra == "doc"
76
- Requires-Dist: ipykernel; extra == "doc"
77
- Requires-Dist: ipywidgets; extra == "doc"
78
- Requires-Dist: m2r2; extra == "doc"
79
- Requires-Dist: lxml-html-clean; extra == "doc"
80
67
  Provides-Extra: eng
81
68
  Requires-Dist: multiprocess; extra == "eng"
82
69
  Requires-Dist: dask; extra == "eng"
@@ -92,11 +79,23 @@ Requires-Dist: distributed; extra == "eng0"
92
79
  Requires-Dist: dask-jobqueue; extra == "eng0"
93
80
  Requires-Dist: setuptools; extra == "eng0"
94
81
  Requires-Dist: ray; extra == "eng0"
95
- Provides-Extra: opt
96
- Requires-Dist: foxes-opt; extra == "opt"
97
82
  Provides-Extra: test
98
83
  Requires-Dist: flake8; extra == "test"
99
84
  Requires-Dist: pytest; extra == "test"
85
+ Provides-Extra: doc
86
+ Requires-Dist: sphinx; extra == "doc"
87
+ Requires-Dist: sphinx-immaterial; extra == "doc"
88
+ Requires-Dist: nbsphinx; extra == "doc"
89
+ Requires-Dist: ipykernel; extra == "doc"
90
+ Requires-Dist: ipywidgets; extra == "doc"
91
+ Requires-Dist: m2r2; extra == "doc"
92
+ Requires-Dist: lxml_html_clean; extra == "doc"
93
+ Provides-Extra: dev
94
+ Requires-Dist: flake8; extra == "dev"
95
+ Requires-Dist: pytest; extra == "dev"
96
+ Requires-Dist: jupyter; extra == "dev"
97
+ Requires-Dist: objsize; extra == "dev"
98
+ Requires-Dist: black[jupyter]; extra == "dev"
100
99
 
101
100
  # Welcome to foxes
102
101
 
@@ -163,6 +162,7 @@ The supported Python versions are:
163
162
  - `Python 3.10`
164
163
  - `Python 3.11`
165
164
  - `Python 3.12`
165
+ - `Python 3.13`
166
166
 
167
167
  ## Installation
168
168