icplot 0.1.4__tar.gz → 0.1.6__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 (49) hide show
  1. {icplot-0.1.4/src/icplot.egg-info → icplot-0.1.6}/PKG-INFO +15 -5
  2. {icplot-0.1.4 → icplot-0.1.6}/README.md +8 -1
  3. icplot-0.1.6/pyproject.toml +154 -0
  4. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/cairo_interface.py +1 -1
  5. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/convert.py +13 -2
  6. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/gantt/gantt.py +7 -0
  7. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/gantt/gantt_renderer.py +5 -4
  8. icplot-0.1.6/src/icplot/geometry.py +151 -0
  9. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/graph/axis.py +4 -2
  10. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/graph/matplotlib.py +3 -6
  11. icplot-0.1.6/src/icplot/graph/mpl.py +216 -0
  12. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/graph/plot.py +37 -2
  13. icplot-0.1.6/src/icplot/graph/plot_group.py +63 -0
  14. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/graph/series.py +7 -0
  15. icplot-0.1.6/src/icplot/graph/video.py +35 -0
  16. icplot-0.1.6/src/icplot/graph/vtk.py +54 -0
  17. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/main_cli.py +12 -1
  18. icplot-0.1.6/src/icplot/mermaid.py +39 -0
  19. icplot-0.1.6/src/icplot/mesh/__init__.py +1 -0
  20. icplot-0.1.6/src/icplot/mesh/foam.py +56 -0
  21. icplot-0.1.6/src/icplot/mesh/mesh.py +79 -0
  22. icplot-0.1.4/src/icplot/geometry.py → icplot-0.1.6/src/icplot/scene.py +25 -1
  23. {icplot-0.1.4 → icplot-0.1.6/src/icplot.egg-info}/PKG-INFO +15 -5
  24. {icplot-0.1.4 → icplot-0.1.6}/src/icplot.egg-info/SOURCES.txt +12 -1
  25. {icplot-0.1.4 → icplot-0.1.6}/src/icplot.egg-info/requires.txt +3 -1
  26. {icplot-0.1.4 → icplot-0.1.6}/test/test_cairo_interface.py +1 -1
  27. {icplot-0.1.4 → icplot-0.1.6}/test/test_line_plots.py +1 -1
  28. icplot-0.1.6/test/test_mermaid.py +24 -0
  29. icplot-0.1.6/test/test_mesh.py +13 -0
  30. icplot-0.1.4/test/test_tex_interface.py → icplot-0.1.6/test/test_tex.py +1 -1
  31. icplot-0.1.4/pyproject.toml +0 -108
  32. {icplot-0.1.4 → icplot-0.1.6}/LICENSE +0 -0
  33. {icplot-0.1.4 → icplot-0.1.6}/setup.cfg +0 -0
  34. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/__init__.py +0 -0
  35. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/color.py +0 -0
  36. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/gantt/__init__.py +0 -0
  37. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/gantt/pgfgantt.py +0 -0
  38. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/graph/__init__.py +0 -0
  39. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/graph/generator.py +0 -0
  40. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/image_utils.py +0 -0
  41. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/py.typed +0 -0
  42. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/tex.py +0 -0
  43. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/trace/__init__.py +0 -0
  44. {icplot-0.1.4 → icplot-0.1.6}/src/icplot/trace/trace.py +0 -0
  45. {icplot-0.1.4 → icplot-0.1.6}/src/icplot.egg-info/dependency_links.txt +0 -0
  46. {icplot-0.1.4 → icplot-0.1.6}/src/icplot.egg-info/entry_points.txt +0 -0
  47. {icplot-0.1.4 → icplot-0.1.6}/src/icplot.egg-info/top_level.txt +0 -0
  48. {icplot-0.1.4 → icplot-0.1.6}/test/test_gantt_chart.py +0 -0
  49. {icplot-0.1.4 → icplot-0.1.6}/test/test_image_utils.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: icplot
