foxes 1.2.2__py3-none-any.whl → 1.2.4__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 (65) hide show
  1. examples/field_data_nc/run.py +11 -4
  2. examples/streamline_wakes/run.py +6 -3
  3. foxes/algorithms/downwind/downwind.py +1 -0
  4. foxes/config/__init__.py +1 -1
  5. foxes/config/config.py +87 -14
  6. foxes/constants.py +12 -1
  7. foxes/core/algorithm.py +13 -8
  8. foxes/core/engine.py +30 -0
  9. foxes/core/farm_controller.py +41 -24
  10. foxes/core/states.py +1 -1
  11. foxes/core/wind_farm.py +109 -0
  12. foxes/engines/dask.py +88 -4
  13. foxes/engines/default.py +45 -2
  14. foxes/engines/mpi.py +5 -16
  15. foxes/engines/multiprocess.py +1 -10
  16. foxes/engines/numpy.py +30 -0
  17. foxes/engines/pool.py +48 -0
  18. foxes/engines/ray.py +1 -1
  19. foxes/engines/single.py +30 -0
  20. foxes/input/farm_layout/from_csv.py +2 -2
  21. foxes/input/farm_layout/from_file.py +2 -2
  22. foxes/input/farm_layout/from_json.py +2 -2
  23. foxes/input/states/__init__.py +0 -1
  24. foxes/input/states/create/random_abl_states.py +2 -2
  25. foxes/input/states/field_data_nc.py +286 -141
  26. foxes/input/states/multi_height.py +3 -3
  27. foxes/input/states/states_table.py +3 -3
  28. foxes/input/yaml/dict.py +83 -46
  29. foxes/input/yaml/windio/__init__.py +2 -1
  30. foxes/input/yaml/windio/read_attributes.py +17 -34
  31. foxes/input/yaml/windio/read_farm.py +57 -3
  32. foxes/input/yaml/windio/read_outputs.py +116 -56
  33. foxes/input/yaml/windio/{get_states.py → read_site.py} +69 -0
  34. foxes/input/yaml/windio/windio.py +42 -119
  35. foxes/input/yaml/yaml.py +3 -3
  36. foxes/models/model_book.py +1 -0
  37. foxes/models/point_models/__init__.py +1 -0
  38. foxes/models/point_models/ustar2ti.py +84 -0
  39. foxes/models/turbine_models/lookup_table.py +2 -2
  40. foxes/models/turbine_models/sector_management.py +2 -2
  41. foxes/models/turbine_models/table_factors.py +2 -2
  42. foxes/models/turbine_types/CpCt_file.py +2 -2
  43. foxes/models/turbine_types/CpCt_from_two.py +3 -3
  44. foxes/models/turbine_types/PCt_file.py +2 -2
  45. foxes/models/turbine_types/PCt_from_two.py +3 -3
  46. foxes/models/turbine_types/TBL_file.py +2 -2
  47. foxes/models/turbine_types/wsrho2PCt_from_two.py +3 -3
  48. foxes/models/turbine_types/wsti2PCt_from_two.py +3 -3
  49. foxes/output/__init__.py +1 -0
  50. foxes/output/output.py +5 -3
  51. foxes/output/slice_data.py +1 -1
  52. foxes/output/slices_data.py +323 -0
  53. foxes/output/state_turbine_table.py +11 -0
  54. foxes/utils/__init__.py +1 -0
  55. foxes/utils/load.py +12 -4
  56. foxes/utils/wrg_utils.py +79 -0
  57. foxes/utils/xarray_utils.py +14 -3
  58. foxes/variables.py +5 -0
  59. {foxes-1.2.2.dist-info → foxes-1.2.4.dist-info}/METADATA +6 -2
  60. {foxes-1.2.2.dist-info → foxes-1.2.4.dist-info}/RECORD +64 -62
  61. foxes/input/states/slice_data_nc.py +0 -687
  62. {foxes-1.2.2.dist-info → foxes-1.2.4.dist-info}/LICENSE +0 -0
  63. {foxes-1.2.2.dist-info → foxes-1.2.4.dist-info}/WHEEL +0 -0
  64. {foxes-1.2.2.dist-info → foxes-1.2.4.dist-info}/entry_points.txt +0 -0
  65. {foxes-1.2.2.dist-info → foxes-1.2.4.dist-info}/top_level.txt +0 -0
