tesorotools-python 0.0.21__tar.gz → 0.0.22__tar.gz

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.
Files changed (57) hide show
  1. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/PKG-INFO +1 -1
  2. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/pyproject.toml +1 -1
  3. tesorotools_python-0.0.22/tesorotools/artists/__init__.py +9 -0
  4. tesorotools_python-0.0.22/tesorotools/artists/barh.md +109 -0
  5. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/artists/barh_plot.py +169 -7
  6. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/render/content/table.py +13 -3
  7. tesorotools_python-0.0.21/tesorotools/artists/__init__.py +0 -5
  8. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/.gitignore +0 -0
  9. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/__init__.py +0 -0
  10. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/artists/line_plot.py +0 -0
  11. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/artists/table.py +0 -0
  12. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/artists/type_curve.py +0 -0
  13. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/assets/README.md +0 -0
  14. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/assets/fonts/CabinetGrotesk-Black.otf +0 -0
  15. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/assets/fonts/CabinetGrotesk-Bold.otf +0 -0
  16. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/assets/fonts/CabinetGrotesk-Extrabold.otf +0 -0
  17. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/assets/fonts/CabinetGrotesk-Extralight.otf +0 -0
  18. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/assets/fonts/CabinetGrotesk-Light.otf +0 -0
  19. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/assets/fonts/CabinetGrotesk-Medium.otf +0 -0
  20. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/assets/fonts/CabinetGrotesk-Regular.otf +0 -0
  21. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/assets/fonts/CabinetGrotesk-Thin.otf +0 -0
  22. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/assets/fonts/README.md +0 -0
  23. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/assets/plots.yaml +0 -0
  24. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/assets/tesoro.mplstyle +0 -0
  25. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/convert.py +0 -0
  26. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/data_sources/README.md +0 -0
  27. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/data_sources/__init__.py +0 -0
  28. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/data_sources/debug.py +0 -0
  29. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/data_sources/lseg.py +0 -0
  30. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/database/__init__.py +0 -0
  31. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/database/local.py +0 -0
  32. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/database/push.py +0 -0
  33. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/dependencies/__init__.py +0 -0
  34. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/dependencies/functions.py +0 -0
  35. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/dependencies/node.py +0 -0
  36. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/dependencies/resolution.py +0 -0
  37. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/main.py +0 -0
  38. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/offsets/__init__.py +0 -0
  39. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/offsets/offsets.py +0 -0
  40. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/offsets/outliers.py +0 -0
  41. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/render/__init__.py +0 -0
  42. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/render/content/__init__.py +0 -0
  43. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/render/content/content.py +0 -0
  44. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/render/content/images.py +0 -0
  45. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/render/content/section.py +0 -0
  46. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/render/content/subtitle.py +0 -0
  47. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/render/content/text.py +0 -0
  48. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/render/content/title.py +0 -0
  49. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/render/report.py +0 -0
  50. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/utils/__init__.py +0 -0
  51. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/utils/config.py +0 -0
  52. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/utils/format.py +0 -0
  53. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/utils/globals.py +0 -0
  54. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/utils/matplotlib.py +0 -0
  55. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/utils/series.py +0 -0
  56. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/utils/shortcuts.py +0 -0
  57. {tesorotools_python-0.0.21 → tesorotools_python-0.0.22}/tesorotools/utils/template.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tesorotools-python
3
- Version: 0.0.21
3
+ Version: 0.0.22
4
4
  Requires-Python: >=3.13
5
5
  Requires-Dist: babel
6
6
  Requires-Dist: eikon
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "tesorotools-python"
3
3
  requires-python = ">=3.13"
