Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions lib/matplotex.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule Matplotex do
@moduledoc """
Module to generate a graph.
"""
alias Matplotex.Figure.Areal.Spline
alias Matplotex.Figure.Areal.Histogram
alias Matplotex.InputError
alias Matplotex.Figure.Radial.Pie
Expand Down Expand Up @@ -33,6 +34,9 @@ defmodule Matplotex do
|> BarChart.create({pos, values, width}, opts)
end

@doc """
Creates a scatter plot based on the given data
"""
def scatter(stream, opts) when is_struct(stream, Stream) do
Scatter.create(stream, opts)
end
Expand All @@ -51,6 +55,9 @@ defmodule Matplotex do
|> Scatter.create({x, y}, opts)
end

@doc """
Creates a piec charts based on the size and opts
"""
def pie(sizes, opts \\ []) do
Pie.create(%Figure{axes: %Pie{}}, sizes, opts)
end
Expand Down Expand Up @@ -84,10 +91,26 @@ defmodule Matplotex do
|> LinePlot.create({x, y}, opts)
end

@doc """
Creates a histogram with given data and bins.

## Examples

iex> Matplotex.hist([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 5)
"""
def hist(data, bins), do: hist(data, bins, [])

def hist(data, bins, opts) do
Histogram.create(%Figure{axes: %Histogram{}}, {data, bins}, opts)
end

def spline(x, y), do: spline(x, y, [])
def spline(x, y, opts), do: spline(%Figure{axes: %Spline{}}, x, y, opts)

def spline(%Figure{} = figure, x, y, opts) do
Spline.create(figure, {x, y}, opts)
end

@doc """
Sets X and Y labels for the graph with given font details

Expand Down
5 changes: 4 additions & 1 deletion lib/matplotex/element.ex
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
defmodule Matplotex.Element do
@callback assemble(element :: struct()) :: String.t()
@callback flipy(element :: struct(), height :: number()) :: struct()
def assemble(%module{} = element), do: module.assemble(element)

def to_pixel({x, y}) do
"#{to_pixel(x)},#{to_pixel(y)}"
end

def to_pixel(inch) when is_number(inch), do: inch * 96
def to_pixel(_), do: 0

Expand Down
4 changes: 0 additions & 4 deletions lib/matplotex/element/circle.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,4 @@ defmodule Matplotex.Element.Circle do
def get_cx(%{cx: x}), do: to_pixel(x)
def get_cy(%{cy: y}), do: to_pixel(y)
def get_r(%{r: r}), do: to_pixel(r)
@impl Element
def flipy(%__MODULE__{cy: y} = circle, height) do
%__MODULE__{circle | cy: height - y}
end
end
4 changes: 0 additions & 4 deletions lib/matplotex/element/label.ex
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,4 @@ defmodule Matplotex.Element.Label do
def get_y(%{y: y}), do: to_pixel(y)
def get_width(%{width: width}), do: to_pixel(width)
def get_height(%{height: height}), do: to_pixel(height)
@impl Element
def flipy(%__MODULE__{y: y} = label, height) do
%__MODULE__{label | y: height - y}
end
end
5 changes: 0 additions & 5 deletions lib/matplotex/element/legend.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@ defmodule Matplotex.Element.Legend do
"""
end

@impl Element
def flipy(%__MODULE__{y: y} = legend, height) do
%__MODULE__{legend | y: height - y, label: Label.flipy(legend.label, height)}
end

defp handle(%__MODULE__{handle: %handle_element{} = handle}) do
handle_element.assemble(handle)
end
Expand Down
4 changes: 0 additions & 4 deletions lib/matplotex/element/line.ex
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ defmodule Matplotex.Element.Line do
def get_x2(%{x2: x2}), do: to_pixel(x2)
def get_y1(%{y1: y1}), do: to_pixel(y1)
def get_y2(%{y2: y2}), do: to_pixel(y2)
@impl Element
def flipy(%__MODULE__{y1: y1, y2: y2} = line, height) do
%__MODULE__{line | y1: height - y1, y2: height - y2}
end

defp stroke_dasharray(%{linestyle: "_"}), do: nil