foxes/input/yaml/dict.py CHANGED
@@ -20,8 +20,9 @@ def read_dict(
20
20
  engine_pars=None,
21
21
  iterative=None,
22
22
  verbosity=None,
23
- work_dir=".",
24
- out_dir=".",
23
+ work_dir=None,
24
+ input_dir=None,
25
+ output_dir=None,
25
26
  **algo_pars,
26
27
  ):
27
28
  """
@@ -48,9 +49,11 @@ def read_dict(
48
49
  verbosity: int, optional
49
50
  Force a verbosity level, 0 = silent, overrules
50
51
  settings from idict
51
- work_dir: str or pathlib.Path
52
+ work_dir: str or pathlib.Path, optional
52
53
  Path to the working directory
53
- out_dir: str or pathlib.Path
54
+ input_dir: str or pathlib.Path, optional
55
+ The default input directory
56
+ output_dir: str or pathlib.Path, optional
54
57
  The default output directory
55
58
  algo_pars: dict, optional
56
59
  Additional parameters for the algorithm, overrules
@@ -72,45 +75,75 @@ def read_dict(
72
75
  print(*args, **kwargs)
73
76
 
74
77
  # set working directory:
75
- config[FC.WORK_DIR] = work_dir
76
- config[FC.OUT_DIR] = out_dir
77
- _print("Working directory:", config.work_dir)
78
- _print("Output directory :", config.out_dir)
78
+ l = 0
79
+ for c, d in zip(
80
+ [FC.WORK_DIR, FC.INPUT_DIR, FC.OUTPUT_DIR], [work_dir, input_dir, output_dir]
81
+ ):
82
+ if d is not None:
83
+ config[c] = d
84
+ l = max(l, len(str(d)))
85
+ _print("\n--------------------- Reading foxes parameter dict ---------------------")
86
+ _print("Working directory :", config.work_dir)
87
+ _print("Input directory :", config.input_dir)
88
+ _print("Output directory :", config.output_dir)
79
89
 
80
90
  # create states:
81
91
  if states is None:
82
- _print("Creating states")
83
- states = States.new(**idict["states"])
92
+ if algo is None:
93
+ _print("Creating states")
94
+ states = States.new(**idict["states"])
95
+ else:
96
+ states = algo.states
97
+ else:
98
+ assert (
99
+ algo is None
100
+ ), f"Cannot handle both the algo and the states argument, please drop one"
84
101
 
85
102
  # create model book:
86
103
  if mbook is None:
87
- mbook = ModelBook()
88
- if "model_book" in idict:
89
- _print("Creating model book")
90
- mdict = idict.get_item("model_book")
91
- for s, mlst in mdict.items():
92
- t = mbook.sources.get_item(s)
93
- c = mbook.base_classes.get_item(s)
94
- ms = [Dict(m, name=f"{mdict.name}.s{i}") for i, m in enumerate(mlst)]
95
- for m in ms:
96
- mname = m.pop_item("name")
97
- _print(f" Adding {s}.{mname}")
98
- t[mname] = c.new(**m)
104
+ if algo is None:
105
+ mbook = ModelBook()
106
+ if "model_book" in idict:
107
+ _print("Creating model book")
108
+ mdict = idict.get_item("model_book")
109
+ for s, mlst in mdict.items():
110
+ t = mbook.sources.get_item(s)
111
+ c = mbook.base_classes.get_item(s)
112
+ ms = [
113
+ Dict(m, name=f"{mdict.name}.s{i}") for i, m in enumerate(mlst)
114
+ ]
115
+ for m in ms:
116
+ mname = m.pop_item("name")
117
+ _print(f" Adding {s}.{mname}")
118
+ t[mname] = c.new(**m)
119
+ else:
120
+ mbook = algo.mbook
121
+ else:
122
+ assert (
123
+ algo is None
124
+ ), f"Cannot handle both the algo and the mbook argument, please drop one"
99
125
 
100
126
  # create farm:
101
127
  if farm is None:
102
- _print("Creating wind farm")
103
- fdict = idict.get_item("wind_farm")
104
- lyts = [
105
- Dict(l, name=f"{fdict.name}.layout{i}")
106
- for i, l in enumerate(fdict.pop_item("layouts"))
107
- ]
108
- farm = WindFarm(**fdict)
109
- for lyt in lyts:
110
- add_fun = getattr(farm_layout, lyt.pop_item("function"))
111
- if verbosity is not None:
112
- lyt["verbosity"] = verbosity - 1
113
- add_fun(farm, **lyt)
128
+ if algo is None:
129
+ _print("Creating wind farm")
130
+ fdict = idict.get_item("wind_farm")
131
+ lyts = [
132
+ Dict(l, name=f"{fdict.name}.layout{i}")
133
+ for i, l in enumerate(fdict.pop_item("layouts"))
134
+ ]
135
+ farm = WindFarm(**fdict)
136
+ for lyt in lyts:
137
+ add_fun = getattr(farm_layout, lyt.pop_item("function"))
138
+ if verbosity is not None:
139
+ lyt["verbosity"] = verbosity - 1
140
+ add_fun(farm, **lyt)
141
+ else:
142
+ farm = algo.farm
143
+ else:
144
+ assert (
145
+ algo is None
146
+ ), f"Cannot handle both the algo and the farm argument, please drop one"
114
147
 
115
148
  # create engine:
116
149
  engine = None
@@ -127,10 +160,10 @@ def read_dict(
127
160
 
128
161
  # create algorithm:
129
162
  if algo is None:
130
- _print("Creating algorithm")
131
163
  adict = idict.get_item("algorithm")
132
164
  if iterative is not None and iterative:
133
165
  adict["algo_type"] = "Iterative"
166
+ _print("Creating algorithm :", adict["algo_type"])
134
167
  adict.update(dict(farm=farm, states=states, mbook=mbook))
135
168
  if verbosity is not None:
136
169
  adict["verbosity"] = verbosity - 1
@@ -138,6 +171,8 @@ def read_dict(
138
171
  adict.update({v: d for v, d in algo_pars.items() if d is not None})
139
172
  algo = Algorithm.new(**adict)
140
173
 
174
+ _print("------------------------------------------------------------------------\n")
175
+
141
176
  return algo, engine
142
177
 
143
178
 
@@ -248,10 +283,10 @@ def run_obj_function(
248
283
  print(*args, **kwargs)
249
284
 
250
285
  fname = fdict.pop_item("function")
251
- _print(f" - {fname}")
252
- plt_show = fdict.pop("plt_show", False)
253
- plt_close = fdict.pop("plt_close", False)
254
- rlbs = fdict.pop("result_labels", None)
286
+ _print(f"Running function {type(obj).__name__}.{fname}")
287
+ plt_show = fdict.pop_item("plt_show", False)
288
+ plt_close = fdict.pop_item("plt_close", False)
289
+ rlbs = fdict.pop_item("result_labels", None)
255
290
 
256
291
  # grab function:
257
292
  ocls = type(obj).__name__
@@ -271,7 +306,7 @@ def run_obj_function(
271
306
  fdict[k] = _get_object(rlabels, d)
272
307
 
273
308
  # run function:
274
- args = fdict.pop("args", tuple())
309
+ args = fdict.pop_item("args", tuple())
275
310
  results = f(*args, **fdict)
276
311
 
277
312
  # pyplot shortcuts:
@@ -338,7 +373,7 @@ def run_outputs(
338
373
  -------
339
374
  outputs: list of tuple
340
375
  For each output enty, a tuple (dict, results),
341
- where results is a tuple that represents one
376
+ where results is a list that represents one
342
377
  entry per function call
343
378
  rlabels: dict, optional
344
379
  The results variables
@@ -354,7 +389,6 @@ def run_outputs(
354
389
  out = []
355
390
  rlabels = Dict(name="result_labels")
356
391
  if "outputs" in idict:
357
- _print("Running outputs")
358
392
  odicts = [
359
393
  Dict(odict, name=f"{idict.name}.output{i}")
360
394
  for i, odict in enumerate(idict["outputs"])
@@ -363,7 +397,7 @@ def run_outputs(
363
397
  for i, d in enumerate(odicts):
364
398
  if "output_type" in d:
365
399
  ocls = d.pop_item("output_type")
366
- _print(f" Output {i}: {ocls}")
400
+ _print(f"\nRunning output {i}: {ocls}")
367
401
  d0 = dict(output_type=ocls)
368
402
  d0.update(d)
369
403
 
@@ -380,8 +414,8 @@ def run_outputs(
380
414
  continue
381
415
 
382
416
  elif "object" in d:
383
- ocls = d.pop("object")
384
- _print(f" Output {i}: Object {ocls}")
417
+ ocls = d.pop_item("object")
418
+ _print(f"Running output {i}: Object {ocls}")
385
419
  o = _get_object(rlabels, ocls)
386
420
  d0 = dict(object=ocls)
387
421
  d0.update(d)
@@ -401,6 +435,9 @@ def run_outputs(
401
435
  fres.append(results)
402
436
  out.append((d0, fres))
403
437
 
438
+ if len(odicts):
439
+ _print()
440
+
404
441
  return out if not ret_rlabels else out, rlabels
405
442
 
406
443
 
@@ -428,7 +465,7 @@ def run_dict(idict, *args, verbosity=None, **kwargs):
428
465
  The point results
429
466
  outputs: list of tuple
430
467
  For each output enty, a tuple (dict, results),
431
- where results is a tuple that represents one
468
+ where results is a list that represents one
432
469
  entry per function call
433
470
 
434
471
  :group: input.yaml
@@ -1,4 +1,5 @@
1
1
  from .windio import foxes_windio, read_windio
2
+ from .read_site import read_site
2
3
  from .read_fields import read_wind_resource_field
3
- from .read_farm import read_layout, read_turbine_types
4
+ from .read_farm import read_layout, read_turbine_types, read_farm
4
5
  from .read_attributes import read_attributes
@@ -2,8 +2,6 @@ from foxes.utils import Dict
2
2
  from foxes.core import WakeModel, WakeFrame
3
3
  import foxes.variables as FV
4
4
 
5
- from .read_outputs import read_outputs
6
-
7
5
 
8
6
  def _read_wind_deficit(
9
7
  wake_model_key,
@@ -29,7 +27,7 @@ def _read_wind_deficit(
29
27
  ws_sup_dict = Dict(
30
28
  {
31
29
  "Linear": "ws_linear",
32
- "Quadratic": "ws_quadratic",
30
+ "Squared": "ws_quadratic",
33
31
  "Product": "ws_product",
34
32
  },
35
33
  name="ws_sup_dict",
@@ -37,14 +35,14 @@ def _read_wind_deficit(
37
35
  ws_sup_amb_dict = Dict(
38
36
  {
39
37
  "Linear": "ws_linear_amb",
40
- "Quadratic": "ws_quadratic_amb",
38
+ "Squared": "ws_quadratic_amb",
41
39
  "Product": "ws_product",
42
40
  },
43
41
  name="ws_sup_dict",
44
42
  )
45
43
 
46
- wname = wind_deficit.pop("name")
47
- eff_ws = wind_deficit.pop("use_effective_ws", True)
44
+ wname = wind_deficit.pop_item("name")
45
+ eff_ws = wind_deficit.pop_item("use_effective_ws", True)
48
46
  if verbosity > 2:
49
47
  print(" Reading", wake_model_key)
50
48
  print(" Name :", wname)
@@ -53,8 +51,8 @@ def _read_wind_deficit(
53
51
  wind_def_dict = Dict(wmodel_type=wind_def_map[wname], induction=induction)
54
52
  kcoef = Dict(wind_deficit["wake_expansion_coefficient"], name="kcoef")
55
53
  ka = kcoef["k_a"]
56
- kb = kcoef.get("k_b", 0.0)
57
- amb_ti = kcoef.get("free_stream_ti", False)
54
+ kb = kcoef.get_item("k_b", 0.0)
55
+ amb_ti = kcoef.get_item("free_stream_ti", False)
58
56
  if ka is None or ka == 0.0:
59
57
  wind_def_dict["k"] = kb
60
58
  if verbosity > 2:
@@ -108,12 +106,12 @@ def _read_turbulence(
108
106
  ti_sup_dict = Dict(
109
107
  {
110
108
  "Linear": "ti_linear",
111
- "Quadratic": "ti_quadratic",
109
+ "Squared": "ti_quadratic",
112
110
  },
113
111
  name="ti_sup_dict",
114
112
  )
115
113
 
116
- wname = turbulence_model.pop("name")
114
+ wname = turbulence_model.pop_item("name")
117
115
  if verbosity > 2:
118
116
  print(" Reading turbulence_model")
119
117
  print(" Name:", wname)
@@ -126,8 +124,8 @@ def _read_turbulence(
126
124
  if "wake_expansion_coefficient" in turbulence_model:
127
125
  kcoef = Dict(turbulence_model["wake_expansion_coefficient"], name="kcoef")
128
126
  ka = kcoef["k_a"]
129
- kb = kcoef.get("k_b", 0.0)
130
- amb_ti = kcoef.get("free_stream_ti", False)
127
+ kb = kcoef.get_item("k_b", 0.0)
128
+ amb_ti = kcoef.get_item("free_stream_ti", False)
131
129
  if ka is None or ka == 0.0:
132
130
  tiwake_dict["k"] = kb
133
131
  if verbosity > 2:
@@ -161,7 +159,7 @@ def _read_blockage(blockage_model, induction, algo_dict, mbook, verbosity):
161
159
  name="twake_def_map",
162
160
  )
163
161
 
164
- wname = blockage_model.pop("name")
162
+ wname = blockage_model.pop_item("name")
165
163
  if verbosity > 2:
166
164
  print(" Reading blockage_model")
167
165
  print(" Name:", wname)
@@ -238,7 +236,7 @@ def _read_deflection(deflection, induction, algo_dict, mbook, verbosity):
238
236
  name="defl_def_map",
239
237
  )
240
238
 
241
- wname = deflection.pop("name")
239
+ wname = deflection.pop_item("name")
242
240
  if verbosity > 2:
243
241
  print(" Reading deflection_model")
244
242
  print(" Name:", wname)
@@ -276,7 +274,7 @@ def _read_analysis(wio_ana, idict, mbook, verbosity):
276
274
  },
277
275
  name="induction mapping",
278
276
  )
279
- induction = imap[wio_ana.get("axial_induction_model", "1D")]
277
+ induction = imap[wio_ana.get_item("axial_induction_model", "1D")]
280
278
  if verbosity > 2:
281
279
  print(" axial induction model:", induction)
282
280
 
@@ -337,14 +335,14 @@ def _read_analysis(wio_ana, idict, mbook, verbosity):
337
335
  print("deflection_model not found, using default settings")
338
336
 
339
337
 
340
- def read_attributes(wio, idict, mbook, verbosity=1):
338
+ def read_attributes(wio_attrs, idict, mbook, verbosity=1):
341
339
  """
