-
Notifications
You must be signed in to change notification settings - Fork 3
/
plotting.py
128 lines (112 loc) · 3.93 KB
/
plotting.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
from typing import Union
import plotly.graph_objs as go
from plotly import offline
def matplotlibify(
fig: go.Figure,
size: int = 24,
width_inches: Union[float, int] = 3.5,
height_inches: Union[float, int] = 3.5,
dpi: int = 142,
return_scale: bool = False,
) -> go.Figure:
"""Make plotly figures look more like matplotlib for academic publishing.
modified from: https://medium.com/swlh/fa56ddd97539
Parameters
----------
fig : go.Figure
Plotly figure to be matplotlibified
size : int, optional
Font size for layout and axes, by default 24
width_inches : Union[float, int], optional
Width of matplotlib figure in inches, by default 3.5
height_inches : Union[float, int], optional
Height of matplotlib figure in Inches, by default 3.5
dpi : int, optional
Dots per inch (resolution) of matplotlib figure, by default 142. Leave as
default unless you're willing to verify nothing strange happens with the output.
return_scale : bool, optional
If true, then return `scale` which is a quantity that helps with creating a
high-resolution image at the specified absolute width and height in inches.
More specifically:
>>> width_default_px = fig.layout.width
>>> targ_dpi = 300
>>> scale = width_inches / (width_default_px / dpi) * (targ_dpi / dpi)
Feel free to ignore this parameter.
Returns
-------
fig : go.Figure
The matplotlibified plotly figure.
Examples
--------
>>> import plotly.express as px
>>> df = px.data.tips()
>>> fig = px.histogram(df, x="day")
>>> fig.show()
>>> fig = matplotlibify(fig, size=24, width_inches=3.5, height_inches=3.5, dpi=142)
>>> fig.show()
Note the difference between
https://user-images.githubusercontent.com/45469701/171044741-35591a2c-dede-4df1-ae47-597bbfdb89cf.png # noqa: E501
and
https://user-images.githubusercontent.com/45469701/171044746-84a0deb0-1e15-40bf-a459-a5a7d3425b20.png, # noqa: E501
which are both static exports of interactive plotly figures.
"""
font_dict = dict(family="Arial", size=size, color="black")
# app = QApplication(sys.argv)
# screen = app.screens()[0]
# dpi = screen.physicalDotsPerInch()
# app.quit()
fig.update_layout(
font=font_dict,
plot_bgcolor="white",
width=width_inches * dpi,
height=height_inches * dpi,
margin=dict(r=40, t=20, b=10),
)
fig.update_yaxes(
showline=True, # add line at x=0
linecolor="black", # line color
linewidth=2.4, # line size
ticks="inside", # ticks outside axis
tickfont=font_dict, # tick label font
mirror="allticks", # add ticks to top/right axes
tickwidth=2.4, # tick width
tickcolor="black", # tick color
)
fig.update_xaxes(
showline=True,
showticklabels=True,
linecolor="black",
linewidth=2.4,
ticks="inside",
tickfont=font_dict,
mirror="allticks",
tickwidth=2.4,
tickcolor="black",
)
fig.update(layout_coloraxis_showscale=False)
width_default_px = fig.layout.width
targ_dpi = 300
scale = width_inches / (width_default_px / dpi) * (targ_dpi / dpi)
if return_scale:
return fig, scale
else:
return fig
def plot_and_save(fig_path, fig, mpl_kwargs={}, show=False, update_legend=False):
if show:
offline.plot(fig)
fig.write_html(fig_path + ".html")
fig.to_json(fig_path + ".json")
if update_legend:
fig.update_layout(
legend=dict(
font=dict(size=16),
yanchor="bottom",
y=0.99,
xanchor="right",
x=0.99,
bgcolor="rgba(0,0,0,0)",
# orientation="h",
)
)
fig = matplotlibify(fig, **mpl_kwargs)
fig.write_image(fig_path + ".png")