4
- version = "0.0.21"
4
+ version = "0.0.22"
5
5
  dependencies = [
6
6
  "psycopg2",
7
7
  "SQLAlchemy",
@@ -0,0 +1,9 @@
1
+ import matplotlib.style
2
+
3
+ from tesorotools.artists.barh_plot import HorizontalBarChart
4
+ from tesorotools.utils.config import TemplateLoader
5
+
6
+ from ..utils.globals import STYLE_SHEET
7
+
8
+ matplotlib.style.use(STYLE_SHEET)
9
+ TemplateLoader.add_constructor("!barh", HorizontalBarChart.from_yaml)
@@ -0,0 +1,109 @@
1
+ # Especificación de gráficos de barras horizontales
2
+
3
+ En un archivo `.yaml` los gráficos de barras horizontales se especifican con el constructor `!barh`.
4
+
5
+ ## Series y bloques de series
6
+
7
+ Pueden especificarse, o bien *series*, con la entrada `series` o bien *bloques de series* con la entrada `blocks`, pero no ambas a la vez.
8
+
9
+ - Cada serie en la entrada `series` representará una barra en el gráfico final.
10
+ - Los *bloques de series* utilizan para controlar los colores de las barras. Las series dentro de un mismo bloque tendrán el mismo color en el gráfico final.
11
+
12
+ ```yaml
13
+ test_plot1: !barh
14
+ blocks:
15
+ block1:
16
+ label: name_to_be_displayed_1
17
+ series:
18
+ series_name_1: series_name_to_be_displayed_1
19
+ series_name_2: series_name_to_be_displayed_2*
20
+ block2:
21
+ label: name_to_be_displayed_2
22
+ series:
23
+ series_name_3: series_name_to_be_displayed_3
24
+ series_name_4: series_name_to_be_displayed_4
25
+
26
+ test_plot2: !barh
27
+ series:
28
+ series_name_5: series_name_to_be_displayed_5
29
+ series_name_6: series_name_to_be_displayed_6
30
+ ```
31
+
32
+ ### Cómo destacar una serie
33
+ Si añadimos un `*` al nombre de una serie, esta será marcada como destacada en el gráfico. Concretamente, se le añadirá cierta transparencia.
34
+
35
+ ## Qué muestra un gráfico de barras horizontales
36
+
37
+ Un gráfico de barras horizontales puede mostrar hasta dos conjuntos de valores asociados de forma simultánea.
38
+
39
+ - Si $(x_1,...,x_n)$ es un conjunto de valores, un gráfico de barras horizontales presenta estos valores de forma que cada uno de ellos queda asociado a una barra de longitud proporcional a su valor.
40
+ - Este conjunto de valores está representado por una *serie* de *pandas* y suele recibir, internamente, el nombre de `value_series`.
41
+ - Opcionalmente, podemos querer acompañar cada valor (o solo algunos) $x_i$ con otro valor auxiliar $y_i$ para añadir contexto.
42
+ - Estos valores auxiliares $y_i$ se monstrarán con el formato que decidamos, entre paréntesis, al lado del nombre asociado al valor $x_i$, en el eje de ordenadas.
43
+ - Este conjunto de valores está respresentado por una *serie* de *pandas* y suele recibir, internamente, el nombre de `axis_series`.
44
+
45
+ ### Formato del eje *x*
46
+ Para especificar el número de decimales, la escala y las unidades que queremos que se muestren para los valores presentados en forma de barras (nótese que esta configración afectará al aspecto del eje *x*) podemos usar la entrada `format`.
47
+
48
+ ```yaml
49
+ nombre_del_grafico: !barh
50
+ # other stuff
51
+ format:
52
+ decimals: 0
53
+ units: "%"
54
+ scale: 100
55
+
56
+ ```
57
+
58
+ ### Formato de los valores representados en el eje *y*
59
+ Para especificar el número de decimales, la escala y las unidades que queremos que se muestren para los valores auxiliares presentados numéricamente en el eje *y*, podemos usar la entrada `axis_format`.
60
+
61
+ ```yaml
62
+ nombre_del_grafico: !barh
63
+ # other stuff
64
+ axis_format:
65
+ decimals: 2
66
+ units: €
67
+ scale: 1
68
+ ```
69
+
70
+ ### Formato de las anotaciones sobre las barras
71
+ En ocasiones es dificil ver el valor exacto asociado a cada barra, sobre todo cuando no hay muchas marcas en el eje $x$, la rejilla es demasiado clara, o la barra queda muy lejos del eje.
72
+
73
+ Para solventar este problema, podemos, opcionalmente, añadir una anotación al lado de cada una de las barras que indique numéricamente, y con el formato que queramos, el valor asociado a cada una de ellas. Para ello, podemos usar la entrada `annot_format`.
74
+
75
+ ```yaml
76
+ nombre_del_grafico: !barh
77
+ # other stuff
78
+ annot_format:
79
+ decimals: 2
80
+ units: €
81
+ scale: 1
82
+ ```
83
+
84
+ ## Ordenar las barras por longitud
85
+
86
+ Usualmente querremos que las barras del gráfico se muestren ordenadas, para ellos podemos usar la entrada `sorted`, que se tomará como `True` por defecto.
87
+
88
+ - *TO DO*: Quizá aquí sería interesante añadir una entrada `ascending` que indique cómo ordenar las barras en caso de que la entrada `sorted` esté a `True`, y que será ignorada en caso de que `sorted` esté a `False`.
89
+
90
+ ```yaml
91
+ nombre_del_grafico: !barh
92
+ # other stuff
93
+ sorted: True # default
94
+
95
+ ```
96
+
97
+ ## Gráficos de series a partir de *dataframes* con formato *flash*
98
+
99
+ ### Entrada *flash*
100
+
101
+ ```yaml
102
+ nombre_del_gráfico: !barh
103
+ # other stuff
104
+ flash:
105
+ date: # if None takes last date
106
+ deviations: True
107
+ offset: ftd # friday to date
108
+ difference: relative # relative/absolute difference
109
+ ```
@@ -1,15 +1,19 @@
1
+ # Añadir anotaciones de tipos, el objetivo sería eliminar todos los diccionarios con anotaciones del tipo dict[str, Any] que dicen más bien poco
2
+ # Tener cuidado para que nada de lo que está hecho con esta librería deje de funcionar
3
+
1
4
  from enum import Enum
2
5
  from pathlib import Path
3
- from typing import Any
6
+ from typing import Any, Self
4
7
 
5
8
  import matplotlib.pyplot as plt
6
9
  import pandas as pd
7
10
  from matplotlib.container import BarContainer
8
11
  from matplotlib.ticker import FuncFormatter
12
+ from yaml import MappingNode
9
13
 
10
14
  from tesorotools.offsets.offsets import Difference, FloatingOffset, Stat
11
15
  from tesorotools.offsets.outliers import flag_outliers
12
- from tesorotools.utils.globals import DEBUG
16
+ from tesorotools.utils.config import TemplateLoader
13
17
  from tesorotools.utils.matplotlib import (
14
18
  PLOT_CONFIG,
15
19
  format_annotation,
@@ -24,6 +28,8 @@ load_fonts()
24
28
 
25
29
 
26
30
  class Column(Enum):
31
+ """Enumerado usado para dar nombres normalizados a las series que se utilizan internamente en este módulo."""
32
+
27
33
  VALUE = "value"
28
34
  AXIS = "axis"
29
35
  DEVIATION = "deviation"
@@ -39,6 +45,16 @@ def _style_spines(
39
45
  color: str,
40
46
  linewidth: str,
41
47
  ):
48
+ """Estiliza los ejes acorde con la configuración
49
+
50
+ Parameters
51
+ ----------
52
+ ax : plt.Axes
53
+ decimals : int
54
+ units : str
55
+ color : str
56
+ linewidth : str
57
+ """
42
58
  ax.grid(visible=True, axis="x")
43
59
  for spine in ax.spines.values():
44
60
  spine.set_color(color)
@@ -69,6 +85,25 @@ def _style_baseline(ax: plt.Axes, **baseline_config):
69
85
  def _collect_series(
70
86
  blocks: dict[str, Any] | None, series: dict[str, str] | None
71
87
  ) -> dict[str, str]:
88
+ """Devuelve la unión de los diccionarios de series contenidos en los bloques. Si el gráfico no contiene bloques de series, simplemente devuelve su diccionario de series. Si contiene series y bloques (cosa que no debería ocurrir), simplemente ignora los bloques de series y devuelve las series.
89
+
90
+ Parameters
91
+ ----------
92
+ blocks : dict[str, Any] | None
93
+ Diccionario de bloques del gráfico
94
+ series : dict[str, str] | None
95
+ Diccionario de series del gráfico
96
+
97
+ Returns
98
+ -------
99
+ dict[str, str]
100
+ Diccionario de series unificado
101
+
102
+ Raises
103
+ ------
104
+ ValueError
105
+ Si en el gráfico no se especifican ni series ni bloques de series, se lanza una excepción.
106
+ """
72
107
  if series is None and blocks is None:
73
108
  raise ValueError("blocks and series cannot be both missing")
74
109
  if series is None and blocks is not None:
@@ -78,6 +113,18 @@ def _collect_series(
78
113
 
79
114
 
80
115
  def _collect_block_series(blocks: dict[str, Any]) -> dict[str, str]:
116
+ """Devuelve la unión de los diccionarios de series contenidos en los bloques
117
+
118
+ Parameters
119
+ ----------
120
+ blocks : dict[str, Any]
121
+ Diccionario de bloques del gráfico
122
+
123
+ Returns
124
+ -------
125
+ dict[str, str]
126
+ Diccionario de series unificado
127
+ """
81
128
  series = {}
82
129
  for _, block_cfg in blocks.items():
83
130
  series = series | block_cfg["series"]
@@ -87,6 +134,24 @@ def _collect_block_series(blocks: dict[str, Any]) -> dict[str, str]:
87
134
  def _infer_colors(
88
135
  value_series: pd.Series, blocks: dict[str, Any] | None
89
136
  ) -> pd.Series:
137
+ """Si en el gráfico no se especifican bloques de series, se asignará el primer color del tema a los valores positivos y el segundo a los colores negativos.
138
+
139
+ Si, por el contrario, se especifican bloques de series, se asignará un color a cada bloque, con independencia del signo de los valores.
140
+
141
+ Parameters
142
+ ----------
143
+ value_series : pd.Series
144
+ Serie a representar en forma de barras
145
+ blocks : dict[str, Any] | None
146
+ Especificación de los bloques de series del gráfico, o None, en caso de no existir.
147
+
148
+ Returns
149
+ -------
150
+ pd.Series
151
+ Serie de strings del mismo tamaño de la serie a representar, representando cada string un color del tema "C0", "C1", etc
152
+ """
153
+
154
+ # create a series with the same index as the value series and a normalized name
90
155
  color_series: pd.Series = pd.Series(
91
156
  index=value_series.index, name=Column.COLOR.value, dtype=str
92
157
  )
@@ -103,6 +168,21 @@ def _infer_colors(
103
168
  def _highlight_series(
104
169
  alias: dict[str, str], value_series: pd.Series
105
170
  ) -> pd.Series:
171
+ """Asignación de la transparencia de cada una de las barras a representar. Si los nombres de las series no contienen un `*` final se le asigna una opacidad de 1, en caso contrario, se asigna una opacidad específica definida en la variable `BARH_CONFIG["highlight_factor"]`
172
+
173
+ Parameters
174
+ ----------
175
+ alias : dict[str, str]
176
+ Diccionario de renombrado de la serie
177
+ value_series : pd.Series
178
+ Serie de valores a representar como barras
179
+
180
+ Returns
181
+ -------
182
+ pd.Series
183
+ Serie con el mismo tamaño que la serie de valores a representar. Contiene las transparencias asociadas a las barras de cada uno de los valores.
184
+ """
185
+ # create a series with the same index as the value series and a normalized name
106
186
  alpha_series: pd.Series = pd.Series(
107
187
  index=value_series.index, name=Column.ALPHA.value
108
188
  )
@@ -118,15 +198,38 @@ def _format_yaxis(
118
198
  value_series: pd.Series,
119
199
  axis_series: pd.Series | None,
120
200
  ) -> pd.Series:
121
- # format y axis ticker labels
201
+ """Formatea el conjunto de valores auxiliares a ser representado, entre paréntesis, en el eje y.
202
+
203
+ Parameters
204
+ ----------
205
+ alias : dict[str, str]
206
+ Diccionario de renombrado del índice de la serie de valores
207
+ axis_format : dict[str, Any]
208
+ Especificación del formateo a ser aplicado
209
+ value_series : pd.Series
210
+ Serie de valores a ser representados como barras (realmente no estoy muy seguro de que la necesitemos)
211
+ axis_series : pd.Series | None
212
+ Serie de valores a ser representados numéricamente en el eje y
213
+
214
+ Returns
215
+ -------
216
+ pd.Series
217
+ Serie de valores a ser representados como barras, con el índice renombrado de tal forma que incluya en sí mismo los valores a ser representados numéricamente en el eje y
218
+ """
219
+
220
+ # remove the `*` from the series display names (this behabiour may change in the future sin may be interesting to be able to display names with the `*` character)
122
221
  renamer = {_: label.replace("*", "") for _, label in alias.items()}
123
222
  value_series = value_series.rename(renamer)
124
223
  if axis_format is not None:
125
224
  decimals: int = axis_format["decimals"]
126
225
  units: str = axis_format["units"]
226
+
227
+ # rename the index and format the values as specified as strings
127
228
  axis_series: pd.Series = axis_series.rename(renamer).apply(
128
229
  lambda x: format_annotation(x, decimals, units)
129
230
  )
231
+
232
+ # add the formatted value next to the series name, parenthesized
130
233
  value_series = value_series.rename(
131
234
  lambda x: f"{x} ({axis_series.loc[x]})"
132
235
  )
@@ -141,14 +244,30 @@ def _annotate(
141
244
  decimals: int,
142
245
  units: str,
143
246
  ):
144
- # annotate
247
+ """Añade las etiquetas a las barras
248
+
249
+ Parameters
250
+ ----------
251
+ fig : plt.Figure
252
+ Fugura de matplotlib
253
+ ax : plt.Axes
254
+ Axes asociado a la figura de matplotlib
255
+ bar_container : BarContainer
256
+ Contenedor de barras
257
+ decimals : int
258
+ Decimales a mostrar en las anotaciones
259
+ units : str
260
+ Unidades a mostrar en las anotaciones
261
+ """
262
+
263
+ # annotate (just use the default matplotlib capabilities)
145
264
  labels = ax.bar_label(
146
265
  container=bar_container,
147
266
  fmt=lambda x: format_annotation(x, decimals, units),
148
267
  padding=BARH_CONFIG["padding"],
149
268
  )
150
269
 
151
- # rescale
270
+ # rescale (kind of hacky, explanation pending)
152
271
  fig.canvas.draw_idle()
153
272
  for label in labels:
154
273
  bbox = label.get_window_extent()
@@ -176,18 +295,21 @@ def _plot_barh_chart(
176
295
  # format y axis ticker labels
177
296
  axis_series = standard_dict[Column.AXIS]
178
297
  value_series = _format_yaxis(alias, axis_format, value_series, axis_series)
298
+
299
+ # change the index of the other auxiliary series accordingly
179
300
  color_series.index = value_series.index
180
301
  alpha_series.index = value_series.index
181
302
 
303
+ # pack all the necessary data in a single dataframe for convenience
182
304
  data: pd.DataFrame = pd.concat(
183
305
  [value_series, color_series, alpha_series], axis=1
184
306
  )
185
307
 
186
- # sort if required
308
+ # sort if required (here should be added the ascending/descending feature)
187
309
  if sorted:
188
310
  data = data.sort_values(by=Column.VALUE.value)
189
311
 
190
- # plot
312
+ ### actually plot code
191
313
  fig = plt.figure(**FIG_CONFIG)
192
314
  ax = fig.add_subplot()
193
315
 
@@ -308,3 +430,43 @@ def plot_barh_charts_from_flash(
308
430
  )
309
431
  out_file = out_path / f"{name}.png"
310
432
  _plot_barh_chart(out_file, standard_dict, alias, **config)
433
+
434
+
435
+ # estaría bien crear un tipo específico para las entradas en el yaml de tipo formato
436
+
437
+
438
+ class HorizontalBarChart:
439
+
440
+ def __init__(self, alias: dict[str, str], **kwargs):
441
+ # el producto de esto deben ser dos series indexadas con el mismo índice
442
+ self._alias = alias
443
+
444
+ @classmethod
445
+ def from_yaml(cls, loader: TemplateLoader, node: MappingNode) -> Self:
446
+ plot_cfg: dict[str, Any] = loader.construct_mapping(node, deep=True)
447
+ plot_name: str = plot_cfg.pop("id")
448
+ blocks: dict[str, Any] | None = plot_cfg.get("blocks", None)
449
+ series: dict[str, str] | None = plot_cfg.get("series", None)
450
+ axis_format: dict[str, Any] | None = plot_cfg.get("axis_format", None)
451
+
452
+ # maybe here it's not the place to get the aliases, maybe the constructor is a better place
453
+ alias: dict[str, str] = _collect_series(blocks, series)
454
+
455
+ return cls(
456
+ alias,
457
+ **plot_cfg,
458
+ )
459
+
460
+ # this may be an "instance" of a protocol, just check what we did in the render package
461
+ def render(self, out: Path | None = None):
462
+ """Export the plot as an image to the path specified in the argument, or, if missing, to the path specified in the template
463
+
464
+ Parameters
465
+ ----------
466
+ out : Path | None, optional
467
+ Path in which the image will be saved, by default None. If None, the image will be saved in the previously specified path in the yaml template.
468
+ """
469
+ pass
470
+
471
+ def __repr__(self):
472
+ return str(self._alias)
@@ -115,7 +115,7 @@ def _style_index_names(cell: TableCell):
115
115
 
116
116
 
117
117
  def _fill_index_names(
118
- index: pd.Index | pd.MultiIndex, table_docx: TableDocx, horizontal: bool
118
+ index: pd.Index | pd.MultiIndex, table_docx: TableDocx, horizontal: bool, index_name: bool
119
119
  ):
120
120
  start_row: int = 2 if horizontal else 1
121
121
 
@@ -125,6 +125,11 @@ def _fill_index_names(
125
125
  else index.get_level_values(level=1)
126
126
  )
127
127
 
128
+ if index_name:
129
+ cell: TableCell = table_docx.cell(start_row-1, 0)
130
+ cell.text = index.name
131
+
132
+
128
133
  for idx, name in enumerate(index_names, start=start_row):
129
134
  cell: TableCell = table_docx.cell(idx, 0)
130
135
  cell.text = name
@@ -232,7 +237,7 @@ def render_table(
232
237
  _style_table(table_docx)
233
238
  _fill_column_names(table, table_docx, horizontal)
234
239
  _fill_index_names(
235
- index=table.index, table_docx=table_docx, horizontal=horizontal
240
+ index=table.index, table_docx=table_docx, horizontal=horizontal, **kwargs
236
241
  )
237
242
  if block_sep:
238
243
  _separate_blocks(table.index, table_docx)
@@ -252,6 +257,7 @@ class Table:
252
257
  block_sep: bool = False,
253
258
  title: str | None = None,
254
259
  columns: list[str] | None = None,
260
+ index_name: bool = False
255
261
  ):
256
262
  if (
257
263
  (data_file is None)
@@ -276,6 +282,7 @@ class Table:
276
282
 
277
283
  self._title: str | None = title
278
284
  self._block_sep: bool = block_sep
285
+ self._index_name: bool = index_name
279
286
 
280
287
  @classmethod
281
288
  def from_yaml(cls, loader: TemplateLoader, node: MappingNode) -> Self:
@@ -303,7 +310,9 @@ class Table:
303
310
  def render(self, document: Document) -> Document:
304
311
  heading = document.add_heading(self._title, level=2)
305
312
  heading.alignment = CENTER
306
- heading.runs[0].font.size = Pt(10)
313
+
314
+ if len(heading.runs) > 0:
315
+ heading.runs[0].font.size = Pt(10)
307
316
 
308
317
  render_table(
309
318
  self._data,
@@ -311,5 +320,6 @@ class Table:
311
320
  self._shade,
312
321
  document,
313
322
  block_sep=self._block_sep,
323
+ index_name=self._index_name
314
324
  )
315
325
  return document
@@ -1,5 +0,0 @@
1
- import matplotlib.style
2
-
3
- from ..utils.globals import STYLE_SHEET
4
-
5
- matplotlib.style.use(STYLE_SHEET)