icplot 0.0.6__tar.gz → 0.0.8__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.
- {icplot-0.0.6/src/icplot.egg-info → icplot-0.0.8}/PKG-INFO +4 -2
- {icplot-0.0.6 → icplot-0.0.8}/pyproject.toml +5 -3
- icplot-0.0.8/src/icplot/color.py +13 -0
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot/geometry.py +1 -7
- icplot-0.0.8/src/icplot/graph/__init__.py +1 -0
- icplot-0.0.8/src/icplot/graph/matplotlib_plot_backend.py +69 -0
- icplot-0.0.8/src/icplot/graph/plot.py +163 -0
- icplot-0.0.8/src/icplot/graph/series.py +54 -0
- {icplot-0.0.6 → icplot-0.0.8/src/icplot.egg-info}/PKG-INFO +4 -2
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot.egg-info/SOURCES.txt +6 -0
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot.egg-info/requires.txt +3 -1
- {icplot-0.0.6 → icplot-0.0.8}/test/test_cairo_interface.py +1 -0
- {icplot-0.0.6 → icplot-0.0.8}/test/test_gantt_chart.py +2 -3
- {icplot-0.0.6 → icplot-0.0.8}/test/test_image_utils.py +3 -3
- icplot-0.0.8/test/test_line_plots.py +23 -0
- {icplot-0.0.6 → icplot-0.0.8}/test/test_tex_interface.py +1 -0
- {icplot-0.0.6 → icplot-0.0.8}/LICENSE +0 -0
- {icplot-0.0.6 → icplot-0.0.8}/README.md +0 -0
- {icplot-0.0.6 → icplot-0.0.8}/setup.cfg +0 -0
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot/__init__.py +0 -0
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot/cairo_interface.py +0 -0
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot/gantt.py +0 -0
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot/image_utils.py +0 -0
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot/main_cli.py +0 -0
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot/project_elements.py +0 -0
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot/tex_interface.py +0 -0
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot.egg-info/dependency_links.txt +0 -0
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot.egg-info/entry_points.txt +0 -0
- {icplot-0.0.6 → icplot-0.0.8}/src/icplot.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: icplot
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8
|
|
4
4
|
Summary: Utilities for generating plots and graphics for technical reports.
|
|
5
5
|
Author-email: "James Grogan, Irish Centre for High End Computing" <james.grogan@ichec.ie>
|
|
6
6
|
Project-URL: Repository, https://git.ichec.ie/performance/toolshed/icplot
|
|
@@ -16,13 +16,15 @@ Description-Content-Type: text/markdown
|
|
|
16
16
|
License-File: LICENSE
|
|
17
17
|
Requires-Dist: wand
|
|
18
18
|
Requires-Dist: matplotlib
|
|
19
|
-
Requires-Dist: iccore==0.0.
|
|
19
|
+
Requires-Dist: iccore==0.0.9
|
|
20
20
|
Provides-Extra: test
|
|
21
21
|
Requires-Dist: pytest; extra == "test"
|
|
22
22
|
Requires-Dist: pytest-cov; extra == "test"
|
|
23
23
|
Requires-Dist: pytest-sugar; extra == "test"
|
|
24
24
|
Requires-Dist: black; extra == "test"
|
|
25
25
|
Requires-Dist: mypy; extra == "test"
|
|
26
|
+
Requires-Dist: flake8; extra == "test"
|
|
27
|
+
Requires-Dist: pylint; extra == "test"
|
|
26
28
|
Provides-Extra: cairo
|
|
27
29
|
Requires-Dist: pycairo; extra == "cairo"
|
|
28
30
|
Requires-Dist: CairoSVG; extra == "cairo"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "icplot"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.8"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name="James Grogan, Irish Centre for High End Computing", email="james.grogan@ichec.ie" },
|
|
6
6
|
]
|
|
@@ -18,7 +18,7 @@ keywords = ["Publishing", "Technical Reports", "Graphics"]
|
|
|
18
18
|
|
|
19
19
|
dependencies = ["wand",
|
|
20
20
|
"matplotlib",
|
|
21
|
-
"iccore==0.0.
|
|
21
|
+
"iccore==0.0.9"]
|
|
22
22
|
|
|
23
23
|
[project.urls]
|
|
24
24
|
Repository = "https://git.ichec.ie/performance/toolshed/icplot"
|
|
@@ -30,7 +30,9 @@ test = [
|
|
|
30
30
|
"pytest-cov",
|
|
31
31
|
"pytest-sugar",
|
|
32
32
|
"black",
|
|
33
|
-
"mypy"
|
|
33
|
+
"mypy",
|
|
34
|
+
"flake8",
|
|
35
|
+
"pylint"
|
|
34
36
|
]
|
|
35
37
|
|
|
36
38
|
cairo = [
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .plot import * # NOQA
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
logging.getLogger("matplotlib").setLevel(logging.WARNING)
|
|
5
|
+
import matplotlib # NOQA
|
|
6
|
+
|
|
7
|
+
default_backend = matplotlib.get_backend()
|
|
8
|
+
matplotlib.use("Agg")
|
|
9
|
+
import matplotlib.pyplot as plt # NOQA
|
|
10
|
+
import matplotlib as mpl # NOQA
|
|
11
|
+
|
|
12
|
+
from icplot.color import ColorMap # NOQA
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MatplotlibColorMap(ColorMap):
|
|
16
|
+
|
|
17
|
+
def __init__(self, label: str):
|
|
18
|
+
super().__init__(label)
|
|
19
|
+
self.c_map = mpl.colormaps[label]
|
|
20
|
+
self.cmap_start_offset = 0.25
|
|
21
|
+
self.cmap_scale = 2
|
|
22
|
+
|
|
23
|
+
def get_color(self, cursor: int, values: list):
|
|
24
|
+
"""
|
|
25
|
+
Returns a colour based on a cmap and how far across
|
|
26
|
+
the datasets you are
|
|
27
|
+
"""
|
|
28
|
+
position = cursor / len(values)
|
|
29
|
+
return self.c_map(self.cmap_start_offset + (position / self.cmap_scale))
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class MatplotlibPlotBackend:
|
|
33
|
+
|
|
34
|
+
def __init__(self):
|
|
35
|
+
self.ax = plt.subplot(111)
|
|
36
|
+
|
|
37
|
+
def set_decorations(self, x_label, y_label, title, x_ticks, y_ticks):
|
|
38
|
+
self.ax.legend(loc="upper left")
|
|
39
|
+
if x_label:
|
|
40
|
+
self.ax.set_xlabel(x_label)
|
|
41
|
+
if y_label:
|
|
42
|
+
self.ax.set_ylabel(y_label)
|
|
43
|
+
if title:
|
|
44
|
+
self.ax.set_title(title)
|
|
45
|
+
if x_ticks:
|
|
46
|
+
self.ax.set_xticks(x_ticks)
|
|
47
|
+
if y_ticks:
|
|
48
|
+
self.ax.set_yticks(y_ticks)
|
|
49
|
+
|
|
50
|
+
def plot_line(self, x, y, label, color):
|
|
51
|
+
self.ax.plot(x, y, label=label, color=color)
|
|
52
|
+
|
|
53
|
+
def plot_scatter(self, data, label, color):
|
|
54
|
+
self.ax.plot(data, label=label, color=color)
|
|
55
|
+
|
|
56
|
+
def make_subplot(self, rows, cols, count):
|
|
57
|
+
plt.subplot(rows, cols, count)
|
|
58
|
+
|
|
59
|
+
def plot_image(self, data):
|
|
60
|
+
plt.imshow(data)
|
|
61
|
+
plt.axis("off")
|
|
62
|
+
|
|
63
|
+
def render(self, path: Path | None = None):
|
|
64
|
+
if path:
|
|
65
|
+
plt.savefig(path)
|
|
66
|
+
else:
|
|
67
|
+
plt.switch_backend(default_backend)
|
|
68
|
+
plt.show()
|
|
69
|
+
plt.switch_backend("Agg")
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module has content for generating plots
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import random
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import cast
|
|
8
|
+
import json
|
|
9
|
+
|
|
10
|
+
from .series import PlotSeries, LinePlotSeries, ScatterPlotSeries, ImageSeries
|
|
11
|
+
from .matplotlib_plot_backend import MatplotlibPlotBackend, MatplotlibColorMap
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Range:
|
|
15
|
+
|
|
16
|
+
def __init__(self, lower, upper, step):
|
|
17
|
+
self.lower = lower
|
|
18
|
+
self.upper = upper
|
|
19
|
+
self.step = step
|
|
20
|
+
|
|
21
|
+
def eval(self):
|
|
22
|
+
return range(self.lower, self.upper, self.step)
|
|
23
|
+
|
|
24
|
+
def serialize(self):
|
|
25
|
+
return {"lower": self.lower, "upper": self.upper, "step": self.step}
|
|
26
|
+
|
|
27
|
+
def __str__(self):
|
|
28
|
+
return json.dumps(self.serialize(), ident=4)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class Plot:
|
|
32
|
+
"""
|
|
33
|
+
A generic plot with optional axis ticks
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
title: str = "",
|
|
39
|
+
x_label: str = "",
|
|
40
|
+
y_label: str = "",
|
|
41
|
+
legend_label: str = "",
|
|
42
|
+
) -> None:
|
|
43
|
+
self.series: list[PlotSeries] = []
|
|
44
|
+
self.title = title
|
|
45
|
+
self.size: tuple | None = None
|
|
46
|
+
self.plot_type = ""
|
|
47
|
+
self.x_label = x_label
|
|
48
|
+
self.y_label = y_label
|
|
49
|
+
self.legend_label = legend_label
|
|
50
|
+
self.x_ticks: Range | None = None
|
|
51
|
+
self.y_ticks: Range | None = None
|
|
52
|
+
self.backend = MatplotlibPlotBackend()
|
|
53
|
+
self.cmap = MatplotlibColorMap("viridis")
|
|
54
|
+
|
|
55
|
+
def set_colour_map(self, cmap):
|
|
56
|
+
self.c_map = MatplotlibColorMap(cmap)
|
|
57
|
+
|
|
58
|
+
def set_x_ticks(self, lower, upper, step):
|
|
59
|
+
self.x_ticks = Range(lower, upper + 1, step)
|
|
60
|
+
|
|
61
|
+
def set_y_ticks(self, lower, upper, step):
|
|
62
|
+
self.y_ticks = Range(lower, upper + 1, step)
|
|
63
|
+
|
|
64
|
+
def set_decorations(self):
|
|
65
|
+
|
|
66
|
+
xtick_range = None
|
|
67
|
+
ytick_range = None
|
|
68
|
+
if self.x_ticks:
|
|
69
|
+
xtick_range = self.x_ticks.eval()
|
|
70
|
+
if self.y_ticks:
|
|
71
|
+
ytick_range = self.y_ticks.eval()
|
|
72
|
+
|
|
73
|
+
self.backend.set_decorations(
|
|
74
|
+
self.x_label,
|
|
75
|
+
self.y_label,
|
|
76
|
+
self.title,
|
|
77
|
+
xtick_range,
|
|
78
|
+
ytick_range,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
def add_series(self, series):
|
|
82
|
+
self.series.append(series)
|
|
83
|
+
|
|
84
|
+
def plot_series(self, series, label):
|
|
85
|
+
if series.series_type == "line":
|
|
86
|
+
line_series = cast(LinePlotSeries, series)
|
|
87
|
+
self.backend.plot_line(
|
|
88
|
+
line_series.x, line_series.y, label=label, color=series.color
|
|
89
|
+
)
|
|
90
|
+
elif series.series_type == "scatter":
|
|
91
|
+
scatter_series = cast(ScatterPlotSeries, series)
|
|
92
|
+
self.backend.plot_scatter(
|
|
93
|
+
scatter_series.data, label=label, color=series.color
|
|
94
|
+
)
|
|
95
|
+
elif series.series_type == "image":
|
|
96
|
+
image_series = cast(ImageSeries, series)
|
|
97
|
+
self.backend.plot_image(image_series.data)
|
|
98
|
+
|
|
99
|
+
def plot(self, path: Path | None = None):
|
|
100
|
+
for idx, series in enumerate(self.series):
|
|
101
|
+
series.color = self.cmap.get_color(idx, self.series)
|
|
102
|
+
|
|
103
|
+
first = True
|
|
104
|
+
for series in self.series:
|
|
105
|
+
label = series.label
|
|
106
|
+
if first and self.legend_label:
|
|
107
|
+
label = f"{label} {self.legend_label}"
|
|
108
|
+
first = False
|
|
109
|
+
self.plot_series(series, label)
|
|
110
|
+
|
|
111
|
+
self.set_decorations()
|
|
112
|
+
self.backend.render(path)
|
|
113
|
+
|
|
114
|
+
def serialize(self):
|
|
115
|
+
return {
|
|
116
|
+
"series": [s.serialize() for s in self.series],
|
|
117
|
+
"title": self.title,
|
|
118
|
+
"type": self.plot_type,
|
|
119
|
+
"xlabel": self.x_label,
|
|
120
|
+
"ylabel": self.y_label,
|
|
121
|
+
"legend_label": self.legend_label,
|
|
122
|
+
"xticks": self.x_ticks.serialize(),
|
|
123
|
+
"yticks": self.y_ticks.serialize(),
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class GridPlot(Plot):
|
|
128
|
+
"""
|
|
129
|
+
Make a grid of plots
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
def __init__(
|
|
133
|
+
self, title: str = "", stride: int = 4, size: tuple = (25, 20)
|
|
134
|
+
) -> None:
|
|
135
|
+
super().__init__(title)
|
|
136
|
+
self.stride = stride
|
|
137
|
+
self.size = size
|
|
138
|
+
|
|
139
|
+
def _subplot(self, rows: int, cols: int, count: int, series):
|
|
140
|
+
|
|
141
|
+
self.backend.make_subplot(rows, cols, count)
|
|
142
|
+
self.plot_series(series, "")
|
|
143
|
+
return count + 1
|
|
144
|
+
|
|
145
|
+
def render(self, data, path: Path, num_samples: int = 0):
|
|
146
|
+
rows = num_samples // self.stride
|
|
147
|
+
cols = num_samples // rows
|
|
148
|
+
count = 1
|
|
149
|
+
if num_samples == 0:
|
|
150
|
+
indices = [random.randint(0, len(data) - 1) for _ in range(num_samples)]
|
|
151
|
+
else:
|
|
152
|
+
indices = list(range(0, len(data)))
|
|
153
|
+
|
|
154
|
+
for index in indices:
|
|
155
|
+
if num_samples > 0 and count == num_samples + 1:
|
|
156
|
+
break
|
|
157
|
+
if isinstance(data[index], list):
|
|
158
|
+
for series in data[index]:
|
|
159
|
+
count = self._subplot(rows, cols, count, series)
|
|
160
|
+
else:
|
|
161
|
+
count = self._subplot(rows, cols, count, data[index])
|
|
162
|
+
|
|
163
|
+
self.backend.render(path)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import json
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class PlotSeries:
|
|
5
|
+
|
|
6
|
+
def __init__(self, label: str = ""):
|
|
7
|
+
self.label = label
|
|
8
|
+
self.color: list[float] = [0.0, 0.0, 0.0]
|
|
9
|
+
self.series_type = ""
|
|
10
|
+
|
|
11
|
+
def serialize(self):
|
|
12
|
+
return {"label": self.label, "color": self.color, "type": self.series_type}
|
|
13
|
+
|
|
14
|
+
def __str__(self):
|
|
15
|
+
return json.dumps(self.serialize(), indent=4)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ImageSeries(PlotSeries):
|
|
19
|
+
def __init__(self, data, label: str = "", transform=None):
|
|
20
|
+
super().__init__(label)
|
|
21
|
+
self.data = data
|
|
22
|
+
self.series_type = "image"
|
|
23
|
+
self.transform = transform
|
|
24
|
+
|
|
25
|
+
def serialize(self):
|
|
26
|
+
ret = super().serialize()
|
|
27
|
+
ret["data"] = self.data
|
|
28
|
+
return ret
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class LinePlotSeries(PlotSeries):
|
|
32
|
+
def __init__(self, x: list[float], y: list[float], label: str = "") -> None:
|
|
33
|
+
super().__init__(label)
|
|
34
|
+
self.series_type = "line"
|
|
35
|
+
self.x = x
|
|
36
|
+
self.y = y
|
|
37
|
+
|
|
38
|
+
def serialize(self):
|
|
39
|
+
ret = super().serialize()
|
|
40
|
+
ret["x"] = self.x
|
|
41
|
+
ret["y"] = self.y
|
|
42
|
+
return ret
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ScatterPlotSeries(PlotSeries):
|
|
46
|
+
def __init__(self, data, label: str = ""):
|
|
47
|
+
super().__init__(label)
|
|
48
|
+
self.data = data
|
|
49
|
+
self.series_type = "scatter"
|
|
50
|
+
|
|
51
|
+
def serialize(self):
|
|
52
|
+
ret = super().serialize()
|
|
53
|
+
ret["data"] = self.data
|
|
54
|
+
return ret
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: icplot
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8
|
|
4
4
|
Summary: Utilities for generating plots and graphics for technical reports.
|
|
5
5
|
Author-email: "James Grogan, Irish Centre for High End Computing" <james.grogan@ichec.ie>
|
|
6
6
|
Project-URL: Repository, https://git.ichec.ie/performance/toolshed/icplot
|
|
@@ -16,13 +16,15 @@ Description-Content-Type: text/markdown
|
|
|
16
16
|
License-File: LICENSE
|
|
17
17
|
Requires-Dist: wand
|
|
18
18
|
Requires-Dist: matplotlib
|
|
19
|
-
Requires-Dist: iccore==0.0.
|
|
19
|
+
Requires-Dist: iccore==0.0.9
|
|
20
20
|
Provides-Extra: test
|
|
21
21
|
Requires-Dist: pytest; extra == "test"
|
|
22
22
|
Requires-Dist: pytest-cov; extra == "test"
|
|
23
23
|
Requires-Dist: pytest-sugar; extra == "test"
|
|
24
24
|
Requires-Dist: black; extra == "test"
|
|
25
25
|
Requires-Dist: mypy; extra == "test"
|
|
26
|
+
Requires-Dist: flake8; extra == "test"
|
|
27
|
+
Requires-Dist: pylint; extra == "test"
|
|
26
28
|
Provides-Extra: cairo
|
|
27
29
|
Requires-Dist: pycairo; extra == "cairo"
|
|
28
30
|
Requires-Dist: CairoSVG; extra == "cairo"
|
|
@@ -4,6 +4,7 @@ pyproject.toml
|
|
|
4
4
|
setup.cfg
|
|
5
5
|
src/icplot/__init__.py
|
|
6
6
|
src/icplot/cairo_interface.py
|
|
7
|
+
src/icplot/color.py
|
|
7
8
|
src/icplot/gantt.py
|
|
8
9
|
src/icplot/geometry.py
|
|
9
10
|
src/icplot/image_utils.py
|
|
@@ -16,7 +17,12 @@ src/icplot.egg-info/dependency_links.txt
|
|
|
16
17
|
src/icplot.egg-info/entry_points.txt
|
|
17
18
|
src/icplot.egg-info/requires.txt
|
|
18
19
|
src/icplot.egg-info/top_level.txt
|
|
20
|
+
src/icplot/graph/__init__.py
|
|
21
|
+
src/icplot/graph/matplotlib_plot_backend.py
|
|
22
|
+
src/icplot/graph/plot.py
|
|
23
|
+
src/icplot/graph/series.py
|
|
19
24
|
test/test_cairo_interface.py
|
|
20
25
|
test/test_gantt_chart.py
|
|
21
26
|
test/test_image_utils.py
|
|
27
|
+
test/test_line_plots.py
|
|
22
28
|
test/test_tex_interface.py
|
|
@@ -20,10 +20,9 @@ def test_gantt_chart():
|
|
|
20
20
|
milestone1.description = "Description of Milestone 1."
|
|
21
21
|
milestone1.start_date = datetime.date(2024, 7, 1)
|
|
22
22
|
milestone1.due_date = datetime.date(2024, 7, 15)
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
gantt = GanttChart()
|
|
25
|
-
gantt.milestones = [milestone0,
|
|
26
|
-
milestone1]
|
|
25
|
+
gantt.milestones = [milestone0, milestone1]
|
|
27
26
|
|
|
28
27
|
output_path = Path(os.getcwd()) / "gantt.svg"
|
|
29
28
|
|
|
@@ -3,9 +3,11 @@ from pathlib import Path
|
|
|
3
3
|
|
|
4
4
|
from icplot.image_utils import svg_to_png, svg_to_pdf
|
|
5
5
|
|
|
6
|
+
|
|
6
7
|
def get_test_data_dir():
|
|
7
8
|
return Path(__file__).parent / "data"
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
|
|
9
11
|
def test_convert_svg():
|
|
10
12
|
|
|
11
13
|
source = get_test_data_dir() / "test.svg"
|
|
@@ -17,5 +19,3 @@ def test_convert_svg():
|
|
|
17
19
|
pdf_out = Path(os.getcwd()) / "out.pdf"
|
|
18
20
|
svg_to_pdf(source, pdf_out)
|
|
19
21
|
pdf_out.unlink()
|
|
20
|
-
|
|
21
|
-
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from icplot.graph import Plot, LinePlotSeries
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_line_plot():
|
|
7
|
+
|
|
8
|
+
plot = Plot(
|
|
9
|
+
title="test", x_label="test_x", y_label="test_y", legend_label="test_legend"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
data = [([0, 5, 10], [1, 2, 3]), ([0, 5, 10], [3, 6, 9]), ([0, 5, 10], [4, 8, 12])]
|
|
13
|
+
|
|
14
|
+
for idx, [x, y] in enumerate(data):
|
|
15
|
+
plot.add_series(LinePlotSeries(x, y, label=f"Series {idx}"))
|
|
16
|
+
|
|
17
|
+
plot.set_x_ticks(0, 10, 5)
|
|
18
|
+
|
|
19
|
+
output_path = Path() / "output.svg"
|
|
20
|
+
plot.plot(output_path)
|
|
21
|
+
|
|
22
|
+
assert output_path.exists()
|
|
23
|
+
output_path.unlink()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|