foxes 0.5.0.2__py3-none-any.whl → 0.5.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.
- foxes/VERSION +1 -1
- foxes/algorithms/downwind/downwind.py +41 -46
- foxes/algorithms/downwind/models/point_wakes_calc.py +4 -9
- foxes/algorithms/downwind/models/set_amb_point_results.py +5 -22
- foxes/core/algorithm.py +1 -1
- foxes/core/data_calc_model.py +26 -2
- foxes/core/partial_wakes_model.py +1 -1
- foxes/core/rotor_model.py +36 -2
- foxes/core/turbine_model.py +36 -0
- foxes/core/turbine_type.py +35 -1
- foxes/core/wake_frame.py +39 -3
- foxes/core/wake_model.py +36 -0
- foxes/models/model_book.py +129 -89
- foxes/models/turbine_models/rotor_centre_calc.py +1 -2
- foxes/models/turbine_types/CpCt_file.py +13 -3
- foxes/models/turbine_types/CpCt_from_two.py +14 -4
- foxes/models/vertical_profiles/abl_log_neutral_ws.py +32 -5
- foxes/models/vertical_profiles/abl_log_stable_ws.py +32 -4
- foxes/models/vertical_profiles/abl_log_unstable_ws.py +32 -4
- foxes/models/vertical_profiles/abl_log_ws.py +50 -18
- foxes/models/wake_frames/yawed_wakes.py +15 -9
- foxes/models/wake_models/induction/__init__.py +1 -1
- foxes/models/wake_models/induction/rankine_half_body.py +33 -7
- foxes/models/wake_models/ti/crespo_hernandez.py +6 -1
- foxes/models/wake_models/ti/iec_ti.py +5 -3
- foxes/models/wake_models/wind/__init__.py +2 -2
- foxes/models/wake_models/wind/{bastankhah.py → bastankhah14.py} +11 -14
- foxes/models/wake_models/wind/{porte_agel.py → bastankhah16.py} +24 -16
- foxes/models/wake_models/wind/turbopark.py +11 -22
- foxes/models/wake_superpositions/__init__.py +9 -5
- foxes/models/wake_superpositions/ti_linear.py +134 -0
- foxes/models/wake_superpositions/ti_max.py +134 -0
- foxes/models/wake_superpositions/{ti_superp.py → ti_pow.py} +15 -57
- foxes/models/wake_superpositions/ti_quadratic.py +134 -0
- foxes/models/wake_superpositions/ws_linear.py +170 -0
- foxes/models/wake_superpositions/ws_max.py +173 -0
- foxes/models/wake_superpositions/ws_pow.py +175 -0
- foxes/models/wake_superpositions/{product.py → ws_product.py} +43 -22
- foxes/models/wake_superpositions/ws_quadratic.py +170 -0
- foxes/output/__init__.py +4 -0
- foxes/output/calc_points.py +143 -0
- foxes/output/flow_plots_2d/__init__.py +1 -0
- foxes/output/flow_plots_2d/common.py +104 -1
- foxes/output/flow_plots_2d/flow_plots.py +237 -569
- foxes/output/flow_plots_2d/get_fig.py +183 -0
- foxes/output/flow_plots_2d/seq_flow_ani_plugin.py +0 -1
- foxes/output/grids.py +705 -0
- foxes/output/output.py +58 -11
- foxes/output/results_writer.py +101 -17
- foxes/output/round.py +10 -0
- foxes/output/slice_data.py +900 -0
- foxes/utils/__init__.py +5 -3
- foxes/utils/exec_python.py +56 -0
- foxes/utils/geopandas_utils.py +294 -0
- foxes/utils/pandas_utils.py +175 -0
- foxes/utils/plotly_utils.py +19 -0
- foxes/utils/xarray_utils.py +38 -0
- {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/METADATA +1 -1
- {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/RECORD +63 -49
- foxes/models/wake_superpositions/linear.py +0 -242
- foxes/models/wake_superpositions/max.py +0 -258
- foxes/models/wake_superpositions/quadratic.py +0 -252
- {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/LICENSE +0 -0
- {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/WHEEL +0 -0
- {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/top_level.txt +0 -0
- {foxes-0.5.0.2.dist-info → foxes-0.5.2.dist-info}/zip-safe +0 -0
foxes/output/output.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
from
|
|
1
|
+
from pathlib import Path
|
|
2
2
|
|
|
3
|
+
from foxes.utils import PandasFileHelper, all_subclasses
|
|
3
4
|
|
|
4
5
|
class Output:
|
|
5
6
|
"""
|
|
@@ -8,12 +9,53 @@ class Output:
|
|
|
8
9
|
The job of this class is to provide handy
|
|
9
10
|
helper functions.
|
|
10
11
|
|
|
12
|
+
Attributes
|
|
13
|
+
----------
|
|
14
|
+
out_dir: pathlib.Path
|
|
15
|
+
The output file directory
|
|
16
|
+
out_fname_fun: Function, optional
|
|
17
|
+
Modifies file names by f(fname)
|
|
18
|
+
|
|
11
19
|
:group: output
|
|
12
20
|
|
|
13
21
|
"""
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
def __init__(self, out_dir=None, out_fname_fun=None):
|
|
24
|
+
"""
|
|
25
|
+
Constructor.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
out_dir: str, optional
|
|
30
|
+
The output file directory
|
|
31
|
+
out_fname_fun: Function, optional
|
|
32
|
+
Modifies file names by f(fname)
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
self.out_dir = Path(out_dir) if out_dir is not None else None
|
|
36
|
+
self.out_fname_fun = out_fname_fun
|
|
37
|
+
|
|
38
|
+
def get_fpath(self, fname):
|
|
39
|
+
"""
|
|
40
|
+
Gets the total file path
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
fname: str
|
|
45
|
+
The file name
|
|
46
|
+
|
|
47
|
+
Returns
|
|
48
|
+
-------
|
|
49
|
+
fpath: pathlib.Path
|
|
50
|
+
The total file path
|
|
51
|
+
|
|
52
|
+
"""
|
|
53
|
+
fnm = Path(fname)
|
|
54
|
+
if self.out_fname_fun is not None:
|
|
55
|
+
fnm = self.out_fname_fun(fnm)
|
|
56
|
+
return self.out_dir/fnm if self.out_dir is not None else fnm
|
|
57
|
+
|
|
58
|
+
def write(self, file_name, data, format_col2var={}, format_dict={}, **kwargs):
|
|
17
59
|
"""
|
|
18
60
|
Writes data to file via pandas.
|
|
19
61
|
|
|
@@ -21,16 +63,16 @@ class Output:
|
|
|
21
63
|
|
|
22
64
|
Parameters
|
|
23
65
|
----------
|
|
24
|
-
|
|
25
|
-
The
|
|
66
|
+
file_name: str
|
|
67
|
+
The output file name
|
|
26
68
|
data: pandas.DataFrame
|
|
27
69
|
The data
|
|
28
70
|
format_col2var: dict
|
|
29
|
-
Mapping from column names to
|
|
71
|
+
Mapping from column names to foxes variables,
|
|
30
72
|
for formatting
|
|
31
73
|
format_dict: dict
|
|
32
74
|
Dictionary with format entries for columns, e.g.
|
|
33
|
-
{FV.P: '{:.4f}'}. Note that the keys are
|
|
75
|
+
{FV.P: '{:.4f}'}. Note that the keys are foxes variables
|
|
34
76
|
|
|
35
77
|
"""
|
|
36
78
|
fdict = {}
|
|
@@ -41,8 +83,9 @@ class Output:
|
|
|
41
83
|
elif v in PandasFileHelper.DEFAULT_FORMAT_DICT:
|
|
42
84
|
fdict[c] = PandasFileHelper.DEFAULT_FORMAT_DICT[v]
|
|
43
85
|
|
|
44
|
-
|
|
45
|
-
|
|
86
|
+
fpath = self.get_fpath(file_name)
|
|
87
|
+
PandasFileHelper.write_file(data, fpath, fdict, **kwargs)
|
|
88
|
+
|
|
46
89
|
@classmethod
|
|
47
90
|
def print_models(cls):
|
|
48
91
|
"""
|
|
@@ -53,7 +96,7 @@ class Output:
|
|
|
53
96
|
print(n)
|
|
54
97
|
|
|
55
98
|
@classmethod
|
|
56
|
-
def new(cls, model_type, **kwargs):
|
|
99
|
+
def new(cls, model_type, *args, **kwargs):
|
|
57
100
|
"""
|
|
58
101
|
Run-time output model factory.
|
|
59
102
|
|
|
@@ -61,6 +104,10 @@ class Output:
|
|
|
61
104
|
----------
|
|
62
105
|
model_type: string
|
|
63
106
|
The selected derived class name
|
|
107
|
+
args: tuple, optional
|
|
108
|
+
Additional parameters for the constructor
|
|
109
|
+
kwargs: dict, optional
|
|
110
|
+
Additional parameters for the constructor
|
|
64
111
|
|
|
65
112
|
"""
|
|
66
113
|
|
|
@@ -73,7 +120,7 @@ class Output:
|
|
|
73
120
|
if found:
|
|
74
121
|
for scls in allc:
|
|
75
122
|
if scls.__name__ == model_type:
|
|
76
|
-
return scls(**kwargs)
|
|
123
|
+
return scls(*args, **kwargs)
|
|
77
124
|
|
|
78
125
|
else:
|
|
79
126
|
estr = "Output type '{}' is not defined, available types are \n {}".format(
|
foxes/output/results_writer.py
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from xarray import Dataset
|
|
3
|
+
|
|
2
4
|
import foxes.constants as FC
|
|
5
|
+
from foxes.utils import write_nc
|
|
3
6
|
|
|
7
|
+
from .output import Output
|
|
4
8
|
|
|
5
9
|
class ResultsWriter(Output):
|
|
6
10
|
"""
|
|
@@ -15,7 +19,7 @@ class ResultsWriter(Output):
|
|
|
15
19
|
|
|
16
20
|
"""
|
|
17
21
|
|
|
18
|
-
def __init__(self, farm_results=None, data=None):
|
|
22
|
+
def __init__(self, farm_results=None, data=None, **kwargs):
|
|
19
23
|
"""
|
|
20
24
|
Constructor.
|
|
21
25
|
|
|
@@ -25,8 +29,12 @@ class ResultsWriter(Output):
|
|
|
25
29
|
The farm results, if data is None
|
|
26
30
|
data: pandas.DataFrame, optional
|
|
27
31
|
The data, if farm_results is None
|
|
32
|
+
kwargs: dict, optional
|
|
33
|
+
Additional parameters for the base class
|
|
28
34
|
|
|
29
35
|
"""
|
|
36
|
+
super().__init__(**kwargs)
|
|
37
|
+
|
|
30
38
|
if farm_results is not None and data is None:
|
|
31
39
|
self.data = farm_results.to_dataframe().reset_index()
|
|
32
40
|
self.data[FC.TNAME] = farm_results[FC.TNAME].to_numpy()[
|
|
@@ -39,12 +47,32 @@ class ResultsWriter(Output):
|
|
|
39
47
|
raise KeyError(
|
|
40
48
|
f"ResultsWriter: Either give 'farm_results' or 'data' arguments"
|
|
41
49
|
)
|
|
50
|
+
|
|
51
|
+
def _get_data_vars(self, variables):
|
|
52
|
+
""" Helper function for variable gathering """
|
|
53
|
+
data = self.data
|
|
54
|
+
if variables is None:
|
|
55
|
+
pass
|
|
56
|
+
elif isinstance(variables, dict):
|
|
57
|
+
inds = {
|
|
58
|
+
s: variables.pop(s) for s in self.data.index.names if s in variables
|
|
59
|
+
}
|
|
60
|
+
if len(variables):
|
|
61
|
+
data = data[list(variables.keys())].rename(variables, axis=1)
|
|
62
|
+
if len(inds):
|
|
63
|
+
for s, ns in inds.items():
|
|
64
|
+
data = data.rename_axis(index={s: ns})
|
|
65
|
+
else:
|
|
66
|
+
data = self.data[list(variables)]
|
|
67
|
+
|
|
68
|
+
return data, data.columns.tolist()
|
|
42
69
|
|
|
43
70
|
def write_csv(
|
|
44
71
|
self,
|
|
45
72
|
file_path,
|
|
46
73
|
variables=None,
|
|
47
74
|
turbine_names=False,
|
|
75
|
+
state_turbine_table=False,
|
|
48
76
|
verbosity=1,
|
|
49
77
|
**kwargs,
|
|
50
78
|
):
|
|
@@ -62,6 +90,9 @@ class ResultsWriter(Output):
|
|
|
62
90
|
written.
|
|
63
91
|
turbine_names: bool
|
|
64
92
|
Use turbine names instead of turbine indices
|
|
93
|
+
state_turbine_table: bool
|
|
94
|
+
Flag for writing a single variable into turbine columns
|
|
95
|
+
for state rows
|
|
65
96
|
verbosity: int
|
|
66
97
|
The verbosity level, 0 = silent
|
|
67
98
|
kwargs: dict, optional
|
|
@@ -71,22 +102,75 @@ class ResultsWriter(Output):
|
|
|
71
102
|
if verbosity:
|
|
72
103
|
print(f"ResultsWriter: Writing file '{file_path}'")
|
|
73
104
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if
|
|
84
|
-
|
|
85
|
-
|
|
105
|
+
data, variables = self._get_data_vars(variables)
|
|
106
|
+
data.reset_index(inplace=True)
|
|
107
|
+
fc2v = kwargs.pop("format_col2var", {})
|
|
108
|
+
tix = FC.TNAME if turbine_names else FC.TURBINE
|
|
109
|
+
|
|
110
|
+
if state_turbine_table:
|
|
111
|
+
if len(variables) != 1:
|
|
112
|
+
raise ValueError(f"state_turbine_table can only be written for a single variable, got {variables}")
|
|
113
|
+
v = variables[0]
|
|
114
|
+
cnames = {t: f"{v}_T{t:04d}" if tix == FC.TURBINE else f"{v}_{t}" for t in data[tix]}
|
|
115
|
+
for ti, (t, g) in enumerate(data.reset_index().set_index(FC.STATE).groupby(tix)):
|
|
116
|
+
if ti == 0:
|
|
117
|
+
odata = pd.DataFrame(index=g.index.to_numpy(), columns=list(cnames.values()))
|
|
118
|
+
odata.index.name = g.index.name
|
|
119
|
+
cname = cnames[t]
|
|
120
|
+
odata[cname] = g[v].to_numpy().copy()
|
|
121
|
+
fc2v[cname] = v
|
|
122
|
+
data = odata
|
|
86
123
|
else:
|
|
87
|
-
data =
|
|
124
|
+
data.set_index([FC.STATE, tix], inplace=True)
|
|
88
125
|
|
|
126
|
+
fpath = self.get_fpath(file_path)
|
|
127
|
+
super().write(fpath, data, format_col2var=fc2v, **kwargs)
|
|
128
|
+
|
|
129
|
+
def write_nc(
|
|
130
|
+
self,
|
|
131
|
+
file_path,
|
|
132
|
+
variables=None,
|
|
133
|
+
turbine_names=False,
|
|
134
|
+
verbosity=1,
|
|
135
|
+
**kwargs,
|
|
136
|
+
):
|
|
137
|
+
"""
|
|
138
|
+
Writes a netCDF file
|
|
139
|
+
|
|
140
|
+
Parameters
|
|
141
|
+
----------
|
|
142
|
+
file_path: str
|
|
143
|
+
Path the the csv file
|
|
144
|
+
variables: dict or list of str, optional
|
|
145
|
+
The variables to be written. If a dict, then
|
|
146
|
+
the keys are the foxes variables and the values
|
|
147
|
+
the column names. If None, then all data will be
|
|
148
|
+
written.
|
|
149
|
+
turbine_names: bool
|
|
150
|
+
Use turbine names instead of turbine indices
|
|
151
|
+
verbosity: int
|
|
152
|
+
The verbosity level, 0 = silent
|
|
153
|
+
kwargs: dict, optional
|
|
154
|
+
Additional parameters for write_nc()
|
|
155
|
+
|
|
156
|
+
"""
|
|
157
|
+
data, variables = self._get_data_vars(variables)
|
|
158
|
+
states = data.index.get_level_values(0).unique()
|
|
159
|
+
n_states = len(states)
|
|
160
|
+
n_turbines = len(data.index.get_level_values(1).unique())
|
|
161
|
+
|
|
162
|
+
crds = {FC.STATE: states}
|
|
89
163
|
if turbine_names:
|
|
90
|
-
|
|
164
|
+
idx = pd.IndexSlice
|
|
165
|
+
crds[FC.TURBINE] = self.data.loc[idx[0, :], FC.TNAME].to_numpy()
|
|
166
|
+
|
|
167
|
+
ds = Dataset(
|
|
168
|
+
coords=crds,
|
|
169
|
+
data_vars={
|
|
170
|
+
v: ((FC.STATE, FC.TURBINE), data[v].to_numpy().reshape(n_states, n_turbines))
|
|
171
|
+
for v in variables
|
|
172
|
+
}
|
|
173
|
+
)
|
|
91
174
|
|
|
92
|
-
|
|
175
|
+
fpath = self.get_fpath(file_path)
|
|
176
|
+
write_nc(ds, fpath, verbosity=verbosity, **kwargs)
|
foxes/output/round.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import foxes.variables as FV
|
|
2
|
+
import foxes.constants as FC
|
|
3
|
+
|
|
4
|
+
round_defaults = {v: 4 for v in FV.__dict__.keys() if isinstance(v, str)}
|
|
5
|
+
round_defaults[FV.WD] = 3
|
|
6
|
+
round_defaults[FV.YAW] = 3
|
|
7
|
+
round_defaults[FV.TI] = 6
|
|
8
|
+
round_defaults[FV.RHO] = 6
|
|
9
|
+
round_defaults[FC.XYH] = 3
|
|
10
|
+
round_defaults.update({FV.var2amb[v]: round_defaults[v] for v in FV.var2amb.keys()})
|