icplot 0.1.0__tar.gz → 0.1.2__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.1.0/src/icplot.egg-info → icplot-0.1.2}/PKG-INFO +23 -18
- {icplot-0.1.0 → icplot-0.1.2}/README.md +21 -16
- {icplot-0.1.0 → icplot-0.1.2}/pyproject.toml +6 -6
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/color.py +3 -6
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/gantt/gantt.py +1 -1
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/graph/__init__.py +1 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/graph/axis.py +5 -2
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/graph/generator.py +3 -7
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/graph/matplotlib.py +44 -19
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/graph/plot.py +17 -11
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/graph/series.py +14 -4
- icplot-0.1.2/src/icplot/trace/trace.py +0 -0
- {icplot-0.1.0 → icplot-0.1.2/src/icplot.egg-info}/PKG-INFO +23 -18
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot.egg-info/requires.txt +1 -1
- {icplot-0.1.0 → icplot-0.1.2}/test/test_cairo_interface.py +6 -6
- icplot-0.1.2/test/test_gantt_chart.py +26 -0
- {icplot-0.1.0 → icplot-0.1.2}/test/test_line_plots.py +8 -9
- {icplot-0.1.0 → icplot-0.1.2}/test/test_tex_interface.py +3 -3
- icplot-0.1.0/src/icplot/__init__.py +0 -3
- icplot-0.1.0/test/test_gantt_chart.py +0 -26
- {icplot-0.1.0 → icplot-0.1.2}/LICENSE +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/setup.cfg +0 -0
- /icplot-0.1.0/src/icplot/py.typed → /icplot-0.1.2/src/icplot/__init__.py +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/cairo_interface.py +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/convert.py +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/gantt/__init__.py +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/gantt/gantt_renderer.py +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/gantt/pgfgantt.py +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/geometry.py +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/image_utils.py +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/main_cli.py +0 -0
- /icplot-0.1.0/src/icplot/trace/trace.py → /icplot-0.1.2/src/icplot/py.typed +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/tex.py +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot/trace/__init__.py +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot.egg-info/SOURCES.txt +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot.egg-info/dependency_links.txt +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot.egg-info/entry_points.txt +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/src/icplot.egg-info/top_level.txt +0 -0
- {icplot-0.1.0 → icplot-0.1.2}/test/test_image_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: icplot
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
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,7 +16,7 @@ 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.1.
|
|
19
|
+
Requires-Dist: iccore==0.1.8
|
|
20
20
|
Provides-Extra: test
|
|
21
21
|
Requires-Dist: pytest; extra == "test"
|
|
22
22
|
Requires-Dist: pytest-cov; extra == "test"
|
|
@@ -31,41 +31,46 @@ Requires-Dist: CairoSVG; extra == "cairo"
|
|
|
31
31
|
|
|
32
32
|
# icplot
|
|
33
33
|
|
|
34
|
-
This
|
|
34
|
+
This is a library used at [The Irish Centre for High End Computing (ICHEC)](https://www.ichec.ie) for generating plots and graphics for technical documents.
|
|
35
35
|
|
|
36
|
-
#
|
|
36
|
+
# Features #
|
|
37
37
|
|
|
38
|
-
The
|
|
38
|
+
The project has support for:
|
|
39
|
+
|
|
40
|
+
* Coverting image formats between pdf, svg and png
|
|
41
|
+
* Building pdf output from tex files, including tikz.
|
|
42
|
+
* Generating plots based on a serializable data model to support reproducible research
|
|
43
|
+
|
|
44
|
+
To covert between image formats you can do:
|
|
39
45
|
|
|
40
46
|
``` shell
|
|
41
|
-
|
|
47
|
+
icplot convert --source my_image.svg --target my_image.png
|
|
42
48
|
```
|
|
43
49
|
|
|
44
|
-
|
|
50
|
+
To render a Tex tikz image as pdf and png you can do:
|
|
45
51
|
|
|
46
52
|
``` shell
|
|
47
|
-
|
|
53
|
+
icplot convert --source my_tikz.tex
|
|
48
54
|
```
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
To generate a plot or collection of plots from a yaml description you can do:
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
* Building pdf output from tex files, including tikz.
|
|
58
|
+
``` shell
|
|
59
|
+
icplot plot --config my_plot.yml
|
|
60
|
+
```
|
|
56
61
|
|
|
57
|
-
|
|
62
|
+
# Installation #
|
|
58
63
|
|
|
59
|
-
|
|
64
|
+
The package is available on PyPI. For a minimal installation you can do:
|
|
60
65
|
|
|
61
66
|
``` shell
|
|
62
|
-
|
|
67
|
+
pip install icplot
|
|
63
68
|
```
|
|
64
69
|
|
|
65
|
-
|
|
70
|
+
For full functionality, particularly conversion of image formats, `imagemagick` and `cairo` are required. On Mac you can install them with:
|
|
66
71
|
|
|
67
72
|
``` shell
|
|
68
|
-
|
|
73
|
+
brew install imagemagick cairo
|
|
69
74
|
```
|
|
70
75
|
|
|
71
76
|
# Copyright #
|
|
@@ -1,40 +1,45 @@
|
|
|
1
1
|
# icplot
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This is a library used at [The Irish Centre for High End Computing (ICHEC)](https://www.ichec.ie) for generating plots and graphics for technical documents.
|
|
4
4
|
|
|
5
|
-
#
|
|
5
|
+
# Features #
|
|
6
6
|
|
|
7
|
-
The
|
|
7
|
+
The project has support for:
|
|
8
|
+
|
|
9
|
+
* Coverting image formats between pdf, svg and png
|
|
10
|
+
* Building pdf output from tex files, including tikz.
|
|
11
|
+
* Generating plots based on a serializable data model to support reproducible research
|
|
12
|
+
|
|
13
|
+
To covert between image formats you can do:
|
|
8
14
|
|
|
9
15
|
``` shell
|
|
10
|
-
|
|
16
|
+
icplot convert --source my_image.svg --target my_image.png
|
|
11
17
|
```
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
To render a Tex tikz image as pdf and png you can do:
|
|
14
20
|
|
|
15
21
|
``` shell
|
|
16
|
-
|
|
22
|
+
icplot convert --source my_tikz.tex
|
|
17
23
|
```
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
To generate a plot or collection of plots from a yaml description you can do:
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
* Building pdf output from tex files, including tikz.
|
|
27
|
+
``` shell
|
|
28
|
+
icplot plot --config my_plot.yml
|
|
29
|
+
```
|
|
25
30
|
|
|
26
|
-
|
|
31
|
+
# Installation #
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
The package is available on PyPI. For a minimal installation you can do:
|
|
29
34
|
|
|
30
35
|
``` shell
|
|
31
|
-
|
|
36
|
+
pip install icplot
|
|
32
37
|
```
|
|
33
38
|
|
|
34
|
-
|
|
39
|
+
For full functionality, particularly conversion of image formats, `imagemagick` and `cairo` are required. On Mac you can install them with:
|
|
35
40
|
|
|
36
41
|
``` shell
|
|
37
|
-
|
|
42
|
+
brew install imagemagick cairo
|
|
38
43
|
```
|
|
39
44
|
|
|
40
45
|
# Copyright #
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "icplot"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.2"
|
|
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.1.
|
|
21
|
+
"iccore==0.1.8"]
|
|
22
22
|
|
|
23
23
|
[project.urls]
|
|
24
24
|
Repository = "https://git.ichec.ie/performance/toolshed/icplot"
|
|
@@ -41,7 +41,7 @@ cairo = [
|
|
|
41
41
|
]
|
|
42
42
|
|
|
43
43
|
[build-system]
|
|
44
|
-
requires = ["setuptools
|
|
44
|
+
requires = ["setuptools", "wheel"]
|
|
45
45
|
build-backend = "setuptools.build_meta"
|
|
46
46
|
|
|
47
47
|
[project.scripts]
|
|
@@ -73,7 +73,7 @@ skip_missing_interpreters = true
|
|
|
73
73
|
[testenv]
|
|
74
74
|
description = run unit tests
|
|
75
75
|
deps =
|
|
76
|
-
pytest
|
|
76
|
+
pytest
|
|
77
77
|
pytest-sugar
|
|
78
78
|
pytest-cov
|
|
79
79
|
.[cairo]
|
|
@@ -85,7 +85,7 @@ description = run linters
|
|
|
85
85
|
skip_install = true
|
|
86
86
|
deps =
|
|
87
87
|
black
|
|
88
|
-
commands = black {posargs:src}
|
|
88
|
+
commands = black {posargs:src test}
|
|
89
89
|
|
|
90
90
|
[testenv:style]
|
|
91
91
|
description = run style check
|
|
@@ -97,7 +97,7 @@ commands = flake8 {posargs:src}
|
|
|
97
97
|
[testenv:type]
|
|
98
98
|
description = run type checks
|
|
99
99
|
deps =
|
|
100
|
-
mypy
|
|
100
|
+
mypy
|
|
101
101
|
commands =
|
|
102
102
|
mypy {posargs:src test}
|
|
103
103
|
|
|
@@ -7,7 +7,7 @@ from typing import Callable
|
|
|
7
7
|
from pydantic import BaseModel
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
class Color(BaseModel):
|
|
10
|
+
class Color(BaseModel, frozen=True):
|
|
11
11
|
"""
|
|
12
12
|
A color class, internal storage is rgba as float.
|
|
13
13
|
"""
|
|
@@ -31,9 +31,6 @@ class Color(BaseModel):
|
|
|
31
31
|
def is_black(self) -> bool:
|
|
32
32
|
return self.r == 0.0 and self.g == 0.0 and self.b == 0.0 and self.a == 1.0
|
|
33
33
|
|
|
34
|
-
def serialize(self) -> str:
|
|
35
|
-
return f"r: {self.r}, g: {self.g}, b: {self.b}, a: {self.a}"
|
|
36
|
-
|
|
37
34
|
|
|
38
35
|
class ColorMap:
|
|
39
36
|
"""
|
|
@@ -44,10 +41,10 @@ class ColorMap:
|
|
|
44
41
|
self.label = label
|
|
45
42
|
self.data_func = data_func
|
|
46
43
|
|
|
47
|
-
def get_color(self, cursor: int,
|
|
44
|
+
def get_color(self, cursor: int, count: int) -> Color:
|
|
48
45
|
"""
|
|
49
46
|
Returns a colour based on a cmap and how far across
|
|
50
47
|
the datasets you are
|
|
51
48
|
"""
|
|
52
|
-
position = cursor / (max(
|
|
49
|
+
position = cursor / (max(count - 1, 1))
|
|
53
50
|
return Color.from_list(self.data_func(position))
|
|
@@ -5,7 +5,7 @@ This module has a plot's axis
|
|
|
5
5
|
from pydantic import BaseModel
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class Range(BaseModel):
|
|
8
|
+
class Range(BaseModel, frozen=True):
|
|
9
9
|
"""
|
|
10
10
|
This is a sequence of numbers specified by lower and upper
|
|
11
11
|
bounds and a step size. Eg (1, 5, 1) gives: [1, 2, 3, 4]
|
|
@@ -19,9 +19,12 @@ class Range(BaseModel):
|
|
|
19
19
|
return list(range(self.lower, self.upper, self.step))
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class PlotAxis(BaseModel):
|
|
22
|
+
class PlotAxis(BaseModel, frozen=True):
|
|
23
23
|
"""
|
|
24
24
|
This is a plot's axis
|
|
25
|
+
|
|
26
|
+
:param str label: The axis label
|
|
27
|
+
:param Range | None: A specification for tick marks
|
|
25
28
|
"""
|
|
26
29
|
|
|
27
30
|
label: str = ""
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
from typing import Any, Callable
|
|
2
|
-
import copy
|
|
3
2
|
import os
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
|
|
@@ -12,7 +11,7 @@ from .series import LinePlotSeries
|
|
|
12
11
|
from .matplotlib import render
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
class PlotConfig(BaseModel):
|
|
14
|
+
class PlotConfig(BaseModel, frozen=True):
|
|
16
15
|
|
|
17
16
|
series_attr: str
|
|
18
17
|
x_attr: str
|
|
@@ -36,10 +35,8 @@ def make_plots(
|
|
|
36
35
|
# Each 'y attribute' in the config corresponds to a 'plot' of this
|
|
37
36
|
# attribute's values.
|
|
38
37
|
for y_attr, plot_template in config.plots.items():
|
|
39
|
-
new_plot = copy.deepcopy(plot_template)
|
|
40
|
-
new_plot.name = y_attr
|
|
41
|
-
series = []
|
|
42
38
|
|
|
39
|
+
series = []
|
|
43
40
|
for label in series_labels:
|
|
44
41
|
# Get results for this series
|
|
45
42
|
label_results = [
|
|
@@ -65,8 +62,7 @@ def make_plots(
|
|
|
65
62
|
)
|
|
66
63
|
else:
|
|
67
64
|
series.append(LinePlotSeries(x=x, y=y, label=label))
|
|
68
|
-
|
|
69
|
-
plots.append(new_plot)
|
|
65
|
+
plots.append(plot_template.copy(update={"name": y_attr, "series": series}))
|
|
70
66
|
return plots
|
|
71
67
|
|
|
72
68
|
|
|
@@ -9,9 +9,9 @@ default_backend = mpl.get_backend()
|
|
|
9
9
|
mpl.use("Agg")
|
|
10
10
|
import matplotlib.pyplot as plt # NOQA
|
|
11
11
|
|
|
12
|
-
from icplot.color import ColorMap # NOQA
|
|
12
|
+
from icplot.color import ColorMap, Color # NOQA
|
|
13
13
|
from .series import PlotSeries, LinePlotSeries, ScatterPlotSeries, ImageSeries # NOQA
|
|
14
|
-
from .plot import Plot, GridPlot,
|
|
14
|
+
from .plot import Plot, GridPlot, get_series_colors # NOQA
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
class MatplotlibColorMap(ColorMap):
|
|
@@ -23,32 +23,53 @@ class MatplotlibColorMap(ColorMap):
|
|
|
23
23
|
super().__init__(label, mpl.colormaps[label])
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
def _set_decorations(
|
|
27
|
-
ax
|
|
26
|
+
def _set_decorations(axs, plot: Plot):
|
|
27
|
+
ax = axs[0]
|
|
28
|
+
if plot.legend.lower() != "none":
|
|
29
|
+
ax.legend(loc=plot.legend)
|
|
28
30
|
if plot.x_axis.label:
|
|
29
31
|
ax.set_xlabel(plot.x_axis.label)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
for idx, y_axis in enumerate(plot.y_axes):
|
|
33
|
+
if y_axis.label:
|
|
34
|
+
axs[idx].set_ylabel(y_axis.label)
|
|
35
|
+
if y_axis.ticks:
|
|
36
|
+
axs[idx].set_yticks(y_axis.resolved_ticks)
|
|
32
37
|
if plot.x_axis.ticks:
|
|
33
38
|
ax.set_xticks(plot.x_axis.resolved_ticks)
|
|
34
|
-
if plot.y_axis.ticks:
|
|
35
|
-
ax.set_yticks(plot.y_axis.resolved_ticks)
|
|
36
39
|
if plot.title:
|
|
37
40
|
ax.set_title(plot.title)
|
|
38
41
|
|
|
39
42
|
|
|
40
|
-
def _plot_line(
|
|
43
|
+
def _plot_line(axs, series: LinePlotSeries, color: Color | None):
|
|
44
|
+
if not series.position_right:
|
|
45
|
+
ax = axs[0]
|
|
46
|
+
else:
|
|
47
|
+
ax = axs[1]
|
|
48
|
+
|
|
49
|
+
if color:
|
|
50
|
+
render_color: list | None = series.color.as_list()
|
|
51
|
+
else:
|
|
52
|
+
render_color = None
|
|
53
|
+
|
|
41
54
|
ax.plot(
|
|
42
55
|
series.x,
|
|
43
56
|
series.y,
|
|
44
57
|
label=series.label,
|
|
45
|
-
color=
|
|
58
|
+
color=render_color,
|
|
46
59
|
marker=series.marker,
|
|
60
|
+
drawstyle=series.drawstyle,
|
|
61
|
+
linestyle=series.linestyle,
|
|
47
62
|
)
|
|
48
63
|
|
|
49
64
|
|
|
50
|
-
def _plot_scatter(ax, series: ScatterPlotSeries):
|
|
51
|
-
|
|
65
|
+
def _plot_scatter(ax, series: ScatterPlotSeries, color: Color | None):
|
|
66
|
+
|
|
67
|
+
if color:
|
|
68
|
+
render_color: list | None = series.color.as_list()
|
|
69
|
+
else:
|
|
70
|
+
render_color = None
|
|
71
|
+
|
|
72
|
+
ax.scatter(series.data, label=series.label, color=render_color)
|
|
52
73
|
|
|
53
74
|
|
|
54
75
|
def _plot_image(ax, series: ImageSeries):
|
|
@@ -56,11 +77,12 @@ def _plot_image(ax, series: ImageSeries):
|
|
|
56
77
|
ax.axis("off")
|
|
57
78
|
|
|
58
79
|
|
|
59
|
-
def _plot_series(
|
|
80
|
+
def _plot_series(axs, series: PlotSeries, color: Color | None = None):
|
|
81
|
+
ax = axs[0]
|
|
60
82
|
if series.series_type == "line":
|
|
61
|
-
_plot_line(
|
|
83
|
+
_plot_line(axs, cast(LinePlotSeries, series), color)
|
|
62
84
|
elif series.series_type == "scatter":
|
|
63
|
-
_plot_scatter(ax, cast(ScatterPlotSeries, series))
|
|
85
|
+
_plot_scatter(ax, cast(ScatterPlotSeries, series), color)
|
|
64
86
|
elif series.series_type == "image":
|
|
65
87
|
_plot_image(ax, cast(ImageSeries, series))
|
|
66
88
|
|
|
@@ -78,14 +100,17 @@ def render(
|
|
|
78
100
|
plot: Plot, path: Path | None = None, cmap=MatplotlibColorMap("gist_rainbow")
|
|
79
101
|
):
|
|
80
102
|
|
|
81
|
-
|
|
103
|
+
colors = get_series_colors(cmap, plot)
|
|
82
104
|
|
|
83
105
|
fig, ax = plt.subplots()
|
|
106
|
+
axs = [ax]
|
|
107
|
+
if len(plot.y_axes) > 1:
|
|
108
|
+
axs.append(ax.twinx())
|
|
84
109
|
|
|
85
|
-
for series in plot.series:
|
|
86
|
-
_plot_series(
|
|
110
|
+
for series, color in zip(plot.series, colors):
|
|
111
|
+
_plot_series(axs, series, color)
|
|
87
112
|
|
|
88
|
-
_set_decorations(
|
|
113
|
+
_set_decorations(axs, plot)
|
|
89
114
|
|
|
90
115
|
_render(fig, path)
|
|
91
116
|
|
|
@@ -6,13 +6,13 @@ import random
|
|
|
6
6
|
|
|
7
7
|
from pydantic import BaseModel
|
|
8
8
|
|
|
9
|
-
from icplot.color import ColorMap
|
|
9
|
+
from icplot.color import ColorMap, Color
|
|
10
10
|
|
|
11
11
|
from .axis import PlotAxis
|
|
12
12
|
from .series import PlotSeries
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class Plot(BaseModel):
|
|
15
|
+
class Plot(BaseModel, frozen=True):
|
|
16
16
|
"""
|
|
17
17
|
A generic plot with optional axis ticks
|
|
18
18
|
"""
|
|
@@ -21,12 +21,13 @@ class Plot(BaseModel):
|
|
|
21
21
|
legend_label: str = ""
|
|
22
22
|
name: str = ""
|
|
23
23
|
x_axis: PlotAxis = PlotAxis()
|
|
24
|
-
|
|
24
|
+
y_axes: list[PlotAxis] = [PlotAxis()]
|
|
25
25
|
plot_type: str = ""
|
|
26
26
|
series: list[PlotSeries] = []
|
|
27
|
+
legend: str = "none"
|
|
27
28
|
|
|
28
29
|
|
|
29
|
-
class GridPlot(Plot):
|
|
30
|
+
class GridPlot(Plot, frozen=True):
|
|
30
31
|
"""
|
|
31
32
|
Make a grid of plots
|
|
32
33
|
"""
|
|
@@ -64,11 +65,16 @@ class GridPlot(Plot):
|
|
|
64
65
|
return rows, cols, subplots
|
|
65
66
|
|
|
66
67
|
|
|
67
|
-
def
|
|
68
|
-
non_highlight = []
|
|
69
|
-
for idx, series in enumerate(plot.series):
|
|
70
|
-
if not series.highlight:
|
|
71
|
-
non_highlight.append(series)
|
|
68
|
+
def get_series_colors(cmap: ColorMap, plot: Plot) -> list[Color | None]:
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
count = 0
|
|
71
|
+
num_colorable = len([s for s in plot.series if not s.highlight])
|
|
72
|
+
colors = []
|
|
73
|
+
for s in plot.series:
|
|
74
|
+
if not s.highlight:
|
|
75
|
+
color = cmap.get_color(count, num_colorable)
|
|
76
|
+
count = count + 1
|
|
77
|
+
else:
|
|
78
|
+
color = None
|
|
79
|
+
colors.append(color)
|
|
80
|
+
return colors
|
|
@@ -5,18 +5,22 @@ from pydantic import BaseModel
|
|
|
5
5
|
from icplot.color import Color
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class PlotSeries(BaseModel):
|
|
8
|
+
class PlotSeries(BaseModel, frozen=True):
|
|
9
9
|
"""
|
|
10
10
|
A data series in a plot, such as a single line in a line-plot
|
|
11
|
+
|
|
12
|
+
:param position_right: allows the series to be plotted on the right y-axis.
|
|
13
|
+
:type position_right: bool, optional
|
|
11
14
|
"""
|
|
12
15
|
|
|
13
16
|
label: str
|
|
14
17
|
color: Color = Color()
|
|
15
18
|
series_type: str = ""
|
|
16
19
|
highlight: bool = False
|
|
20
|
+
position_right: bool = False
|
|
17
21
|
|
|
18
22
|
|
|
19
|
-
class ImageSeries(PlotSeries):
|
|
23
|
+
class ImageSeries(PlotSeries, frozen=True):
|
|
20
24
|
"""
|
|
21
25
|
A plot data series where the elements are images
|
|
22
26
|
"""
|
|
@@ -26,18 +30,24 @@ class ImageSeries(PlotSeries):
|
|
|
26
30
|
series_type: str = "image"
|
|
27
31
|
|
|
28
32
|
|
|
29
|
-
class LinePlotSeries(PlotSeries):
|
|
33
|
+
class LinePlotSeries(PlotSeries, frozen=True):
|
|
30
34
|
"""
|
|
31
35
|
A plot series for line plots
|
|
36
|
+
|
|
37
|
+
:param drawstyle: Naming comes from matplotlib API, allows for various square plots,
|
|
38
|
+
default is a normal point to point line plot.
|
|
39
|
+
:type drawstyle: str, optional
|
|
32
40
|
"""
|
|
33
41
|
|
|
34
42
|
x: list
|
|
35
43
|
y: list
|
|
36
44
|
marker: str = "o"
|
|
37
45
|
series_type: str = "line"
|
|
46
|
+
drawstyle: str = "default"
|
|
47
|
+
linestyle: str = "-"
|
|
38
48
|
|
|
39
49
|
|
|
40
|
-
class ScatterPlotSeries(PlotSeries):
|
|
50
|
+
class ScatterPlotSeries(PlotSeries, frozen=True):
|
|
41
51
|
|
|
42
52
|
data: typing.Any
|
|
43
53
|
series_type: str = "scatter"
|
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: icplot
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
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,7 +16,7 @@ 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.1.
|
|
19
|
+
Requires-Dist: iccore==0.1.8
|
|
20
20
|
Provides-Extra: test
|
|
21
21
|
Requires-Dist: pytest; extra == "test"
|
|
22
22
|
Requires-Dist: pytest-cov; extra == "test"
|
|
@@ -31,41 +31,46 @@ Requires-Dist: CairoSVG; extra == "cairo"
|
|
|
31
31
|
|
|
32
32
|
# icplot
|
|
33
33
|
|
|
34
|
-
This
|
|
34
|
+
This is a library used at [The Irish Centre for High End Computing (ICHEC)](https://www.ichec.ie) for generating plots and graphics for technical documents.
|
|
35
35
|
|
|
36
|
-
#
|
|
36
|
+
# Features #
|
|
37
37
|
|
|
38
|
-
The
|
|
38
|
+
The project has support for:
|
|
39
|
+
|
|
40
|
+
* Coverting image formats between pdf, svg and png
|
|
41
|
+
* Building pdf output from tex files, including tikz.
|
|
42
|
+
* Generating plots based on a serializable data model to support reproducible research
|
|
43
|
+
|
|
44
|
+
To covert between image formats you can do:
|
|
39
45
|
|
|
40
46
|
``` shell
|
|
41
|
-
|
|
47
|
+
icplot convert --source my_image.svg --target my_image.png
|
|
42
48
|
```
|
|
43
49
|
|
|
44
|
-
|
|
50
|
+
To render a Tex tikz image as pdf and png you can do:
|
|
45
51
|
|
|
46
52
|
``` shell
|
|
47
|
-
|
|
53
|
+
icplot convert --source my_tikz.tex
|
|
48
54
|
```
|
|
49
55
|
|
|
50
|
-
|
|
56
|
+
To generate a plot or collection of plots from a yaml description you can do:
|
|
51
57
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
* Building pdf output from tex files, including tikz.
|
|
58
|
+
``` shell
|
|
59
|
+
icplot plot --config my_plot.yml
|
|
60
|
+
```
|
|
56
61
|
|
|
57
|
-
|
|
62
|
+
# Installation #
|
|
58
63
|
|
|
59
|
-
|
|
64
|
+
The package is available on PyPI. For a minimal installation you can do:
|
|
60
65
|
|
|
61
66
|
``` shell
|
|
62
|
-
|
|
67
|
+
pip install icplot
|
|
63
68
|
```
|
|
64
69
|
|
|
65
|
-
|
|
70
|
+
For full functionality, particularly conversion of image formats, `imagemagick` and `cairo` are required. On Mac you can install them with:
|
|
66
71
|
|
|
67
72
|
``` shell
|
|
68
|
-
|
|
73
|
+
brew install imagemagick cairo
|
|
69
74
|
```
|
|
70
75
|
|
|
71
76
|
# Copyright #
|
|
@@ -12,14 +12,15 @@ def test_cairo_interface():
|
|
|
12
12
|
|
|
13
13
|
scene_items = []
|
|
14
14
|
rect = Rectangle(
|
|
15
|
-
w=20,
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
w=20,
|
|
16
|
+
h=20,
|
|
17
|
+
location=(10, 10),
|
|
18
|
+
fill=Color.from_rgba(0.5, 0.5, 1, 0.5),
|
|
19
|
+
stroke=Color.from_rgba(0.5, 0.0, 0.0, 0.5),
|
|
18
20
|
)
|
|
19
21
|
scene_items.append(rect)
|
|
20
22
|
|
|
21
|
-
text = TextPath(content="Hello World",
|
|
22
|
-
location=(5,5))
|
|
23
|
+
text = TextPath(content="Hello World", location=(5, 5))
|
|
23
24
|
scene_items.append(text)
|
|
24
25
|
|
|
25
26
|
output_dir = get_test_output_dir()
|
|
@@ -28,4 +29,3 @@ def test_cairo_interface():
|
|
|
28
29
|
scene = Scene(items=scene_items)
|
|
29
30
|
cairo_interface.draw_svg(scene, output_dir / "output.svg")
|
|
30
31
|
shutil.rmtree(output_dir)
|
|
31
|
-
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import datetime
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from iccore.project import Milestone
|
|
6
|
+
|
|
7
|
+
from icplot.gantt import GanttChart
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_gantt_chart():
|
|
11
|
+
|
|
12
|
+
milestone0 = Milestone(
|
|
13
|
+
title="My Milestone 0",
|
|
14
|
+
description="Description of Milestone 0.",
|
|
15
|
+
start_date=datetime.date(2024, 6, 30),
|
|
16
|
+
due_date=datetime.date(2024, 7, 12),
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
milestone1 = Milestone(
|
|
20
|
+
title="My Milestone 1",
|
|
21
|
+
description="Description of Milestone 1.",
|
|
22
|
+
start_date=datetime.date(2024, 7, 1),
|
|
23
|
+
due_date=datetime.date(2024, 7, 15),
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
_ = GanttChart(milestones=[milestone0, milestone1])
|
|
@@ -10,16 +10,15 @@ def test_line_plot():
|
|
|
10
10
|
|
|
11
11
|
series = []
|
|
12
12
|
for idx, [x, y] in enumerate(data):
|
|
13
|
-
series_config = {"label"
|
|
13
|
+
series_config = {"label": f"Series {idx}", "x": x, "y": y}
|
|
14
14
|
series.append(LinePlotSeries(**series_config))
|
|
15
|
-
|
|
16
|
-
plot_config = {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"step" : 5}}}
|
|
15
|
+
|
|
16
|
+
plot_config = {
|
|
17
|
+
"title": "test",
|
|
18
|
+
"legend_label": "test_legend",
|
|
19
|
+
"series": series,
|
|
20
|
+
"x_axis": {"label": "test_x", "ticks": {"lower": 0, "upper": 10, "step": 5}},
|
|
21
|
+
}
|
|
23
22
|
|
|
24
23
|
plot = Plot(**plot_config)
|
|
25
24
|
|
|
@@ -12,12 +12,12 @@ def test_tex_interface():
|
|
|
12
12
|
data_dir = get_test_data_dir()
|
|
13
13
|
build_dir = get_test_output_dir()
|
|
14
14
|
source = data_dir / "test.tex"
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
settings = TexBuildSettings(source, build_dir, build_dir)
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
tex.build(settings)
|
|
19
19
|
|
|
20
20
|
assert Path(build_dir / "test.pdf").exists()
|
|
21
21
|
assert Path(build_dir / "test.png").exists()
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
shutil.rmtree(build_dir)
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import datetime
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
|
|
5
|
-
from iccore.project import Milestone
|
|
6
|
-
|
|
7
|
-
from icplot.gantt import GanttChart
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def test_gantt_chart():
|
|
11
|
-
|
|
12
|
-
milestone0 = Milestone()
|
|
13
|
-
milestone0.title = "My Milestone 0"
|
|
14
|
-
milestone0.description = "Description of Milestone 0."
|
|
15
|
-
milestone0.start_date = datetime.date(2024, 6, 30)
|
|
16
|
-
milestone0.due_date = datetime.date(2024, 7, 12)
|
|
17
|
-
|
|
18
|
-
milestone1 = Milestone()
|
|
19
|
-
milestone1.title = "My Milestone 1"
|
|
20
|
-
milestone1.description = "Description of Milestone 1."
|
|
21
|
-
milestone1.start_date = datetime.date(2024, 7, 1)
|
|
22
|
-
milestone1.due_date = datetime.date(2024, 7, 15)
|
|
23
|
-
|
|
24
|
-
gantt = GanttChart()
|
|
25
|
-
gantt.milestones = [milestone0, milestone1]
|
|
26
|
-
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|