icplot 0.0.10__tar.gz → 0.0.12__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 (47) hide show
  1. {icplot-0.0.10/src/icplot.egg-info → icplot-0.0.12}/PKG-INFO +8 -2
  2. {icplot-0.0.10 → icplot-0.0.12}/README.md +6 -0
  3. {icplot-0.0.10 → icplot-0.0.12}/pyproject.toml +2 -2
  4. icplot-0.0.12/src/icplot/cairo_interface.py +59 -0
  5. {icplot-0.0.10 → icplot-0.0.12}/src/icplot/color.py +3 -6
  6. icplot-0.0.12/src/icplot/gantt/gantt_renderer.py +59 -0
  7. icplot-0.0.12/src/icplot/gantt/pgfgantt.py +15 -0
  8. icplot-0.0.12/src/icplot/geometry.py +45 -0
  9. icplot-0.0.12/src/icplot/graph/axis.py +34 -0
  10. {icplot-0.0.10 → icplot-0.0.12}/src/icplot/graph/matplotlib.py +5 -5
  11. icplot-0.0.12/src/icplot/graph/plot.py +61 -0
  12. {icplot-0.0.10 → icplot-0.0.12}/src/icplot/graph/plotter.py +6 -5
  13. icplot-0.0.12/src/icplot/graph/series.py +43 -0
  14. {icplot-0.0.10 → icplot-0.0.12}/src/icplot/main_cli.py +47 -8
  15. icplot-0.0.12/src/icplot/tex.py +77 -0
  16. icplot-0.0.12/src/icplot/trace/__init__.py +1 -0
  17. icplot-0.0.12/src/icplot/trace/trace.py +0 -0
  18. {icplot-0.0.10 → icplot-0.0.12/src/icplot.egg-info}/PKG-INFO +8 -2
  19. {icplot-0.0.10 → icplot-0.0.12}/src/icplot.egg-info/SOURCES.txt +4 -2
  20. {icplot-0.0.10 → icplot-0.0.12}/src/icplot.egg-info/requires.txt +1 -1
  21. icplot-0.0.12/test/test_cairo_interface.py +31 -0
  22. icplot-0.0.12/test/test_line_plots.py +32 -0
  23. icplot-0.0.12/test/test_tex_interface.py +23 -0
  24. icplot-0.0.10/src/icplot/cairo_interface.py +0 -60
  25. icplot-0.0.10/src/icplot/gantt/gantt_renderer.py +0 -59
  26. icplot-0.0.10/src/icplot/gantt/pgfgantt_interface.py +0 -26
  27. icplot-0.0.10/src/icplot/geometry.py +0 -50
  28. icplot-0.0.10/src/icplot/graph/axis.py +0 -44
  29. icplot-0.0.10/src/icplot/graph/plot.py +0 -92
  30. icplot-0.0.10/src/icplot/graph/series.py +0 -111
  31. icplot-0.0.10/src/icplot/tex_interface.py +0 -92
  32. icplot-0.0.10/test/test_cairo_interface.py +0 -29
  33. icplot-0.0.10/test/test_line_plots.py +0 -29
  34. icplot-0.0.10/test/test_tex_interface.py +0 -18
  35. {icplot-0.0.10 → icplot-0.0.12}/LICENSE +0 -0
  36. {icplot-0.0.10 → icplot-0.0.12}/setup.cfg +0 -0
  37. {icplot-0.0.10 → icplot-0.0.12}/src/icplot/__init__.py +0 -0
  38. {icplot-0.0.10 → icplot-0.0.12}/src/icplot/gantt/__init__.py +0 -0
  39. {icplot-0.0.10 → icplot-0.0.12}/src/icplot/gantt/gantt.py +0 -0
  40. {icplot-0.0.10 → icplot-0.0.12}/src/icplot/graph/__init__.py +0 -0
  41. {icplot-0.0.10 → icplot-0.0.12}/src/icplot/image_utils.py +0 -0
  42. {icplot-0.0.10 → icplot-0.0.12}/src/icplot/py.typed +0 -0
  43. {icplot-0.0.10 → icplot-0.0.12}/src/icplot.egg-info/dependency_links.txt +0 -0
  44. {icplot-0.0.10 → icplot-0.0.12}/src/icplot.egg-info/entry_points.txt +0 -0
  45. {icplot-0.0.10 → icplot-0.0.12}/src/icplot.egg-info/top_level.txt +0 -0
  46. {icplot-0.0.10 → icplot-0.0.12}/test/test_gantt_chart.py +0 -0
  47. {icplot-0.0.10 → icplot-0.0.12}/test/test_image_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: icplot
