Skip to content

Commit

Permalink
Add param default and type to math docs (#690)
Browse files Browse the repository at this point in the history
  • Loading branch information
brynpickering authored Sep 30, 2024
1 parent e447d17 commit 99e5211
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

### User-facing changes

|new| (non-NaN) Default values and data types for parameters appear in math documentation (if they appear in the model definition schema) (#677).

|changed| `data_sources` -> `data_tables` and `data_sources.source` -> `data_tables.data`.
This change has occurred to avoid confusion between data "sources" and model energy "sources" (#673).

Expand Down
2 changes: 2 additions & 0 deletions src/calliope/backend/backend_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class BackendModelGenerator(ABC):
"description",
"unit",
"default",
"type",
"title",
"math_repr",
"original_dtype",
Expand All @@ -74,6 +75,7 @@ class BackendModelGenerator(ABC):
_PARAM_TITLES = extract_from_schema(MODEL_SCHEMA, "title")
_PARAM_DESCRIPTIONS = extract_from_schema(MODEL_SCHEMA, "description")
_PARAM_UNITS = extract_from_schema(MODEL_SCHEMA, "x-unit")
_PARAM_TYPE = extract_from_schema(MODEL_SCHEMA, "x-type")

def __init__(self, inputs: xr.Dataset, **kwargs):
"""Abstract base class to build a representation of the optimisation problem.
Expand Down
25 changes: 21 additions & 4 deletions src/calliope/backend/latex_backend_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import jinja2
import numpy as np
import pandas as pd
import xarray as xr

from calliope.backend import backend_model, parsing
Expand Down Expand Up @@ -224,6 +225,10 @@ class LatexBackendModel(backend_model.BackendModelGenerator):
**Default**: {{ equation.default }}
{% endif %}
{% if equation.type is not none %}
**Type**: {{ equation.type }}
{% endif %}
{% if equation.expression != "" %}
.. container:: scrolling-wrapper
Expand Down Expand Up @@ -299,6 +304,10 @@ class LatexBackendModel(backend_model.BackendModelGenerator):
\textbf{Default}: {{ equation.default }}
{% endif %}
{% if equation.type is not none %}
\textbf{Type}: {{ equation.type }}
{% endif %}
{% if equation.expression != "" %}
\begin{equation}
Expand Down Expand Up @@ -371,6 +380,10 @@ class LatexBackendModel(backend_model.BackendModelGenerator):
**Default**: {{ equation.default }}
{% endif %}
{% if equation.type is not none %}
**Type**: {{ equation.type }}
{% endif %}
{% if equation.expression != "" %}
{% if mkdocs_features and yaml_snippet is not none%}
Expand Down Expand Up @@ -421,14 +434,17 @@ def add_parameter( # noqa: D102, override
"title": self._PARAM_TITLES.get(parameter_name, None),
"description": self._PARAM_DESCRIPTIONS.get(parameter_name, None),
"unit": self._PARAM_UNITS.get(parameter_name, None),
"type": self._PARAM_TYPE.get(parameter_name, None),
"math_repr": rf"\textit{{{parameter_name}}}"
+ self._dims_to_var_string(parameter_values),
}
if pd.notna(default):
attrs["default"] = default

self._add_to_dataset(parameter_name, parameter_values, "parameters", attrs)

def add_constraint( # noqa: D102, override
self, name: str, constraint_dict: parsing.UnparsedConstraint | None = None
self, name: str, constraint_dict: parsing.UnparsedConstraint
) -> None:
equation_strings: list = []

Expand Down Expand Up @@ -488,7 +504,7 @@ def _constraint_setter(where: xr.DataArray, references: set) -> xr.DataArray:
)

def add_global_expression( # noqa: D102, override
self, name: str, expression_dict: parsing.UnparsedExpression | None = None
self, name: str, expression_dict: parsing.UnparsedExpression
) -> None:
equation_strings: list = []

Expand All @@ -515,7 +531,7 @@ def _expression_setter(
)

def add_variable( # noqa: D102, override
self, name: str, variable_dict: parsing.UnparsedVariable | None = None
self, name: str, variable_dict: parsing.UnparsedVariable
) -> None:
domain_dict = {"real": r"\mathbb{R}\;", "integer": r"\mathbb{Z}\;"}
bound_refs: set = set()
Expand Down Expand Up @@ -544,7 +560,7 @@ def _variable_setter(where: xr.DataArray, references: set) -> xr.DataArray:
)

def add_objective( # noqa: D102, override
self, name: str, objective_dict: parsing.UnparsedObjective | None = None
self, name: str, objective_dict: parsing.UnparsedObjective
) -> None:
sense_dict = {
"minimize": r"\min{}",
Expand Down Expand Up @@ -623,6 +639,7 @@ def generate_math_doc(
),
"uses": sorted(list(uses[name] - set([name]))),
"default": da.attrs.get("default", None),
"type": da.attrs.get("type", None),
"unit": da.attrs.get("unit", None),
"yaml_snippet": da.attrs.get("yaml_snippet", None),
}
Expand Down
4 changes: 4 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,9 +289,13 @@ def dummy_model_data(config_defaults, model_defaults):
"all_nan": np.nan,
"with_inf": 100,
"only_techs": 5,
"no_dims": 0,
**model_defaults,
}
)
# This value is set on the parameter directly to ensure it finds its way through to the LaTex math.
model_data.no_dims.attrs["default"] = 0

model_data.attrs["math"] = AttrDict(
{"constraints": {}, "variables": {}, "global_expressions": {}, "objectives": {}}
)
Expand Down
58 changes: 58 additions & 0 deletions tests/test_backend_latex_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@ def test_create_obj_list(self, dummy_latex_backend_model):
\begin{itemize}
\item expr
\end{itemize}
\textbf{Default}: 0
\end{document}"""
),
),
Expand Down Expand Up @@ -421,6 +423,8 @@ def test_create_obj_list(self, dummy_latex_backend_model):
**Used in**:
* expr
**Default**: 0
"""
),
),
Expand Down Expand Up @@ -454,6 +458,8 @@ def test_create_obj_list(self, dummy_latex_backend_model):
**Used in**:
* [expr](#expr)
**Default**: 0
"""
),
),
Expand Down Expand Up @@ -589,6 +595,8 @@ def test_generate_math_doc_mkdocs_features_admonition(self, dummy_model_data):
??? info "Used in"
* [expr](#expr)
**Default**: 0
"""
)

Expand Down Expand Up @@ -709,3 +717,53 @@ def test_get_variable_bounds_string(self, dummy_latex_backend_model):
"expression": r"\textbf{multi_dim_var}_\text{node,tech} \leq 2\mathord{\times}10^{+06}"
}
assert refs == {"multi_dim_var"}

def test_param_type(self, dummy_model_data):
backend_model = latex_backend_model.LatexBackendModel(dummy_model_data)
backend_model.add_global_expression(
"expr",
{
"equations": [{"expression": "1 + flow_cap_max"}],
"description": "foobar",
"default": 0,
},
)
doc = backend_model.generate_math_doc(format="md")
assert doc == textwrap.dedent(
r"""
## Where
### expr
foobar
**Uses**:
* [flow_cap_max](#flow_cap_max)
**Default**: 0
$$
\begin{array}{l}
\quad 1 + \textit{flow\_cap\_max}\\
\end{array}
$$
## Parameters
### flow_cap_max
Limits `flow_cap` to a maximum.
**Used in**:
* [expr](#expr)
**Unit**: power.
**Default**: inf
**Type**: float
"""
)

0 comments on commit 99e5211

Please sign in to comment.