icplot 0.0.1__tar.gz → 0.0.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: icplot
3
- Version: 0.0.1
3
+ Version: 0.0.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
@@ -14,6 +14,7 @@ Classifier: Topic :: System :: Distributed Computing
14
14
  Requires-Python: >=3.8
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
+ Requires-Dist: wand
17
18
  Provides-Extra: test
18
19
  Requires-Dist: pytest; extra == "test"
19
20
  Requires-Dist: pytest-cov; extra == "test"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "icplot"
3
- version = "0.0.1"
3
+ version = "0.0.2"
4
4
  authors = [
5
5
  { name="James Grogan, Irish Centre for High End Computing", email="james.grogan@ichec.ie" },
6
6
  ]
@@ -16,6 +16,8 @@ classifiers = [
16
16
  ]
17
17
  keywords = ["Publishing", "Technical Reports", "Graphics"]
18
18
 
19
+ dependencies = ["wand"]
20
+
19
21
  [project.urls]
20
22
  Repository = "https://git.ichec.ie/performance/toolshed/icplot"
21
23
  Homepage = "https://git.ichec.ie/performance/toolshed/icplot"
@@ -0,0 +1,64 @@
1
+ from pathlib import Path
2
+ from .cairo_interface import CairoInterface
3
+ from .geometry import Scene, Color, Rectangle
4
+
5
+
6
+ class GanttChart:
7
+
8
+ def __init__(self):
9
+ self.milestones = []
10
+ self.start_date = None
11
+ self.end_date = None
12
+ self.milestone_bar_max_height = 0.1
13
+ self.height = 100
14
+ self.width = 500
15
+ self.milestone_color = Color(0.7, 0, 0)
16
+
17
+ def _add_milestone(self, scene, milestone, chart_range, yloc):
18
+ chart_delta = chart_range[1] - chart_range[0]
19
+ start_delta = milestone.start_date - chart_range[0]
20
+ milestone_delta = milestone.due_date - milestone.start_date
21
+
22
+ start_frac = float(start_delta / chart_delta)
23
+ milestone_frac = float(milestone_delta / chart_delta)
24
+
25
+ w = milestone_frac * self.width
26
+ h = self.milestone_bar_max_height * self.height
27
+ x = start_frac * self.width
28
+ y = yloc
29
+
30
+ rect = Rectangle(w, h)
31
+ rect.location = (x, y)
32
+ rect.fill = self.milestone_color
33
+ scene.items.append(rect)
34
+
35
+ def _add_milestones(self, scene):
36
+
37
+ if not self.milestones:
38
+ return
39
+
40
+ milestones = self.milestones
41
+ milestones.sort(key=lambda x: x.start_date, reverse=True)
42
+
43
+ start_date = self.start_date
44
+ end_date = self.end_date
45
+ if not start_date:
46
+ start_date = milestones[0].start_date
47
+
48
+ if not end_date:
49
+ end_date = max(m.due_date for m in milestones)
50
+
51
+ chart_range = (start_date, end_date)
52
+ yloc = 0
53
+ bar_height = self.milestone_bar_max_height * self.height
54
+ for milestone in milestones:
55
+ self._add_milestone(scene, milestone, chart_range, yloc)
56
+ yloc += bar_height
57
+
58
+ def plot(self, path: Path):
59
+ scene = Scene()
60
+
61
+ self._add_milestones(scene)
62
+
63
+ renderer = CairoInterface()
64
+ renderer.draw_svg(scene, path)
@@ -0,0 +1,16 @@
1
+ import logging
2
+ from pathlib import Path
3
+
4
+ from wand.image import Image
5
+ from wand.color import Color
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+
10
+ def pdf_to_png(source_path: Path):
11
+ png_filename = source_path.parent / f"{source_path.stem}.png"
12
+ with Image(filename=source_path, resolution=300) as img:
13
+ img.format = "png"
14
+ img.background_color = Color("white")
15
+ img.alpha_channel = "remove"
16
+ img.save(filename=png_filename)
@@ -0,0 +1,95 @@
1
+ import argparse
2
+ import subprocess
3
+ import shutil
4
+ import os
5
+ from pathlib import Path
6
+ import logging
7
+
8
+ from .image_utils import pdf_to_png
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class TexInterface:
14
+
15
+ def __init__(self, build_dir: Path, output_dir: Path):
16
+
17
+ if not build_dir.is_absolute():
18
+ build_dir = Path(os.getcwd()) / build_dir
19
+
20
+ if not output_dir:
21
+ output_dir = build_dir
22
+
23
+ if not output_dir.is_absolute():
24
+ output_dir = Path(os.getcwd()) / output_dir
25
+ self.build_dir = build_dir
26
+ self.output_dir = output_dir
27
+ self.build_engine = "pdflatex"
28
+
29
+ def build_pdf(self, source_path: Path, build_dir: Path):
30
+ cmd = f"{self.build_engine} {source_path}"
31
+ subprocess.run(cmd, shell=True, check=True, cwd=build_dir)
32
+
33
+ def build_single(self, source_path: Path):
34
+ logging.info("Building source: %s", source_path)
35
+
36
+ # Make a working dir
37
+ work_dir = self.build_dir / source_path.stem
38
+ os.makedirs(work_dir, exist_ok=True)
39
+
40
+ tex_path = work_dir / source_path.name
41
+ shutil.copy(source_path, tex_path)
42
+
43
+ self.build_pdf(tex_path, work_dir)
44
+
45
+ pdf_path = tex_path.parent / f"{tex_path.stem}.pdf"
46
+ pdf_to_png(pdf_path)
47
+
48
+ # If output dir is different to build dir copy final content there
49
+ if self.output_dir != self.build_dir:
50
+ png_path = pdf_path.parent / f"{tex_path.stem}.png"
51
+ shutil.copy(pdf_path, self.output_dir)
52
+ shutil.copy(png_path, self.output_dir)
53
+
54
+ def build(self, search_path: Path):
55
+
56
+ if not search_path.is_absolute():
57
+ search_path = Path(os.getcwd()) / search_path
58
+
59
+ os.makedirs(self.output_dir, exist_ok=True)
60
+
61
+ if search_path.is_dir():
62
+ for tex_file in search_path.glob("*.tex"):
63
+ self.build_single(tex_file)
64
+ else:
65
+ self.build_single(search_path)
66
+
67
+ logger.info("Finished building sources")
68
+
69
+
70
+ if __name__ == "__main__":
71
+
72
+ parser = argparse.ArgumentParser()
73
+ parser.add_argument(
74
+ "--source",
75
+ type=Path,
76
+ help="Path to the tikz source",
77
+ )
78
+ parser.add_argument(
79
+ "--build_dir",
80
+ type=Path,
81
+ default=Path(os.getcwd()) / "_build/tikz",
82
+ help="Path for build output",
83
+ )
84
+ parser.add_argument(
85
+ "--output_dir",
86
+ type=Path,
87
+ default="",
88
+ help="Optional dir to collect build output",
89
+ )
90
+
91
+ logging.basicConfig(encoding="utf-8", level=logging.INFO)
92
+ args = parser.parse_args()
93
+
94
+ tex = TexInterface(args.build_dir, args.output_dir)
95
+ tex.build(args.source)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: icplot
3
- Version: 0.0.1
3
+ Version: 0.0.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
@@ -14,6 +14,7 @@ Classifier: Topic :: System :: Distributed Computing
14
14
  Requires-Python: >=3.8
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
+ Requires-Dist: wand
17
18
  Provides-Extra: test