3
- Version: 0.0.10
3
+ Version: 0.0.12
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.0
19
+ Requires-Dist: iccore==0.1.5
20
20
  Provides-Extra: test
21
21
  Requires-Dist: pytest; extra == "test"
22
22
  Requires-Dist: pytest-cov; extra == "test"
@@ -62,6 +62,12 @@ To covert between image formats you can do:
62
62
  icplot convert --source my_image.svg --target my_image.png
63
63
  ```
64
64
 
65
+ To render a Tex tikz image as pdf and png you can do:
66
+
67
+ ``` shell
68
+ icplot convert --source my_tikz.tex
69
+ ```
70
+
65
71
  # Copyright #
66
72
 
67
73
  Copyright 2024 Irish Centre for High End Computing
@@ -31,6 +31,12 @@ To covert between image formats you can do:
31
31
  icplot convert --source my_image.svg --target my_image.png
32
32
  ```
33
33
 
34
+ To render a Tex tikz image as pdf and png you can do:
35
+
36
+ ``` shell
37
+ icplot convert --source my_tikz.tex
38
+ ```
39
+
34
40
  # Copyright #
35
41
 
36
42
  Copyright 2024 Irish Centre for High End Computing
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "icplot"
3
- version = "0.0.10"
3
+ version = "0.0.12"
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.0"]
21
+ "iccore==0.1.5"]
22
22
 
23
23
  [project.urls]
24
24
  Repository = "https://git.ichec.ie/performance/toolshed/icplot"
@@ -0,0 +1,59 @@
1
+ from pathlib import Path
2
+
3
+ import cairo
4
+
5
+ from .geometry import Scene, Rectangle
6
+
7
+
8
+ def draw_rect(cr, rect: Rectangle):
9
+ x0, y0 = rect.location
10
+ x1 = rect.w
11
+ y1 = rect.h
12
+ cr.move_to(x0, y0)
13
+ cr.line_to(x1, y0)
14
+ cr.line_to(x1, y1)
15
+ cr.line_to(x0, y1)
16
+ cr.close_path()
17
+
18
+
19
+ def draw_shape(cr, shape):
20
+ cr.save()
21
+ if shape.shape_type == "rect":
22
+ draw_rect(cr, shape)
23
+ else:
24
+ return
25
+ cr.set_source_rgba(shape.fill.r, shape.fill.g, shape.fill.b, shape.fill.a)
26
+ cr.fill_preserve()
27
+ if shape.stroke is not None:
28
+ cr.set_source_rgba(
29
+ shape.stroke.r, shape.stroke.g, shape.stroke.b, shape.stroke.a
30
+ )
31
+ cr.set_line_width(shape.stroke_thickness)
32
+ cr.stroke()
33
+
34
+ cr.restore()
35
+
36
+
37
+ def draw_text(cr, text):
38
+ cr.save()
39
+
40
+ cr.select_font_face(text.font.family)
41
+ cr.set_font_size(text.font.size)
42
+ cr.move_to(text.location[0], text.location[1])
43
+ cr.show_text(text.content)
44
+
45
+ cr.restore()
46
+
47
+
48
+ def draw_scene(cr, scene: Scene):
49
+ for item in scene.items:
50
+ if item.item_type == "shape":
51
+ draw_shape(cr, item)
52
+ elif item.item_type == "text":
53
+ draw_text(cr, item)
54
+
55
+
56
+ def draw_svg(scene: Scene, path: Path):
57
+ with cairo.SVGSurface(path, scene.size[0], scene.size[1]) as surface:
58
+ cr = cairo.Context(surface)
59
+ draw_scene(cr, scene)
@@ -34,6 +34,7 @@ class Color(BaseModel):
34
34
  def serialize(self) -> str:
35
35
  return f"r: {self.r}, g: {self.g}, b: {self.b}, a: {self.a}"
36
36
 
37
+
37
38
  class ColorMap:
38
39
  """
39
40
  A mapping from a flat index to a color
@@ -42,15 +43,11 @@ class ColorMap:
42
43
  def __init__(self, label: str, data_func: Callable):
43
44
  self.label = label
44
45
  self.data_func = data_func
45
- self.start_offset = 0.25
46
- self.scale = 2
47
46
 
48
47
  def get_color(self, cursor: int, values: list) -> Color:
49
48
  """
