1
|
|
|
from typing import Optional |
|
|
|
|
2
|
|
|
|
3
|
|
|
import pandas as pd |
|
|
|
|
4
|
|
|
import regex |
|
|
|
|
5
|
|
|
from IPython.display import HTML, Markdown, display |
|
|
|
|
6
|
|
|
|
7
|
|
|
_color_pattern = regex.compile("#?[A-Z0-9a-z]{6}", flags=regex.V1) |
8
|
|
|
|
9
|
|
|
|
10
|
|
|
# noinspection PyTypeChecker |
11
|
|
|
class J: |
|
|
|
|
12
|
|
|
""" |
13
|
|
|
Convenience user tools to display HTML text in Jupyter notebooks. |
14
|
|
|
""" |
15
|
|
|
|
16
|
|
|
from IPython.display import clear_output, display |
|
|
|
|
17
|
|
|
from IPython.utils import io as __io |
|
|
|
|
18
|
|
|
|
19
|
|
|
RED, GREEN, BLUE, PURPLE, CYAN, BOLD = ( |
20
|
|
|
"#cc0000", |
21
|
|
|
"#008800", |
22
|
|
|
"#0000cc", |
23
|
|
|
"#880099", |
24
|
|
|
"#007777", |
25
|
|
|
"600", |
26
|
|
|
) |
27
|
|
|
|
28
|
|
|
@classmethod |
29
|
|
|
def full_width(cls, percent: bool = 100): |
|
|
|
|
30
|
|
|
display(HTML("<style>.container { width:" + str(percent) + "% !important; }</style>")) |
31
|
|
|
|
32
|
|
|
@classmethod |
33
|
|
|
def full(cls, df: pd.DataFrame) -> None: |
|
|
|
|
34
|
|
|
with pd.option_context("display.max_rows", 10 ** 10): |
35
|
|
|
with pd.option_context("display.max_columns", 10 ** 10): |
36
|
|
|
display(df) |
37
|
|
|
|
38
|
|
|
@classmethod |
39
|
|
|
def confirm(cls, msg: Optional[str] = None) -> bool: |
|
|
|
|
40
|
|
|
# return Tools.confirm(lambda: cls.blue("Confirm? [yes/no]" if msg is None else msg)) |
41
|
|
|
cls.bold_colored("Confirm? [yes/no]" if msg is None else msg, cls.BLUE) |
42
|
|
|
return cls.__io.ask_yes_no("") |
43
|
|
|
|
44
|
|
|
@classmethod |
45
|
|
|
def hyperlink(cls, text: str, url: str) -> None: |
|
|
|
|
46
|
|
|
display(HTML(f'<a href="{url}">{text}</a>')) |
47
|
|
|
|
48
|
|
|
@classmethod |
49
|
|
|
def red(cls, text: str) -> None: |
|
|
|
|
50
|
|
|
cls.colored(text, cls.RED) |
51
|
|
|
|
52
|
|
|
@classmethod |
53
|
|
|
def blue(cls, text: str) -> None: |
|
|
|
|
54
|
|
|
cls.colored(text, cls.BLUE) |
55
|
|
|
|
56
|
|
|
@classmethod |
57
|
|
|
def green(cls, text: str) -> None: |
|
|
|
|
58
|
|
|
cls.colored(text, cls.GREEN) |
59
|
|
|
|
60
|
|
|
@classmethod |
61
|
|
|
def bold(cls, text: str) -> None: |
|
|
|
|
62
|
|
|
cls.styled(text, font_weight=cls.BOLD) |
63
|
|
|
|
64
|
|
|
@classmethod |
65
|
|
|
def colored(cls, text: str, color: str, **kwargs) -> None: |
|
|
|
|
66
|
|
|
cls.styled(text, color=cls._color(color), **kwargs) |
67
|
|
|
|
68
|
|
|
@classmethod |
69
|
|
|
def bold_colored(cls, text: str, color: str) -> None: |
|
|
|
|
70
|
|
|
cls.styled(text, color=color, font_weight=cls.BOLD) |
71
|
|
|
|
72
|
|
|
@classmethod |
73
|
|
|
def code(cls, text: str, **kwargs) -> None: |
|
|
|
|
74
|
|
|
cls.styled(text, white_space="pre", font_family="monospace", **kwargs) |
75
|
|
|
|
76
|
|
|
@classmethod |
77
|
|
|
def md(cls, text: str) -> None: |
|
|
|
|
78
|
|
|
display(Markdown(text)) |
79
|
|
|
|
80
|
|
|
@classmethod |
81
|
|
|
def html(cls, text: str) -> None: |
|
|
|
|
82
|
|
|
display(HTML(text)) |
83
|
|
|
|
84
|
|
|
@classmethod |
85
|
|
|
def styled(cls, text: str, *main, **css: str) -> None: |
86
|
|
|
""" |
87
|
|
|
Display a span element styled with free CSS arguments. |
88
|
|
|
|
89
|
|
|
Args: |
90
|
|
|
text: The text to include in an HTML span |
91
|
|
|
main: Any free text of CSS, or a list of parameters |
92
|
|
|
css: Any free dict of CSS style parameters; spaces and underscores in the keys will be replaced with hypens |
|
|
|
|
93
|
|
|
""" |
94
|
|
|
main = ";".join(main) |
95
|
|
|
css = ";".join( |
96
|
|
|
"{}: {}".format(k.replace("_", "-").replace(" ", "-"), str(v)) for k, v in css.items() |
97
|
|
|
) |
98
|
|
|
if len(main) > 0 and not main.endswith(";"): |
99
|
|
|
main += ";" |
100
|
|
|
z = (main + css) if (main + css).endswith(";") else (main + css + ";") |
|
|
|
|
101
|
|
|
display(HTML('<span style="{}">{}</span>'.format(z, text))) |
102
|
|
|
|
103
|
|
|
@classmethod |
104
|
|
|
def _color(cls, color: str) -> str: |
105
|
|
|
if _color_pattern.fullmatch(color) is None: |
106
|
|
|
raise ValueError(f"Invalid hex color {color}") |
107
|
|
|
return color if color.startswith("#") else "#" + color |
108
|
|
|
|
109
|
|
|
|
110
|
|
|
class JFonts: |
111
|
|
|
""" |
112
|
|
|
Renders HTML for matplotlib fonts. |
113
|
|
|
""" |
114
|
|
|
|
115
|
|
|
@classmethod |
116
|
|
|
def one(cls, name: str) -> None: |
117
|
|
|
""" |
118
|
|
|
Shows a single typeface as itself. Ex; will show Helvetica in Helvetica. |
119
|
|
|
""" |
120
|
|
|
J.html(f'<p style="font-family:{name};">{name}</p>') |
121
|
|
|
|
122
|
|
|
@classmethod |
123
|
|
|
def mine(cls) -> None: |
124
|
|
|
""" |
125
|
|
|
Shows all typefaces currently in the matplotlib rcParams. |
126
|
|
|
Each typeface is rendered as itself. Ex; will show Helvetica in Helvetica. |
127
|
|
|
Each font family (``plt.rcParams['font.family']``) is shown separately, with all its fonts underneath. |
|
|
|
|
128
|
|
|
""" |
129
|
|
|
import matplotlib.pyplot as plt |
|
|
|
|
130
|
|
|
|
131
|
|
|
for family in plt.rcParams["font.family"]: |
132
|
|
|
items = "\n".join( |
133
|
|
|
[ |
134
|
|
|
f'<li style="font-family:{family};">{family}</li>' |
135
|
|
|
for font in plt.rcParams.get("font." + family, []) |
136
|
|
|
] |
137
|
|
|
) |
138
|
|
|
J.html( |
139
|
|
|
( |
140
|
|
|
'<h4 style="padding-bottom:0;margin-bottom:0;">{}:</h4>\n' |
141
|
|
|
'<ul style="padding-top:0;margin-top:0;margin-bottom:0;margin-top:0;">\n' |
142
|
|
|
"{}\n</ul>" |
143
|
|
|
).format(family, items) |
144
|
|
|
) |
145
|
|
|
|
146
|
|
|
@classmethod |
147
|
|
|
def every(cls, n_cols: int = 4) -> None: |
148
|
|
|
""" |
149
|
|
|
Shows an HTML table of all typefaces rendered as themselves. Ex; will show Helvetica in Helvetica. |
|
|
|
|
150
|
|
|
Displays as an HTML table with `n_cols`. |
151
|
|
|
Thanks to https://jonathansoma.com/lede/data-studio/matplotlib/list-all-fonts-available-in-matplotlib-plus-samples/. |
|
|
|
|
152
|
|
|
|
153
|
|
|
Args: |
154
|
|
|
n_cols: Number of columns in the created HTML table |
155
|
|
|
""" |
156
|
|
|
from matplotlib.font_manager import fontManager |
|
|
|
|
157
|
|
|
|
158
|
|
|
def _show_font(name: str): |
159
|
|
|
return f"<p style='font-family:{name};'>{name}</p>" |
160
|
|
|
|
161
|
|
|
fonts = set([f.name for f in fontManager.ttflist]) |
|
|
|
|
162
|
|
|
code = "\n".join([_show_font(font) for font in sorted(fonts)]) |
163
|
|
|
J.html(f'<div style="column-count: {n_cols};">{code}</div>') |
164
|
|
|
|
165
|
|
|
|
166
|
|
|
__all__ = ["J", "JFonts"] |
167
|
|
|
|