18
19
  Requires-Dist: pytest; extra == "test"
19
20
  Requires-Dist: pytest-cov; extra == "test"
@@ -6,10 +6,14 @@ src/icplot/__init__.py
6
6
  src/icplot/cairo_interface.py
7
7
  src/icplot/gantt.py
8
8
  src/icplot/geometry.py
9
+ src/icplot/image_utils.py
9
10
  src/icplot/project_elements.py
11
+ src/icplot/tex_interface.py
10
12
  src/icplot.egg-info/PKG-INFO
11
13
  src/icplot.egg-info/SOURCES.txt
12
14
  src/icplot.egg-info/dependency_links.txt
13
15
  src/icplot.egg-info/requires.txt
14
16
  src/icplot.egg-info/top_level.txt
15
- test/test_cairo_interface.py
17
+ test/test_cairo_interface.py
18
+ test/test_gantt_chart.py
19
+ test/test_tex_interface.py
@@ -1,3 +1,4 @@
1
+ wand
1
2
 
2
3
  [cairo]
3
4
  pycairo
@@ -0,0 +1,28 @@
1
+ import os
2
+ import datetime
3
+ from pathlib import Path
4
+ from icplot.gantt import GanttChart
5
+ from icplot.project_elements import Milestone
6
+
7
+
8
+ def test_gantt_chart():
9
+
10
+ milestone0 = Milestone()
11
+ milestone0.title = "My Milestone 0"
12
+ milestone0.description = "Description of Milestone 0."
13
+ milestone0.start_date = datetime.date(2024, 6, 30)
14
+ milestone0.due_date = datetime.date(2024, 7, 12)
15
+
16
+ milestone1 = Milestone()
17
+ milestone1.title = "My Milestone 1"
18
+ milestone1.description = "Description of Milestone 1."
19
+ milestone1.start_date = datetime.date(2024, 7, 1)
20
+ milestone1.due_date = datetime.date(2024, 7, 15)
21
+
22
+ gantt = GanttChart()
23
+ gantt.milestones = [milestone0,
24
+ milestone1]
25
+
26
+ output_path = Path(os.getcwd()) / "gantt.svg"
27
+
28
+ gantt.plot(output_path)
@@ -0,0 +1,17 @@
1
+ import os
2
+ import shutil
3
+ from pathlib import Path
4
+ from icplot.tex_interface import TexInterface
5
+
6
+ def test_tex_interface():
7
+
8
+ build_dir = Path(os.getcwd()) / "tmp_build"
9
+ tex = TexInterface(build_dir, build_dir)
10
+
11
+ data_dir = Path(__file__).parent / "data"
12
+ tex_file = data_dir / "test.tex"
13
+
14
+ tex = TexInterface(build_dir, build_dir)
15
+ tex.build(tex_file)
16
+
17
+ shutil.rmtree(build_dir)
@@ -1,7 +0,0 @@
1
- class GanttChart:
2
-
3
- def __init__(self):
4
- self.milestones = []
5
-
6
- def plot(self):
7
- pass
File without changes
File without changes
File without changes
File without changes
File without changes