From 3e6493c67701c0921b64376a00ff804f56c87235 Mon Sep 17 00:00:00 2001 From: Mohammed Sadique Date: Tue, 11 Feb 2025 18:57:32 +0530 Subject: [PATCH 1/7] stacked bar --- lib/matplotex/figure/areal/bar_chart.ex | 45 ++++++++++++++++++++++ lib/matplotex/figure/areal/plot_options.ex | 10 +++-- lib/matplotex/figure/dataset.ex | 3 +- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/lib/matplotex/figure/areal/bar_chart.ex b/lib/matplotex/figure/areal/bar_chart.ex index d87734e..617651c 100644 --- a/lib/matplotex/figure/areal/bar_chart.ex +++ b/lib/matplotex/figure/areal/bar_chart.ex @@ -50,6 +50,51 @@ defmodule Matplotex.Figure.Areal.BarChart do def materialize(figure) do materialize_bars(figure) end + defp materialize_bars( + %Figure{ + axes: + %{ + dataset: datasets, + data: data, + limit: %{x: xlim, y: ylim}, + type: "stacked", + region_content: %Region{ + x: x_region_content, + y: y_region_content, + width: width_region_content, + height: height_region_content + }, + element: elements + } = axes, + 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 + shrinked_width_region_content = width_region_content - x_padding_value * 2 + + bar_elements = + datasets + |> Enum.map(fn dataset -> + dataset + |> do_transform( + xlim, + ylim, + shrinked_width_region_content, + height_region_content, + {x_region_content + x_padding_value, y_region_content} + ) + |> capture(-y_region_content, concurrency) + end) + |> List.flatten() + + elements_with_bar = elements ++ bar_elements + + %Figure{figure | axes: %{axes | element: elements_with_bar}} + end defp materialize_bars( %Figure{ diff --git a/lib/matplotex/figure/areal/plot_options.ex b/lib/matplotex/figure/areal/plot_options.ex index 1ff8001..d717fc5 100644 --- a/lib/matplotex/figure/areal/plot_options.ex +++ b/lib/matplotex/figure/areal/plot_options.ex @@ -36,10 +36,11 @@ defmodule Matplotex.Figure.Areal.PlotOptions do opts = Keyword.delete(opts, :label) cmap = Keyword.get(opts, :cmap) colors = Keyword.get(opts, :colors) + bottom = Keyword.get(opts, :bottom) %Figure{ figure - | axes: axes |> struct(opts) |> cast_two_d_structs(opts)|> update_cmap(cmap, colors) + | axes: axes |> struct(opts) |> cast_two_d_structs(opts)|> update_cmap(cmap, colors) |> update_type(bottom) } end @@ -63,7 +64,6 @@ defmodule Matplotex.Figure.Areal.PlotOptions do Keyword.drop(opts, @immutable_keys) end defp update_cmap(axes, nil, colors) when is_list(colors) do - %{axes | cmap: Colormap.fetch_cmap(@default_cmap)} end @@ -71,5 +71,9 @@ defmodule Matplotex.Figure.Areal.PlotOptions do %{axes | cmap: Colormap.fetch_cmap(cmap)} end - defp update_cmap(figure, _, _), do: figure + defp update_cmap(axes, _, _), do: axes + defp update_type(axes, nil), do: axes + defp update_type(axes, bottom) when is_list(bottom) do + %{axes | type: "stacked"} + end end diff --git a/lib/matplotex/figure/dataset.ex b/lib/matplotex/figure/dataset.ex index ca84be5..ae23b1e 100644 --- a/lib/matplotex/figure/dataset.ex +++ b/lib/matplotex/figure/dataset.ex @@ -24,7 +24,8 @@ defmodule Matplotex.Figure.Dataset do marker: @default_marker, linestyle: @default_linestyle, marker_size: @default_marker_size, - line_width: @line_width + line_width: @line_width, + bottom: nil ] def cast(dataset, values) do From ee923db7b4d6461142da18136b34dcfc4acd59eb Mon Sep 17 00:00:00 2001 From: Mohammed Sadique Date: Wed, 12 Feb 2025 18:58:34 +0530 Subject: [PATCH 2/7] making whole data --- lib/matplotex/figure/areal.ex | 12 +++++++++++- lib/matplotex/figure/areal/bar_chart.ex | 5 +++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/matplotex/figure/areal.ex b/lib/matplotex/figure/areal.ex index 416c9d1..aaa971f 100644 --- a/lib/matplotex/figure/areal.ex +++ b/lib/matplotex/figure/areal.ex @@ -58,7 +58,6 @@ defmodule Matplotex.Figure.Areal do end def add_title(axes, title, opts) when is_binary(title) do - # title = Text.create_text(title, opts) %{axes | title: title, show_title: true} end @@ -170,6 +169,17 @@ defmodule Matplotex.Figure.Areal do data_with_label(data) end end + # For stacked bar chart the flattening supposed to be the sumation of yaxis data + def flatten_for_data(datasets,_data, nil), do: flatten_for_data(datasets) + def flatten_for_data(_datasets,%{x: x, y: y} = _data, bottom) do + y = bottom + |> Tuple.to_list() + |> Kernel.++(y) + |> Nx.tensor(names: [:x, :y]) + |> Nx.sum(axes: [:x]) + |> Nx.to_list() + {x, y} + end def flatten_for_data(datasets) do datasets diff --git a/lib/matplotex/figure/areal/bar_chart.ex b/lib/matplotex/figure/areal/bar_chart.ex index 617651c..268a135 100644 --- a/lib/matplotex/figure/areal/bar_chart.ex +++ b/lib/matplotex/figure/areal/bar_chart.ex @@ -36,7 +36,8 @@ defmodule Matplotex.Figure.Areal.BarChart do x = hypox(values) dataset = Dataset.cast(%Dataset{x: x, y: values, pos: pos, width: width}, opts) datasets = data ++ [dataset] - xydata = flatten_for_data(datasets) + bottom = Keyword.get(opts, :bottom) + xydata = flatten_for_data(datasets,data, bottom) %Figure{ figure @@ -55,7 +56,7 @@ defmodule Matplotex.Figure.Areal.BarChart do axes: %{ dataset: datasets, - data: data, + data: {_x, y}, limit: %{x: xlim, y: ylim}, type: "stacked", region_content: %Region{ From 5fc14a07c8387eaba44459e2d348500d50fd5eb9 Mon Sep 17 00:00:00 2001 From: Mohammed Sadique Date: Thu, 13 Feb 2025 20:51:52 +0530 Subject: [PATCH 3/7] capture stacked --- lib/matplotex/figure/areal/bar_chart.ex | 67 +++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/lib/matplotex/figure/areal/bar_chart.ex b/lib/matplotex/figure/areal/bar_chart.ex index 268a135..89038d1 100644 --- a/lib/matplotex/figure/areal/bar_chart.ex +++ b/lib/matplotex/figure/areal/bar_chart.ex @@ -1,6 +1,7 @@ defmodule Matplotex.Figure.Areal.BarChart do @moduledoc false import Matplotex.Figure.Numer + alias Matplotex.Utils.Algebra alias Matplotex.Figure.Areal.PlotOptions alias Matplotex.Figure.Areal.Region alias Matplotex.Element.Legend @@ -81,7 +82,7 @@ defmodule Matplotex.Figure.Areal.BarChart do datasets |> Enum.map(fn dataset -> dataset - |> do_transform( + |> do_transform_with_bottom( xlim, ylim, shrinked_width_region_content, @@ -208,7 +209,41 @@ defmodule Matplotex.Figure.Areal.BarChart do end def capture([], captured, _dataset, _bly), do: captured + defp capture_stacked([{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 + {y, bottom_y} = if is_list(y) do + {Enum.sum(y), y|>tl()|>Enum.sum()} + else + {y, bly} + end + + capture_stacked( + to_capture, + captured ++ + [ + %Rect{ + type: "figure.bar", + x: bar_position(x, pos_factor), + y: y, + width: width, + height: bottom_y - y, + color: color, + stroke: edge_color || color, + fill_opacity: alpha, + stroke_opacity: alpha, + stroke_width: line_width + } + ], + dataset, bly + ) + end defp hypox(y) do nof_x = length(y) @xmin_value |> Nx.linspace(nof_x, n: nof_x) |> Nx.to_list() @@ -218,12 +253,38 @@ defmodule Matplotex.Figure.Areal.BarChart do x + pos_factor end - - defp list_of_ticks(data, step) do 1..length(data) |> Enum.into([], fn d -> d * step end) end + + defp do_transform_with_bottom(%Dataset{x: x, y: y, bottom: bottom} = dataset, xlim, ylim, width, height, transition) do + y = [y | bottom]|> Nx.tensor() |> Nx.transpose()|> Nx.to_list() + + transformed = + x + |> Enum.zip(y) + |> Enum.map(fn {x, y} -> + transform_with_bottom(x,y, xlim, ylim, width, height, transition) + end) + + %Dataset{dataset | transformed: transformed} + end + + defp transform_with_bottom(x, y, xlim, ylim, width, height, transition) when is_list(y) do + transformed = Enum.map(y, fn y_with_bottom -> + transformation(x, y_with_bottom, xlim, ylim, width, height, transition) + |> Algebra.flip_y_coordinate() + end) + |>Enum.unzip() + + {transformed|>elem(0)|>hd, transformed|> elem(1)} + end + + defp transform_with_bottom(x, y, xlim, ylim, width, height, transition) do + transformation(x, y, xlim, ylim, width, height, transition) + |> Algebra.flip_y_coordinate() + end end From d50d96127fd1065435908b66254fa23382adc499 Mon Sep 17 00:00:00 2001 From: Mohammed Sadique Date: Fri, 14 Feb 2025 17:39:56 +0530 Subject: [PATCH 4/7] unit test --- lib/matplotex.ex | 15 ++- lib/matplotex/figure.ex | 2 + lib/matplotex/figure/areal.ex | 13 ++- lib/matplotex/figure/areal/bar_chart.ex | 94 +++++++++++-------- .../matplotex/figure/areal/bar_chart_test.exs | 16 +++- 5 files changed, 90 insertions(+), 50 deletions(-) diff --git a/lib/matplotex.ex b/lib/matplotex.ex index 3720f77..9003b25 100644 --- a/lib/matplotex.ex +++ b/lib/matplotex.ex @@ -213,9 +213,7 @@ defmodule Matplotex do bar(pos, values, width, []) end - def bar(pos, values, width, opts) do - BarChart.create(%Figure{axes: %BarChart{}}, {pos, values, width}, opts) - end + @doc """ Adds an additional dataset to a bar plot in the given `%Figure{}`. @@ -251,12 +249,19 @@ defmodule Matplotex do |> M.bar(0, values2, width, label: "Dataset2", color: "#D3D3D3") |> M.bar(width, values2, width, label: "Dataset3", color: "green") """ + + def bar(%Figure{} = figure, values, width, opts), do: bar(figure, width, values, width, opts) + + def bar(pos, values, width, opts) do + BarChart.create(%Figure{axes: %BarChart{}}, {pos, values, width}, opts) + end def bar(%Figure{} = figure, pos, values, width, opts) do figure |> show_legend() |> BarChart.create({pos, values, width}, opts) end + @doc """ Creates a scatter plot based on the given `x` and `y` values, with optional customization provided via `opts`. @@ -751,7 +756,9 @@ defmodule Matplotex do def show_legend(figure) do Figure.show_legend(figure) end - + def hide_legend(figure) do + Figure.hide_legend(figure) + end def set_options(figure, opts) do PlotOptions.set_options_in_figure(figure, opts) end diff --git a/lib/matplotex/figure.ex b/lib/matplotex/figure.ex index 6ac9857..d1d993f 100644 --- a/lib/matplotex/figure.ex +++ b/lib/matplotex/figure.ex @@ -62,6 +62,8 @@ defmodule Matplotex.Figure do def show_legend(%__MODULE__{axes: %module{} = axes} = figure), do: %{figure | axes: module.show_legend(axes)} + def hide_legend(%__MODULE__{axes: %module{} = axes} = figure), + do: %{figure | axes: module.hide_legend(axes)} def set_figure_size(%__MODULE__{margin: margin, axes: axes} = figure, {fwidth, fheight} = fsize) do frame_size = {fwidth - fwidth * 2 * margin, fheight - fheight * 2 * margin} diff --git a/lib/matplotex/figure/areal.ex b/lib/matplotex/figure/areal.ex index aaa971f..e71ce96 100644 --- a/lib/matplotex/figure/areal.ex +++ b/lib/matplotex/figure/areal.ex @@ -170,11 +170,11 @@ defmodule Matplotex.Figure.Areal do end end # For stacked bar chart the flattening supposed to be the sumation of yaxis data - def flatten_for_data(datasets,_data, nil), do: flatten_for_data(datasets) - def flatten_for_data(_datasets,%{x: x, y: y} = _data, bottom) do - y = bottom - |> Tuple.to_list() - |> Kernel.++(y) + def flatten_for_data(datasets, nil), do: flatten_for_data(datasets) + def flatten_for_data([%{x: x, y: y}| _datasets], bottom) do + + y= bottom + |> Kernel.++([y]) |> Nx.tensor(names: [:x, :y]) |> Nx.sum(axes: [:x]) |> Nx.to_list() @@ -215,6 +215,9 @@ defmodule Matplotex.Figure.Areal do def show_legend(%__MODULE__{} = axes) do %__MODULE__{axes | show_legend: true} end + def hide_legend(%__MODULE__{} = axes) do + %__MODULE__{axes | show_legend: false} + end def set_frame_size(%__MODULE__{} = axes, frame_size) do %__MODULE__{axes | size: frame_size} diff --git a/lib/matplotex/figure/areal/bar_chart.ex b/lib/matplotex/figure/areal/bar_chart.ex index 89038d1..0c1e5e4 100644 --- a/lib/matplotex/figure/areal/bar_chart.ex +++ b/lib/matplotex/figure/areal/bar_chart.ex @@ -38,7 +38,7 @@ defmodule Matplotex.Figure.Areal.BarChart do dataset = Dataset.cast(%Dataset{x: x, y: values, pos: pos, width: width}, opts) datasets = data ++ [dataset] bottom = Keyword.get(opts, :bottom) - xydata = flatten_for_data(datasets,data, bottom) + xydata = datasets|>Enum.reverse()|> flatten_for_data(bottom) %Figure{ figure @@ -57,7 +57,6 @@ defmodule Matplotex.Figure.Areal.BarChart do axes: %{ dataset: datasets, - data: {_x, y}, limit: %{x: xlim, y: ylim}, type: "stacked", region_content: %Region{ @@ -70,14 +69,12 @@ defmodule Matplotex.Figure.Areal.BarChart do } = axes, rc_params: %RcParams{ x_padding: x_padding, - white_space: white_space, - concurrency: concurrency + white_space: white_space } } = figure ) do x_padding_value = width_region_content * x_padding + white_space shrinked_width_region_content = width_region_content - x_padding_value * 2 - bar_elements = datasets |> Enum.map(fn dataset -> @@ -89,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, concurrency) + |> capture_stacked(-y_region_content) end) |> List.flatten() @@ -164,7 +161,6 @@ defmodule Matplotex.Figure.Areal.BarChart do step = (max - min) / (side * 2) {min..max |> Enum.into([], fn d -> d * round_to_best(step) end), lim} end - def capture(%Dataset{transformed: transformed} = dataset, bly, concurrency) do if concurrency do process_concurrently(transformed, concurrency, [[], dataset, bly]) @@ -173,6 +169,37 @@ defmodule Matplotex.Figure.Areal.BarChart do end end + def capture([{{x, y}, bottom} | to_capture], captured, %Dataset{ + color: color, + width: width, + pos: pos_factor, + edge_color: edge_color, + alpha: alpha, + line_width: line_width + } = dataset) do + capture( + to_capture, + captured ++ + [ + %Rect{ + type: "figure.bar", + x: bar_position(x, pos_factor), + y: y, + width: width, + height: bottom - y, + color: color, + stroke: edge_color || color, + fill_opacity: alpha, + stroke_opacity: alpha, + stroke_width: line_width + } + ], + dataset + ) + end + def capture([], captured, _dataset), do: captured + + def capture( [{x, y} | to_capture], captured, @@ -209,40 +236,23 @@ defmodule Matplotex.Figure.Areal.BarChart do end def capture([], captured, _dataset, _bly), do: captured - defp capture_stacked([{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 - {y, bottom_y} = if is_list(y) do - {Enum.sum(y), y|>tl()|>Enum.sum()} - else - {y, bly} - end + defp capture_stacked(%Dataset{transformed: transformed}=dataset, bly) do + capture_stacked(transformed, [],dataset, bly) + end + defp capture_stacked(to_capture, captured, dataset, bly) do + to_capture + |>Enum.map(fn point -> + calculate_point(point, bly) + end) + |>capture(captured, dataset) + end + defp calculate_point({x, y}, _bly) when is_list(y) do + {{x, Enum.sum(y)}, y|>tl()|>Enum.sum()} + end - capture_stacked( - to_capture, - captured ++ - [ - %Rect{ - type: "figure.bar", - x: bar_position(x, pos_factor), - y: y, - width: width, - height: bottom_y - y, - color: color, - stroke: edge_color || color, - fill_opacity: alpha, - stroke_opacity: alpha, - stroke_width: line_width - } - ], - dataset, bly - ) + defp calculate_point({x, y}, bly) do + {{x, y}, bly} end defp hypox(y) do nof_x = length(y) @@ -260,7 +270,7 @@ defmodule Matplotex.Figure.Areal.BarChart do end) end - defp do_transform_with_bottom(%Dataset{x: x, y: y, bottom: bottom} = dataset, xlim, ylim, width, height, transition) do + defp do_transform_with_bottom(%Dataset{x: x, y: y, bottom: bottom} = dataset, xlim, ylim, width, height, transition) when is_list(bottom) do y = [y | bottom]|> Nx.tensor() |> Nx.transpose()|> Nx.to_list() transformed = @@ -273,6 +283,10 @@ defmodule Matplotex.Figure.Areal.BarChart do %Dataset{dataset | transformed: transformed} end + defp do_transform_with_bottom(dataset, xlim, ylim, width, height, transition) do + do_transform(dataset, xlim, ylim, width, height, transition) + end + defp transform_with_bottom(x, y, xlim, ylim, width, height, transition) when is_list(y) do transformed = Enum.map(y, fn y_with_bottom -> transformation(x, y_with_bottom, xlim, ylim, width, height, transition) diff --git a/test/matplotex/figure/areal/bar_chart_test.exs b/test/matplotex/figure/areal/bar_chart_test.exs index df39618..d7763f4 100644 --- a/test/matplotex/figure/areal/bar_chart_test.exs +++ b/test/matplotex/figure/areal/bar_chart_test.exs @@ -15,8 +15,22 @@ defmodule Matplotex.Figure.Areal.BarChartTest do assert %Figure{axes: %{element: elements}} = BarChart.materialized_by_region(figure) |> BarChart.materialize() - assert assert Enum.filter(elements, fn x -> x.type == "figure.bar" end) |> length() == + assert Enum.filter(elements, fn x -> x.type == "figure.bar" end) |> length() == length(y) end + + test "bottom variable in opts makes stacked bar chart and it will stack the bars" do + values1 = [2,4,3,2] + values2 = [1,2,1,4] + values3 = [3,1,2,1] + width = 0.3 + bar = Matplotex.bar(values1, width)|> Matplotex.bar(values2, width, bottom: [values1]) + |> Matplotex.bar(values3, width, bottom: [values2, values1]) + expected_elements_count = values1 ++ values2 ++ values3 |> length() + assert %Figure{axes: %{element: elements}} = Figure.materialize(bar) + + assert Enum.filter(elements, fn x -> x.type == "figure.bar" end) |> length() == + expected_elements_count + end end end From c95f892ec20cb4d85e3e7094eb95a2fc9e2d26f1 Mon Sep 17 00:00:00 2001 From: Mohammed Sadique Date: Mon, 17 Feb 2025 16:00:08 +0530 Subject: [PATCH 5/7] scceed --- lib/matplotex/figure/areal/bar_chart.ex | 29 +++++++++++-------- .../matplotex/figure/areal/bar_chart_test.exs | 9 ++++-- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/lib/matplotex/figure/areal/bar_chart.ex b/lib/matplotex/figure/areal/bar_chart.ex index 0c1e5e4..ee6d688 100644 --- a/lib/matplotex/figure/areal/bar_chart.ex +++ b/lib/matplotex/figure/areal/bar_chart.ex @@ -242,16 +242,18 @@ defmodule Matplotex.Figure.Areal.BarChart do defp capture_stacked(to_capture, captured, dataset, bly) do to_capture |>Enum.map(fn point -> - calculate_point(point, bly) + format_point(point, bly) end) |>capture(captured, dataset) end - defp calculate_point({x, y}, _bly) when is_list(y) do - {{x, Enum.sum(y)}, y|>tl()|>Enum.sum()} - end + defp format_point({{_x, _y}, _y_bottom} = point, _bly), do: point + # sum_of_tail = y |> Enum.sort()|>tl()|>Enum.sum + # sum_of_second_tail = y|>tl()|>tl()|>Enum.sum() + # {{x, y|>Enum.max()|>Kernel.-(sum_of_tail)}, y|>tl()|>Enum.max()|> Kernel.-(sum_of_second_tail)} + # end - defp calculate_point({x, y}, bly) do + defp format_point({x, y}, bly) do {{x, y}, bly} end defp hypox(y) do @@ -288,13 +290,16 @@ defmodule Matplotex.Figure.Areal.BarChart do end defp transform_with_bottom(x, y, xlim, ylim, width, height, transition) when is_list(y) do - transformed = Enum.map(y, fn y_with_bottom -> - transformation(x, y_with_bottom, xlim, ylim, width, height, transition) - |> Algebra.flip_y_coordinate() - end) - |>Enum.unzip() - - {transformed|>elem(0)|>hd, transformed|> elem(1)} + # transformed = Enum.map(y, fn y_with_bottom -> + # transformation(x, y_with_bottom, xlim, ylim, width, height, transition) + # |> Algebra.flip_y_coordinate() + # end) + # |>Enum.unzip() + y_top = Enum.sum(y) + y_bottom = y|>tl()|>Enum.sum() + transformed = transformation(x, y_top, xlim, ylim, width, height, transition) |> Algebra.flip_y_coordinate() + {_, transformed_y_bottom} = transformation(x, y_bottom, xlim, ylim, width, height,transition) |> Algebra.flip_y_coordinate() + {transformed, transformed_y_bottom} end defp transform_with_bottom(x, y, xlim, ylim, width, height, transition) do diff --git a/test/matplotex/figure/areal/bar_chart_test.exs b/test/matplotex/figure/areal/bar_chart_test.exs index d7763f4..9152b41 100644 --- a/test/matplotex/figure/areal/bar_chart_test.exs +++ b/test/matplotex/figure/areal/bar_chart_test.exs @@ -28,9 +28,12 @@ defmodule Matplotex.Figure.Areal.BarChartTest do |> Matplotex.bar(values3, width, bottom: [values2, values1]) expected_elements_count = values1 ++ values2 ++ values3 |> length() assert %Figure{axes: %{element: elements}} = Figure.materialize(bar) - - assert Enum.filter(elements, fn x -> x.type == "figure.bar" end) |> length() == - expected_elements_count + bar_elements = Enum.filter(elements, fn x -> x.type == "figure.bar" end) + assert bar_elements |> length() == expected_elements_count + assert Enum.all?(bar_elements, fn rect -> assert_valid_coords(rect) end) end end + defp assert_valid_coords(rect) do + rect.x > 0 and rect.y > 0 and rect.width > 0 and rect.height > 0 + end end From 84073d4c56a2d2ed46c7d64c6b837f85eaddaf7f Mon Sep 17 00:00:00 2001 From: Mohammed Sadique Date: Mon, 17 Feb 2025 17:36:15 +0530 Subject: [PATCH 6/7] cleanup --- lib/matplotex/figure/areal.ex | 22 +++++ lib/matplotex/figure/areal/bar_chart.ex | 103 +----------------------- 2 files changed, 25 insertions(+), 100 deletions(-) diff --git a/lib/matplotex/figure/areal.ex b/lib/matplotex/figure/areal.ex index e71ce96..0a4c9ba 100644 --- a/lib/matplotex/figure/areal.ex +++ b/lib/matplotex/figure/areal.ex @@ -395,6 +395,19 @@ defmodule Matplotex.Figure.Areal do Algebra.transform_given_point(x, y, sx, sy, tx, ty) end + + def do_transform(%Dataset{x: x, y: y, bottom: bottom} = dataset, xlim, ylim, width, height, transition) when is_list(bottom) do + y = [y | bottom]|> Nx.tensor() |> Nx.transpose()|> Nx.to_list() + + transformed = + x + |> Enum.zip(y) + |> Enum.map(fn {x, y} -> + transform_with_bottom(x,y, xlim, ylim, width, height, transition) + end) + + %Dataset{dataset | transformed: transformed} + end def do_transform(%Dataset{x: x, y: y} = dataset, xlim, ylim, width, height, transition) do transformed = x @@ -407,4 +420,13 @@ defmodule Matplotex.Figure.Areal do %Dataset{dataset | transformed: transformed} end + + + defp transform_with_bottom(x, y, xlim, ylim, width, height, transition) when is_list(y) do + y_top = Enum.sum(y) + y_bottom = y|>tl()|>Enum.sum() + transformed = transformation(x, y_top, xlim, ylim, width, height, transition) |> Algebra.flip_y_coordinate() + {_, transformed_y_bottom} = transformation(x, y_bottom, xlim, ylim, width, height,transition) |> Algebra.flip_y_coordinate() + {transformed, transformed_y_bottom} + end end diff --git a/lib/matplotex/figure/areal/bar_chart.ex b/lib/matplotex/figure/areal/bar_chart.ex index ee6d688..b3bc833 100644 --- a/lib/matplotex/figure/areal/bar_chart.ex +++ b/lib/matplotex/figure/areal/bar_chart.ex @@ -1,7 +1,6 @@ defmodule Matplotex.Figure.Areal.BarChart do @moduledoc false import Matplotex.Figure.Numer - alias Matplotex.Utils.Algebra alias Matplotex.Figure.Areal.PlotOptions alias Matplotex.Figure.Areal.Region alias Matplotex.Element.Legend @@ -52,48 +51,6 @@ defmodule Matplotex.Figure.Areal.BarChart do def materialize(figure) do materialize_bars(figure) end - defp materialize_bars( - %Figure{ - axes: - %{ - dataset: datasets, - limit: %{x: xlim, y: ylim}, - type: "stacked", - region_content: %Region{ - x: x_region_content, - y: y_region_content, - width: width_region_content, - height: height_region_content - }, - element: elements - } = axes, - rc_params: %RcParams{ - x_padding: x_padding, - white_space: white_space - } - } = figure - ) do - x_padding_value = width_region_content * x_padding + white_space - shrinked_width_region_content = width_region_content - x_padding_value * 2 - bar_elements = - datasets - |> Enum.map(fn dataset -> - dataset - |> do_transform_with_bottom( - xlim, - ylim, - shrinked_width_region_content, - height_region_content, - {x_region_content + x_padding_value, y_region_content} - ) - |> capture_stacked(-y_region_content) - end) - |> List.flatten() - - elements_with_bar = elements ++ bar_elements - - %Figure{figure | axes: %{axes | element: elements_with_bar}} - end defp materialize_bars( %Figure{ @@ -176,7 +133,7 @@ defmodule Matplotex.Figure.Areal.BarChart do edge_color: edge_color, alpha: alpha, line_width: line_width - } = dataset) do + } = dataset, bly) do capture( to_capture, captured ++ @@ -194,10 +151,10 @@ defmodule Matplotex.Figure.Areal.BarChart do stroke_width: line_width } ], - dataset + dataset, + bly ) end - def capture([], captured, _dataset), do: captured def capture( @@ -236,26 +193,6 @@ defmodule Matplotex.Figure.Areal.BarChart do end def capture([], captured, _dataset, _bly), do: captured - defp capture_stacked(%Dataset{transformed: transformed}=dataset, bly) do - capture_stacked(transformed, [],dataset, bly) - end - defp capture_stacked(to_capture, captured, dataset, bly) do - to_capture - |>Enum.map(fn point -> - format_point(point, bly) - end) - |>capture(captured, dataset) - end - - defp format_point({{_x, _y}, _y_bottom} = point, _bly), do: point - # sum_of_tail = y |> Enum.sort()|>tl()|>Enum.sum - # sum_of_second_tail = y|>tl()|>tl()|>Enum.sum() - # {{x, y|>Enum.max()|>Kernel.-(sum_of_tail)}, y|>tl()|>Enum.max()|> Kernel.-(sum_of_second_tail)} - # end - - defp format_point({x, y}, bly) do - {{x, y}, bly} - end defp hypox(y) do nof_x = length(y) @xmin_value |> Nx.linspace(nof_x, n: nof_x) |> Nx.to_list() @@ -272,38 +209,4 @@ defmodule Matplotex.Figure.Areal.BarChart do end) end - defp do_transform_with_bottom(%Dataset{x: x, y: y, bottom: bottom} = dataset, xlim, ylim, width, height, transition) when is_list(bottom) do - y = [y | bottom]|> Nx.tensor() |> Nx.transpose()|> Nx.to_list() - - transformed = - x - |> Enum.zip(y) - |> Enum.map(fn {x, y} -> - transform_with_bottom(x,y, xlim, ylim, width, height, transition) - end) - - %Dataset{dataset | transformed: transformed} - end - - defp do_transform_with_bottom(dataset, xlim, ylim, width, height, transition) do - do_transform(dataset, xlim, ylim, width, height, transition) - end - - defp transform_with_bottom(x, y, xlim, ylim, width, height, transition) when is_list(y) do - # transformed = Enum.map(y, fn y_with_bottom -> - # transformation(x, y_with_bottom, xlim, ylim, width, height, transition) - # |> Algebra.flip_y_coordinate() - # end) - # |>Enum.unzip() - y_top = Enum.sum(y) - y_bottom = y|>tl()|>Enum.sum() - transformed = transformation(x, y_top, xlim, ylim, width, height, transition) |> Algebra.flip_y_coordinate() - {_, transformed_y_bottom} = transformation(x, y_bottom, xlim, ylim, width, height,transition) |> Algebra.flip_y_coordinate() - {transformed, transformed_y_bottom} - end - - defp transform_with_bottom(x, y, xlim, ylim, width, height, transition) do - transformation(x, y, xlim, ylim, width, height, transition) - |> Algebra.flip_y_coordinate() - end end From f2f6aef24725e41f04c5110af6d3d9d469af4a27 Mon Sep 17 00:00:00 2001 From: Mohammed Sadique Date: Mon, 17 Feb 2025 17:36:34 +0530 Subject: [PATCH 7/7] format --- lib/matplotex.ex | 6 +- lib/matplotex/colorscheme/blender.ex | 20 ++--- lib/matplotex/colorscheme/colormap.ex | 15 ++-- lib/matplotex/colorscheme/garner.ex | 36 +++++--- lib/matplotex/colorscheme/rgb.ex | 88 ++++++++++--------- lib/matplotex/element.ex | 2 +- lib/matplotex/element/cmap.ex | 2 +- lib/matplotex/figure.ex | 1 + lib/matplotex/figure/areal.ex | 50 +++++++---- lib/matplotex/figure/areal/bar_chart.ex | 29 +++--- lib/matplotex/figure/areal/plot_options.ex | 13 ++- lib/matplotex/figure/areal/step.ex | 2 +- lib/matplotex/figure/cast.ex | 9 +- lib/matplotex/figure/sketch.ex | 2 - test/matplotex/colorscheme/garner_test.exs | 4 +- .../matplotex/figure/areal/bar_chart_test.exs | 21 +++-- .../figure/areal/plot_options_test.exs | 13 +-- 17 files changed, 182 insertions(+), 131 deletions(-) diff --git a/lib/matplotex.ex b/lib/matplotex.ex index 9003b25..0f7c402 100644 --- a/lib/matplotex.ex +++ b/lib/matplotex.ex @@ -213,8 +213,6 @@ defmodule Matplotex do bar(pos, values, width, []) end - - @doc """ Adds an additional dataset to a bar plot in the given `%Figure{}`. @@ -255,13 +253,13 @@ defmodule Matplotex do def bar(pos, values, width, opts) do BarChart.create(%Figure{axes: %BarChart{}}, {pos, values, width}, opts) end + def bar(%Figure{} = figure, pos, values, width, opts) do figure |> show_legend() |> BarChart.create({pos, values, width}, opts) end - @doc """ Creates a scatter plot based on the given `x` and `y` values, with optional customization provided via `opts`. @@ -756,9 +754,11 @@ defmodule Matplotex do def show_legend(figure) do Figure.show_legend(figure) end + def hide_legend(figure) do Figure.hide_legend(figure) end + def set_options(figure, opts) do PlotOptions.set_options_in_figure(figure, opts) end diff --git a/lib/matplotex/colorscheme/blender.ex b/lib/matplotex/colorscheme/blender.ex index 460d32f..9cc549b 100644 --- a/lib/matplotex/colorscheme/blender.ex +++ b/lib/matplotex/colorscheme/blender.ex @@ -1,19 +1,17 @@ defmodule Matplotex.Colorscheme.Blender do -@moduledoc false -alias Matplotex.Colorscheme.Rgb + @moduledoc false + alias Matplotex.Colorscheme.Rgb @rgb_fields [:red, :green, :blue, :alpha] @type color :: %Rgb{ - red: :float, - green: :float, - blue: :float, - alpha: :float - } - + red: :float, + green: :float, + blue: :float, + alpha: :float + } def mix(color1, color2, weight \\ 0.5) do - p = weight w = p * 2 - 1 a = color1.alpha - color2.alpha @@ -30,10 +28,10 @@ alias Matplotex.Colorscheme.Rgb alpha = get_alpha(color1) * p + get_alpha(color2) * (1 - p) rgb(r, g, b, alpha) end + defdelegate rgb(red, green, blue), to: Rgb defdelegate rgb(red, green, blue, alpha), to: Rgb - @doc """ Gets the `:red` property of the color. """ @@ -87,6 +85,4 @@ alias Matplotex.Colorscheme.Rgb end defp cast_color_by_attribute(color, attribute) when attribute in @rgb_fields, do: color - - end diff --git a/lib/matplotex/colorscheme/colormap.ex b/lib/matplotex/colorscheme/colormap.ex index 1a8baee..90f52c2 100644 --- a/lib/matplotex/colorscheme/colormap.ex +++ b/lib/matplotex/colorscheme/colormap.ex @@ -1,20 +1,21 @@ defmodule Matplotex.Colorscheme.Colormap do -@moduledoc false + @moduledoc false defstruct [:color, :offset, opacity: 1] + def viridis do - ["#fde725","#21918c","#3b528b","#440154"] + ["#fde725", "#21918c", "#3b528b", "#440154"] end def plasma do - ["#F7E425","#ED6925", "#9C179E", "#0C0786" ] + ["#F7E425", "#ED6925", "#9C179E", "#0C0786"] end def inferno do - ["#FCFFA4","#F56C3E","#B12A90","#000004"] + ["#FCFFA4", "#F56C3E", "#B12A90", "#000004"] end def magma do - ["#FCFDBF","#FB8861", "#B73779", "#000004"] + ["#FCFDBF", "#FB8861", "#B73779", "#000004"] end def fetch_cmap(cmap) when is_binary(cmap), do: cmap |> String.to_atom() |> fetch_cmap() @@ -22,8 +23,10 @@ defmodule Matplotex.Colorscheme.Colormap do def fetch_cmap(cmap) do apply(__MODULE__, cmap, []) |> make_colormap() end + def make_colormap(colors) do size = length(colors) + colors |> Enum.with_index() |> Enum.map(&colormap(&1, size)) @@ -35,6 +38,4 @@ defmodule Matplotex.Colorscheme.Colormap do offset = idx / size * 100 %__MODULE__{color: color, offset: offset} end - - end diff --git a/lib/matplotex/colorscheme/garner.ex b/lib/matplotex/colorscheme/garner.ex index d3e279a..fa3e08b 100644 --- a/lib/matplotex/colorscheme/garner.ex +++ b/lib/matplotex/colorscheme/garner.ex @@ -1,13 +1,14 @@ defmodule Matplotex.Colorscheme.Garner do -@moduledoc false -alias Matplotex.Colorscheme.Rgb -alias Matplotex.Colorscheme.Blender -alias Matplotex.InputError + @moduledoc false + alias Matplotex.Colorscheme.Rgb + alias Matplotex.Colorscheme.Blender + alias Matplotex.InputError - defstruct [:range, :color_cue, :cmap, :preceeding, :minor, :major, :final] + defstruct [:range, :color_cue, :cmap, :preceeding, :minor, :major, :final] def garn_color({min, max} = range, point, cmap) when max != min do cue = (point - min) / (max - min) + cmap |> make_from_cmap() |> put_range(range, cue) @@ -16,8 +17,8 @@ alias Matplotex.InputError defp make_from_cmap(cmap) do cmap - |>to_rgb() - |>place_edges() + |> to_rgb() + |> place_edges() end defp put_range(%__MODULE__{} = garner, range, cue) do @@ -28,22 +29,29 @@ alias Matplotex.InputError Enum.map(color_map, &Rgb.from_cmap!(&1)) end - defp place_edges([preceeding, minor, major,final]) do - %__MODULE__{preceeding: preceeding.color, minor: minor.color, major: major.color, final: final.color} + defp place_edges([preceeding, minor, major, final]) do + %__MODULE__{ + preceeding: preceeding.color, + minor: minor.color, + major: major.color, + final: final.color + } end + defp place_edges(_) do raise InputError, message: "Invalid colormap" end - defp point_color(%__MODULE__{color_cue: cue, preceeding: preceeding, minor: minor}) when cue < minor do - minor|> Blender.mix(preceeding, cue)|> Rgb.to_string() + defp point_color(%__MODULE__{color_cue: cue, preceeding: preceeding, minor: minor}) + when cue < minor do + minor |> Blender.mix(preceeding, cue) |> Rgb.to_string() end defp point_color(%__MODULE__{color_cue: cue, minor: minor, major: major}) when cue < major do - major|> Blender.mix(minor, cue)|> Rgb.to_string() + major |> Blender.mix(minor, cue) |> Rgb.to_string() end defp point_color(%__MODULE__{color_cue: cue, major: major, final: final}) when cue >= major do - final|> Blender.mix(major)|> Rgb.to_string() + final |> Blender.mix(major) |> Rgb.to_string() end - end +end diff --git a/lib/matplotex/colorscheme/rgb.ex b/lib/matplotex/colorscheme/rgb.ex index 590c960..3c350ce 100644 --- a/lib/matplotex/colorscheme/rgb.ex +++ b/lib/matplotex/colorscheme/rgb.ex @@ -1,18 +1,25 @@ defmodule Matplotex.Colorscheme.Rgb do @moduledoc false -alias Matplotex.Colorscheme.Colormap + alias Matplotex.Colorscheme.Colormap + defstruct [ - red: 0.0, # 0-255 - green: 0.0, # 0-255 - blue: 0.0, # 0-255 - alpha: 1.0 # 0-1 + # 0-255 + red: 0.0, + # 0-255 + green: 0.0, + # 0-255 + blue: 0.0, + # 0-1 + alpha: 1.0 ] - def rgb(red, green, blue, alpha\\1.0) - def rgb({red, :percent}, {green, :percent}, {blue, :percent}, alpha) do + def rgb(red, green, blue, alpha \\ 1.0) + + def rgb({red, :percent}, {green, :percent}, {blue, :percent}, alpha) do rgb(red * 255, green * 255, blue * 255, alpha) end - def rgb(red, green, blue, alpha) do + + def rgb(red, green, blue, alpha) do %__MODULE__{ red: cast(red, :red), green: cast(green, :green), @@ -21,65 +28,64 @@ alias Matplotex.Colorscheme.Colormap } end - def to_string(struct, type\\nil) + def to_string(struct, type \\ nil) + + def to_string(struct, nil) do + type = + case struct.alpha do + 1.0 -> :hex + _ -> :rgba + end - def to_string(struct, :nil) do - type = case struct.alpha do - 1.0 -> :hex - _ -> :rgba - end to_string(struct, type) end def to_string(%__MODULE__{red: r, green: g, blue: b, alpha: alpha}, :rgba) do "rgba(#{round(r)}, #{round(g)}, #{round(b)}, #{alpha})" end + def to_string(%__MODULE__{red: r, green: g, blue: b, alpha: 1.0}, :hex) do "#" <> to_hex(r) <> to_hex(g) <> to_hex(b) end def cast(value, field) when field in [:red, :green, :blue] do - value/1 + (value / 1) |> min(255.0) |> max(0.0) end + def cast(value, :alpha) do - value/1 + (value / 1) |> min(1.0) |> max(0.0) end - defp to_hex(value) when is_float(value), do: - to_hex(round(value)) - defp to_hex(value) when value < 16, do: - "0" <> Integer.to_string(value, 16) - defp to_hex(value) when is_integer(value), do: - Integer.to_string(value, 16) - - def from_hex!(input) do - {:ok, color} = from_hex(input) - color - end + defp to_hex(value) when is_float(value), do: to_hex(round(value)) + defp to_hex(value) when value < 16, do: "0" <> Integer.to_string(value, 16) + defp to_hex(value) when is_integer(value), do: Integer.to_string(value, 16) - def from_cmap!(%Colormap{color: color} = cmap) do - %Colormap{cmap | color: from_hex!(color) } - end + def from_hex!(input) do + {:ok, color} = from_hex(input) + color + end - def from_hex("#" <> <>) do - {:ok, rgb(parse_hex(r), parse_hex(g), parse_hex(b))} - end - def from_hex("#" <> <>) do - {:ok, rgb(parse_hex(r <> r), parse_hex(g <> g), parse_hex(b <> b))} - end + def from_cmap!(%Colormap{color: color} = cmap) do + %Colormap{cmap | color: from_hex!(color)} + end - defp parse_hex(s), do: String.to_integer(s, 16) + def from_hex("#" <> <>) do + {:ok, rgb(parse_hex(r), parse_hex(g), parse_hex(b))} + end + def from_hex("#" <> <>) do + {:ok, rgb(parse_hex(r <> r), parse_hex(g <> g), parse_hex(b <> b))} + end + defp parse_hex(s), do: String.to_integer(s, 16) end - defimpl String.Chars, for: CssColors.RGB do -def to_string(struct) do - Matplotex.Colorscheme.Rgb.to_string(struct) -end + def to_string(struct) do + Matplotex.Colorscheme.Rgb.to_string(struct) + end end diff --git a/lib/matplotex/element.ex b/lib/matplotex/element.ex index 2a80b6d..20e7c8d 100644 --- a/lib/matplotex/element.ex +++ b/lib/matplotex/element.ex @@ -17,7 +17,7 @@ defmodule Matplotex.Element do defimpl String.Chars, for: __MODULE__ do def to_string(%module{} = element) do - module.assemble(element) + module.assemble(element) end end end diff --git a/lib/matplotex/element/cmap.ex b/lib/matplotex/element/cmap.ex index 0494e1a..ac71971 100644 --- a/lib/matplotex/element/cmap.ex +++ b/lib/matplotex/element/cmap.ex @@ -1,5 +1,5 @@ defmodule Matplotex.Element.Cmap do -@moduledoc false + @moduledoc false alias Matplotex.Element.Rect alias Matplotex.Element use Element diff --git a/lib/matplotex/figure.ex b/lib/matplotex/figure.ex index d1d993f..bdaa0c5 100644 --- a/lib/matplotex/figure.ex +++ b/lib/matplotex/figure.ex @@ -62,6 +62,7 @@ defmodule Matplotex.Figure do def show_legend(%__MODULE__{axes: %module{} = axes} = figure), do: %{figure | axes: module.show_legend(axes)} + def hide_legend(%__MODULE__{axes: %module{} = axes} = figure), do: %{figure | axes: module.hide_legend(axes)} diff --git a/lib/matplotex/figure/areal.ex b/lib/matplotex/figure/areal.ex index 0a4c9ba..9c23061 100644 --- a/lib/matplotex/figure/areal.ex +++ b/lib/matplotex/figure/areal.ex @@ -169,16 +169,19 @@ defmodule Matplotex.Figure.Areal do data_with_label(data) end end + # For stacked bar chart the flattening supposed to be the sumation of yaxis data def flatten_for_data(datasets, nil), do: flatten_for_data(datasets) - def flatten_for_data([%{x: x, y: y}| _datasets], bottom) do - y= bottom - |> Kernel.++([y]) - |> Nx.tensor(names: [:x, :y]) - |> Nx.sum(axes: [:x]) - |> Nx.to_list() - {x, y} + def flatten_for_data([%{x: x, y: y} | _datasets], bottom) do + y = + bottom + |> Kernel.++([y]) + |> Nx.tensor(names: [:x, :y]) + |> Nx.sum(axes: [:x]) + |> Nx.to_list() + + {x, y} end def flatten_for_data(datasets) do @@ -215,6 +218,7 @@ defmodule Matplotex.Figure.Areal do def show_legend(%__MODULE__{} = axes) do %__MODULE__{axes | show_legend: true} end + def hide_legend(%__MODULE__{} = axes) do %__MODULE__{axes | show_legend: false} end @@ -395,19 +399,27 @@ defmodule Matplotex.Figure.Areal do Algebra.transform_given_point(x, y, sx, sy, tx, ty) end - - def do_transform(%Dataset{x: x, y: y, bottom: bottom} = dataset, xlim, ylim, width, height, transition) when is_list(bottom) do - y = [y | bottom]|> Nx.tensor() |> Nx.transpose()|> Nx.to_list() + def do_transform( + %Dataset{x: x, y: y, bottom: bottom} = dataset, + xlim, + ylim, + width, + height, + transition + ) + when is_list(bottom) do + y = [y | bottom] |> Nx.tensor() |> Nx.transpose() |> Nx.to_list() transformed = x |> Enum.zip(y) |> Enum.map(fn {x, y} -> - transform_with_bottom(x,y, xlim, ylim, width, height, transition) + transform_with_bottom(x, y, xlim, ylim, width, height, transition) end) %Dataset{dataset | transformed: transformed} end + def do_transform(%Dataset{x: x, y: y} = dataset, xlim, ylim, width, height, transition) do transformed = x @@ -421,12 +433,18 @@ defmodule Matplotex.Figure.Areal do %Dataset{dataset | transformed: transformed} end - defp transform_with_bottom(x, y, xlim, ylim, width, height, transition) when is_list(y) do y_top = Enum.sum(y) - y_bottom = y|>tl()|>Enum.sum() - transformed = transformation(x, y_top, xlim, ylim, width, height, transition) |> Algebra.flip_y_coordinate() - {_, transformed_y_bottom} = transformation(x, y_bottom, xlim, ylim, width, height,transition) |> Algebra.flip_y_coordinate() + y_bottom = y |> tl() |> Enum.sum() + + transformed = + transformation(x, y_top, xlim, ylim, width, height, transition) + |> Algebra.flip_y_coordinate() + + {_, transformed_y_bottom} = + transformation(x, y_bottom, xlim, ylim, width, height, transition) + |> Algebra.flip_y_coordinate() + {transformed, transformed_y_bottom} - end + end end diff --git a/lib/matplotex/figure/areal/bar_chart.ex b/lib/matplotex/figure/areal/bar_chart.ex index b3bc833..16ae106 100644 --- a/lib/matplotex/figure/areal/bar_chart.ex +++ b/lib/matplotex/figure/areal/bar_chart.ex @@ -36,8 +36,8 @@ defmodule Matplotex.Figure.Areal.BarChart do x = hypox(values) dataset = Dataset.cast(%Dataset{x: x, y: values, pos: pos, width: width}, opts) datasets = data ++ [dataset] - bottom = Keyword.get(opts, :bottom) - xydata = datasets|>Enum.reverse()|> flatten_for_data(bottom) + bottom = Keyword.get(opts, :bottom) + xydata = datasets |> Enum.reverse() |> flatten_for_data(bottom) %Figure{ figure @@ -118,6 +118,7 @@ defmodule Matplotex.Figure.Areal.BarChart do step = (max - min) / (side * 2) {min..max |> Enum.into([], fn d -> d * round_to_best(step) end), lim} end + def capture(%Dataset{transformed: transformed} = dataset, bly, concurrency) do if concurrency do process_concurrently(transformed, concurrency, [[], dataset, bly]) @@ -126,14 +127,19 @@ defmodule Matplotex.Figure.Areal.BarChart do end end - def capture([{{x, y}, bottom} | 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}, bottom} | 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 ++ @@ -156,7 +162,6 @@ defmodule Matplotex.Figure.Areal.BarChart do ) end - def capture( [{x, y} | to_capture], captured, @@ -193,6 +198,7 @@ defmodule Matplotex.Figure.Areal.BarChart do end def capture([], captured, _dataset, _bly), do: captured + defp hypox(y) do nof_x = length(y) @xmin_value |> Nx.linspace(nof_x, n: nof_x) |> Nx.to_list() @@ -208,5 +214,4 @@ defmodule Matplotex.Figure.Areal.BarChart do d * step end) end - end diff --git a/lib/matplotex/figure/areal/plot_options.ex b/lib/matplotex/figure/areal/plot_options.ex index d717fc5..e119752 100644 --- a/lib/matplotex/figure/areal/plot_options.ex +++ b/lib/matplotex/figure/areal/plot_options.ex @@ -21,6 +21,7 @@ defmodule Matplotex.Figure.Areal.PlotOptions do @spec set_options_in_figure(Figure.t(), keyword()) :: Figure.t() def set_options_in_figure(%Figure{} = figure, opts) do opts = sanitize(opts) + figure |> cast_figure(opts) |> cast_axes(opts) @@ -32,7 +33,6 @@ defmodule Matplotex.Figure.Areal.PlotOptions do end defp cast_axes(%Figure{axes: axes} = figure, opts) do - opts = Keyword.delete(opts, :label) cmap = Keyword.get(opts, :cmap) colors = Keyword.get(opts, :colors) @@ -40,7 +40,12 @@ defmodule Matplotex.Figure.Areal.PlotOptions do %Figure{ figure - | axes: axes |> struct(opts) |> cast_two_d_structs(opts)|> update_cmap(cmap, colors) |> update_type(bottom) + | axes: + axes + |> struct(opts) + |> cast_two_d_structs(opts) + |> update_cmap(cmap, colors) + |> update_type(bottom) } end @@ -63,16 +68,18 @@ defmodule Matplotex.Figure.Areal.PlotOptions do defp sanitize(opts) do Keyword.drop(opts, @immutable_keys) end + defp update_cmap(axes, nil, colors) when is_list(colors) do %{axes | cmap: Colormap.fetch_cmap(@default_cmap)} end defp update_cmap(axes, cmap, colors) when is_list(colors) do - %{axes | cmap: Colormap.fetch_cmap(cmap)} + %{axes | cmap: Colormap.fetch_cmap(cmap)} end defp update_cmap(axes, _, _), do: axes defp update_type(axes, nil), do: axes + defp update_type(axes, bottom) when is_list(bottom) do %{axes | type: "stacked"} end diff --git a/lib/matplotex/figure/areal/step.ex b/lib/matplotex/figure/areal/step.ex index 11889db..11568fb 100644 --- a/lib/matplotex/figure/areal/step.ex +++ b/lib/matplotex/figure/areal/step.ex @@ -1,5 +1,5 @@ defmodule Matplotex.Figure.Areal.Step do -@moduledoc false + @moduledoc false alias Matplotex.Figure.Areal.LinePlot alias Matplotex.Figure alias Matplotex.InputError diff --git a/lib/matplotex/figure/cast.ex b/lib/matplotex/figure/cast.ex index a9c94c2..801eadd 100644 --- a/lib/matplotex/figure/cast.ex +++ b/lib/matplotex/figure/cast.ex @@ -550,8 +550,11 @@ defmodule Matplotex.Figure.Cast do |> Algebra.flip_y_coordinate() |> Algebra.transform_given_point({0, height_region_content}) - {x2_cmap_tick, _} = tick_x2 = Algebra.transform_given_point(tick_coords, {tick_line_length, 0}) + {x2_cmap_tick, _} = + tick_x2 = Algebra.transform_given_point(tick_coords, {tick_line_length, 0}) + {tick_label_x, _} = Algebra.transform_given_point(tick_x2, {tick_line_length, 0}) + tick_label = Label.cast_label( %Label{type: "tick.cmap", x: tick_label_x, y: y_cord_tick, text: tick}, @@ -583,7 +586,8 @@ defmodule Matplotex.Figure.Cast do width: cmap_width, height: height_region_content } - }|>Cmap.color_gradient() + } + |> Cmap.color_gradient() ] ++ ticks end) |> List.flatten() @@ -593,7 +597,6 @@ defmodule Matplotex.Figure.Cast do def cast_legends(figure), do: figure - defp calculate_center(%Region{x: x, y: y, width: width}, :x) do {calculate_distance({x, y}, {x + width, y}) / 2 + x, y} end diff --git a/lib/matplotex/figure/sketch.ex b/lib/matplotex/figure/sketch.ex index 5b4a1e0..dcd7338 100644 --- a/lib/matplotex/figure/sketch.ex +++ b/lib/matplotex/figure/sketch.ex @@ -19,8 +19,6 @@ defmodule Matplotex.Figure.Sketch do end}" end - - defp wrap_with_tag(svg, width, height) do ~s( <<_r :: binary-size(2), _g :: binary-size(2), _b :: binary-size(2)>>), do: true + defp is_color("#" <> <<_r::binary-size(2), _g::binary-size(2), _b::binary-size(2)>>), do: true defp is_color(_), do: false end diff --git a/test/matplotex/figure/areal/bar_chart_test.exs b/test/matplotex/figure/areal/bar_chart_test.exs index 9152b41..8afd591 100644 --- a/test/matplotex/figure/areal/bar_chart_test.exs +++ b/test/matplotex/figure/areal/bar_chart_test.exs @@ -15,24 +15,29 @@ defmodule Matplotex.Figure.Areal.BarChartTest do assert %Figure{axes: %{element: elements}} = BarChart.materialized_by_region(figure) |> BarChart.materialize() - assert Enum.filter(elements, fn x -> x.type == "figure.bar" end) |> length() == - length(y) + assert Enum.filter(elements, fn x -> x.type == "figure.bar" end) |> length() == + length(y) end test "bottom variable in opts makes stacked bar chart and it will stack the bars" do - values1 = [2,4,3,2] - values2 = [1,2,1,4] - values3 = [3,1,2,1] + values1 = [2, 4, 3, 2] + values2 = [1, 2, 1, 4] + values3 = [3, 1, 2, 1] width = 0.3 - bar = Matplotex.bar(values1, width)|> Matplotex.bar(values2, width, bottom: [values1]) - |> Matplotex.bar(values3, width, bottom: [values2, values1]) - expected_elements_count = values1 ++ values2 ++ values3 |> length() + + bar = + Matplotex.bar(values1, width) + |> Matplotex.bar(values2, width, bottom: [values1]) + |> Matplotex.bar(values3, width, bottom: [values2, values1]) + + expected_elements_count = (values1 ++ values2 ++ values3) |> length() assert %Figure{axes: %{element: elements}} = Figure.materialize(bar) bar_elements = Enum.filter(elements, fn x -> x.type == "figure.bar" end) assert bar_elements |> length() == expected_elements_count assert Enum.all?(bar_elements, fn rect -> assert_valid_coords(rect) end) end end + defp assert_valid_coords(rect) do rect.x > 0 and rect.y > 0 and rect.width > 0 and rect.height > 0 end diff --git a/test/matplotex/figure/areal/plot_options_test.exs b/test/matplotex/figure/areal/plot_options_test.exs index 807dc15..4595875 100644 --- a/test/matplotex/figure/areal/plot_options_test.exs +++ b/test/matplotex/figure/areal/plot_options_test.exs @@ -28,12 +28,15 @@ defmodule Matplotex.Figure.Areal.PlotOptionsTest do refute figure.axes.element == nil refute figure.axes == nil end + test "updates cmap as a list by its name" do - assert %Figure{axes: %{cmap: cmap}} = [1, 2, 3, 4, 5, 6] - |> Matplotex.plot([1, 2, 3, 4, 5], - cmap: "viridis", - colors: [3, 4, 5, 6, 7, 3, 2, 4] - ) + assert %Figure{axes: %{cmap: cmap}} = + [1, 2, 3, 4, 5, 6] + |> Matplotex.plot([1, 2, 3, 4, 5], + cmap: "viridis", + colors: [3, 4, 5, 6, 7, 3, 2, 4] + ) + assert is_list(cmap) end end