50
49
  Returns a colour based on a cmap and how far across
51
50
  the datasets you are
52
51
  """
53
- position = cursor / len(values)
54
- return Color.from_list(
55
- self.data_func(self.start_offset + (position / self.scale))
56
- )
52
+ position = cursor / (len(values) - 1)
53
+ return Color.from_list(self.data_func(position))
@@ -0,0 +1,59 @@
1
+ from iccore.project import Milestone
2
+ from icplot.geometry import Scene, SceneItem, Rectangle
3
+
4
+ from .gantt import GanttChart
5
+
6
+
7
+ def _render_milestone(
8
+ gantt: GanttChart, milestone: Milestone, chart_range, yloc
9
+ ) -> SceneItem:
10
+ # chart_delta = chart_range[1] - chart_range[0]
11
+ chart_delta = 0
12
+ start_delta = milestone.start_date - chart_range[0]
13
+ # milestone_delta = milestone.due_date - milestone.start_date
14
+ milestone_delta = 0
15
+
16
+ start_frac = float(start_delta / chart_delta)
17
+ milestone_frac = float(milestone_delta / chart_delta)
18
+
19
+ w = milestone_frac * gantt.width
20
+ h = gantt.bar_max_height * gantt.height
21
+ x = start_frac * gantt.width
22
+ y = yloc
23
+
24
+ rect = Rectangle(w=w, h=h, location=(x, y), fill=gantt.bar_color)
25
+ return rect
26
+
27
+
28
+ def _render_milestones(gantt: GanttChart):
29
+
30
+ if not gantt.milestones:
31
+ return
32
+
33
+ milestones = gantt.milestones
34
+ # milestones.sort(key=lambda x: x.start_date, reverse=True)
35
+
36
+ start_date = gantt.start_date
37
+ end_date = gantt.end_date
38
+ if not start_date:
39
+ start_date = milestones[0].start_date
40
+
41
+ # if not end_date:
42
+ # end_date = max(m.due_date for m in milestones)
43
+
44
+ chart_range = (start_date, end_date)
45
+ yloc = 0.0
46
+ bar_height = gantt.bar_max_height * gantt.height
47
+ scene_items = []
48
+ for milestone in milestones:
49
+ item = _render_milestone(gantt, milestone, chart_range, yloc)
50
+ scene_items.append(item)
51
+ yloc += bar_height
52
+ return scene_items
53
+
54
+
55
+ def render(gantt: GanttChart) -> Scene:
56
+ scene = Scene()
57
+ items = _render_milestones(gantt)
58
+ scene.items.extend(items)
59
+ return scene
@@ -0,0 +1,15 @@
1
+ from pathlib import Path
2
+
3
+ from .gantt import GanttChart
4
+
5
+
6
+ def render(gantt: GanttChart) -> str:
7
+
8
+ with open(Path(__file__).parent / "pgfgantt.tex", "r", encoding="utf-8") as f:
9
+ template = f.read()
10
+
11
+ if gantt.title:
12
+ title_str = f"\\title{{{gantt.title}}}"
13
+ template.replace("%%TITLE%%", title_str)
14
+
15
+ return template
@@ -0,0 +1,45 @@
1
+ from pydantic import BaseModel
2
+
3
+ from .color import Color
4
+
5
+
6
+ class Font(BaseModel):
7
+
8
+ family: str = "Sans"
9
+ weight: str = "normal"
10
+ slant: str = "normal"
11
+ size: float = 0.5
12
+
13
+
14
+ class SceneItem(BaseModel):
15
+
16
+ item_type: str
17
+ location: tuple[float, float] = (0.0, 0.0)
18
+
19
+
20
+ class Shape(SceneItem):
21
+
22
+ item_type: str = "shape"
23
+ fill: Color = Color()
24
+ stroke: Color = Color()
25
+ stroke_thickness: float = 0.5
26
+
27
+
28
+ class TextPath(SceneItem):
29
+
30
+ item_type: str = "text"
31
+ content: str
32
+ font: Font = Font()
33
+
34
+
35
+ class Rectangle(Shape):
36
+
37
+ item_type: str = "rect"
38
+ w: float
39
+ h: float
40
+
41
+
42
+ class Scene(BaseModel):
43
+
44
+ items: list[SceneItem] = []
45
+ size: tuple[int, int] = (100, 100)
@@ -0,0 +1,34 @@
1
+ """
2
+ This module has a plot's axis
3
+ """
4
+
5
+ from pydantic import BaseModel
6
+
7
+
8
+ class Range(BaseModel):
9
+ """
10
+ This is a sequence of numbers specified by lower and upper
11
+ bounds and a step size. Eg (1, 5, 1) gives: [1, 2, 3, 4]
12
+ """
13
+
14
+ lower: int
15
+ upper: int
16
+ step: int
17
+
18
+ def eval(self) -> list:
19
+ return list(range(self.lower, self.upper, self.step))
20
+
21
+
22
+ class PlotAxis(BaseModel):
23
+ """
24
+ This is a plot's axis
25
+ """
26
+
27
+ label: str = ""
28
+ ticks: Range | None = None
29
+
30
+ @property
31
+ def resolved_ticks(self) -> list:
32
+ if self.ticks:
33
+ return self.ticks.eval()
34
+ return []
@@ -29,7 +29,7 @@ class MatplotlibPlotter(Plotter):
29
29
  A plot backend for matplotlib
30
30
  """