342
340
  Reads the attributes part of windio
343
341
 
344
342
  Parameters
345
343
  ----------
346
- wio: foxes.utils.Dict
347
- The windio data
344
+ wio_attrs: foxes.utils.Dict
345
+ The windio attributes data
348
346
  idict: foxes.utils.Dict
349
347
  The foxes input data dictionary
350
348
  mbook: foxes.models.ModelBook
@@ -352,15 +350,9 @@ def read_attributes(wio, idict, mbook, verbosity=1):
352
350
  verbosity: int
353
351
  The verbosity level, 0=silent
354
352
 
355
- Returns
356
- -------
357
- odir: pathlib.Path
358
- The output directory
359
-
360
353
  :group: input.yaml.windio
361
354
 
362
355
  """
363
- wio_attrs = Dict(wio["attributes"], name=wio.name + ".attributes")
364
356
  if verbosity > 1:
365
357
  print("Reading attributes")
366
358
  print(" Contents:", [k for k in wio_attrs.keys()])
@@ -368,7 +360,7 @@ def read_attributes(wio, idict, mbook, verbosity=1):
368
360
  # read flow model:
369
361
  if "flow_model" in wio_attrs:
370
362
  flow_model = Dict(wio_attrs["flow_model"], name="flow_model")
371
- fmname = flow_model.pop("name")
363
+ fmname = flow_model.pop_item("name")
372
364
  if verbosity > 2:
373
365
  print(" Reading flow_model")
374
366
  print(" Name:", fmname)
@@ -379,12 +371,3 @@ def read_attributes(wio, idict, mbook, verbosity=1):
379
371
  # read analysis:
380
372
  wio_ana = Dict(wio_attrs["analysis"], name=wio_attrs.name + ".analysis")
381
373
  _read_analysis(wio_ana, idict, mbook, verbosity)
382
-
383
- # outputs:
384
- odict = idict["outputs"]
385
- odir = "."
386
- if "outputs" in wio_attrs:
387
- outputs = Dict(wio_attrs["outputs"], name=wio_attrs.name + ".outputs")
388
- odir = read_outputs(outputs, odict, verbosity=verbosity)
389
-
390
- return odir
@@ -2,7 +2,7 @@ import numpy as np
2
2
  import pandas as pd
3
3
 
4
4
  from foxes.utils import Dict
5
- from foxes.core import Turbine, TurbineType
5
+ from foxes.core import Turbine, TurbineType, WindFarm
6
6
  import foxes.variables as FV
7
7
 
8
8
 
@@ -42,7 +42,7 @@ def read_turbine_types(wio_farm, mbook, ws_exp_P, ws_exp_ct, verbosity):
42
42
 
43
43
  ttypes = {}
44
44
  for k, wio_trbns in wio_farm["turbine_types"].items():
45
- tname = wio_trbns.pop("name")
45
+ tname = wio_trbns.pop_item("name")
46
46
  ttypes[k] = tname
47
47
  _print(" Reading turbine type", k, level=3)
48
48
  _print(" Name:", tname, level=3)
@@ -155,7 +155,7 @@ def read_layout(lname, ldict, farm, ttypes, verbosity=1):
155
155
  if verbosity > 2:
156
156
  print(f" Reading '{lname}'")
157
157
  cdict = Dict(ldict["coordinates"], name="coordinates")
158
- tmap = ldict.get("turbine_types", None)
158
+ tmap = ldict.get_item("turbine_types", None)
159
159
  if verbosity > 2:
160
160
  print(f" Turbine type map:", tmap)
161
161
  for i, xy in enumerate(zip(cdict["x"], cdict["y"])):
@@ -166,3 +166,57 @@ def read_layout(lname, ldict, farm, ttypes, verbosity=1):
166
166
  )
167
167
  if verbosity > 2:
168
168
  print(f" Added {farm.n_turbines} turbines")
169
+
170
+
171
+ def read_farm(wio_dict, mbook, verbosity):
172
+ """
173
+ Reads the wind farm information
174
+
175
+ Parameters
176
+ ----------
177
+ wio_dict: foxes.utils.Dict
178
+ The windio data
179
+ verbosity: int
180
+ The verbosity level, 0=silent
181
+
182
+ Returns
183
+ -------
184
+ farm: foxes.core.WindFarm
185
+ The wind farm
186
+
187
+ :group: input.yaml.windio
188
+
189
+ """
190
+ wio_farm = Dict(wio_dict["wind_farm"], name=wio_dict.name + ".wind_farm")
191
+ if verbosity > 1:
192
+ print("Reading wind farm")
193
+ print(" Name:", wio_farm.pop_item("name", None))
194
+ print(" Contents:", [k for k in wio_farm.keys()])
195
+
196
+ # find REWS exponents:
197
+ try:
198
+ rotor_averaging = wio_dict["attributes"]["analysis"]["rotor_averaging"]
199
+ ws_exp_P = rotor_averaging["wind_speed_exponent_for_power"]
200
+ ws_exp_ct = rotor_averaging["wind_speed_exponent_for_ct"]
201
+ except KeyError:
202
+ ws_exp_P = 1
203
+ ws_exp_ct = 1
204
+
205
+ # read turbine type:
206
+ ttypes = read_turbine_types(wio_farm, mbook, ws_exp_P, ws_exp_ct, verbosity)
207
+
208
+ # read layouts and create wind farm:
209
+ farm = WindFarm()
210
+ wfarm = wio_farm["layouts"]
211
+ if isinstance(wfarm, dict):
212
+ layouts = Dict(wfarm, name=wio_farm.name + ".layouts")
213
+ else:
214
+ layouts = {str(i): l for i, l in enumerate(wfarm)}
215
+ layouts = Dict(layouts, name=wio_farm.name + ".layouts")
216
+ if verbosity > 2:
217
+ print(" Reading layouts")
218
+ print(" Contents:", [k for k in layouts.keys()])
219
+ for lname, ldict in layouts.items():
220
+ read_layout(lname, ldict, farm, ttypes, verbosity)
221
+
222
+ return farm