3
- Version: 0.1.4
3
+ Version: 0.1.6
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
@@ -11,12 +11,14 @@ Classifier: Programming Language :: Python :: 3
11
11
  Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
12
12
  Classifier: Operating System :: OS Independent
13
13
  Classifier: Topic :: System :: Distributed Computing
14
- Requires-Python: >=3.8
14
+ Requires-Python: >=3.10
15
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.1.9
19
+ Requires-Dist: vtk
20
+ Requires-Dist: moviepy
21
+ Requires-Dist: iccore==0.1.13
20
22
  Provides-Extra: test
21
23
  Requires-Dist: pytest; extra == "test"
22
24
  Requires-Dist: pytest-cov; extra == "test"
@@ -28,6 +30,7 @@ Requires-Dist: pylint; extra == "test"
28
30
  Provides-Extra: cairo
29
31
  Requires-Dist: pycairo; extra == "cairo"
30
32
  Requires-Dist: CairoSVG; extra == "cairo"
33
+ Dynamic: license-file
31
34
 
32
35
  # icplot
33
36
 
@@ -38,8 +41,9 @@ This is a library used at [The Irish Centre for High End Computing (ICHEC)](http
38
41
  The project has support for:
39
42
 
40
43
  * Coverting image formats between pdf, svg and png
41
- * Building pdf output from tex files, including tikz.
44
+ * Building pdf and png output from tex files, including tikz.
42
45
  * Generating plots based on a serializable data model to support reproducible research
46
+ * Generating mermaid plots
43
47
 
44
48
  To covert between image formats you can do:
45
49
 
@@ -53,6 +57,12 @@ To render a Tex tikz image as pdf and png you can do:
53
57
  icplot convert --source my_tikz.tex
54
58
  ```
55
59
 
60
+ To render a Mermaid plot as png you can do:
61
+
62
+ ``` shell
63
+ icplot convert --source my_mermaid.mmd
64
+ ```
65
+
56
66
  To generate a plot or collection of plots from a yaml description you can do:
57
67
 
58
68
  ``` shell
@@ -7,8 +7,9 @@ This is a library used at [The Irish Centre for High End Computing (ICHEC)](http
7
7
  The project has support for:
8
8
 
9
9
  * Coverting image formats between pdf, svg and png
10
- * Building pdf output from tex files, including tikz.
10
+ * Building pdf and png output from tex files, including tikz.
11
11
  * Generating plots based on a serializable data model to support reproducible research
12
+ * Generating mermaid plots
12
13
 
13
14
  To covert between image formats you can do:
14
15
 
@@ -22,6 +23,12 @@ To render a Tex tikz image as pdf and png you can do:
22
23
  icplot convert --source my_tikz.tex
23
24
  ```
24
25
 
26
+ To render a Mermaid plot as png you can do:
27
+
28
+ ``` shell
29
+ icplot convert --source my_mermaid.mmd
30
+ ```
31
+
25
32
  To generate a plot or collection of plots from a yaml description you can do:
26
33
 
27
34
  ``` shell
@@ -0,0 +1,154 @@
1
+ [project]
2
+ name = "icplot"
3
+ version = "0.1.6"
4
+ authors = [
5
+ { name="James Grogan, Irish Centre for High End Computing", email="james.grogan@ichec.ie" },
6
+ ]
7
+ description = "Utilities for generating plots and graphics for technical reports."
8
+ readme = "README.md"
9
+ requires-python = ">=3.10"
10
+ classifiers = [
11
+ "Development Status :: 3 - Alpha",
12
+ "Programming Language :: Python :: 3",
13
+ "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
14
+ "Operating System :: OS Independent",
15
+ "Topic :: System :: Distributed Computing"
16
+ ]
17
+ keywords = ["Publishing", "Technical Reports", "Graphics"]
18
+
19
+ dependencies = ["wand",
20
+ "matplotlib",
21
+ "vtk",
22
+ "moviepy",
23
+ "iccore==0.1.13"]
24
+
25
+ [project.urls]
26
+ Repository = "https://git.ichec.ie/performance/toolshed/icplot"
27
+ Homepage = "https://git.ichec.ie/performance/toolshed/icplot"
28
+
29
+ [project.optional-dependencies]
30
+ test = [
31
+ "pytest",
32
+ "pytest-cov",
33
+ "pytest-sugar",
34
+ "black",
35
+ "mypy",
36
+ "flake8",
37
+ "pylint"
38
+ ]
39
+
40
+ cairo = [
41
+ "pycairo",
42
+ "CairoSVG"
43
+ ]
44
+
45
+ [build-system]
46
+ requires = ["setuptools", "wheel"]
47
+ build-backend = "setuptools.build_meta"
48
+
49
+ [project.scripts]
50
+ icplot = "icplot.main_cli:main_cli"
51
+
52
+ [tool.setuptools.package-data]
53
+ "icplot" = ["py.typed"]
54
+
55
+ [tool.setuptools.packages.find]
56
+ where = ["src"]
57
+
58
+ [tool.mypy]
59
+ ignore_missing_imports = true
60
+
61
+ [tool.pylint.main]
62
+
63
+ source-roots = ["src"]
64
+ fail-under = 9.33
65
+
66
+ [tool.pylint.basic]
67
+
68
+ class-const-naming-style = "UPPER_CASE"
69
+ class-naming-style = "PascalCase"
70
+ const-naming-style = "UPPER_CASE"
71
+ docstring-min-length = -1
72
+
73
+ function-naming-style = "snake_case"
74
+ method-naming-style = "snake_case"
75
+ module-naming-style = "snake_case"
76
+ variable-naming-style = "snake_case"
77
+
78
+ no-docstring-rgx = "^_"
79
+
80
+ [tool.pylint.design]
81
+ # Maximum number of arguments for function / method.
82
+ max-args = 6
83
+ # Maximum number of attributes for a class (see R0902).
84
+ max-attributes = 7
85
+ # Minimum number of public methods for a class (see R0903).
86
+ min-public-methods = 1
87
+
88
+ [tool.pylint.logging]
89
+ # The type of string formatting that logging methods do. `old` means using %
90
+ # formatting, `new` is for `{}` formatting.
91
+ logging-format-style = "old"
92
+
93
+ # Disable the message, report, category or checker with the given id(s). You can
94
+ # either give multiple identifiers separated by comma (,) or put this option
95
+ # multiple times (only on the command line, not in the configuration file where
96
+ # it should appear only once). You can also use "--disable=all" to disable
97
+ # everything first and then re-enable specific checks. For example, if you want
98
+ # to run only the similarities checker, you can use "--disable=all
99
+ # --enable=similarities". If you want to run only the classes checker, but have
100
+ # no Warning level messages displayed, use "--disable=all --enable=classes
101
+ # --disable=W".
102
+ disable = ["raw-checker-failed", "missing-module-docstring", "missing-function-docstring", "bad-inline-option", "locally-disabled", "file-ignored", "suppressed-message", "useless-suppression", "deprecated-pragma", "use-symbolic-message-instead", "use-implicit-booleaness-not-comparison-to-string", "use-implicit-booleaness-not-comparison-to-zero"]
103
+
104
+ [tool.pytest.ini_options]
105
+ testpaths = ["test",]
106
+ log_cli = 1
107
+ log_cli_level = "debug"
108
+ addopts = "--cov=icplot --cov-report term --cov-fail-under=59 --cov-report xml:coverage.xml --cov-report html"
109
+
110
+ [tool.tox]
111
+ requires = ["tox"]
112
+ env_list = ["format_check", "lint", "style", "type", "3.10", "3.13", "docs"]
113
+ skip_missing_interpreters = true
114
+
115
+ [tool.tox.env_run_base]
116
+ description = "Run Unit and Integration Tests"
117
+ deps = [".[test, cairo]"]
118
+ commands = [["pytest", "test"]]
119
+
120
+ [tool.tox.env.format_apply]
121
+ description = "Run Format Apply"
122
+ skip_install = true
123
+ deps = ["black"]
124
+ commands = [["black", "src"], ["black", "test"]]
125
+
126
+ [tool.tox.env.format_check]
127
+ description = "Run Format Check"
128
+ skip_install = true
129
+ deps = ["black"]
130
+ commands = [
131
+ ["black", "--check", "--diff", "src"],
132
+ ["black", "--check", "--diff", "test"]]
133
+
134
+ [tool.tox.env.lint]
135
+ description = "Run Linter"
136
+ deps = ["pylint"]
137
+ commands = [["pylint", "src"]]
138
+
139
+ [tool.tox.env.style]
140
+ description = "Run Style Check"
141
+ skip_install = true
142
+ deps = ["flake8"]
143
+ commands = [["flake8", "src"]]
144
+
145
+ [tool.tox.env.type]
146
+ description = "Run Type Checks"
147
+ deps = ["mypy", ".[types]"]
148
+ commands = [["mypy", "src"]]
149
+
150
+ [tool.tox.env.docs]
151
+ description = "Generate Documentation"
152
+ changedir = "docs"
153
+ deps = ["sphinx"]
154
+ commands = [["sphinx-build","-W", "-b","html","-d","{envtmpdir}/doctrees","."," {envtmpdir}/html"]]
@@ -2,7 +2,7 @@ from pathlib import Path
2
2
 
3
3
  import cairo
4
4
 
5
- from .geometry import Scene, Rectangle
5
+ from .scene import Scene, Rectangle
6
6
 
7
7
 
8
8
  def draw_rect(cr, rect: Rectangle):
@@ -1,8 +1,12 @@
1
+ """
2
+ Module supporting conversion between various formats
3
+ """
4
+
1
5
  import logging
2
6
  import os
3
7
  from pathlib import Path
4
8
 
5
- from icplot import tex
9
+ from icplot import tex, mermaid
6
10
  from icplot.tex import TexBuildSettings
7
11
  from icplot.image_utils import pdf_to_png, svg_to_pdf, svg_to_png
8
12
 
@@ -10,7 +14,9 @@ from icplot.image_utils import pdf_to_png, svg_to_pdf, svg_to_png
10
14
  logger = logging.getLogger(__name__)
11
15
 
12
16
 
13
- def convert(source: Path, target: Path, build_dir: Path):
17
+ def convert(
18
+ source: Path, target: Path, build_dir: Path, extra_config: Path | None = None
19
+ ):
14
20
  """
15
21
  Convert the file at source outputing at target and using
16
22
  the source and target file extensions as format hints.
@@ -36,5 +42,10 @@ def convert(source: Path, target: Path, build_dir: Path):
36
42
  target = Path(os.getcwd())
37
43
  settings = TexBuildSettings(source, build_dir, target)
38
44
  tex.build(settings)
45
+ elif source.suffix == ".mmd":
46
+ if not target:
47
+ target = Path(os.getcwd())
48
+ settings = TexBuildSettings(source, build_dir, target)
49
+ mermaid.convert(source, target, extra_config)
39
50
 
40
51
  logger.info("Finished conversion")
@@ -1,3 +1,7 @@
1
+ """
2
+ This module represents a gantt chard
3
+ """
4
+
1
5
  from datetime import datetime
2
6
 
3
7
  from pydantic import BaseModel
@@ -8,6 +12,9 @@ from icplot.color import Color
8
12
 
9
13
 
10
14
  class GanttChart(BaseModel, frozen=True):
15
+ """
16
+ A gantt chart
17
+ """
11
18
 
12
19
  milestones: list[Milestone] = []
13
20
  title: str = ""
@@ -1,5 +1,5 @@
1
1
  from iccore.project import Milestone
2
- from icplot.geometry import Scene, SceneItem, Rectangle
2
+ from icplot.scene import Scene, SceneItem, Rectangle
3
3
 
4
4
  from .gantt import GanttChart
5
5
 
@@ -25,10 +25,11 @@ def _render_milestone(
25
25
  return rect
26
26
 
27
27
 
28
- def _render_milestones(gantt: GanttChart):
28
+ def _render_milestones(gantt: GanttChart) -> list[SceneItem]:
29
29
 
30
+ scene_items: list = []
30
31
  if not gantt.milestones:
31
- return
32
+ return scene_items
32
33
 
33
34
  milestones = gantt.milestones
34
35
  # milestones.sort(key=lambda x: x.start_date, reverse=True)
@@ -44,7 +45,7 @@ def _render_milestones(gantt: GanttChart):
44
45
  chart_range = (start_date, end_date)
45
46
  yloc = 0.0
46
47
  bar_height = gantt.bar_max_height * gantt.height
47
- scene_items = []
48
+
48
49
  for milestone in milestones:
49
50
  item = _render_milestone(gantt, milestone, chart_range, yloc)
50
51
  scene_items.append(item)
@@ -0,0 +1,151 @@
1
+ """
2
+ Module for primitive geometries. This is used to keep dependencies simple,
3
+ consider a real geometry library like cgal for more complex or performance
4
+ dependent work.
5
+ """
6
+
7
+ from __future__ import annotations
8
+ import copy
9
+ from dataclasses import dataclass
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class Vector:
14
+ """
15
+ A 3d spatial vector
16
+ """
17
+
18
+ x: float
19
+ y: float = 0.0
20
+ z: float = 0.0
21
+
22
+ def scale(self, factor: float) -> Vector:
23
+ return Vector(self.x * factor, self.y * factor, self.z * factor)
24
+
25
+
26
+ @dataclass(frozen=True)
27
+ class Point:
28
+ """
29
+ A location in 3d space
30
+ """
31
+
32
+ x: float
33
+ y: float = 0.0
34
+ z: float = 0.0
35
+
36
+ def translate(self, v: Vector) -> Point:
37
+ return Point(self.x + v.x, self.y + v.y, self.z + v.z)
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class Shape:
42
+ """
43
+ A shape in 3d space, defaults to having a normal to Z
44
+ """
45
+
46
+ loc: Point
47
+ normal: Vector = Vector(0.0, 0.0, 1.0)
48
+
49
+
50
+ @dataclass(frozen=True)
51
+ class Quad(Shape):
52
+ """
53
+ A regular quadrilateral in 3d space, defaults to be normal to Z
54
+ """
55
+
56
+ width: float = 1.0
57
+ height: float = 1.0
58
+
59
+ @property
60
+ def points(self) -> list[Point]:
61
+ p = copy.deepcopy(self.loc)
62
+ return [
63
+ p,
64
+ p.translate(Vector(self.width)),
65
+ p.translate(Vector(self.width, self.height)),
66
+ p.translate(Vector(0.0, self.height)),
67
+ ]
68
+
69
+ def translate(self, v: Vector) -> Quad:
70
+ return Quad(self.loc.translate(v), self.normal, self.width, self.height)
71
+
72
+
73
+ @dataclass(frozen=True)
74
+ class Cuboid(Shape):
75
+ """
76
+ A regular cuboid
77
+ """
78
+
79
+ loc: Point
80
+ width: float = 1.0
81
+ height: float = 1.0
82
+ depth: float = 1.0
83
+
84
+ def translate(self, v: Vector) -> Cuboid:
85
+ return Cuboid(
86
+ self.loc.translate(v), self.normal, self.width, self.height, self.depth
87
+ )
88
+
89
+ @property
90
+ def points(self) -> list[Point]:
91
+
92
+ base = Quad(self.loc, self.normal, self.width, self.height)
93
+ top = base.translate(self.normal.scale(self.depth))
94
+ return base.points + top.points
95
+
96
+
97
+ @dataclass(frozen=True)
98
+ class Cylinder(Shape):
99
+ """
100
+ A cylinder
101
+ """
102
+
103
+ diameter: float = 1.0
104
+ length: float = 1.0
105
+
106
+ @property
107
+ def start(self) -> Point:
108
+ return self.loc
109
+
110
+ @property
111
+ def end(self) -> Point:
112
+ return self.loc.translate(self.normal.scale(self.length))
113
+
114
+
115
+ @dataclass(frozen=True)
116
+ class Revolution(Shape):
117
+ """
118
+ A revolved profile sitting on the plane given by the loc
119
+ and normal and revolved about the normal.
120
+ """
121
+
122
+ diameter: float = 1.0
123
+ length: float = 1.0
124
+ profile: str = "arc"
125
+
126
+
127
+ @dataclass(frozen=True)
128
+ class CuboidGrid:
129
+ """
130
+ A irregular grid composed of cuboids. Can be useful for
131
+ generating topological meshes like OpenFoam's blockMesh.
132
+ """
133
+
134
+ x_locs: list[float]
135
+ y_locs: list[float]
136
+ z_locs: list[float]
137
+
138
+ @property
139
+ def cuboids(self) -> list[Cuboid]:
140
+ ret = []
141
+
142
+ for kdx, z in enumerate(self.z_locs[:-1]):
143
+ for jdx, y in enumerate(self.y_locs[:-1]):
144
+ for idx, x in enumerate(self.x_locs[:-1]):
145
+ width = self.x_locs[idx + 1] - x
146
+ height = self.y_locs[jdx + 1] - y
147
+ depth = self.z_locs[kdx + 1] - z
148
+ ret.append(
149
+ Cuboid(Point(x, y, z), width=width, height=height, depth=depth)
150
+ )
151
+ return ret
@@ -28,7 +28,7 @@ class PlotAxis(BaseModel, frozen=True):
28
28
  """
29
29
 
30
30
  label: str = ""
31
- ticks: Range | None = None
31
+ ticks: Range | list[int] | None = None
32
32
  scale: str = "linear"
33
33
  text_fontsize: int = 10
34
34
  tick_fontsize: int = 10
@@ -38,5 +38,7 @@ class PlotAxis(BaseModel, frozen=True):
38
38
  @property
39
39
  def resolved_ticks(self) -> list:
40
40
  if self.ticks:
41
- return self.ticks.eval()
41
+ if isinstance(self.ticks, Range):
42
+ return self.ticks.eval()
43
+ return self.ticks
42
44
  return []
@@ -31,10 +31,7 @@ def str_exact_values_formatter(x, pos):
31
31
  then when using plain formatter values less than 1 come out as 0. A way around
32
32
  this is this custom formatter.
33
33
  """
34
- if x.is_integer():
35
- return str(int(x))
36
- else:
37
- return str(x)
34
+ return str(int(x)) if x.is_integer else str(x)
38
35
 
39
36
 
40
37
  def _set_legend_decorations(axs, plot):
@@ -80,9 +77,9 @@ def _set_y_axes_decorations(y_axes: list[PlotAxis], axs):
80
77
  if y_axis.max_ticks:
81
78
  axs[idx].yaxis.set_major_locator(plt.MaxNLocator(y_axis.max_ticks))
82
79
  for key, item in y_axis.limits.items():
83
- if key == "bottom" or key == "ymin":
80
+ if key in ("bottom", "ymin"):
84
81
  axs[idx].set_ylim(ymin=item)
85
- elif key == "top" or key == "ymax":
82
+ elif key in ("top", "ymax"):
86
83
  axs[idx].set_ylim(ymax=item)
87
84
 
88
85