31
31
 
32
- def __init__(self, cmap_label="viridis"):
32
+ def __init__(self, cmap_label="gist_rainbow"):
33
33
  super().__init__(MatplotlibColorMap(cmap_label))
34
34
 
35
35
  def set_decorations(self, ax, plot: Plot):
@@ -39,9 +39,9 @@ class MatplotlibPlotter(Plotter):
39
39
  if plot.y_axis.label:
40
40
  ax.set_ylabel(plot.y_axis.label)
41
41
  if plot.x_axis.ticks:
42
- ax.set_xticks(plot.x_axis.get_resolved_ticks())
42
+ ax.set_xticks(plot.x_axis.resolved_ticks)
43
43
  if plot.y_axis.ticks:
44
- ax.set_yticks(plot.y_axis.get_resolved_ticks())
44
+ ax.set_yticks(plot.y_axis.resolved_ticks)
45
45
  if plot.title:
46
46
  ax.set_title(plot.title)
47
47
 
@@ -50,12 +50,12 @@ class MatplotlibPlotter(Plotter):
50
50
  series.x,
51
51
  series.y,
52
52
  label=series.label,
53
- color=series.get_color().as_list(),
53
+ color=series.color.as_list(),
54
54
  marker=series.marker,
55
55
  )
56
56
 
57
57
  def plot_scatter(self, ax, series: ScatterPlotSeries):
58
- ax.scatter(series.data, label=series.label, color=series.get_color().as_list())
58
+ ax.scatter(series.data, label=series.label, color=series.color.as_list())
59
59
 
60
60
  def plot_image(self, ax, series: ImageSeries):
61
61
  ax.imshow(series.data)
@@ -0,0 +1,61 @@
1
+ """
2
+ This module has content for generating plots
3
+ """
4
+
5
+ import random
6
+
7
+ from pydantic import BaseModel
8
+
9
+ from .axis import PlotAxis
10
+ from .series import PlotSeries
11
+
12
+
13
+ class Plot(BaseModel):
14
+ """
15
+ A generic plot with optional axis ticks
16
+ """
17
+
18
+ title: str = ""
19
+ legend_label: str = ""
20
+ x_axis: PlotAxis = PlotAxis()
21
+ y_axis: PlotAxis = PlotAxis()
22
+ plot_type: str = ""
23
+ series: list[PlotSeries] = []
24
+
25
+
26
+ class GridPlot(Plot):
27
+ """
28
+ Make a grid of plots
29
+ """
30
+
31
+ stride: int = 4
32
+ size: tuple = (25, 20)
33
+ data: list = []
34
+
35
+ def get_series_indices(self, num_samples: int = 0):
36
+ rows = num_samples // self.stride
37
+ cols = num_samples // rows
38
+ len_data = len(self.data)
39
+
40
+ if num_samples == 0:
41
+ indices = list(range(0, len_data))
42
+ else:
43
+ indices = [random.randint(0, len_data - 1) for _ in range(num_samples)]
44
+ return rows, cols, indices
45
+
46
+ def get_subplots(self, num_samples: int = 0):
47
+ rows, cols, indices = self.get_series_indices(num_samples)
48
+
49
+ subplots = []
50
+ count = 1
51
+ for index in indices:
52
+ if num_samples > 0 and count == num_samples + 1:
53
+ break
54
+ if isinstance(self.data[index], list):
55
+ for series in self.data[index]:
56
+ subplots.append(series)
57
+ count += 1
58
+ else:
59
+ subplots.append(self.data[index])
60
+ count += 1
61
+ return rows, cols, subplots
@@ -11,12 +11,13 @@ class Plotter:
11
11
  self.cmap = cmap