Expand Down
12 changes: 0 additions & 12 deletions lib/matplotex/element/polygon.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,6 @@ defmodule Matplotex.Element.Polygon do
)
end

@impl Element
def flipy(%__MODULE__{points: point} = label, height) do
%__MODULE__{label | points: flip_point(point, height)}
end

defp flip_point(point, height) do
Enum.map(point, &flip_coord(&1, height))
end

defp flip_coord({x, y}, height) do
{x, height - y}
end

defp assemble_point(%{points: point}) do
for {x, y} <- point do
Expand Down
5 changes: 0 additions & 5 deletions lib/matplotex/element/rad_legend.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@ defmodule Matplotex.Element.RadLegend do
"""
end

@impl Element
def flipy(%__MODULE__{y: y} = legend, height) do
%__MODULE__{legend | y: height - y, label: Label.flipy(legend.label, height)}
end

def with_label(
%__MODULE__{
label: text,
Expand Down
4 changes: 0 additions & 4 deletions lib/matplotex/element/rect.ex
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,4 @@ defmodule Matplotex.Element.Rect do
def get_y(%{y: y}), do: to_pixel(y)
def get_width(%{width: width}), do: to_pixel(width)
def get_height(%{height: height}), do: to_pixel(height)
@impl Element
def flipy(%__MODULE__{y: y} = rect, height) do
%__MODULE__{rect | y: height - y}
end
end
4 changes: 0 additions & 4 deletions lib/matplotex/element/slice.ex
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,4 @@ defmodule Matplotex.Element.Slice do
def get_cx(%{cx: cx}), do: to_pixel(cx)
def get_cy(%{cy: cy}), do: to_pixel(cy)
def get_radius(%{radius: radius}), do: to_pixel(radius)
@impl Element
def flipy(slice, _height) do
slice
end
end
40 changes: 40 additions & 0 deletions lib/matplotex/element/spline.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
defmodule Matplotex.Element.Spline do
alias Matplotex.Element
use Element
@default_stroke_width 2
@default_stroke "black"

@fill "none"
defstruct [
:type,
:moveto,
:cubic,
:smooths,
fill: @fill,
stroke: @default_stroke,
stroke_width: @default_stroke_width
]

@impl Element
def assemble(element) do
"""
<path d="M #{to_pixel(element.moveto)}
C #{points(element.cubic)} #{smooth_beizer(element.smooths)} "
fill="#{element.fill}"
stroke="#{element.stroke}"
stroke-width="#{element.stroke_width}" />
"""
end

defp points(points) do
for point <- points do
"#{to_pixel(point)} "
end
end

defp smooth_beizer(points) do
for point <- points do
"S #{points(point)}"
end
end
end
9 changes: 0 additions & 9 deletions lib/matplotex/element/tick.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,4 @@ defmodule Matplotex.Element.Tick do
#{Element.assemble(tick.label)}
)
end

@impl Element
def flipy(%__MODULE__{label: label, tick_line: tick_line} = tick, height) do
%__MODULE__{
tick
| label: Label.flipy(label, height),
tick_line: Line.flipy(tick_line, height)
}
end
end
20 changes: 12 additions & 8 deletions lib/matplotex/figure/areal.ex
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,18 @@ defmodule Matplotex.Figure.Areal do
|> update_tick(tick)
end

def add_ticks(%__MODULE__{tick: tick, size: {width, height}= size} = axes, {key, {_min, _max} = lim}) do
number_of_ticks = if key == :x do
ceil(width)
else
ceil(height)
end
{ticks, lim} = Ticker.generate_ticks(lim, number_of_ticks )
def add_ticks(
%__MODULE__{tick: tick, size: {width, height} = size} = axes,
{key, {_min, _max} = lim}
) do
number_of_ticks =
if key == :x do
ceil(width)
else
ceil(height)
end

{ticks, lim} = Ticker.generate_ticks(lim, number_of_ticks)

tick = Map.put(tick, key, ticks)

Expand Down Expand Up @@ -122,7 +127,6 @@ defmodule Matplotex.Figure.Areal do
%{axes | legend: legend}
end


defp update_limit(%TwoD{x: nil} = limit, :x, xlim) do
%TwoD{limit | x: xlim}
end
Expand Down
63 changes: 49 additions & 14 deletions lib/matplotex/figure/areal/histogram.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,20 @@ defmodule Matplotex.Figure.Areal.Histogram do
)

@impl Areal
def create(%Figure{axes: %__MODULE__{} = axes, rc_params: rc_params} = figure, {data, bins}, opts) do
def create(
%Figure{axes: %__MODULE__{} = axes, rc_params: rc_params} = figure,
{data, bins},
opts
) do
{x, y} = bins_and_hists(data, bins)

dataset = Dataset.cast(%Dataset{x: x, y: y}, opts)
%Figure{figure | axes: %__MODULE__{axes | data: {x, y}, dataset: [dataset]}, rc_params: %RcParams{rc_params | y_padding: @make_it_zero}}

%Figure{
figure
| axes: %__MODULE__{axes | data: {x, y}, dataset: [dataset]},
rc_params: %RcParams{rc_params | y_padding: @make_it_zero}
}
|> PlotOptions.set_options_in_figure(opts)
end

Expand All @@ -39,18 +48,38 @@ defmodule Matplotex.Figure.Areal.Histogram do
|> materialize_hist()
end

defp materialize_hist(%Figure{axes: %{dataset: data,limit: %TwoD{x: x_lim, y: y_lim}, region_content: %Region{x: x_region_content, y: y_region_content, width: width_region_content, height: height_region_content}, element: element}, rc_params: %RcParams{x_padding: x_padding, white_space: white_space}}) do
defp materialize_hist(%Figure{
axes: %{
dataset: data,
limit: %TwoD{x: x_lim, y: y_lim},
region_content: %Region{
x: x_region_content,
y: y_region_content,
width: width_region_content,
height: height_region_content
},
element: element
},
rc_params: %RcParams{x_padding: x_padding, white_space: white_space}
}) do
x_padding_value = width_region_content * x_padding + white_space
shrinked_width_region_content = width_region_content - x_padding_value * 2

hist_elements =
data
|>Enum.map(fn dataset ->
dataset
|> do_transform(x_lim, y_lim, shrinked_width_region_content, height_region_content, {x_region_content + x_padding_value, y_region_content})
|> capture(abs(y_region_content), shrinked_width_region_content)
end)
|>List.flatten()
data
|> Enum.map(fn dataset ->
dataset
|> do_transform(
x_lim,
y_lim,
shrinked_width_region_content,
height_region_content,
{x_region_content + x_padding_value, y_region_content}
)
|> capture(abs(y_region_content), shrinked_width_region_content)
end)
|> List.flatten()

%Figure{axes: %{element: element ++ hist_elements}}
end

Expand Down Expand Up @@ -95,12 +124,12 @@ defmodule Matplotex.Figure.Areal.Histogram do

defp capture([], captured, _dataset, _bly, _region_width), do: captured


defp bin_position(x, pos_factor) when pos_factor < 0 do
x + pos_factor
end

defp bin_position(x, _pos_factor), do: x

defp bins_and_hists(data, bins) do
{data_min, data_max} = Enum.min_max(data)

Expand All @@ -118,10 +147,16 @@ defmodule Matplotex.Figure.Areal.Histogram do
{bins_dist, hists}
end

defp sanitize(%Figure{axes: %__MODULE__{data: {x, y}}= axes} = figure) do
defp sanitize(%Figure{axes: %__MODULE__{data: {x, y}} = axes} = figure) do
{ymin, ymax} = Enum.min_max(y)
{xmin, xmax} = Enum.min_max(x)

%Figure{figure | axes: %__MODULE__{axes | limit: %TwoD{x: {floor(xmin), ceil(xmax)},y: {floor(ymin), ceil(ymax)}}}}
end
%Figure{
figure
| axes: %__MODULE__{
axes
| limit: %TwoD{x: {floor(xmin), ceil(xmax)}, y: {floor(ymin), ceil(ymax)}}
}
}
end
end
Loading
Loading