icplot 0.0.7__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.
Files changed (31) hide show
  1. {icplot-0.0.7/src/icplot.egg-info → icplot-0.0.8}/PKG-INFO +1 -1
  2. {icplot-0.0.7 → icplot-0.0.8}/pyproject.toml +1 -1
  3. icplot-0.0.8/src/icplot/color.py +13 -0
  4. {icplot-0.0.7 → icplot-0.0.8}/src/icplot/geometry.py +1 -7
  5. icplot-0.0.8/src/icplot/graph/matplotlib_plot_backend.py +69 -0
  6. icplot-0.0.8/src/icplot/graph/plot.py +163 -0
  7. icplot-0.0.8/src/icplot/graph/series.py +54 -0
  8. {icplot-0.0.7 → icplot-0.0.8/src/icplot.egg-info}/PKG-INFO +1 -1
  9. {icplot-0.0.7 → icplot-0.0.8}/src/icplot.egg-info/SOURCES.txt +3 -0
  10. {icplot-0.0.7 → icplot-0.0.8}/test/test_cairo_interface.py +1 -0
  11. {icplot-0.0.7 → icplot-0.0.8}/test/test_gantt_chart.py +2 -3
  12. {icplot-0.0.7 → icplot-0.0.8}/test/test_image_utils.py +3 -3
  13. icplot-0.0.8/test/test_line_plots.py +23 -0
  14. {icplot-0.0.7 → icplot-0.0.8}/test/test_tex_interface.py +1 -0
  15. icplot-0.0.7/src/icplot/graph/plot.py +0 -200
  16. icplot-0.0.7/test/test_line_plots.py +0 -26
  17. {icplot-0.0.7 → icplot-0.0.8}/LICENSE +0 -0
  18. {icplot-0.0.7 → icplot-0.0.8}/README.md +0 -0
  19. {icplot-0.0.7 → icplot-0.0.8}/setup.cfg +0 -0
  20. {icplot-0.0.7 → icplot-0.0.8}/src/icplot/__init__.py +0 -0
  21. {icplot-0.0.7 → icplot-0.0.8}/src/icplot/cairo_interface.py +0 -0
  22. {icplot-0.0.7 → icplot-0.0.8}/src/icplot/gantt.py +0 -0
  23. {icplot-0.0.7 → icplot-0.0.8}/src/icplot/graph/__init__.py +0 -0
  24. {icplot-0.0.7 → icplot-0.0.8}/src/icplot/image_utils.py +0 -0
  25. {icplot-0.0.7 → icplot-0.0.8}/src/icplot/main_cli.py +0 -0
  26. {icplot-0.0.7 → icplot-0.0.8}/src/icplot/project_elements.py +0 -0
  27. {icplot-0.0.7 → icplot-0.0.8}/src/icplot/tex_interface.py +0 -0
  28. {icplot-0.0.7 → icplot-0.0.8}/src/icplot.egg-info/dependency_links.txt +0 -0
  29. {icplot-0.0.7 → icplot-0.0.8}/src/icplot.egg-info/entry_points.txt +0 -0
  30. {icplot-0.0.7 → icplot-0.0.8}/src/icplot.egg-info/requires.txt +0 -0
  31. {icplot-0.0.7 → 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.7
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "icplot"
3
- version = "0.0.7"
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
  ]
@@ -0,0 +1,13 @@
1
+ class Color:
2
+
3
+ def __init__(self, r=1, g=1, b=1, a=1):
4
+ self.r = r
5
+ self.g = g
6
+ self.b = b
7
+ self.a = a
8
+
9
+
10
+ class ColorMap:
11
+
12
+ def __init__(self, label: str):
13
+ self.label = label
@@ -1,10 +1,4 @@
1
- class Color:
2
-
3
- def __init__(self, r=1, g=1, b=1, a=1):
4
- self.r = r
5
- self.g = g
6
- self.b = b
7
- self.a = a
1
+ from .color import Color
8
2
 
