tikzplotly 0.1.6__tar.gz → 0.2.0__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.
Files changed (36) hide show
  1. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/PKG-INFO +11 -6
  2. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/README.md +7 -4
  3. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/pyproject.toml +4 -2
  4. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tests/test_heatmaps.py +9 -9
  5. tikzplotly-0.2.0/src/tests/test_histograms.py +284 -0
  6. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tests/test_line_charts.py +26 -1
  7. tikzplotly-0.2.0/src/tikzplotly/__about__.py +1 -0
  8. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly/_axis.py +86 -36
  9. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly/_heatmap.py +1 -1
  10. tikzplotly-0.2.0/src/tikzplotly/_histogram.py +132 -0
  11. tikzplotly-0.2.0/src/tikzplotly/_marker.py +228 -0
  12. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly/_save.py +26 -7
  13. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly/_tex.py +30 -1
  14. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly/_utils.py +49 -4
  15. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly.egg-info/PKG-INFO +11 -6
  16. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly.egg-info/SOURCES.txt +5 -1
  17. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/tests/test_heatmap.py +10 -1
  18. tikzplotly-0.2.0/tests/test_histograms.py +95 -0
  19. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/tests/test_markers.py +6 -3
  20. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/tests/test_scatter.py +83 -3
  21. tikzplotly-0.2.0/tests/test_tikzplotly.py +39 -0
  22. tikzplotly-0.1.6/src/tikzplotly/__about__.py +0 -1
  23. tikzplotly-0.1.6/src/tikzplotly/_marker.py +0 -121
  24. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/LICENSE +0 -0
  25. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/setup.cfg +0 -0
  26. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tests/test_markers.py +0 -0
  27. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly/__init__.py +0 -0
  28. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly/_annotations.py +0 -0
  29. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly/_color.py +0 -0
  30. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly/_dash.py +0 -0
  31. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly/_data.py +0 -0
  32. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly/_dataContainer.py +0 -0
  33. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly/_scatter.py +0 -0
  34. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly.egg-info/dependency_links.txt +0 -0
  35. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly.egg-info/requires.txt +0 -0
  36. {tikzplotly-0.1.6 → tikzplotly-0.2.0}/src/tikzplotly.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: tikzplotly
3
- Version: 0.1.6
3
+ Version: 0.2.0
4
4
  Summary: Convert plotly figures to LaTeX / tikz figures
5
5
  Author-email: Thomas Saigre <tikzplotly@outlook.fr>
6
6
  License: The MIT License (MIT)
@@ -30,9 +30,11 @@ Keywords: plotly,latex,tikz,figure,conversion,graphics
30
30
  Classifier: Development Status :: 5 - Production/Stable
31
31
  Classifier: Programming Language :: Python
32
32
  Classifier: Programming Language :: Python :: 3
33
- Classifier: Programming Language :: Python :: 3.8
34
33
  Classifier: Programming Language :: Python :: 3.9
35
34
  Classifier: Programming Language :: Python :: 3.10
35
+ Classifier: Programming Language :: Python :: 3.11
36
+ Classifier: Programming Language :: Python :: 3.12
37
+ Classifier: Programming Language :: Python :: 3.13
36
38
  Classifier: License :: OSI Approved :: MIT License
37
39
  Classifier: Operating System :: OS Independent
38
40
  Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
@@ -45,11 +47,15 @@ Requires-Dist: pillow
45
47
  Provides-Extra: dev
46
48
  Requires-Dist: pandas; extra == "dev"
47
49
 
