"KeyError dimensionless" error message from finam-formind/examples/formind.py
The formind.py script in the examples folder from finam-formind has created the following error message on my system. However there is a workaround by adding "fm.UNITS.define("dimensionless = 1")" after def run(): Please find attached the changed formind.py code with the workaround after the error message.
(base) C:\Users\haeffner\finam-formind>python examples/formind.py
2024-11-26 12:26:24,386 INFO: init composition - FINAM
2024-11-26 12:26:24,391 INFO: validate composition - FINAM
2024-11-26 12:26:24,392 INFO: connect components - FINAM
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
INFO: Default value of the number of simulated plots per hectars is used (switches.Maxplot = 25).
INFO: Default value for the hectar size is used (switches.Hectare = 10000.0).
INFO: Default value for the side length of a hectare is used (switches.Hecside = 100.0).
2024-11-26 12:26:27,305 INFO: validate components - FINAM
2024-11-26 12:26:27,517 INFO: run composition - FINAM
Traceback (most recent call last):
File "C:\Users\haeffner\finam-formind\examples\formind.py", line 125, in <module>
run()
File "C:\Users\haeffner\finam-formind\examples\formind.py", line 121, in run
composition.run(end_time=datetime(2025, 1, 1))
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\finam\schedule.py", line 253, in run
updated = self._update_recursive(to_update)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\finam\schedule.py", line 309, in _update_recursive
module.update()
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\finam\sdk\component.py", line 159, in update
self._update()
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\finam_plot\time_series.py", line 354, in _update
units = f" [{units}]" if units else ""
^^^^^^^
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\pint\facets\plain\unit.py", line 67, in __format__
return self._REGISTRY.formatter.format_unit(self, spec)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\pint\delegates\formatter\full.py", line 137, in format_unit
return self.get_formatter(uspec).format_unit(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\pint\delegates\formatter\_to_register.py", line 104, in format_unit
return func(units, registry=self._registry)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\finam\data\cf_units.py", line 38, in short_formatter
s = f"{unit:~D}"
^^^^^^^^^
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\pint\facets\plain\unit.py", line 67, in __format__
return self._REGISTRY.formatter.format_unit(self, spec)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\pint\delegates\formatter\full.py", line 137, in format_unit
return self.get_formatter(uspec).format_unit(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\pint\delegates\formatter\plain.py", line 90, in format_unit
numerator, denominator = prepare_compount_unit(
^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\pint\delegates\formatter\_compound_unit_helpers.py", line 298, in prepare_compount_unit
numerator = sort_func(numerator, registry)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\pint\delegates\formatter\_compound_unit_helpers.py", line 190, in sort_by_unit_name
return sorted(items, key=lambda el: el[2])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\pint\delegates\formatter\_compound_unit_helpers.py", line 161, in to_symbol_exponent_name
return registry._get_symbol(el[0]), el[1], el[0]
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\haeffner\AppData\Roaming\Python\Python312\site-packages\pint\facets\plain\registry.py", line 708, in _get_symbol
return self._units[name].symbol
~~~~~~~~~~~^^^^^^
File "C:\ProgramData\anaconda3\Lib\collections\__init__.py", line 1015, in __getitem__
return self.__missing__(key) # support subclasses that define __missing__
^^^^^^^^^^^^^^^^^^^^^
File "C:\ProgramData\anaconda3\Lib\collections\__init__.py", line 1007, in __missing__
raise KeyError(key)
KeyError: 'dimensionless'
Workaround formind.py
from datetime import datetime, timedelta
import finam as fm
import numpy as np
# pip install finam_plot
from finam_plot import ImagePlot, StepTimeSeriesPlot
from finam_formind import Formind
def run():
fm.UNITS.define("dimensionless = 1")
start = datetime(2000, 1, 1)
sw_info = fm.Info(
time=start,
grid=fm.UniformGrid(
dims=(4, 5), spacing=(1000, 1000), data_location=fm.Location.POINTS
),
units=fm.UNITS.dimensionless,
)
def soil_water(t):
dt = (t - start).days
v = 40.0 if dt / 365 < 10 else 10.0
return fm.data.full(v, sw_info)
sw_comp = fm.modules.CallbackGenerator(
callbacks={"soil_water": (soil_water, sw_info)},
start=start,
step=timedelta(days=1),
)
formind_comp = Formind(
start_year=start.year,
par_file="examples/formind_parameters/beech_forest.par",
inventory="forest_test.inv",
climate_input=False,
)
soil_props_gen = fm.modules.StaticCallbackGenerator(
callbacks={
"field_capacity": (
lambda: 40.0,
fm.Info(time=None, grid=fm.NoGrid(), units=""),
),
"permanent_wilting_point": (
lambda: 20.0,
fm.Info(time=None, grid=fm.NoGrid(), units=""),
),
},
)
soil_water_csv = fm.modules.CsvWriter(
inputs=["SW"],
path="soil_water.csv",
start=start,
step=timedelta(days=1),
)
formind_plot = StepTimeSeriesPlot(
inputs=["LAI"],
start=start,
step=timedelta(days=365),
)
sw_plot = StepTimeSeriesPlot(
inputs=["SW_in"],
start=start,
step=timedelta(days=365),
)
fm_viewer = ImagePlot(vmin=0.0, vmax=4.0)
composition = fm.Composition(
[
sw_comp,
soil_props_gen,
formind_comp,
soil_water_csv,
formind_plot,
sw_plot,
fm_viewer,
]
)
composition.initialize()
# Model coupling
(sw_comp.outputs["soil_water"] >> formind_comp.inputs["soil_water"])
(
soil_props_gen.outputs["field_capacity"]
>> fm.adapters.ValueToGrid(grid=None)
>> formind_comp.inputs["field_capacity"]
)
(
soil_props_gen.outputs["permanent_wilting_point"]
>> fm.adapters.ValueToGrid(grid=None)
>> formind_comp.inputs["permanent_wilting_point"]
)
(
sw_comp.outputs["soil_water"]
>> fm.adapters.GridToValue(func=np.ma.mean)
>> soil_water_csv.inputs["SW"]
)
(
sw_comp.outputs["soil_water"]
>> fm.adapters.GridToValue(func=np.ma.mean)
>> fm.adapters.AvgOverTime()
>> sw_plot.inputs["SW_in"]
)
(
formind_comp.outputs["LAI"]
>> fm.adapters.GridToValue(func=np.ma.mean)
>> fm.adapters.LinearTime()
>> formind_plot.inputs["LAI"]
)
_ = formind_comp.outputs["LAI"] >> fm_viewer.inputs["Grid"]
composition.connect(start_time=start)
composition.run(end_time=datetime(2025, 1, 1))
if __name__ == "__main__":
run()