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.
- KI_Inst_design_template/KIEL Wortbildmarke black.png +0 -0
- KI_Inst_design_template/KI_Inst_design_template.py +403 -0
- KI_Inst_design_template/__init__.py +1 -0
- ki_inst_design_template-0.0.3.dist-info/METADATA +185 -0
- ki_inst_design_template-0.0.3.dist-info/RECORD +7 -0
- ki_inst_design_template-0.0.3.dist-info/WHEEL +4 -0
- ki_inst_design_template-0.0.3.dist-info/licenses/LICENSE +21 -0
|
Binary file
|
|
@@ -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,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.
|