12
12
 
13
13
  def apply_cmap_colors(self, plot: Plot):
14
- skipped_color = 0
14
+ non_highlight = []
15
15
  for idx, series in enumerate(plot.series):
16
- if not series.color:
17
- series.color = self.cmap.get_color(idx - skipped_color, plot.series)
18
- else:
19
- skipped_color += 1
16
+ if not series.highlight:
17
+ non_highlight.append(series)
18
+
19
+ for idx, series in enumerate(non_highlight):
20
+ series.color = self.cmap.get_color(idx, non_highlight)
20
21
 
21
22
  def plot(self, plot: Plot, path: Path | None = None):
22
23
  pass
@@ -0,0 +1,43 @@
1
+ import typing
2
+
3
+ from pydantic import BaseModel
4
+
5
+ from icplot.color import Color
6
+
7
+
8
+ class PlotSeries(BaseModel):
9
+ """
10
+ A data series in a plot, such as a single line in a line-plot
11
+ """
12
+
13
+ label: str
14
+ color: Color = Color()
15
+ series_type: str = ""
16
+ highlight: bool = False
17
+
18
+
19
+ class ImageSeries(PlotSeries):
20
+ """
21
+ A plot data series where the elements are images
22
+ """
23
+
24
+ data: typing.Any
25
+ transform: typing.Any
26
+ series_type: str = "image"
27
+
28
+
29
+ class LinePlotSeries(PlotSeries):
30
+ """
31
+ A plot series for line plots
32
+ """
33
+
34
+ x: list
35
+ y: list
36
+ marker: str = "o"
37
+ series_type: str = "line"
38
+
39
+
40
+ class ScatterPlotSeries(PlotSeries):
41
+
42
+ data: typing.Any
43
+ series_type: str = "scatter"
@@ -2,24 +2,24 @@
2
2
  import argparse
3
3
  import logging
4
4
  from pathlib import Path
5
+ import os
5
6
 
6
- from iccore import logging_utils
7
- from iccore import runtime
7
+ from iccore.cli_utils import launch_common
8
+ from iccore.serialization import read_yaml
8
9
 
10
+ from icplot.graph import Plot
11
+ from icplot.graph.matplotlib import MatplotlibPlotter
9
12
  from icplot.image_utils import pdf_to_png, svg_to_png, svg_to_pdf
13
+ from icplot import tex
14
+ from icplot.tex import TexBuildSettings
10
15
 
11
16
  logger = logging.getLogger(__name__)
12
17
 
13
18
 
14
- def launch_common(args):
15
- runtime.ctx.set_is_dry_run(args.dry_run)
16
- logging_utils.setup_default_logger()
17
-
18
-
19
19
  def convert(args):
20
20
  launch_common(args)
21
21
 
22
- logger.info("Attempting coversion between %s %s", args.source, args.target)
22
+ logger.info("Startubg conversion between %s and %s", args.source, args.target)
23
23
 
24
24
  if args.target:
25
25
  target = Path(args.target).resolve()
@@ -36,9 +36,33 @@ def convert(args):
36
36
  svg_to_pdf(args.source.resolve(), target)
37
37
  else:
38
38
  svg_to_png(args.source)
39
+ elif args.source.suffix == ".tex":
40
+ if args.target:
41
+ target = Path(args.target).resolve()
42
+ else:
43
+ target = Path(os.getcwd())
44
+
45
+ settings = TexBuildSettings(
46
+ args.source.resolve(), args.build_dir.resolve(), args.target
47
+ )
48
+ tex.build(settings)
49
+
39
50
  logger.info("Finished conversion")
40
51
 
41
52
 
53
+ def plot(args):
54
+
55
+ launch_common(args)
56
+
57
+ config = read_yaml(args.config.resolve())
58
+
59
+ plotter = MatplotlibPlotter()
60
+ if ["plots"] in config:
61
+ for eachplot in config["plots"]:
62
+ plot = Plot(**eachplot)
63
+ plotter.plot(plot, args.output_dir.resolve())
64
+
65
+
42
66
  def main_cli():
43
67
  parser = argparse.ArgumentParser()
44
68
  parser.add_argument(
@@ -61,8 +85,23 @@ def main_cli():
61
85
  default="",
62
86
  help="Path to file to be converted to",
63
87
  )
88
+ convert_parser.add_argument(
89
+ "--build_dir",
90
+ default=Path(os.getcwd()) / "_build/tikz",
91
+ help="Path for build output",
92
+ )
64
93
  convert_parser.set_defaults(func=convert)
65
94
 
95
+ plot_parser = subparsers.add_parser("plot")
96
+ plot_parser.add_argument("--config", type=Path, help="Path to the plot config")
97
+ plot_parser.add_argument(
98
+ "--output_dir",
99
+ type=Path,
100
+ default=Path(os.getcwd()),
101
+ help="Path to the plot output directory",
102
+ )
103
+ plot_parser.set_defaults(func=plot)
104
+
66
105
  args = parser.parse_args()
67
106
  args.func(args)
68
107
 
@@ -0,0 +1,77 @@
1
+ """
2
+ This module has functionality for publishing Tex documents
3
+ """
4
+
5
+ import subprocess
6
+ from typing import NamedTuple
7
+ import shutil
8
+ import os
9
+ from pathlib import Path
10
+ import logging
11
+
12
+ from .image_utils import pdf_to_png
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class TexBuildSettings(NamedTuple):
18
+ """
19
+ This holds settings for the Tex build
20
+ """
21
+
22
+ source: Path
23
+ build_dir: Path
24
+ output_dir: Path | None = None
25
+ build_engine: str = "pdflatex"
26
+ output_png: bool = True
27
+ clear_workdir: bool = True
28
+
29
+
30
+ def build_pdf(settings: TexBuildSettings, work_dir: Path):
31
+
32
+ cmd = f"{settings.build_engine} {settings.source}"
33
+ with open(work_dir / "stdout.txt", "w", encoding="utf-8") as f:
34
+ subprocess.run(cmd, shell=True, check=True, cwd=work_dir, stdout=f, stderr=f)
35
+
36
+
37
+ def build_single(settings: TexBuildSettings):
38
+ logger.info("Building source: %s", settings.source)
39
+
40
+ # Make a working dir
41
+ work_dir = settings.build_dir / settings.source.stem
42
+ os.makedirs(work_dir, exist_ok=True)
43
+
44
+ build_pdf(settings, work_dir)
45
+
46
+ tex_path = work_dir / settings.source.name
47
+ pdf_path = tex_path.parent / f"{tex_path.stem}.pdf"
48
+ if settings.output_png:
49
+ pdf_to_png(pdf_path)
50
+
51
+ # If output dir is different to build dir copy final content there
52
+ if settings.output_dir and settings.output_dir != work_dir:
53
+ os.makedirs(settings.output_dir, exist_ok=True)
54
+ shutil.copy(pdf_path, settings.output_dir)
55
+
56
+ if settings.output_png:
57
+ png_path = pdf_path.parent / f"{tex_path.stem}.png"
58
+ shutil.copy(png_path, settings.output_dir)
59
+
60
+ if settings.clear_workdir:
61
+ shutil.rmtree(work_dir)
62
+
63
+
64
+ def build(settings: TexBuildSettings):
65
+ if settings.source.is_dir():
66
+ for tex_file in settings.source.glob("*.tex"):
67
+ single_build = TexBuildSettings(
68
+ tex_file,
69
+ settings.build_dir,
70
+ settings.output_dir,
71
+ settings.build_engine,
72
+ )
73
+ build_single(single_build)
74
+ else:
75
+ build_single(settings)
76
+
77
+ logger.info("Finished building sources")
@@ -0,0 +1 @@
1
+ from .trace import * # NOQA
File without changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: icplot
3
- Version: 0.0.10
3
+ Version: 0.0.12
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.0
19
+ Requires-Dist: iccore==0.1.5
20
20
  Provides-Extra: test
21
21
  Requires-Dist: pytest; extra == "test"
22
22
  Requires-Dist: pytest-cov; extra == "test"
@@ -62,6 +62,12 @@ To covert between image formats you can do:
62
62
  icplot convert --source my_image.svg --target my_image.png
63
63
  ```
64
64
 
65
+ To render a Tex tikz image as pdf and png you can do:
66
+
67
+ ``` shell
68
+ icplot convert --source my_tikz.tex
69
+ ```
70
+
65
71
  # Copyright #
66
72
 
67
73
  Copyright 2024 Irish Centre for High End Computing