48
- ![logo-tikzplotly](https://raw.githubusercontent.com/thomas-saigre/tikzplotly/main/doc/img/logo.svg "Tikzplotly")
50
+ ![logo-tikzplotly](https://raw.githubusercontent.com/thomas-saigre/tikzplotly/main/docs/assets/logo.svg "Tikzplotly")
51
+
49
52
 
50
53
  [![PyPi Version](https://img.shields.io/pypi/v/tikzplotly.svg?style=flat-square)](https://pypi.org/project/tikzplotly)
54
+ [![PyPi Downloads](https://img.shields.io/pypi/dm/tikzplotly.svg?style=flat-square)](https://pypi.org/project/tikzplotly)
55
+ [![PyPi License](https://img.shields.io/pypi/l/tikzplotly.svg?style=flat-square)](https://pypi.org/project/tikzplotly)
51
56
  [![PyPI pyversions](https://img.shields.io/pypi/pyversions/tikzplotly.svg?style=flat-square)](https://pypi.org/pypi/tikzplotly/)
52
57
 
58
+ [![GitHub release](https://img.shields.io/github/release/thomas-saigre/tikzplotly.svg?style=flat-square)](https://github.com/thomas-saigre/tikzplotly/releases)
53
59
  [![Issue](https://img.shields.io/github/issues-raw/thomas-saigre/tikzplotly?style=flat-square)](https://github.com/thomas-saigre/tikzplotly/issues)
54
60
  [![codecov](https://img.shields.io/codecov/c/github/thomas-saigre/tikzplotly.svg?style=flat-square)](https://codecov.io/gh/thomas-saigre/tikzplotly)
55
61
  ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/thomas-saigre/tikzplotly/ci.yml?style=flat-square)
@@ -142,8 +148,7 @@ To correctly compile the document, you will need to add the following packages t
142
148
 
143
149
  * This module is in development and new features are added bit by bit, when needed. If you have a feature request, please open an issue with the plotly figure you want to convert and the desired output.
144
150
  You can also submit a pull request with the desired feature !
145
- * Some feature can result in different output between the plotly figure and the tikz figure, for instance the size of markers.
146
- * More details in [doc/NB.md](doc/NB.md).
151
+ * Some feature can result in different output between the plotly figure and the tikz figure, for instance the size of markers, more details can be found in the documentation.
147
152
 
148
153
 
149
154
  ## References
@@ -1,8 +1,12 @@
1
- ![logo-tikzplotly](https://raw.githubusercontent.com/thomas-saigre/tikzplotly/main/doc/img/logo.svg "Tikzplotly")
1
+ ![logo-tikzplotly](https://raw.githubusercontent.com/thomas-saigre/tikzplotly/main/docs/assets/logo.svg "Tikzplotly")
2
+
2
3
 
3
4
  [![PyPi Version](https://img.shields.io/pypi/v/tikzplotly.svg?style=flat-square)](https://pypi.org/project/tikzplotly)
5
+ [![PyPi Downloads](https://img.shields.io/pypi/dm/tikzplotly.svg?style=flat-square)](https://pypi.org/project/tikzplotly)
6
+ [![PyPi License](https://img.shields.io/pypi/l/tikzplotly.svg?style=flat-square)](https://pypi.org/project/tikzplotly)
4
7
  [![PyPI pyversions](https://img.shields.io/pypi/pyversions/tikzplotly.svg?style=flat-square)](https://pypi.org/pypi/tikzplotly/)
5
8
 
9
+ [![GitHub release](https://img.shields.io/github/release/thomas-saigre/tikzplotly.svg?style=flat-square)](https://github.com/thomas-saigre/tikzplotly/releases)
6
10
  [![Issue](https://img.shields.io/github/issues-raw/thomas-saigre/tikzplotly?style=flat-square)](https://github.com/thomas-saigre/tikzplotly/issues)
7
11
  [![codecov](https://img.shields.io/codecov/c/github/thomas-saigre/tikzplotly.svg?style=flat-square)](https://codecov.io/gh/thomas-saigre/tikzplotly)
8
12
  ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/thomas-saigre/tikzplotly/ci.yml?style=flat-square)
@@ -95,8 +99,7 @@ To correctly compile the document, you will need to add the following packages t
95
99
 
96
100
  * This module is in development and new features are added bit by bit, when needed. If you have a feature request, please open an issue with the plotly figure you want to convert and the desired output.
97
101
  You can also submit a pull request with the desired feature !
98
- * Some feature can result in different output between the plotly figure and the tikz figure, for instance the size of markers.
99
- * More details in [doc/NB.md](doc/NB.md).
102
+ * Some feature can result in different output between the plotly figure and the tikz figure, for instance the size of markers, more details can be found in the documentation.
100
103
 
101
104
 
102
105
  ## References
@@ -109,4 +112,4 @@ You can also submit a pull request with the desired feature !
109
112
 
110
113
  ## License
111
114
 
112
- This project is licensed under the MIT [License](LICENSE).
115
+ This project is licensed under the MIT [License](LICENSE).
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tikzplotly"
7
- version = "0.1.6"
7
+ version = "0.2.0"
8
8
  description = "Convert plotly figures to LaTeX / tikz figures"
9
9
  readme = "README.md"
10
10
  authors = [{name = "Thomas Saigre", email = "tikzplotly@outlook.fr"}]
@@ -13,9 +13,11 @@ classifiers = [
13
13
  "Development Status :: 5 - Production/Stable",
14
14
  "Programming Language :: Python",
15
15
  "Programming Language :: Python :: 3",
16
- "Programming Language :: Python :: 3.8",
17
16
  "Programming Language :: Python :: 3.9",
18
17
  "Programming Language :: Python :: 3.10",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
19
21
  "License :: OSI Approved :: MIT License",
20
22
  "Operating System :: OS Independent",
21
23
  "Topic :: Multimedia :: Graphics :: Graphics Conversion",
@@ -166,16 +166,16 @@ if __name__ == "__main__":
166
166
  file_directory = os.path.dirname(os.path.abspath(__file__))
167
167
 
168
168
  functions = [
169
- # ("1", fig1),
170
- # ("2", fig2),
171
- # # ("3", fig3), # texttemplate not supported
172
- # ("4", fig4),
173
- # ("5", fig5),
174
- # ("6", fig6),
169
+ ("1", fig1),
170
+ ("2", fig2),
171
+ # ("3", fig3), # texttemplate not supported
172
+ ("4", fig4),
173
+ ("5", fig5),
174
+ ("6", fig6),
175
175
  ("7", fig7),
176
- # # ("8", fig8), # Not supported
177
- # ("9", fig9),
178
- # ("11", fig11)
176
+ # ("8", fig8), # Not supported
177
+ ("9", fig9),
178
+ ("11", fig11)
179
179
  ]
180
180
 
181
181
  main_tex_content = tex_create_document(options="twocolumn", compatibility="newest")
@@ -0,0 +1,284 @@
1
+ # From https://plotly.com/python/histograms/
2
+ import plotly
3
+ import plotly.express as px
4
+ import plotly.graph_objects as go
5
+ from plotly.subplots import make_subplots
6
+
7
+ import numpy as np
8
+ import tikzplotly
9
+ import os
10
+ from warnings import warn
11
+ from tikzplotly._tex import tex_create_document, tex_begin_environment, tex_end_environment, tex_end_all_environment
12
+
13
+ def fig1():
14
+ df = px.data.tips()
15
+ fig = px.histogram(df, x="total_bill")
16
+ # fig.show()
17
+ return fig, "Histogram of total bill"
18
+
19
+ def fig2():
20
+ df = px.data.tips()
21
+ # Here we use a column with categorical data
22
+ fig = px.histogram(df, x="day")
23
+ # fig.show()
24
+ return fig, "Histogram of days"
25
+
26
+ def fig3():
27
+ df = px.data.tips()
28
+ fig = px.histogram(df, x="total_bill", nbins=20)
29
+ # fig.show()
30
+ return fig, "Choose the number of bins"
31
+
32
+ def fig4():
33
+ warn("NB: This example is quite not working because of the high number of different dates present in the data set")
34
+ df = px.data.stocks()
35
+ fig = px.histogram(df, x="date")
36
+ fig.update_layout(bargap=0.2)
37
+ # fig.show()
38
+ return fig, "Histogram on date data"
39
+
40
+ def fig5():
41
+ df = px.data.tips()
42
+ fig = px.histogram(df, x="day", category_orders=dict(day=["Thur", "Fri", "Sat", "Sun"]))
43
+ # fig.show()
44
+ return fig, "Histograms on Categorical Data"
45
+
46
+ def fig6():
47
+ df = px.data.tips()
48
+ fig = px.histogram(df, x="total_bill", histnorm='probability density')
49
+ # fig.show()
50
+ return fig, "Type of normalization"
51
+
52
+ def fig7():
53
+ df = px.data.tips()
54
+ fig = px.histogram(df, x="total_bill",
55
+ title='Histogram of bills',
56
+ labels={'total_bill':'total bill'}, # can specify one label per df column
57
+ opacity=0.8,
58
+ log_y=True, # represent bars with log scale
59
+ color_discrete_sequence=['indianred'] # color of histogram bars
60
+ )
61
+ # fig.show()
62
+ return fig, "Aspect of the histogram plot"
63
+
64
+ def fig8():
65
+ df = px.data.tips()
66
+ fig = px.histogram(df, x="total_bill", color="sex")
67
+ # fig.show()
68
+ return fig, "Several histograms for different values of one column"
69
+
70
+ def fig9():
71
+ df = px.data.tips()
72
+ fig = px.histogram(df, x="total_bill", color="sex", marginal="rug", # can be `box`, `violin`
73
+ hover_data=df.columns)
74
+ return fig, "Histograms with pattern shapes"
75
+
76
+ def fig10():
77
+ df = px.data.tips()
78
+ fig = px.histogram(df, x="total_bill", y="tip", histfunc="avg", nbins=8, text_auto=True)
79
+ return fig, "Adding text labels"
80
+
81
+ def fig11():
82
+ np.random.seed(1)
83
+ x = np.random.randn(500)
84
+ fig = go.Figure(data=[go.Histogram(x=x)])
85
+ return fig, "Basic Histogram"
86
+
87
+ def fig12():
88
+ x = np.random.randn(500)
89
+ fig = go.Figure(data=[go.Histogram(x=x, histnorm='probability')])
90
+ return fig, "Normalized Histogram"
91
+
92
+ def fig13():
93
+ y = np.random.randn(500)
94
+ fig = go.Figure(data=[go.Histogram(y=y)])
95
+ return fig, "Horizontal Histogram"
96
+
97
+ def fig14():
98
+
99
+ x0 = np.random.randn(500)
100
+ x1 = np.random.randn(500) + 1
101
+
102
+ fig = go.Figure()
103
+ fig.add_trace(go.Histogram(x=x0))
104
+ fig.add_trace(go.Histogram(x=x1))
105
+
106
+ # Overlay both histograms
107
+ fig.update_layout(barmode='overlay')
108
+ # Reduce opacity to see both histograms
109
+ fig.update_traces(opacity=0.75)
110
+ return fig, "Overlay Histograms"
111
+
112
+ def fig15():
113
+ x0 = np.random.randn(500)
114
+ x1 = np.random.randn(500)
115
+
116
+ fig = go.Figure()
117
+ fig.add_trace(go.Histogram(x=x0))
118
+ fig.add_trace(go.Histogram(x=x1))
119
+
120
+ # The two histograms are drawn on top of another
121
+ fig.update_layout(barmode='stack')
122
+ return fig, "Stacked Histograms"
123
+
124
+ def fig16():
125
+ x0 = np.random.randn(500)
126
+ x1 = np.random.randn(500) + 1
127
+
128
+ fig = go.Figure()
129
+ fig.add_trace(go.Histogram(
130
+ x=x0,
131
+ histnorm='percent',
132
+ name='control', # name used in legend and hover labels
133
+ xbins=dict( # bins used for histogram
134
+ start=-4.0,
135
+ end=3.0,
136
+ size=0.5
137
+ ),
138
+ marker_color='#EB89B5',
139
+ opacity=0.75
140
+ ))
141
+ fig.add_trace(go.Histogram(
142
+ x=x1,
143
+ histnorm='percent',
144
+ name='experimental',
145
+ xbins=dict(
146
+ start=-3.0,
147
+ end=4,
148
+ size=0.5
149
+ ),
150
+ marker_color='#330C73',
151
+ opacity=0.75
152
+ ))
153
+
154
+ fig.update_layout(
155
+ title_text='Sampled Results', # title of plot
156
+ xaxis_title_text='Value', # xaxis label
157
+ yaxis_title_text='Count', # yaxis label
158
+ bargap=0.2, # gap between bars of adjacent location coordinates
159
+ bargroupgap=0.1 # gap between bars of the same location coordinates
160
+ )
161
+ return fig, "Styled Histogram"
162
+
163
+ def fig17():
164
+ numbers = ["5", "10", "3", "10", "5", "8", "5", "5"]
165
+ fig = go.Figure()
166
+ fig.add_trace(go.Histogram(x=numbers, name="count", texttemplate="%{x}", textfont_size=20))
167
+ return fig, "Histogram Bar Text"
168
+
169
+ def fig18():
170
+ x = np.random.randn(500)
171
+ fig = go.Figure(data=[go.Histogram(x=x, cumulative_enabled=True)])
172
+ return fig, "Cumulative Histogram"
173
+
174
+ def fig19():
175
+ x = ["Apples","Apples","Apples","Oranges", "Bananas"]
176
+ y = ["5","10","3","10","5"]
177
+
178
+ fig = go.Figure()
179
+ fig.add_trace(go.Histogram(histfunc="count", y=y, x=x, name="count"))
180
+ fig.add_trace(go.Histogram(histfunc="sum", y=y, x=x, name="sum"))
181
+ return fig, "Specify Aggregation Function"
182
+
183
+ def fig20():
184
+ x = ['1970-01-01', '1970-01-01', '1970-02-01', '1970-04-01', '1970-01-02',
185
+ '1972-01-31', '1970-02-13', '1971-04-19']
186
+
187
+ fig = make_subplots(rows=3, cols=2)
188
+
189
+ trace0 = go.Histogram(x=x, nbinsx=4)
190
+ trace1 = go.Histogram(x=x, nbinsx = 8)
191
+ trace2 = go.Histogram(x=x, nbinsx=10)
192
+ trace3 = go.Histogram(x=x,
193
+ xbins=dict(
194
+ start='1969-11-15',
195
+ end='1972-03-31',
196
+ size='M18'), # M18 stands for 18 months
197
+ autobinx=False
198
+ )
199
+ trace4 = go.Histogram(x=x,
200
+ xbins=dict(
201
+ start='1969-11-15',
202
+ end='1972-03-31',
203
+ size='M4'), # 4 months bin size
204
+ autobinx=False
205
+ )
206
+ trace5 = go.Histogram(x=x,
207
+ xbins=dict(
208
+ start='1969-11-15',
209
+ end='1972-03-31',
210
+ size= 'M2'), # 2 months
211
+ autobinx = False
212
+ )
213
+
214
+ fig.append_trace(trace0, 1, 1)
215
+ fig.append_trace(trace1, 1, 2)
216
+ fig.append_trace(trace2, 2, 1)
217
+ fig.append_trace(trace3, 2, 2)
218
+ fig.append_trace(trace4, 3, 1)
219
+ fig.append_trace(trace5, 3, 2)
220
+
221
+ return fig, "Custom Binning"
222
+
223
+ def fig21():
224
+ df = px.data.tips()
225
+ fig = px.histogram(df, x="day").update_xaxes(categoryorder='total ascending')
226
+ return fig, "Sort Histogram by Category Order"
227
+
228
+
229
+ if __name__ == "__main__":
230
+
231
+ print("Tikzploty : ", tikzplotly.__version__)
232
+ print("Plotly : ", plotly.__version__)
233
+ print("Test histograms")
234
+
235
+
236
+ file_directory = os.path.dirname(os.path.abspath(__file__))
237
+
238
+ functions = [
239
+ ("1", fig1),
240
+ ("2", fig2),
241
+ ("3", fig3),
242
+ # ("4", fig4),
243
+ ("5", fig5),
244
+ ("6", fig6),
245
+ ("7", fig7),
246
+ ("8", fig8),
247
+ # ("9", fig9), # Trace type box is not yet supported
248
+ # ("10", fig10), # Text template is not supported yet.
249
+ ("11", fig11),
250
+ ("12", fig12),
251
+ ("13", fig13),
252
+ ("14", fig14),
253
+ ("15", fig15),
254
+ # ("16", fig16), # Layout of this example not supported yet
255
+ ("17", fig17), # Text template is not supported yet.
256
+ ("18", fig18),
257
+ ("19", fig19),
258
+ # ("20", fig20), # Subplots not supported yet
259
+ ("21", fig21) # Category order not supported yet
260
+ ]
261
+
262
+ main_tex_content = tex_create_document(options="twocolumn", compatibility="newest")
263
+ main_tex_content += "\\usepackage[left=1cm, right=1cm, top=1cm, bottom=1cm]{geometry}\n"
264
+ main_tex_content += "\n"
265
+ stack_env = []
266
+ main_tex_content += tex_begin_environment("document", stack_env) + '\n'
267
+
268
+ for i, f in functions:
269
+ print(f"Figure {i}")
270
+ fig, title = f()
271
+ data = fig.data
272
+ save_path = os.path.join(file_directory, "outputs", "test_histograms", "fig{}.tex".format(i))
273
+ tikzplotly.save(save_path, fig)
274
+ main_tex_content += tex_begin_environment("figure", stack_env)
275
+ main_tex_content += " \\input{fig" + str(i) + ".tex}\n"
276
+ main_tex_content += " \\caption{" + title + "}\n"
277
+ main_tex_content += tex_end_environment(stack_env) + '\n'
278
+
279
+ main_tex_content += "\n" + tex_end_all_environment(stack_env)
280
+
281
+ main_tex_path = os.path.join(file_directory, "outputs", "test_histograms", "main.tex")
282
+ print("Save main tex file : ", main_tex_path)
283
+ with open(main_tex_path, "w") as f:
284
+ f.write(main_tex_content)
@@ -371,6 +371,28 @@ def fig15():
371
371
  # fig.show()
372
372
  return fig, "Filled Lines"
373
373
 
374
+ # https://plotly.com/python/log-plot/
375
+
376
+ def fig16():
377
+ df = px.data.gapminder().query("year == 2007")
378
+ fig = px.scatter(df, x="gdpPercap", y="lifeExp", hover_name="country", log_x=True)
379
+ return fig, "Log Scale"
380
+
381
+ def fig17():
382
+ df = px.data.gapminder().query("year == 2007")
383
+
384
+ fig = px.scatter(df, x="gdpPercap", y="lifeExp", hover_name="country",
385
+ log_x=True, range_x=[1,100000], range_y=[0,100])
386
+ return fig, "Log scale with range"
387
+
388
+ def fig18():
389
+ df = px.data.gapminder().query("year == 2007")
390
+
391
+ fig = px.scatter(df, x="gdpPercap", y="lifeExp", hover_name="country",
392
+ log_x=True, range_x=[1,100000], range_y=[0,100])
393
+
394
+ fig.update_xaxes(minor=dict(ticks="inside", ticklen=6, showgrid=True))
395
+ return fig, "Log scale with range and minor ticks"
374
396
 
375
397
  if __name__ == "__main__":
376
398
 
@@ -394,7 +416,10 @@ if __name__ == "__main__":
394
416
  ("11", fig11),
395
417
  # ("12", fig12),
396
418
  ("14", fig14),
397
- ("15", fig15)
419
+ ("15", fig15),
420
+ ("16", fig16),
421
+ ("17", fig17),
422
+ ("18", fig18),
398
423
  ]
399
424
 
400
425
  main_tex_content = tex_create_document(options="twocolumn", compatibility="newest")
@@ -0,0 +1 @@
1
+ __version__ = "0.2.0"
@@ -1,6 +1,8 @@
1
1
  from ._color import convert_color
2
2
  from ._tex import tex_begin_environment
3
- from ._utils import sanitize_TeX_text, option_dict_to_str
3
+ from ._utils import sanitize_TeX_text, option_dict_to_str, get_ticks_str
4
+ from warnings import warn
5
+
4
6
  class Axis():
5
7
 
6
8
  def __init__(self, layout, colors_set, axis_options=None):
@@ -15,9 +17,8 @@ class Axis():
15
17
  axis_options
16
18
  options given to the axis environment, by default None. Can be a dict ({option: value}) or a string ("option1=value1, option2=value2").
17
19
  """
18
- self.x_label = layout.xaxis.title.text
19
- self.y_label = layout.yaxis.title.text
20
- self.title = layout.title.text
20
+ self.layout = layout
21
+
21
22
  self.options = {}
22
23
  if isinstance(axis_options, dict):
23
24
  self.options = axis_options
@@ -31,41 +32,14 @@ class Axis():
31
32
  self.options[option] = None
32
33
  self.environment = "axis"
33
34
 
34
- if layout.xaxis.visible is False:
35
- self.x_label = None
36
- self.add_option("hide x axis", None)
37
- if layout.yaxis.visible is False:
38
- self.y_label = None
39
- self.add_option("hide y axis", None)
35
+ self.xticks = None
36
+
37
+ self.treat_axis_layout()
38
+ self.treat_background_layout(colors_set)
39
+ self.treat_bar_layout()
40
40
 
41
- # Handle log axes
42
- if layout.xaxis.type == "log":
43
- self.add_option("xmode", "log")
44
- if layout.yaxis.type == "log":
45
- self.add_option("ymode", "log")
46
41
 
47
- # Handle range
48
- # In log mode, the range is the exponent of the range : https://plotly.com/python/reference/layout/xaxis/#layout-xaxis-range
49
- # For more information, refer to documentation https://plotly.com/python/reference/layout/xaxis/#layout-xaxis-autorange
50
- if layout.xaxis.autorange is False or layout.xaxis.range is not None:
51
- self.add_option("xmin", layout.xaxis.range[0] if layout.xaxis.type != "log" else 10**layout.xaxis.range[0])
52
- self.add_option("xmax", layout.xaxis.range[1] if layout.xaxis.type != "log" else 10**layout.xaxis.range[1])
53
- if layout.yaxis.autorange is False or layout.yaxis.range is not None:
54
- self.add_option("ymin", layout.yaxis.range[0] if layout.yaxis.type != "log" else 10**layout.yaxis.range[0])
55
- self.add_option("ymax", layout.yaxis.range[1] if layout.yaxis.type != "log" else 10**layout.yaxis.range[1])
56
- if layout.xaxis.autorange == "reversed":
57
- self.add_option("x dir", "reverse")
58
- if layout.yaxis.autorange == "reversed":
59
- self.add_option("y dir", "reverse")
60
42
 
61
- if layout.plot_bgcolor is not None:
62
- bg_color = convert_color(layout.plot_bgcolor)
63
- colors_set.add(bg_color[:3])
64
- opacity = bg_color[3]
65
- if opacity < 1:
66
- self.add_option("axis background/.style", f"{{fill={bg_color[0]}, opacity={opacity}}}")
67
- else:
68
- self.add_option("axis background/.style", f"{{fill={bg_color[0]}}}")
69
43
 
70
44
  def set_x_label(self, x_label):
71
45
  """Set the x label.
@@ -125,3 +99,79 @@ class Axis():
125
99
  self.options["ylabel"] = sanitize_TeX_text(self.y_label)
126
100
  options_str = option_dict_to_str(self.options, sep="\n")
127
101
  return options_str
102
+
103
+
104
+ def treat_axis_layout(self):
105
+ """Treat the layout of the axis."""
106
+
107
+ self.set_x_label(self.layout.xaxis.title.text)
108
+ self.set_y_label(self.layout.yaxis.title.text)
109
+ self.title = self.layout.title.text
110
+
111
+ if self.layout.xaxis.visible is False:
112
+ self.x_label = None
113
+ self.add_option("hide x axis", None)
114
+ if self.layout.yaxis.visible is False:
115
+ self.y_label = None
116
+ self.add_option("hide y axis", None)
117
+
118
+ # Handle log axes
119
+ if self.layout.xaxis.type == "log":
120
+ self.add_option("xmode", "log")
121
+ if self.layout.yaxis.type == "log":
122
+ self.add_option("ymode", "log")
123
+
124
+ # Handle range
125
+ # In log mode, the range is the exponent of the range : https://plotly.com/python/reference/layout/xaxis/#layout-xaxis-range
126
+ # For more information, refer to documentation https://plotly.com/python/reference/layout/xaxis/#layout-xaxis-autorange
127
+ if self.layout.xaxis.autorange is False or self.layout.xaxis.range is not None:
128
+ self.add_option("xmin", self.layout.xaxis.range[0] if self.layout.xaxis.type != "log" else 10**self.layout.xaxis.range[0])
129
+ self.add_option("xmax", self.layout.xaxis.range[1] if self.layout.xaxis.type != "log" else 10**self.layout.xaxis.range[1])
130
+ if self.layout.yaxis.autorange is False or self.layout.yaxis.range is not None:
131
+ self.add_option("ymin", self.layout.yaxis.range[0] if self.layout.yaxis.type != "log" else 10**self.layout.yaxis.range[0])
132
+ self.add_option("ymax", self.layout.yaxis.range[1] if self.layout.yaxis.type != "log" else 10**self.layout.yaxis.range[1])
133
+ if self.layout.xaxis.autorange == "reversed":
134
+ self.add_option("x dir", "reverse")
135
+ if self.layout.yaxis.autorange == "reversed":
136
+ self.add_option("y dir", "reverse")
137
+
138
+ if self.layout.xaxis.showline == False:
139
+ self.add_option("axis x line", "none")
140
+ if self.layout.yaxis.showline == False:
141
+ self.add_option("axis y line", "none")
142
+ if self.layout.xaxis.categoryorder == "array":
143
+ self.xticks = self.layout.xaxis.categoryarray
144
+ ticks, ticklabels = get_ticks_str(self.layout.xaxis.categoryarray)
145
+ self.add_option("xtick", ticks)
146
+ self.add_option("xticklabels", ticklabels)
147
+
148
+ if self.layout.xaxis.categoryorder != "trace" or self.layout.yaxis.categoryorder != "trace" or self.layout.xaxis.categoryorder != "total descending":
149
+ warn("The categoryorder option is not supported (yet 🤞) for the axis environment.")
150
+
151
+ if self.layout.xaxis.showgrid:
152
+ self.add_option("xmajorgrids", None)
153
+ if self.layout.yaxis.showgrid:
154
+ self.add_option("ymajorgrids", None)
155
+ if self.layout.xaxis.ticklen is not None:
156
+ self.add_option("tickwidth", self.layout.xaxis.ticklen)
157
+ if self.layout.yaxis.ticklen is not None:
158
+ self.add_option("tickwidth", self.layout.yaxis.ticklen)
159
+
160
+ if (m := self.layout.xaxis.minor) is not None:
161
+ if m.showgrid:
162
+ self.add_option("xminorgrids", None)
163
+ if m.ticklen is not None:
164
+ self.add_option("subtickwidth", m.ticklen)
165
+
166
+
167
+ def treat_background_layout(self, colors_set):
168
+ if self.layout.plot_bgcolor is not None:
169
+ bg_color = convert_color(self.layout.plot_bgcolor)
170
+ colors_set.add(bg_color[:3])
171
+ opacity = bg_color[3]
172
+ self.add_option("axis background/.style", f"{{fill={bg_color[0]}}}")
173
+
174
+ def treat_bar_layout(self):
175
+ if (barmode := self.layout.barmode) is not None:
176
+ if barmode == "stack":
177
+ self.add_option("ybar stacked", None)
@@ -140,6 +140,6 @@ def draw_heatmap(data, fig, img_name, axis: Axis):
140
140
  axis.add_option("tick align", "outside")
141
141
  axis.add_option("tick pos", "left")
142
142
 
143
- code += tex_addplot(img_name, type="graphics", type_options=f"includegraphics cmd=\pgfimage,xmin={xmin}, xmax={xmax}, ymin={ymin}, ymax={ymax}")
143
+ code += tex_addplot(img_name, type="graphics", type_options=f"includegraphics cmd=\\pgfimage,xmin={xmin}, xmax={xmax}, ymin={ymin}, ymax={ymax}")
144
144
 
145
145
  return code