diff --git a/lib/matplotex.ex b/lib/matplotex.ex index f1ed65d..97a9aef 100644 --- a/lib/matplotex.ex +++ b/lib/matplotex.ex @@ -773,11 +773,6 @@ defmodule Matplotex do Figure.set_rc_params(figure, rc_params) end - def show({stream, figure}) do - Scatter.materialize(stream, figure) - |> Sketch.call() - end - def show(figure) do figure |> Figure.materialize() diff --git a/lib/matplotex/figure/areal.ex b/lib/matplotex/figure/areal.ex index 6ba5d40..eae79df 100644 --- a/lib/matplotex/figure/areal.ex +++ b/lib/matplotex/figure/areal.ex @@ -210,6 +210,20 @@ defmodule Matplotex.Figure.Areal do %__MODULE__{axes | size: frame_size} end + def process_concurrently(transformed, concurrency, args) do + chunk_size = div(length(transformed), concurrency) + + transformed + |> Enum.chunk_every(chunk_size) + |> Task.async_stream(fn part -> + args = [part | args] + apply(__MODULE__, :capture, args) + end) + |> Enum.reduce([], fn {:ok, elements}, acc -> + acc ++ elements + end) + end + def set_region_title( %Figure{ axes: diff --git a/lib/matplotex/figure/areal/bar_chart.ex b/lib/matplotex/figure/areal/bar_chart.ex index 77ce19a..bf1fcc3 100644 --- a/lib/matplotex/figure/areal/bar_chart.ex +++ b/lib/matplotex/figure/areal/bar_chart.ex @@ -65,7 +65,11 @@ defmodule Matplotex.Figure.Areal.BarChart do }, element: elements } = axes, - rc_params: %RcParams{x_padding: x_padding, white_space: white_space} + rc_params: %RcParams{ + x_padding: x_padding, + white_space: white_space, + concurrency: concurrency + } } = figure ) do x_padding_value = width_region_content * x_padding + white_space @@ -82,7 +86,7 @@ defmodule Matplotex.Figure.Areal.BarChart do height_region_content, {x_region_content + x_padding_value, y_region_content} ) - |> capture(-y_region_content) + |> capture(-y_region_content, concurrency) end) |> List.flatten() @@ -114,23 +118,27 @@ defmodule Matplotex.Figure.Areal.BarChart do {min..max |> Enum.into([], fn d -> d * round_to_best(step) end), lim} end - defp capture(%Dataset{transformed: transformed} = dataset, bly) do - capture(transformed, [], dataset, bly) + def capture(%Dataset{transformed: transformed} = dataset, bly, concurrency) do + if concurrency do + process_concurrently(transformed, concurrency, [[], dataset, bly]) + else + capture(transformed, [], dataset, bly) + end end - defp capture( - [{x, y} | to_capture], - captured, - %Dataset{ - color: color, - width: width, - pos: pos_factor, - edge_color: edge_color, - alpha: alpha, - line_width: line_width - } = dataset, - bly - ) do + def capture( + [{x, y} | to_capture], + captured, + %Dataset{ + color: color, + width: width, + pos: pos_factor, + edge_color: edge_color, + alpha: alpha, + line_width: line_width + } = dataset, + bly + ) do capture( to_capture, captured ++ @@ -153,7 +161,7 @@ defmodule Matplotex.Figure.Areal.BarChart do ) end - defp capture([], captured, _dataset, _bly), do: captured + def capture([], captured, _dataset, _bly), do: captured defp hypox(y) do nof_x = length(y) diff --git a/lib/matplotex/figure/areal/histogram.ex b/lib/matplotex/figure/areal/histogram.ex index bc9dc0f..a3129f6 100644 --- a/lib/matplotex/figure/areal/histogram.ex +++ b/lib/matplotex/figure/areal/histogram.ex @@ -63,7 +63,11 @@ defmodule Matplotex.Figure.Areal.Histogram do }, element: element }, - rc_params: %RcParams{x_padding: x_padding, white_space: white_space} + rc_params: %RcParams{ + x_padding: x_padding, + white_space: white_space, + concurrency: concurrency + } }) do x_padding_value = width_region_content * x_padding + white_space shrinked_width_region_content = width_region_content - x_padding_value * 2 @@ -79,15 +83,19 @@ defmodule Matplotex.Figure.Areal.Histogram do height_region_content, {x_region_content + x_padding_value, y_region_content} ) - |> capture(abs(y_region_content), shrinked_width_region_content) + |> capture(abs(y_region_content), shrinked_width_region_content, concurrency) end) |> List.flatten() %Figure{axes: %{element: element ++ hist_elements}} end - defp capture(%Dataset{transformed: transformed} = dataset, bly, region_width) do - capture(transformed, [], dataset, bly, region_width) + defp capture(%Dataset{transformed: transformed} = dataset, bly, region_width, concurrency) do + if concurrency do + process_concurrently(transformed, concurrency, [[], dataset, bly, region_width]) + else + capture(transformed, [], dataset, bly, region_width) + end end defp capture( diff --git a/lib/matplotex/figure/areal/line_plot.ex b/lib/matplotex/figure/areal/line_plot.ex index c977c8c..5174d75 100644 --- a/lib/matplotex/figure/areal/line_plot.ex +++ b/lib/matplotex/figure/areal/line_plot.ex @@ -65,7 +65,11 @@ defmodule Matplotex.Figure.Areal.LinePlot do }, element: elements } = axes, - rc_params: %RcParams{x_padding: x_padding, y_padding: y_padding} + rc_params: %RcParams{ + x_padding: x_padding, + y_padding: y_padding, + concurrency: concurrency + } } = figure ) do # {x_region_content, y_region_content} = Algebra.flip_y_coordinate({x_region_content, y_region_content}) @@ -85,7 +89,7 @@ defmodule Matplotex.Figure.Areal.LinePlot do shrinked_height_region_content, {x_region_content + x_padding_value, y_region_content + y_padding_value} ) - |> capture() + |> capture(concurrency) end) |> List.flatten() @@ -129,19 +133,23 @@ defmodule Matplotex.Figure.Areal.LinePlot do {Ticker.generate_ticks(lim), lim} end - defp capture(%Dataset{transformed: transformed} = dataset) do - capture(transformed, [], dataset) + def capture(%Dataset{transformed: transformed} = dataset, concurrency) do + if concurrency do + process_concurrently(transformed, concurrency, [[], dataset]) + else + capture(transformed, [], dataset) + end end - defp capture( - [{x1, y1} | [{x2, y2} | _] = to_capture], - captured, - %Dataset{ - color: color, - marker: marker, - linestyle: linestyle - } = dataset - ) do + def capture( + [{x1, y1} | [{x2, y2} | _] = to_capture], + captured, + %Dataset{ + color: color, + marker: marker, + linestyle: linestyle + } = dataset + ) do capture( to_capture, captured ++ @@ -162,7 +170,7 @@ defmodule Matplotex.Figure.Areal.LinePlot do ) end - defp capture([{x, y}], captured, %Dataset{color: color, marker: marker}) do + def capture([{x, y}], captured, %Dataset{color: color, marker: marker}) do captured ++ [Marker.generate_marker(marker, x, y, color, @marker_size)] end end diff --git a/lib/matplotex/figure/areal/scatter.ex b/lib/matplotex/figure/areal/scatter.ex index cde60da..61a375c 100644 --- a/lib/matplotex/figure/areal/scatter.ex +++ b/lib/matplotex/figure/areal/scatter.ex @@ -58,7 +58,11 @@ defmodule Matplotex.Figure.Areal.Scatter do }, element: elements } = axes, - rc_params: %RcParams{x_padding: x_padding, y_padding: y_padding} + rc_params: %RcParams{ + x_padding: x_padding, + y_padding: y_padding, + concurrency: concurrency + } } = figure ) do x_padding_value = width_region_content * x_padding @@ -77,7 +81,7 @@ defmodule Matplotex.Figure.Areal.Scatter do shrinked_height_region_content, {x_region_content + x_padding_value, y_region_content + y_padding_value} ) - |> capture() + |> capture(concurrency) end) |> List.flatten() @@ -85,42 +89,23 @@ defmodule Matplotex.Figure.Areal.Scatter do %Figure{figure | axes: %{axes | element: elements}} end - def materialize(xystream, figure) do - __MODULE__.materialized_by_region(figure) - |> material_stream(xystream) + def capture(%Dataset{transformed: transformed} = dataset, concurrency) do + if concurrency do + process_concurrently(transformed, concurrency, [[], dataset]) + else + capture(transformed, [], dataset) + end end - def material_stream( - %Figure{ - axes: %__MODULE__{ - limit: %TwoD{x: xlim, y: ylim}, - element: element, - coords: %Coords{bottom_left: {blx, bly}}, - size: {width, height} - } - } = figure, - xystream + def capture( + [{x, y} | to_capture], + captured, + %Dataset{ + color: color, + marker: marker, + marker_size: marker_size + } = dataset ) do - {Stream.map(xystream, fn {x, y} -> - {matx, maty} = transformation(x, y, xlim, ylim, width, height, {blx, bly}) - Marker.generate_marker("o", matx, maty, "blue", 5) - end) - |> Stream.concat(element), figure} - end - - defp capture(%Dataset{transformed: transformed} = dataset) do - capture(transformed, [], dataset) - end - - defp capture( - [{x, y} | to_capture], - captured, - %Dataset{ - color: color, - marker: marker, - marker_size: marker_size - } = dataset - ) do capture( to_capture, captured ++ @@ -131,7 +116,7 @@ defmodule Matplotex.Figure.Areal.Scatter do ) end - defp capture(_, captured, _), do: captured + def capture(_, captured, _), do: captured @impl Areal def with_legend_handle( diff --git a/lib/matplotex/figure/dataset.ex b/lib/matplotex/figure/dataset.ex index 58d0af6..5acf25c 100644 --- a/lib/matplotex/figure/dataset.ex +++ b/lib/matplotex/figure/dataset.ex @@ -4,7 +4,7 @@ defmodule Matplotex.Figure.Dataset do @default_marker "o" @default_linestyle "_" @default_width 0.2 - @default_marker_size 3.5 + @default_marker_size 1 @default_alpha 1.0 @line_width 2 diff --git a/lib/matplotex/figure/rc_params.ex b/lib/matplotex/figure/rc_params.ex index 2e1791b..c79e590 100644 --- a/lib/matplotex/figure/rc_params.ex +++ b/lib/matplotex/figure/rc_params.ex @@ -52,7 +52,8 @@ defmodule Matplotex.Figure.RcParams do legend_width: @default_legend_width_percentage, legend_items_orientation: @default_legend_items_orientation, x_ticks_count: nil, - y_ticks_count: nil + y_ticks_count: nil, + concurrency: nil def get_rc(%__MODULE__{} = rc_param, get_func) do apply(__MODULE__, get_func, [rc_param]) diff --git a/test/matplotex/figure/areal/line_plot_test.exs b/test/matplotex/figure/areal/line_plot_test.exs index 26f2970..005f4d7 100644 --- a/test/matplotex/figure/areal/line_plot_test.exs +++ b/test/matplotex/figure/areal/line_plot_test.exs @@ -14,6 +14,14 @@ defmodule Matplotex.Figure.Areal.LinePlotTest do assert elem1.fill == "blue" assert elem1.linestyle == "_" end + + test "materialize concurrently if rc_params contains a positive integer", %{figure: figure} do + figure = Matplotex.set_rc_params(figure, concurrency: 2) + assert %Figure{axes: %{element: elements}} = LinePlot.materialize(figure) + [elem1 | _] = Enum.filter(elements, fn elem -> elem.type == "plot.line" end) + assert elem1.fill == "blue" + assert elem1.linestyle == "_" + end end describe "create/4" do diff --git a/test/matplotex/figure/radial/pie_test.exs b/test/matplotex/figure/radial/pie_test.exs index 18fbdda..746e463 100644 --- a/test/matplotex/figure/radial/pie_test.exs +++ b/test/matplotex/figure/radial/pie_test.exs @@ -42,7 +42,7 @@ defmodule Matplotex.Figure.Radial.PieTest do # Colors for the slices colors = ["lightblue", "lightgreen", "orange", "pink"] figure = Pie.create(%Figure{axes: %Pie{}}, sizes, labels: labels, colors: colors) - assert %Figure{axes: %{element: element}} = figure|> Figure.materialize() + assert %Figure{axes: %{element: element}} = figure |> Figure.materialize() assert Enum.filter(element, fn elem -> elem.type == "pie.slice" end) |> length() == length(sizes)