KI-Inst-design-template 0.0.3__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.
@@ -0,0 +1,403 @@
1
+ import matplotlib.pyplot as plt
2
+ from cycler import cycler
3
+ import os
4
+ import matplotlib.image as mpimg
5
+ import matplotlib.transforms as transform
6
+ import textwrap
7
+ from pathlib import Path
8
+ from matplotlib import font_manager
9
+ import warnings
10
+ import sys
11
+ from importlib.resources import files
12
+
13
+ # Add Suisse Fonts
14
+ user_home = os.path.expanduser("~")
15
+ search_dirs = []
16
+
17
+ if sys.platform.startswith("win"):
18
+ search_dirs = [
19
+ os.path.join(os.getenv('LOCALAPPDATA'), "Microsoft", "Windows", "Fonts"),
20
+ r"C:\Windows\Fonts"
21
+ ]
22
+ elif sys.platform.startswith("linux"):
23
+ search_dirs = [
24
+ os.path.join(user_home, ".local", "share", "fonts"),
25
+ os.path.join(user_home, ".fonts"),
26
+ "/usr/share/fonts"
27
+ ]
28
+ elif sys.platform == "darwin":
29
+ search_dirs = [
30
+ os.path.join(user_home, "Library", "Fonts"),
31
+ "/Library/Fonts",
32
+ "/System/Library/Fonts"
33
+ ]
34
+
35
+ def find_path(filename):
36
+ for d in search_dirs:
37
+ p = Path(d)
38
+ if p.exists():
39
+ # rglob handles nested folders (Linux) and flats (Windows)
40
+ matches = list(p.rglob(filename))
41
+ if matches: return matches[0]
42
+ return Path(filename) # Fallback to current dir
43
+
44
+ intl_medium_path = find_path("SuisseIntl-Medium.ttf")
45
+ mono_regular_path = find_path("SuisseIntlMono-Regular.ttf")
46
+ intl_regular_path = find_path("SuisseIntl-Regular.ttf")
47
+
48
+ intl_medium_font_big = font_manager.FontProperties(fname=intl_medium_path, size=15)
49
+ intl_medium_font_small = font_manager.FontProperties(fname=intl_medium_path, size=7)
50
+ mono_regular_font = font_manager.FontProperties(fname=mono_regular_path, size=5)
51
+ intl_regular_font = font_manager.FontProperties(fname=intl_regular_path, size=7)
52
+
53
+ # === Kiel Institute COLOR PALETTE ===================
54
+
55
+ KIEL_BRAND_COLORS = {
56
+ "kiel_blue": "#194ABB",
57
+ "kiel_orange": "#FF6A00",
58
+ }
59
+
60
+ KIEL_BLUE_TINTS = {
61
+ "kiel_blue_80": "#4169C3",
62
+ "kiel_blue_60": "#9BADD5",
63
+ "kiel_blue_40": "#C8CFDE",
64
+ "kiel_blue_20": "#DFE0E3"
65
+ }
66
+
67
+ KIEL_ORANGE_TINTS = {
68
+ "kiel_orange_80": "#FAAE74",
69
+ "kiel_orange_60": "#F7CFAD",
70
+ "kiel_orange_40": "#F6E0CA",
71
+ "kiel_orange_20": "#F6E9D9"
72
+ }
73
+
74
+ KIEL_BLUE_SPECTRUM = {
75
+ "kiel_blue_01": "#304DC3",
76
+ "kiel_blue_02": "#43A1FF",
77
+ "kiel_blue_03": "#32C2FF",
78
+ "kiel_blue_04": "#3083C3",
79
+ "kiel_blue_05": "#43D9FF",
80
+ "kiel_blue_06": "#43F2FF",
81
+ "kiel_blue_07": "#1B48FF",
82
+ "kiel_blue_08": "#2E89FF",
83
+ "kiel_blue_09": "#4372FF",
84
+ "kiel_blue_10": "#0032FF",
85
+ "kiel_blue_11": "#007FFF",
86
+ "kiel_blue_12": "#00CCFF"
87
+ }
88
+
89
+ KIEL_SECONDARY_COLORS = {
90
+ "kiel_red": "#CC3333",
91
+ "kiel_green": "#33CC3D",
92
+ "kiel_turquoise": "#33C9CC",
93
+ "kiel_purple": "#7033CC",
94
+ "kiel_pink": "#CC339C"
95
+ }
96
+
97
+ # Create a single master dictionary for lookup
98
+ KIEL_COLORS = {
99
+ **KIEL_BRAND_COLORS,
100
+ **KIEL_BLUE_TINTS,
101
+ **KIEL_ORANGE_TINTS,
102
+ **KIEL_BLUE_SPECTRUM,
103
+ **KIEL_SECONDARY_COLORS
104
+ }
105
+
106
+ # Define the default order for the matplotlib cycler
107
+ DEFAULT_COLOR_ORDER = [
108
+ "kiel_blue",
109
+ "kiel_orange",
110
+ "kiel_turquoise",
111
+ "kiel_red",
112
+ "kiel_green",
113
+ "kiel_purple",
114
+ "kiel_pink"
115
+ ]
116
+
117
+ def show_kiel_institute_colors():
118
+ """
119
+ Displays all available Kiel Institute color palettes in a plot.
120
+ """
121
+ palettes = {
122
+ "Brand Colors": KIEL_BRAND_COLORS,
123
+ "Blue Tints": KIEL_BLUE_TINTS,
124
+ "Orange Tints": KIEL_ORANGE_TINTS,
125
+ "Blue Spectrum": KIEL_BLUE_SPECTRUM,
126
+ "Secondary Colors": KIEL_SECONDARY_COLORS,
127
+ }
128
+
129
+ # Use the theme's font settings if available
130
+
131
+ fig, axs = plt.subplots(nrows=len(palettes), figsize=(12, len(palettes) * 1.4),
132
+ constrained_layout=True)
133
+ fig.suptitle('Kiel Institute Color Pallette',
134
+ fontproperties=intl_medium_font_big) # Title
135
+
136
+ for i, (title, colors) in enumerate(palettes.items()):
137
+ ax = axs[i]
138
+ n = len(colors)
139
+ ax.set_title(title, loc='left', fontproperties=intl_medium_font_big) # Palette titles
140
+
141
+ for j, (name, hex_code) in enumerate(colors.items()):
142
+ # Add color patch
143
+ ax.add_patch(plt.Rectangle((j, 0.3), 1, 0.7, color=hex_code))
144
+ # Add name
145
+ ax.text(j + 0.5, 0.15, name, ha='center', va='top',
146
+ fontproperties=intl_medium_font_small) # Names
147
+ # Add hex code
148
+ ax.text(j + 0.5, 0.0, hex_code, ha='center', va='top',
149
+ fontproperties=mono_regular_font) # Hex
150
+
151
+ ax.set_xlim(0, n)
152
+ ax.set_ylim(0, 1)
153
+ ax.axis('off')
154
+
155
+ plt.show()
156
+
157
+ def palette_kiel_institute(color_names=None, n=None):
158
+ """
159
+ Returns a list of hex codes from the Kiel Institute palette.
160
+
161
+ Args:
162
+ color_names (list, optional):
163
+ A list of color names (e.g., ["blue", "red", "blau_01"]).
164
+ If None, uses the DEFAULT_COLOR_ORDER.
165
+ n (int, optional):
166
+ The total number of colors desired. If n is greater than
167
+ the number of colors in the list, the list will be repeated.
168
+ """
169
+ base_colors_hex = []
170
+
171
+ if color_names is None:
172
+ base_colors_hex = [KIEL_COLORS[name] for name in DEFAULT_COLOR_ORDER]
173
+ else:
174
+ for name in color_names:
175
+ hex_code = KIEL_COLORS.get(name)
176
+ if hex_code:
177
+ base_colors_hex.append(hex_code)
178
+ else:
179
+ print(f"Warning: Color '{name}' not in KIEL_COLORS. Skipping.")
180
+
181
+ if not base_colors_hex:
182
+ print("Error: No valid colors specified. Returning default blue.")
183
+ base_colors_hex = [KIEL_COLORS["blue"]]
184
+
185
+ if n is None:
186
+ return base_colors_hex
187
+ else:
188
+ repeats = (n + len(base_colors_hex) - 1) // len(base_colors_hex)
189
+ return (base_colors_hex * repeats)[:n]
190
+
191
+
192
+ # === Kiel Institute MATPLOTLIB THEME ==========================================
193
+
194
+ def init_kiel_institute_theme():
195
+ """
196
+ Apply the Kiel Institute theme to matplotlib globally.
197
+ """
198
+ print("Applying Kiel Institute visual theme for matplotlib...")
199
+
200
+ BG_COLOR = "#F5F1E7"
201
+ TEXT_COLOR = "#000000"
202
+
203
+ font_manager.fontManager.addfont(mono_regular_path)
204
+ prop = font_manager.FontProperties(fname=mono_regular_path)
205
+ FONT = prop.get_name()
206
+
207
+ plt.rcParams.update({
208
+ # --- Figure ---
209
+ "figure.facecolor": BG_COLOR,
210
+ "figure.figsize": (8, 6),
211
+ "figure.autolayout": False,
212
+
213
+ # --- Colors & grids ---
214
+ "axes.prop_cycle": cycler(color=palette_kiel_institute()),
215
+ "axes.facecolor": BG_COLOR,
216
+ "axes.edgecolor": TEXT_COLOR,
217
+ "axes.grid": True,
218
+ "grid.color": TEXT_COLOR,
219
+ "grid.linestyle": "-",
220
+ "grid.linewidth": 0.5,
221
+
222
+ # --- Spines ---
223
+ "axes.spines.top": False,
224
+ "axes.spines.right": False,
225
+ "axes.spines.left": True,
226
+ "axes.spines.bottom": True,
227
+
228
+ # --- Fonts & text ---
229
+ "font.family": FONT, # Default for all text
230
+ "font.size": 15,
231
+ "text.color": TEXT_COLOR,
232
+
233
+ # --- CHANGE ---
234
+ # Set plot titles and labels to bold
235
+ # They will use the default font
236
+ "axes.titleweight": "bold",
237
+ "axes.labelweight": "bold",
238
+
239
+ "axes.titlesize": 15,
240
+ "axes.titlecolor": TEXT_COLOR,
241
+ "axes.labelsize": 15,
242
+ "axes.labelcolor": TEXT_COLOR,
243
+ "xtick.color": TEXT_COLOR,
244
+ "ytick.color": TEXT_COLOR,
245
+ "xtick.labelsize": 15,
246
+ "ytick.labelsize": 15,
247
+
248
+ # --- Lines & markers ---
249
+ "lines.linewidth": 2,
250
+ "lines.markersize": 6,
251
+
252
+ # --- Legend ---
253
+ "legend.frameon": True,
254
+ "legend.framealpha": 1.0,
255
+ "legend.edgecolor": TEXT_COLOR,
256
+ "legend.facecolor": BG_COLOR,
257
+ "legend.loc": "best",
258
+ "legend.fancybox": False,
259
+
260
+ # --- Save settings ---
261
+ "savefig.facecolor": BG_COLOR,
262
+ "savefig.dpi": 150
263
+ })
264
+
265
+ print("Kiel Institute matplotlib theme applied successfully.")
266
+
267
+
268
+ # === OPTIONAL: SAVE FUNCTION WITH HEADER/FOOTER ============================
269
+
270
+ def save_kiel_institute(fig, ax, filename, title, source, logo="KIEL Wortbildmarke black.png", subtitle=None, description=None,
271
+ footer=None, grid="horizontal", figsize=(2000, 2182)):
272
+ """
273
+ Save a matplotlib figure with Kiel Institute-style header, footer, and logo.
274
+ """
275
+ print(f"Saving Kiel Institute-styled figure: {filename}...")
276
+
277
+ fig.set_size_inches(max(figsize[0],2000)/150,max(figsize[1],2182)/150)
278
+ ax.set_axisbelow(True)
279
+
280
+ font_manager.fontManager.addfont(intl_medium_path)
281
+ prop_title = font_manager.FontProperties(fname=intl_medium_path)
282
+ FONT_DEFAULT = prop_title.get_name() # Font for the title, subtitle and source
283
+ font_manager.fontManager.addfont(mono_regular_path)
284
+ prop_footer = font_manager.FontProperties(fname=mono_regular_path)
285
+ FONT_FOOTER = prop_footer.get_name() # Font for the footer
286
+ font_manager.fontManager.addfont(intl_regular_path)
287
+ prop_desc = font_manager.FontProperties(fname=intl_regular_path)
288
+ FONT_DESCRIPTION = prop_desc.get_name() # Font for the description
289
+
290
+ fig.patch.set_facecolor("#F5F1E7")
291
+
292
+ if grid=="vertical":
293
+ ax.grid(visible=False, axis="y")
294
+ else:
295
+ ax.grid(visible=False, axis="x")
296
+
297
+ transform_title = transform.offset_copy( #Set the location of the title
298
+ fig.transFigure, fig= fig,
299
+ x = 0.9*72,
300
+ y = -0.9*72,
301
+ units="points"
302
+ )
303
+ wrapped_title = textwrap.fill(title, width=int(fig.get_figwidth() * 2.85))
304
+ title = fig.text(0, 1, wrapped_title, ha="left", va="top",
305
+ fontsize=45, color="#000000",
306
+ family=FONT_DEFAULT,fontweight="bold", transform=transform_title)
307
+
308
+ fig.canvas.draw()
309
+ title_box = title.get_window_extent()
310
+ title_box_percent = title_box.transformed(fig.transFigure.inverted())
311
+
312
+ if subtitle:
313
+ transform_subtitle = transform.offset_copy(
314
+ fig.transFigure, fig= fig,
315
+ x = 0.9*72,
316
+ y = (title_box.y0/fig.dpi)*72 - 0.15748*72,
317
+ units="points"
318
+ )
319
+ wrapped_subtitle = textwrap.fill(subtitle, width=int(fig.get_figwidth() * 6.0))
320
+ subtitle = fig.text(0, 0, wrapped_subtitle, ha="left", va="top",
321
+ fontsize=21, color="#000000",
322
+ family=FONT_DEFAULT, fontweight="bold", transform=transform_subtitle)
323
+ fig.canvas.draw()
324
+ subtitle_box = subtitle.get_window_extent()
325
+ subtitle_box_percent = subtitle_box.transformed(fig.transFigure.inverted())
326
+
327
+ if footer:
328
+ transform_footer = transform.offset_copy(
329
+ fig.transFigure, fig= fig,
330
+ x = -0.9*72,
331
+ y = 0.9*72,
332
+ units="points"
333
+ )
334
+ footer = fig.text(1, 0, footer, ha="right", va="bottom",
335
+ color="#000000", fontsize=15,
336
+ family=FONT_FOOTER, transform=transform_footer)
337
+ fig.canvas.draw()
338
+ footer_box = footer.get_window_extent()
339
+
340
+ transform_source = transform.offset_copy(
341
+ fig.transFigure, fig= fig,
342
+ x = 0.9*72,
343
+ y = 0.9*72,
344
+ units="points"
345
+ )
346
+
347
+ if footer:
348
+ max_width = min(int(fig.get_figwidth() * 4.35),int(((footer_box.x0 / fig.dpi) - 0.9) * (130/21)))
349
+ if max_width <= 0:
350
+ print("Error: The footer is too long! Please use a shorter footer or adjust figure width.")
351
+ return
352
+ wrapped_source = textwrap.fill(source,width=max_width)
353
+ else:
354
+ wrapped_source = textwrap.fill(source,width=int(fig.get_figwidth() * 4.35))
355
+ source = fig.text(0, 0, wrapped_source, ha="left", va="bottom",
356
+ fontsize=21, color="#000000",
357
+ family=FONT_DEFAULT, fontweight="bold", transform=transform_source)
358
+ fig.canvas.draw()
359
+ source_box = source.get_window_extent()
360
+
361
+
362
+ logo = str(files("KI_Inst_design_template").joinpath(logo))
363
+ logo = mpimg.imread(logo)
364
+ if footer:
365
+ ax_logo = fig.add_axes([0.73, 0.02, 0.21, 0.21], zorder=10)
366
+ else:
367
+ ax_logo = fig.add_axes([0.73, -0.01, 0.21, 0.21], zorder=10)
368
+ ax_logo.imshow(logo)
369
+ ax_logo.axis("off")
370
+ logo_percent = ax_logo.get_position()
371
+
372
+
373
+ if description:
374
+ transform_description = transform.offset_copy(
375
+ fig.transFigure, fig= fig,
376
+ x = 0.9*72,
377
+ y = (source_box.y1/fig.dpi)*72 + 0.9*72,
378
+ units="points"
379
+ )
380
+ wrapped_description = textwrap.fill(description, width=int(fig.get_figwidth() * 4.35))
381
+ description = fig.text(0, 0, wrapped_description, ha="left", va="bottom",
382
+ color="#000000", fontsize=21,
383
+ family=FONT_DESCRIPTION, transform=transform_description)
384
+ fig.canvas.draw()
385
+ description_box = description.get_window_extent()
386
+ description_box_percent = description_box.transformed(fig.transFigure.inverted())
387
+
388
+ if description:
389
+ bottom_gap = description_box_percent.y1 + 0.04
390
+ else:
391
+ bottom_gap = logo_percent.y1 + 0.01
392
+ if subtitle:
393
+ top_gap = (subtitle_box_percent.y0-0.04)
394
+ else:
395
+ top_gap = (title_box_percent.y0-0.04)
396
+
397
+ with warnings.catch_warnings():
398
+ warnings.simplefilter("ignore", UserWarning)
399
+ fig.tight_layout(rect=[0.05, bottom_gap, 0.95, top_gap])
400
+
401
+ fig.savefig(filename, dpi=150, facecolor="#F5F1E7")
402
+ print(f"Saved {filename}")
403
+ plt.close(fig)
@@ -0,0 +1 @@
1
+ from .KI_Inst_design_template import show_kiel_institute_colors, init_kiel_institute_theme, save_kiel_institute, KIEL_COLORS, DEFAULT_COLOR_ORDER
@@ -0,0 +1,185 @@
1
+ Metadata-Version: 2.1
2
+ Name: KI_Inst_design_template
3
+ Version: 0.0.3
4
+ Summary: First upload of this package
5
+ Project-URL: Homepage, https://github.com/kielinstitute/kielinstitutPython
6
+ Project-URL: Issues, https://github.com/kielinstitute/kielinstitutPython/issues
7
+ Author-email: Florian Ivan Hinrichsen <florian.hinrichsen@ifw-kiel.de>
8
+ License: All Rights Reserved
9
+
10
+ Copyright (c) 2025 Kiel Institute for the World Economy
11
+
12
+ 1. RESTRICTIONS
13
+ The content of this software is proprietary and confidential. Unauthorized copying, transfer, or use of this file, via any medium, is strictly prohibited, except as explicitly granted below.
14
+
15
+ 2. GRANT OF LICENSE
16
+ Permission is hereby granted, free of charge, to all members of the Kiel Institute for the World Economy to deal in the Software without restriction, including the rights to use, copy, and modify copies of the Software.
17
+
18
+ For all other parties, no rights are granted.
19
+
20
+ 3. DISCLAIMER OF WARRANTY
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28
+ THE SOFTWARE.
29
+ Classifier: Operating System :: OS Independent
30
+ Classifier: Programming Language :: Python :: 3
31
+ Requires-Python: >=3.10
32
+ Description-Content-Type: text/markdown
33
+
34
+ # Kiel Institute Design Template
35
+ This Design Template allows you to automatically apply the corporate design of the Kiel Institute for the World Economy to Matplotlib charts. It handles custom fonts, specific color palettes, and layout requirements to ensure that visualizations are publication-ready.
36
+
37
+ ## Prerequisites
38
+ To use this module effectively, you need to ensure that the following files and libraries are installed.
39
+
40
+ ### 1. Python Libraries
41
+ This module requires matplotlib and cycler. If you do not have them installed, run the following command into the terminal or command prompt:
42
+
43
+ ```bash
44
+ pip install matplotlib
45
+ ```
46
+
47
+ Usually the cycler module is included in matplotlib. If it wasn't installed in the previous step run the following command aswell:
48
+
49
+ ```bash
50
+ pip install cycler
51
+ ```
52
+
53
+ ### 2. Font Files
54
+ The Kiel Institute fonts are all from the 'Suisse' font familly. Usually the required fonts should be preinstalled on all Kiel Institute devices. If that is not the case, or if you are using your own device, please install the 'Suisse' fontkit.
55
+
56
+ ### 3. Python Version
57
+ It is recomended that you use Python 3.11 for this template. For newer or older versions functionality is not guaranteed.
58
+
59
+ ## Installation
60
+ Type the following command into the terminal or command prompt:
61
+
62
+ ```bash
63
+ pip install KI_Inst_design_template
64
+ ```
65
+
66
+ ## Functionalities
67
+ This template has three functionalities, that will be introduced and shortly explained in the following.
68
+
69
+ ### 1. Show Kiel Colours
70
+ The Colour Pallette of the Kiel Institute Brand Colours can be displayed by calling the show_kiel_institute_colors()-function in a python script:
71
+ ```python
72
+ from KI_Inst_design_template import show_kiel_institute_colors
73
+
74
+ show_kiel_institute_colors()
75
+ ```
76
+
77
+ This opens a window, where the available colors and the names by which they can be accessed are displayed, aswell as their corresponding HEX-codes.
78
+
79
+ ### 2. Initialize Design Template
80
+ The corparate design of the Kiel Institute can be applied globally to matplotlib, by calling the init_kiel_institute_theme-function:
81
+
82
+ ```python
83
+ from KI_Inst_design_template import init_kiel_institute_theme
84
+
85
+ init_kiel_institute_theme()
86
+ ```
87
+
88
+ This applies the visual theme of the Kiel Institute to your plot.
89
+
90
+ ### 3. Save charts in a file
91
+ Figures generated with Matplotlib can be saved in full compliance with the Kiel Institute's official layout guidelines:
92
+
93
+ ```python
94
+ from KI_Inst_design_template import save_kiel_institute
95
+ import matplotlib as plt
96
+ import pandas as pd
97
+
98
+ save_kiel_institute(fig, ax, filename, title, source, subtitle, description,
99
+ footer, "vertical")
100
+ ```
101
+
102
+ It is required, that a ==filename==, ==title== and ==source== are passed to the function as arguments in addition to the ==figure== (fig) and ==axes== (ax) objects. Specifying the other arguments is optional.
103
+
104
+ ## Example Usage
105
+ This is an example usage of the template with data form the [GREIX](https://greix.de):
106
+
107
+ ```python
108
+ from KI_Inst_design_template import *
109
+ import matplotlib.pyplot as plt
110
+ import pandas as pd
111
+
112
+ show_kiel_institute_colors()
113
+
114
+ init_kiel_institute_theme()
115
+
116
+ df = pd.read_csv("Mietpreisindex_jährlich.csv", sep=";")
117
+ df_real = df[df['real_nominal_str'] == 'Real']
118
+
119
+ # Define a specific color map for the cities using the "KIEL_COLORS" variables
120
+ # This ensures consistent branding/coloring across charts
121
+ city_color_map = {
122
+ "Berlin": KIEL_COLORS["kiel_blue"],
123
+ "Aachen": KIEL_COLORS["kiel_orange"],
124
+ "Düsseldorf": KIEL_COLORS["kiel_green"],
125
+ "München": KIEL_COLORS["kiel_red"],
126
+ "Hamburg": KIEL_COLORS["kiel_turquoise"],
127
+ "Kiel": KIEL_COLORS["kiel_pink"],
128
+ "Köln": KIEL_COLORS["kiel_purple"]
129
+ }
130
+ cities = list(city_color_map.keys())
131
+
132
+ df_filtered = df_real[df_real['Value-Column Titles'].isin(cities)]
133
+ df_filtered_pivot = df_filtered.pivot(index='Year', columns='Value-Column Titles', values='Values')
134
+
135
+ # Initialize the figure and axis for the line plot
136
+ fig, ax = plt.subplots()
137
+
138
+ # Plot the time-series data on the axis using the specific colors defined earlier
139
+ df_filtered_pivot.plot(ax=ax, color=city_color_map)
140
+
141
+ df_filtered_bar = df[df["Year"]==2024]
142
+ df_filtered_bar = df_filtered_bar[df_filtered_bar["Value-Column Titles"].isin(cities)]
143
+ df_pivot_bar = df_filtered_bar.pivot(index="Value-Column Titles", columns="real_nominal_str",values="Values")
144
+
145
+ # Initialize the figure and axis for the bar plot
146
+ fig_bar, ax_bar = plt.subplots()
147
+
148
+ # Plot the "Nominal" and "Real" data on top of each other and specify the coloring using "KIEL_COLORS"
149
+ b1 = ax_bar.bar(df_pivot_bar.index,df_pivot_bar["Real"], label="Real Index", color=KIEL_COLORS["kiel_blue"])
150
+ b1 = ax_bar.bar(df_pivot_bar.index,df_pivot_bar["Nominal"], bottom=df_pivot_bar["Real"], label="Nominal Index", color=KIEL_COLORS["kiel_blue_60"])
151
+
152
+ # Add a legend to the bar chart if it isn't done automatically
153
+ ax_bar.legend()
154
+
155
+ # Use the save_kiel_institute function to save the charts in a .png file
156
+
157
+ save_kiel_institute(
158
+ fig_bar,
159
+ ax_bar,
160
+ "bar_plott.png",
161
+ title="Rental Price Index: Nominal vs. Real",
162
+ subtitle="subtitle subtitle subtitle subtitle subtitle subtitle subtitle",
163
+ source="kielinstitut.de",
164
+ description="description description description description description description description description" \
165
+ " description description description description description description description description description description",
166
+ footer="footer footer footer footer footer footer footer"
167
+ )
168
+
169
+ save_kiel_institute(
170
+ fig,
171
+ ax,
172
+ "graph.png",
173
+ title="Rental Price Development In German cities over time",
174
+ subtitle="subtitle subtitle subtitle subtitle subtitle subtitle subtitle",
175
+ source="kielinstitut.de",
176
+ description="description description description description description description description description" \
177
+ " description description description description description description description description description description",
178
+ )
179
+ ```
180
+
181
+ ## Support
182
+ If you experience any difficulties with the template's functionality, we encourage you to submit an issue via [GitHub](https://github.com/kielinstitute/kielinstitutPython/issues). We will try to resolve the matter as quickly as possible.
183
+
184
+ ## License
185
+ This project is licensed under an All Rights Reserved License. See the LICENSE file for details.
@@ -0,0 +1,7 @@
1
+ KI_Inst_design_template/KIEL Wortbildmarke black.png,sha256=9Dmt9l_N38TCWV9QVtyZ7UTQLe6CGKUkZQsprvBcnpE,187117
2
+ KI_Inst_design_template/KI_Inst_design_template.py,sha256=nnDujTRmprRJ-DtLJp3RbdK1y0-FacLFE-99a1oNtDA,13970
3
+ KI_Inst_design_template/__init__.py,sha256=Cn5ltwP6-C1fWlXPDH4iXLHk3FOQNChGrawfnUckNC4,145
4
+ ki_inst_design_template-0.0.3.dist-info/METADATA,sha256=TnqOxM05QcbTQpU9_M5IpF6pLDSYokutHF0ybrFFqxY,8005
5
+ ki_inst_design_template-0.0.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
6
+ ki_inst_design_template-0.0.3.dist-info/licenses/LICENSE,sha256=s-5mNHj0ha5xXiygME7o9f777zaGzAfwl_aWbluB8k4,1081
7
+ ki_inst_design_template-0.0.3.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,21 @@
1
+ All Rights Reserved
2
+
3
+ Copyright (c) 2025 Kiel Institute for the World Economy
4
+
5
+ 1. RESTRICTIONS
6
+ The content of this software is proprietary and confidential. Unauthorized copying, transfer, or use of this file, via any medium, is strictly prohibited, except as explicitly granted below.
7
+
8
+ 2. GRANT OF LICENSE
9
+ Permission is hereby granted, free of charge, to all members of the Kiel Institute for the World Economy to deal in the Software without restriction, including the rights to use, copy, and modify copies of the Software.
10
+
11
+ For all other parties, no rights are granted.
12
+
13
+ 3. DISCLAIMER OF WARRANTY
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.