9
3
 
10
4
  class Font:
@@ -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.7
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
@@ -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
@@ -17,7 +18,9 @@ src/icplot.egg-info/entry_points.txt
17
18
  src/icplot.egg-info/requires.txt
18
19
  src/icplot.egg-info/top_level.txt
19
20
  src/icplot/graph/__init__.py
21
+ src/icplot/graph/matplotlib_plot_backend.py
20
22
  src/icplot/graph/plot.py
23
+ src/icplot/graph/series.py
21
24
  test/test_cairo_interface.py
22
25
  test/test_gantt_chart.py
23
26
  test/test_image_utils.py
@@ -1,5 +1,6 @@
1
1
  from icplot.cairo_interface import CairoInterface
2
2
 
3
+
3
4
  def test_cairo_interface():
4
5
 
5
6
  cairo_interface = CairoInterface()
@@ -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()
@@ -3,6 +3,7 @@ import shutil
3
3
  from pathlib import Path
4
4
  from icplot.tex_interface import TexInterface
5
5
 
6
+
6
7
  def test_tex_interface():
7
8
 
8
9
  build_dir = Path(os.getcwd()) / "tmp_build"
@@ -1,200 +0,0 @@
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
-
9
- import logging
10
-
11
- logging.getLogger("matplotlib").setLevel(logging.WARNING)
12
- import matplotlib # NOQA
13
-
14
- matplotlib.use("Agg")
15
- import matplotlib.pyplot as plt # NOQA
16
- import matplotlib as mpl # NOQA
17
-
18
-
19
- class PlotSeries:
20
-
21
- def __init__(self, label: str = ""):
22
- self.label = label
23
-
24
-
25
- class LinePlotSeries(PlotSeries):
26
- def __init__(self, x: list[float], y: list[float], label: str = "") -> None:
27
- super().__init__(label)
28
- self.x = x
29
- self.y = y
30
-
31
-
32
- class MatplotlibPlotter:
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 render(self, path: Path | None = None):
54
- if path:
55
- plt.savefig(path)
56
- else:
57
- plt.show()
58
-
59
-
60
- class Plot:
61
- def __init__(
62
- self,
63
- title: str = "",
64
- x_label: str = "",
65
- y_label: str = "",
66
- legend_label: str = "",
67
- ) -> None:
68
- self.series: list[PlotSeries] = []
69
- self.title = title
70
- self.plot_type = ""
71
- self.x_label = x_label
72
- self.y_label = y_label
73
- self.legend_label = legend_label
74
- self.c_map = mpl.colormaps["viridis"]
75
- self.x_ticks = None
76
- self.y_ticks = None
77
- self.impl = MatplotlibPlotter()
78
-
79
- def get_colour(self, curr, values, c_map):
80
- """
81
- Returns a colour based on a cmap and how far across
82
- the datasets you are
83
- """
84
- length = len(values)
85
- position = curr / length
86
- return c_map(0.25 + (position / 2))
87
-
88
- def set_colour_map(self, cmap="viridis"):
89
- self.c_map = mpl.colormaps[cmap]
90
-
91
- def set_x_ticks(self, lower, upper, step):
92
- self.x_ticks = range(lower, upper + 1, step)
93
-
94
- def set_y_ticks(self, lower, upper, step):
95
- self.y_ticks = range(lower, upper + 1, step)
96
-
97
- def set_decorations(self):
98
- self.impl.set_decorations(
99
- self.x_label, self.y_label, self.title, self.x_ticks, self.y_ticks
100
- )
101
-
102
- def plot(self, path: Path | None = None):
103
- raise NotImplementedError()
104
-
105
-
106
- class LinePlot(Plot):
107
-
108
- def plot(self, path: Path | None = None):
109
-
110
- first = True
111
- for i, series in enumerate(self.series):
112
- colour = self.get_colour(i, self.series, self.c_map)
113
- label = f"{series.label}"
114
- if first and self.legend_label:
115
- label = f"{label} {self.legend_label}"
116
- first = False
117
- line_series = cast(LinePlotSeries, series)
118
- self.impl.plot_line(line_series.x, line_series.y, label=label, color=colour)
119
-
120
- self.set_decorations()
121
- self.impl.render(path)
122
-
123
-
124
- class MultiFigureLinePlotter:
125
- """
126
- Plot with multiple figures. Each is a line plot
127
- """
128
-
129
- def __init__(self, data: dict, figures: list, xlabel: str) -> None:
130
- self.data = data
131
- self.figures = figures
132
- self.size: tuple = (10, 5)
133
- self.xlabel = xlabel
134
- self.output_fmt = "svg"
135
-
136
- def _plot_line(self, key: str, label: str):
137
- plt.plot(self.data[key], label=label)
138
-
139
- def _decorate(self, ylabel: str, title: str):
140
- plt.title(title)
141
- plt.xlabel(self.xlabel)
142
- plt.ylabel(ylabel)
143
- plt.legend()
144
- plt.show()
145
-
146
- def plot(self, output_path: Path):
147
- """
148
- Do the plot
149
- """
150
-
151
- for idx, figure_info in enumerate(self.figures):
152
- plt.figure(figsize=self.size)
153
-
154
- for data_key, label in zip(figure_info["keys"], figure_info["labels"]):
155
- self._plot_line(data_key, label)
156
-
157
- title = figure_info["title"]
158
- ylabel = figure_info["ylabel"]
159
-
160
- self._decorate(ylabel, title)
161
- plt.savefig(str(output_path) + f"_{idx}.{self.output_fmt}")
162
-
163
-
164
- class DatasetGridPlotter:
165
- """
166
- Plot a dataset on a grid. A dataset has pairs of images corresponding
167
- to an image and an associated mask.
168
- """
169
-
170
- def __init__(
171
- self, title: str = "", stride: int = 4, size: tuple = (25, 20)
172
- ) -> None:
173
- self.title = title
174
- self.stride = stride
175
- self.size = size
176
-
177
- def _plot_grid_element(self, rows: int, cols: int, count: int, image, transform):
178
- plt.subplot(rows, cols, count)
179
- if transform:
180
- plt.imshow(transform.reverse(image.squeeze(0).float()))
181
- else:
182
- plt.imshow(image.squeeze(0).float())
183
- plt.axis("off")
184
- plt.title(self.title)
185
- return count + 1
186
-
187
- def plot(self, data, num_samples: int, output_path: Path, transform=None):
188
- plt.figure(figsize=self.size)
189
- rows = num_samples // self.stride
190
- cols = num_samples // rows
191
- count = 1
192
- indices = [random.randint(0, len(data) - 1) for _ in range(num_samples)]
193
-
194
- for index in indices:
195
- if count == num_samples + 1:
196
- break
197
- x, y = data[index]
198
- count = self._plot_grid_element(rows, cols, count, x, transform)
199
- count = self._plot_grid_element(rows, cols, count, y, transform)
200
- plt.savefig(output_path)
@@ -1,26 +0,0 @@
1
- from pathlib import Path
2
-
3
- from icplot.graph import LinePlot, LinePlotSeries
4
-
5
-
6
- def test_line_plot():
7
-
8
- plot = LinePlot(title="test",
9
- x_label="test_x",
10
- y_label="test_y",
11
- legend_label="test_legend")
12
-
13
- data = [([0, 5, 10], [1, 2, 3]),
14
- ([0, 5, 10], [3, 6, 9]),
15
- ([0, 5, 10], [4, 8, 12])]
16
-
17
- for idx, [x, y] in enumerate(data):
18
- plot.series.append(LinePlotSeries(x, y, label=f"Series {idx}"))
19
-
20
- plot.set_x_ticks(0, 10, 5)
21
-
22
- output_path = Path() / "output.svg"
23
- plot.plot(output_path)
24
-
25
- assert output_path.exists()
26
- output_path.unlink()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes