toolsos 0.1.4__tar.gz → 0.2.6__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.
- {toolsos-0.1.4 → toolsos-0.2.6}/PKG-INFO +12 -5
- {toolsos-0.1.4 → toolsos-0.2.6}/README.md +9 -2
- {toolsos-0.1.4 → toolsos-0.2.6}/pyproject.toml +4 -4
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/cbs_tools.py +36 -17
- {toolsos-0.1.4/src/toolsos → toolsos-0.2.6/src/toolsos/database}/database_connection.py +54 -13
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/geo.py +1 -1
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/huisstijl/graphs/bargraph.py +11 -1
- toolsos-0.2.6/src/toolsos/huisstijl/graphs/graph_styles.py +32 -0
- toolsos-0.2.6/src/toolsos/huisstijl/graphs/linegraph.py +35 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/huisstijl/graphs/piegraph.py +5 -1
- toolsos-0.2.6/src/toolsos/huisstijl/graphs/styler.py +189 -0
- toolsos-0.2.6/src/toolsos/huisstijl/tables/table_helpers.py +76 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/huisstijl/tables/tables.py +265 -116
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos.egg-info/PKG-INFO +12 -5
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos.egg-info/SOURCES.txt +3 -2
- toolsos-0.1.4/src/toolsos/huisstijl/graphs/graph_styles.py +0 -24
- toolsos-0.1.4/src/toolsos/huisstijl/graphs/linegraph.py +0 -20
- toolsos-0.1.4/src/toolsos/huisstijl/graphs/styler.py +0 -103
- {toolsos-0.1.4 → toolsos-0.2.6}/setup.cfg +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/__init__.py +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/create_tables.py +0 -0
- {toolsos-0.1.4/src/toolsos → toolsos-0.2.6/src/toolsos/database}/database_transfer.py +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/download.py +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/helpers.py +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/huisstijl/__init__.py +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/huisstijl/colors.py +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/huisstijl/graphs/__init__.py +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/huisstijl/tables/__init__.py +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/huisstijl/tables/table_styles.py +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos/polars_helpers.py +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos.egg-info/dependency_links.txt +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos.egg-info/requires.txt +0 -0
- {toolsos-0.1.4 → toolsos-0.2.6}/src/toolsos.egg-info/top_level.txt +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: toolsos
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.6
|
|
4
4
|
Summary: OS tools
|
|
5
5
|
Author-email: OS <d.schmitz@amsterdam.nl>
|
|
6
6
|
Keywords: tools,Onderzoek & Statistiek
|
|
7
7
|
Classifier: License :: OSI Approved :: MIT License
|
|
8
8
|
Classifier: Programming Language :: Python
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Requires-Python: >=3.
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
12
|
Provides-Extra: dev
|
|
13
13
|
Requires-Dist: black; extra == "dev"
|
|
@@ -63,5 +63,12 @@ Instructions on building a package can be found [here](https://packaging.python.
|
|
|
63
63
|
|
|
64
64
|
- make a pypi account
|
|
65
65
|
- ask to be added as collaborator to toolsos
|
|
66
|
-
- first update twine: py -m pip install --upgrade
|
|
67
|
-
- upload to pypi: twine upload dist/*
|
|
66
|
+
- first update twine: py -m pip install --upgrade twine
|
|
67
|
+
- upload to pypi: twine upload dist/* --skip-existing
|
|
68
|
+
|
|
69
|
+
## Install to local enviroment for testing
|
|
70
|
+
|
|
71
|
+
- python -m venv local (maak een lokale venv aan)
|
|
72
|
+
- local\Scripts\activate (activeer de venv)
|
|
73
|
+
- pip install -e . (installer toolsos)
|
|
74
|
+
- pip install -r local_requirements.txt (installeer de benodigde dependencies)
|
|
@@ -34,5 +34,12 @@ Instructions on building a package can be found [here](https://packaging.python.
|
|
|
34
34
|
|
|
35
35
|
- make a pypi account
|
|
36
36
|
- ask to be added as collaborator to toolsos
|
|
37
|
-
- first update twine: py -m pip install --upgrade
|
|
38
|
-
- upload to pypi: twine upload dist/*
|
|
37
|
+
- first update twine: py -m pip install --upgrade twine
|
|
38
|
+
- upload to pypi: twine upload dist/* --skip-existing
|
|
39
|
+
|
|
40
|
+
## Install to local enviroment for testing
|
|
41
|
+
|
|
42
|
+
- python -m venv local (maak een lokale venv aan)
|
|
43
|
+
- local\Scripts\activate (activeer de venv)
|
|
44
|
+
- pip install -e . (installer toolsos)
|
|
45
|
+
- pip install -r local_requirements.txt (installeer de benodigde dependencies)
|
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "toolsos"
|
|
9
|
-
version = "0.
|
|
9
|
+
version = "0.2.6"
|
|
10
10
|
description = "OS tools"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
authors = [{ name = "OS", email = "d.schmitz@amsterdam.nl" }]
|
|
@@ -25,7 +25,7 @@ keywords = ["tools", "Onderzoek & Statistiek"]
|
|
|
25
25
|
# use pip install "toolsos[all]" to pip install with al dependencies
|
|
26
26
|
|
|
27
27
|
dependencies = []
|
|
28
|
-
requires-python = ">=3.
|
|
28
|
+
requires-python = ">=3.10"
|
|
29
29
|
|
|
30
30
|
[project.optional-dependencies]
|
|
31
31
|
dev = [
|
|
@@ -49,5 +49,5 @@ all = [
|
|
|
49
49
|
"sqlalchemy",
|
|
50
50
|
]
|
|
51
51
|
|
|
52
|
-
#[project.urls]
|
|
53
|
-
#Homepage = "
|
|
52
|
+
# [project.urls]
|
|
53
|
+
#Homepage = ""
|
|
@@ -2,8 +2,9 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import pickle
|
|
5
|
+
from datetime import datetime
|
|
5
6
|
from pathlib import Path
|
|
6
|
-
from typing import TYPE_CHECKING, Iterator, Optional
|
|
7
|
+
from typing import TYPE_CHECKING, Any, Iterator, Optional
|
|
7
8
|
|
|
8
9
|
import pandas as pd
|
|
9
10
|
import pyarrow as pa
|
|
@@ -14,18 +15,27 @@ if TYPE_CHECKING:
|
|
|
14
15
|
import pyreadstat
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
def get_batch_size(path, memory_limit):
|
|
19
|
+
df, _ = prs.read_sav(path, row_limit=1000)
|
|
20
|
+
|
|
21
|
+
# memory in megabytes
|
|
22
|
+
mem_size = df.memory_usage().sum() / 1_000_000
|
|
23
|
+
|
|
24
|
+
# The amount of blocks (of a thousand rows fit in the memory_limit)
|
|
25
|
+
n_blocks = memory_limit / mem_size
|
|
26
|
+
|
|
27
|
+
# Calculate the number of rows that fit within the memory limit
|
|
28
|
+
return round(n_blocks * 1000)
|
|
29
|
+
|
|
30
|
+
|
|
17
31
|
class SavToParquet:
|
|
18
32
|
def __init__(
|
|
19
|
-
self,
|
|
20
|
-
file: str,
|
|
21
|
-
folder_out: str,
|
|
22
|
-
chunksize: Optional[int] = None,
|
|
23
|
-
verbose: bool = False,
|
|
33
|
+
self, file: str, folder_out: str, verbose: bool = False, memory_limit=10_000
|
|
24
34
|
) -> None:
|
|
25
35
|
self.file = file
|
|
26
36
|
self.folder_out = folder_out
|
|
27
37
|
self.verbose = verbose
|
|
28
|
-
self.
|
|
38
|
+
self.memory_limit = memory_limit
|
|
29
39
|
|
|
30
40
|
@property
|
|
31
41
|
def path_out(self) -> str:
|
|
@@ -33,20 +43,27 @@ class SavToParquet:
|
|
|
33
43
|
|
|
34
44
|
@property
|
|
35
45
|
def chunks(self) -> Iterator[tuple["pyreadstat.metadata_container", pd.DataFrame]]:
|
|
36
|
-
return prs.read_file_in_chunks(
|
|
37
|
-
prs.read_sav, self.file, chunksize=self.chunksize
|
|
38
|
-
)
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
chunksize = get_batch_size(self.file, self.memory_limit)
|
|
48
|
+
|
|
49
|
+
if self.verbose:
|
|
50
|
+
print(f"Reading file in blocks of {chunksize} rows")
|
|
51
|
+
print("One such block should fit within the memory limit")
|
|
52
|
+
|
|
53
|
+
return prs.read_file_in_chunks(prs.read_sav, self.file, chunksize=chunksize)
|
|
42
54
|
|
|
43
55
|
def write_meta_to_json(self) -> None:
|
|
44
56
|
json_path = self.path_out.replace(".parquet", "_meta.json")
|
|
45
57
|
|
|
46
58
|
meta_dict = {}
|
|
47
|
-
for
|
|
48
|
-
if not
|
|
49
|
-
|
|
59
|
+
for attr_name in dir(self.meta):
|
|
60
|
+
if not attr_name.startswith("__"):
|
|
61
|
+
attr = getattr(self.meta, attr_name)
|
|
62
|
+
|
|
63
|
+
if isinstance(attr, datetime):
|
|
64
|
+
attr = attr.strftime("%Y-%m-%d %H:%M:%S")
|
|
65
|
+
|
|
66
|
+
meta_dict[attr_name] = attr
|
|
50
67
|
|
|
51
68
|
with open(json_path, "w") as file:
|
|
52
69
|
json.dump(meta_dict, file)
|
|
@@ -58,10 +75,12 @@ class SavToParquet:
|
|
|
58
75
|
pickle.dump(self.meta, file)
|
|
59
76
|
|
|
60
77
|
def write_to_parquet(self) -> None:
|
|
61
|
-
meta_df, self.meta = self.get_meta()
|
|
62
|
-
schema = table = pa.Table.from_pandas(meta_df).schema
|
|
63
78
|
|
|
64
79
|
print("Writing table")
|
|
80
|
+
|
|
81
|
+
line1, self.meta = prs.read_sav(self.file, row_limit=1)
|
|
82
|
+
schema = pa.Table.from_pandas(line1).schema
|
|
83
|
+
|
|
65
84
|
with pq.ParquetWriter(self.path_out, schema) as writer:
|
|
66
85
|
for idx, (df, _) in enumerate(self.chunks):
|
|
67
86
|
if self.verbose:
|
|
@@ -2,8 +2,10 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import getpass
|
|
4
4
|
import json
|
|
5
|
+
import os
|
|
5
6
|
import subprocess
|
|
6
7
|
from json import JSONDecodeError
|
|
8
|
+
from pathlib import Path
|
|
7
9
|
from typing import Optional
|
|
8
10
|
|
|
9
11
|
import keyring
|
|
@@ -33,7 +35,7 @@ def get_db_connection_strings(
|
|
|
33
35
|
for dbname, params in db_info.items():
|
|
34
36
|
flush = dbname in reset_pw if reset_pw else False
|
|
35
37
|
|
|
36
|
-
if params["
|
|
38
|
+
if params["password"] == "access_token":
|
|
37
39
|
pw = get_azure_access_token()
|
|
38
40
|
else:
|
|
39
41
|
pw = get_pw_from_keyring(dbname=dbname, user=params["user"], reset_pw=flush)
|
|
@@ -94,21 +96,60 @@ def get_azure_access_token():
|
|
|
94
96
|
result = subprocess.run(command, capture_output=True, shell=True, text=True)
|
|
95
97
|
|
|
96
98
|
try:
|
|
97
|
-
json.loads(result.stdout)["accessToken"]
|
|
99
|
+
return json.loads(result.stdout)["accessToken"]
|
|
98
100
|
except JSONDecodeError:
|
|
99
101
|
subprocess.run("az login", shell=True)
|
|
100
102
|
|
|
101
103
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
def get_token_from_pgpass() -> None:
|
|
105
|
+
p = Path(os.getenv("APPDATA")) / "postgresql" / "pgpass.conf"
|
|
106
|
+
with open(p) as f:
|
|
107
|
+
token = f.readline().split(":")[4]
|
|
105
108
|
|
|
106
|
-
|
|
107
|
-
# engine_strings = get_db_connection_strings("python/database_config.yml")
|
|
108
|
-
# print(engine_strings.ruimte_analyse222)
|
|
109
|
+
return token
|
|
109
110
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
111
|
+
|
|
112
|
+
def write_pgpass(
|
|
113
|
+
host: str, port: str, database: str, user: str, path: str | None = None
|
|
114
|
+
) -> None:
|
|
115
|
+
password = get_azure_access_token()
|
|
116
|
+
conn_string = f"{host}:{port}:{database}:{user}:{password}"
|
|
117
|
+
|
|
118
|
+
if not path:
|
|
119
|
+
if os.name == "nt":
|
|
120
|
+
path = Path(os.getenv("APPDATA")) / "postgresql" / "pgpass.conf"
|
|
121
|
+
else:
|
|
122
|
+
path = Path("$home/.pgpass")
|
|
123
|
+
|
|
124
|
+
if not path.parent.exists():
|
|
125
|
+
path.parent.mkdir()
|
|
126
|
+
|
|
127
|
+
with open(path, "w") as f:
|
|
128
|
+
f.write(conn_string)
|
|
129
|
+
|
|
130
|
+
if os.name != "nt":
|
|
131
|
+
path.chmod("0600")
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def write_multiple_pgpass(conn_details, path: str | None = None):
|
|
135
|
+
password = get_azure_access_token()
|
|
136
|
+
|
|
137
|
+
conn_strings = []
|
|
138
|
+
for c in conn_details:
|
|
139
|
+
c_string = f'{c["host"]}:{c["port"]}:{c["database"]}:{c["user"]}:{password}'
|
|
140
|
+
conn_strings.append(c_string)
|
|
141
|
+
|
|
142
|
+
if not path:
|
|
143
|
+
if os.name == "nt":
|
|
144
|
+
path = Path(os.getenv("APPDATA")) / "postgresql" / "pgpass.conf"
|
|
145
|
+
else:
|
|
146
|
+
path = Path("$home/.pgpass")
|
|
147
|
+
|
|
148
|
+
if not path.parent.exists():
|
|
149
|
+
path.parent.mkdir()
|
|
150
|
+
|
|
151
|
+
with open(path, "w") as f:
|
|
152
|
+
f.writelines(line + "\n" for line in conn_strings)
|
|
153
|
+
|
|
154
|
+
if os.name != "nt":
|
|
155
|
+
path.chmod("0600")
|
|
@@ -17,7 +17,7 @@ def get_geo_json(
|
|
|
17
17
|
Returns:
|
|
18
18
|
dict[str, str]: geo json containg of the desired level and year
|
|
19
19
|
"""
|
|
20
|
-
base_url = "https://gitlab.com/os-amsterdam/datavisualisatie-onderzoek-en-statistiek/-/raw/main/geo/"
|
|
20
|
+
base_url = "https://gitlab.com/os-amsterdam/datavisualisatie-onderzoek-en-statistiek/-/raw/main/public/geo/"
|
|
21
21
|
|
|
22
22
|
if mra:
|
|
23
23
|
level = f"{level}-mra"
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import plotly.express as px
|
|
2
|
+
|
|
2
3
|
from .styler import BaseStyle
|
|
3
4
|
|
|
4
5
|
basestyle = BaseStyle()
|
|
@@ -14,6 +15,7 @@ def bar(
|
|
|
14
15
|
barmode=None,
|
|
15
16
|
width=750,
|
|
16
17
|
height=490,
|
|
18
|
+
font="Amsterdam Sans",
|
|
17
19
|
**kwargs,
|
|
18
20
|
):
|
|
19
21
|
fig = px.bar(
|
|
@@ -21,7 +23,7 @@ def bar(
|
|
|
21
23
|
x=x,
|
|
22
24
|
y=y,
|
|
23
25
|
color=color,
|
|
24
|
-
template=basestyle.get_base_template("bar", orientation=orientation),
|
|
26
|
+
template=basestyle.get_base_template("bar", orientation=orientation, font=font),
|
|
25
27
|
width=width,
|
|
26
28
|
color_discrete_sequence=color_discrete_sequence,
|
|
27
29
|
height=height,
|
|
@@ -43,6 +45,7 @@ def stacked_single(
|
|
|
43
45
|
color: str = None,
|
|
44
46
|
color_discrete_sequence: list = None,
|
|
45
47
|
orientation="v",
|
|
48
|
+
font="Amsterdam Sans",
|
|
46
49
|
**kwargs,
|
|
47
50
|
):
|
|
48
51
|
fig = bar(
|
|
@@ -53,6 +56,7 @@ def stacked_single(
|
|
|
53
56
|
color_discrete_sequence=color_discrete_sequence,
|
|
54
57
|
barmode="relative",
|
|
55
58
|
orientation=orientation,
|
|
59
|
+
font=font,
|
|
56
60
|
**kwargs,
|
|
57
61
|
)
|
|
58
62
|
|
|
@@ -71,6 +75,7 @@ def stacked_multiple(
|
|
|
71
75
|
color: str = None,
|
|
72
76
|
color_discrete_sequence: list = None,
|
|
73
77
|
orientation="v",
|
|
78
|
+
font="Amsterdam Sans",
|
|
74
79
|
**kwargs,
|
|
75
80
|
):
|
|
76
81
|
fig = bar(
|
|
@@ -81,6 +86,7 @@ def stacked_multiple(
|
|
|
81
86
|
color_discrete_sequence=color_discrete_sequence,
|
|
82
87
|
barmode="stack",
|
|
83
88
|
orientation=orientation,
|
|
89
|
+
font=font,
|
|
84
90
|
**kwargs,
|
|
85
91
|
)
|
|
86
92
|
|
|
@@ -94,6 +100,7 @@ def grouped(
|
|
|
94
100
|
color: str = None,
|
|
95
101
|
color_discrete_sequence: list = None,
|
|
96
102
|
orientation="v",
|
|
103
|
+
font="Amsterdam Sans",
|
|
97
104
|
**kwargs,
|
|
98
105
|
):
|
|
99
106
|
fig = bar(
|
|
@@ -104,6 +111,7 @@ def grouped(
|
|
|
104
111
|
color_discrete_sequence=color_discrete_sequence,
|
|
105
112
|
barmode="group",
|
|
106
113
|
orientation=orientation,
|
|
114
|
+
font=font,
|
|
107
115
|
**kwargs,
|
|
108
116
|
)
|
|
109
117
|
|
|
@@ -116,6 +124,7 @@ def single(
|
|
|
116
124
|
y: str,
|
|
117
125
|
color_discrete_sequence: list = None,
|
|
118
126
|
orientation="v",
|
|
127
|
+
font="Amsterdam Sans",
|
|
119
128
|
**kwargs,
|
|
120
129
|
):
|
|
121
130
|
fig = bar(
|
|
@@ -124,6 +133,7 @@ def single(
|
|
|
124
133
|
y=y,
|
|
125
134
|
color_discrete_sequence=color_discrete_sequence,
|
|
126
135
|
orientation=orientation,
|
|
136
|
+
font=font,
|
|
127
137
|
**kwargs,
|
|
128
138
|
)
|
|
129
139
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
font = "Amsterdam Sans ExtraBold, Corbel"
|
|
2
|
+
# font = "Arial"
|
|
3
|
+
|
|
4
|
+
STYLE_OLD = {
|
|
5
|
+
"font": {"family": "Corbel", "size": 15},
|
|
6
|
+
"plot_bgcolor": "#FFFFFF",
|
|
7
|
+
"gridline_color": "#E8E8E8",
|
|
8
|
+
"gridlinewidth": 0.75,
|
|
9
|
+
"showline": True,
|
|
10
|
+
"showgrid": False,
|
|
11
|
+
"zerolinecolor": "#E8E8E8",
|
|
12
|
+
"gridcolor": "#E8E8E8",
|
|
13
|
+
"separators": ",",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
STYLE_NEW = {
|
|
18
|
+
"font_bold": {"family": "Amsterdam Sans ExtraBold, Corbel", "size": 15},
|
|
19
|
+
"font_bold_corbel": {"family": "Corbel Bold", "size": 15},
|
|
20
|
+
"font": {"family": "Amsterdam Sans, Corbel", "size": 15},
|
|
21
|
+
"font_corbel": {"family": "Corbel", "size": 15},
|
|
22
|
+
"axis_font": {"family": "Amsterdam Sans ExtraBold, Corbel", "size": 15},
|
|
23
|
+
"plot_bgcolor": "#FFFFFF",
|
|
24
|
+
"gridline_color": "#dbdbdb",
|
|
25
|
+
"gridline_width": 0.75,
|
|
26
|
+
"showline": True,
|
|
27
|
+
"showgrid": False,
|
|
28
|
+
"zerolinecolor": "#dbdbdb",
|
|
29
|
+
"gridcolor": "#dbdbdb",
|
|
30
|
+
"gridlinecolor": "#dbdbdb",
|
|
31
|
+
"separators": ",",
|
|
32
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import plotly.express as px
|
|
2
|
+
|
|
3
|
+
from .styler import BaseStyle
|
|
4
|
+
|
|
5
|
+
basestyle = BaseStyle()
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def line(
|
|
9
|
+
data,
|
|
10
|
+
x,
|
|
11
|
+
y,
|
|
12
|
+
color: None,
|
|
13
|
+
width=750,
|
|
14
|
+
height=490,
|
|
15
|
+
color_discrete_sequence=None,
|
|
16
|
+
font="Amsterdam Sans",
|
|
17
|
+
**kwargs,
|
|
18
|
+
):
|
|
19
|
+
fig = px.line(
|
|
20
|
+
data_frame=data,
|
|
21
|
+
x=x,
|
|
22
|
+
y=y,
|
|
23
|
+
color=color,
|
|
24
|
+
width=width,
|
|
25
|
+
height=height,
|
|
26
|
+
color_discrete_sequence=color_discrete_sequence,
|
|
27
|
+
template=BaseStyle().get_base_template(graph_type="line", font=font),
|
|
28
|
+
**kwargs,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
fig.update_layout(
|
|
32
|
+
dict(xaxis_title_text="", yaxis_title_text="", legend_title_text="")
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
return fig
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import plotly.express as px
|
|
2
|
+
|
|
2
3
|
from .styler import BaseStyle
|
|
3
4
|
|
|
4
5
|
basestyle = BaseStyle()
|
|
@@ -12,6 +13,8 @@ def pie(
|
|
|
12
13
|
width=750,
|
|
13
14
|
height=490,
|
|
14
15
|
text_format: str = None,
|
|
16
|
+
color_discrete_sequence=None,
|
|
17
|
+
font="Amsterdam Sans",
|
|
15
18
|
**kwargs,
|
|
16
19
|
):
|
|
17
20
|
fig = px.pie(
|
|
@@ -21,7 +24,8 @@ def pie(
|
|
|
21
24
|
width=width,
|
|
22
25
|
height=height,
|
|
23
26
|
hole=hole,
|
|
24
|
-
template=BaseStyle().get_base_template(),
|
|
27
|
+
template=BaseStyle().get_base_template(font=font),
|
|
28
|
+
color_discrete_sequence=color_discrete_sequence,
|
|
25
29
|
**kwargs,
|
|
26
30
|
)
|
|
27
31
|
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
import plotly.graph_objects as go
|
|
4
|
+
import requests
|
|
5
|
+
from requests import ConnectionError
|
|
6
|
+
|
|
7
|
+
from .graph_styles import STYLE_NEW
|
|
8
|
+
|
|
9
|
+
# class BaseStyle:
|
|
10
|
+
# style_url = (
|
|
11
|
+
# "https://raw.githubusercontent.com/jbosga-ams/oistyle/main/base_style.json"
|
|
12
|
+
# )
|
|
13
|
+
|
|
14
|
+
# def __init__(self):
|
|
15
|
+
# self.grab_styling()
|
|
16
|
+
|
|
17
|
+
# def grab_styling(self, style_path: str = None):
|
|
18
|
+
# if not style_path:
|
|
19
|
+
# try:
|
|
20
|
+
# res = requests.get(self.style_url).json()
|
|
21
|
+
# except ConnectionError:
|
|
22
|
+
# print("Failed grabbing basestyle from the interwebs")
|
|
23
|
+
# # Add option to manually provide json file
|
|
24
|
+
# else:
|
|
25
|
+
# res = json.loads()
|
|
26
|
+
|
|
27
|
+
# for k, v in res.items():
|
|
28
|
+
# setattr(self, k, v)
|
|
29
|
+
|
|
30
|
+
# self.font = "Amsterdam Sans ExtraBold, Corbel"
|
|
31
|
+
|
|
32
|
+
# def _get_axis_format(self):
|
|
33
|
+
# self.gridline_color = "#dbdbdb" # Jorren vragen om deze aan te passen
|
|
34
|
+
|
|
35
|
+
# return {
|
|
36
|
+
# "zerolinecolor": self.gridline_color,
|
|
37
|
+
# "gridcolor": self.gridline_color,
|
|
38
|
+
# "gridwidth": self.gridline_width,
|
|
39
|
+
# "showline": True,
|
|
40
|
+
# "linewidth": self.gridline_width,
|
|
41
|
+
# "linecolor": self.gridline_color,
|
|
42
|
+
# # "mirror": True,
|
|
43
|
+
# "showgrid": False,
|
|
44
|
+
# }
|
|
45
|
+
|
|
46
|
+
# def _get_base_template_layout(self):
|
|
47
|
+
# return go.layout.Template(
|
|
48
|
+
# layout={
|
|
49
|
+
# "font": {"family": self.font, "size": self.font_size},
|
|
50
|
+
# "plot_bgcolor": self.plot_bgcolor,
|
|
51
|
+
# "colorway": self.colors["darkblue_lightblue_gradient_5"],
|
|
52
|
+
# "separators": ",", # Jorren vragen om deze toe te voegen
|
|
53
|
+
# }
|
|
54
|
+
# )
|
|
55
|
+
|
|
56
|
+
# def get_base_template(
|
|
57
|
+
# self, graph_type: str = None, orientation: str = None, colors: str = None
|
|
58
|
+
# ):
|
|
59
|
+
# """[summary]
|
|
60
|
+
|
|
61
|
+
# Args:
|
|
62
|
+
# graph_type (str, optional): Pick 'bar', 'line' or 'bar'. Defaults to None.
|
|
63
|
+
# orientation (str, optional): [description]. Pick horizontal ('h') or vertical 'v'. Defaults to None.
|
|
64
|
+
# colors (str, optional): Set basecolors. Defaults to None.
|
|
65
|
+
|
|
66
|
+
# Raises:
|
|
67
|
+
# ValueError: [description]
|
|
68
|
+
|
|
69
|
+
# Returns:
|
|
70
|
+
# [type]: [description]
|
|
71
|
+
# """
|
|
72
|
+
# base_template = self._get_base_template_layout()
|
|
73
|
+
# axis_format = self._get_axis_format()
|
|
74
|
+
|
|
75
|
+
# if graph_type == "bar":
|
|
76
|
+
# if orientation in ["v", "vertical"]:
|
|
77
|
+
# base_template.layout.xaxis.update(axis_format)
|
|
78
|
+
# base_template.layout.yaxis.update(zeroline=False)
|
|
79
|
+
# elif orientation in ["h", "horizontal"]:
|
|
80
|
+
# base_template.layout.yaxis.update(axis_format)
|
|
81
|
+
# base_template.layout.xaxis.update(zeroline=False)
|
|
82
|
+
# else:
|
|
83
|
+
# raise ValueError(
|
|
84
|
+
# "Orientation ('v'/'vertical' or 'h'/'horizontal') should be supplied with graph_type=='bar'"
|
|
85
|
+
# )
|
|
86
|
+
|
|
87
|
+
# elif graph_type == "line":
|
|
88
|
+
# base_template.layout.xaxis.update(axis_format)
|
|
89
|
+
|
|
90
|
+
# if colors:
|
|
91
|
+
# base_template.layout.update({"colorway": colors})
|
|
92
|
+
|
|
93
|
+
# return base_template
|
|
94
|
+
|
|
95
|
+
# def get_ois_colors(self, colorscale):
|
|
96
|
+
# colorscale = self.colors.get(colorscale, [])
|
|
97
|
+
# if not colorscale:
|
|
98
|
+
# raise Exception(f"Kies uit {self.colors.keys()}")
|
|
99
|
+
|
|
100
|
+
# return colorscale
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class BaseStyle:
|
|
104
|
+
def __init__(self, style_path=None):
|
|
105
|
+
if style_path is None:
|
|
106
|
+
self.style = STYLE_NEW
|
|
107
|
+
else:
|
|
108
|
+
with open(style_path) as file:
|
|
109
|
+
self.style = json.load(file)
|
|
110
|
+
|
|
111
|
+
def _get_axis_format(self):
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
"zerolinecolor": self.style["gridline_color"],
|
|
115
|
+
"gridcolor": self.style["gridline_color"],
|
|
116
|
+
"gridwidth": self.style["gridline_width"],
|
|
117
|
+
"showline": True,
|
|
118
|
+
"linewidth": self.style["gridline_width"],
|
|
119
|
+
"linecolor": self.style["gridline_color"],
|
|
120
|
+
"showgrid": self.style["showgrid"],
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
def _get_base_template_layout(self, font):
|
|
124
|
+
if font == "Amsterdam Sans":
|
|
125
|
+
font_ = self.style["font"]
|
|
126
|
+
font_bold_ = self.style["font_bold"]
|
|
127
|
+
elif font == "Corbel":
|
|
128
|
+
font_ = self.style["font_corbel"]
|
|
129
|
+
font_bold_ = self.style["font_bold_corbel"]
|
|
130
|
+
else:
|
|
131
|
+
raise ValueError("Font should be 'Amsterdam Sans' or 'Corbel'")
|
|
132
|
+
|
|
133
|
+
return go.layout.Template(
|
|
134
|
+
layout={
|
|
135
|
+
"xaxis": {
|
|
136
|
+
"tickfont": font_bold_,
|
|
137
|
+
},
|
|
138
|
+
"yaxis": {
|
|
139
|
+
"tickfont": font_bold_,
|
|
140
|
+
},
|
|
141
|
+
"legend": {"font": font_},
|
|
142
|
+
"plot_bgcolor": self.style["plot_bgcolor"],
|
|
143
|
+
"separators": ",",
|
|
144
|
+
"font": font_bold_,
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
def get_base_template(
|
|
149
|
+
self,
|
|
150
|
+
graph_type: str = None,
|
|
151
|
+
orientation: str = None,
|
|
152
|
+
colors: str = None,
|
|
153
|
+
font: str = "Amsterdam Sans",
|
|
154
|
+
):
|
|
155
|
+
"""[summary]
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
graph_type (str, optional): Pick 'bar', 'line' or 'bar'. Defaults to None.
|
|
159
|
+
orientation (str, optional): [description]. Pick horizontal ('h') or vertical 'v'. Defaults to None.
|
|
160
|
+
colors (str, optional): Set basecolors. Defaults to None.
|
|
161
|
+
|
|
162
|
+
Raises:
|
|
163
|
+
ValueError: [description]
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
[type]: [description]
|
|
167
|
+
"""
|
|
168
|
+
base_template = self._get_base_template_layout(font)
|
|
169
|
+
axis_format = self._get_axis_format()
|
|
170
|
+
|
|
171
|
+
if graph_type == "bar":
|
|
172
|
+
if orientation in ["v", "vertical"]:
|
|
173
|
+
base_template.layout.xaxis.update(axis_format)
|
|
174
|
+
base_template.layout.yaxis.update(zeroline=False)
|
|
175
|
+
elif orientation in ["h", "horizontal"]:
|
|
176
|
+
base_template.layout.yaxis.update(axis_format)
|
|
177
|
+
base_template.layout.xaxis.update(zeroline=False)
|
|
178
|
+
else:
|
|
179
|
+
raise ValueError(
|
|
180
|
+
"Orientation ('v'/'vertical' or 'h'/'horizontal') should be supplied with graph_type=='bar'"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
elif graph_type == "line":
|
|
184
|
+
base_template.layout.xaxis.update(axis_format)
|
|
185
|
+
|
|
186
|
+
if colors:
|
|
187
|
+
base_template.layout.update({"colorway": colors})
|
|
188
|
+
|
|
189
|
+
return base_template
|