{"id":13508627,"url":"https://github.com/MaxStrange/expyplot","last_synced_at":"2025-03-30T11:32:24.260Z","repository":{"id":62429398,"uuid":"87988069","full_name":"MaxStrange/expyplot","owner":"MaxStrange","description":"Matplotlib for Elixir","archived":false,"fork":false,"pushed_at":"2020-08-25T17:23:41.000Z","size":590,"stargazers_count":33,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-12T16:05:59.335Z","etag":null,"topics":["elixir","elixir-lang","matplotlib","plotting","python"],"latest_commit_sha":null,"homepage":null,"language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MaxStrange.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-04-11T23:22:14.000Z","updated_at":"2024-07-09T00:39:41.000Z","dependencies_parsed_at":"2022-11-01T20:09:29.231Z","dependency_job_id":null,"html_url":"https://github.com/MaxStrange/expyplot","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxStrange%2Fexpyplot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxStrange%2Fexpyplot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxStrange%2Fexpyplot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxStrange%2Fexpyplot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MaxStrange","download_url":"https://codeload.github.com/MaxStrange/expyplot/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246230542,"owners_count":20744349,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["elixir","elixir-lang","matplotlib","plotting","python"],"created_at":"2024-08-01T02:00:55.831Z","updated_at":"2025-03-30T11:32:19.712Z","avatar_url":"https://github.com/MaxStrange.png","language":"Elixir","funding_links":[],"categories":["Miscellaneous"],"sub_categories":[],"readme":"# Expyplot\n\nInspired by this project:\nhttps://github.com/JordiPolo/explot, but I wanted something more transparent.\n\n\u003cb\u003eDocumentation can be found at\u003c/b\u003e [https://hexdocs.pm/expyplot](https://hexdocs.pm/expyplot).\n\nExpyplot allows you to use 'all' of the functions in matplotlib.pyplot (in reality, there are some that I left out because they don't make any sense in this context, or\nare deprecated).\n\nUnfortunately, I have not tested anywhere near all of the functions, but they should mostly work. If any don't work, please open an issue, or better yet,\nmake a fix and open a pull request! This library is simple enough that you should be able to grok it without too much effort.\n\nPerhaps the most limiting thing about this library is that it currently has to convert return values from the matplotlib functions into strings before\nsending them back to Elixir, so rather than returning `true`, you will get `\"True\"`, and good luck piecing back to gether complicated objects. The reason I went this route\nis that JSON is unable to parse pretty much any complicated data type that comes back from a matplotlib function, and I didn't feel like writing a JSON parser. If you\nwant to do something about it, please by all means, write a JSON parser capable of serializing all the different return types from matplotlib functions: the python\nside of this library is very simple - it is located in priv/mat.py.\n\n## Differences\n\nUnfortunately (or rather, fortunately if we are celebrating linguistic diversity!), I could not attain complete transparency. This is a list of some notable differences\nbetween this library and the real matplotlib.pyplot:\n\n- Return values are strings currently\n- Variable arguments must be wrapped in a list, so: `plt.plot(a, b)` becomes `Plot.plot([a, b])`, \u003cb\u003ebut especially notice:\u003c/b\u003e `Plot.plot([[1..10], other_args])`\n- Named args and keyword args are atoms: `Plot.grid(b: true)`, though they don't have to be, so: `Plot.plot([[1..10], \"r+\"])`\n- Keyword args that are not keyword only arguments must be written with keywords, you can't do them positionally, so while `plt.grid(True)` works in Python,\n  you have to name the argument in Elixir: `Plot.grid(b: true)`; if you ever get the error: \"argument error: :erlang.++(something, [])\", this is the reason. You need\n  to rewrite the argument list as a keyword list.\n- Any keyword argument or named argument that starts with a capital letter needs to be renamed with an underscore: `Fs` -\u003e `:_Fs`\n\n## Installation\n\n\u003cb\u003eYou must have python3 installed and in your path\u003c/b\u003e\n\n\u003cb\u003eYou must also pip3 install PyQt5 and matplotlib:\u003c/b\u003e\n`pip3 install PyQt5`, `pip3 install matplotlib`, or however you install packages for python3 on your particular system.\n\n```elixir\ndef deps do\n  [{:expyplot, \"~\u003e 1.1.2\"}]\nend\n```\n\n## Examples\n\nExamples taken from http://matplotlib.org/examples/pylab_examples and then rewritten in Elixir to use this Expyplot.\n\nTo run the examples, start an iex -S mix session and run:\n\n```elixir\nCode.load_file \"./path/to/example/EXAMPLE.exs\"\n```\n\n### Histogram\n\n```elixir\ndefmodule HistogramExample do\n  alias Expyplot.Plot\n\n  {mu, sigma} = {100, 15}\n  x = 1..10_000 |\u003e Stream.map(fn(_) -\u003e Statistics.Distributions.Normal.rand(mu, sigma) end) |\u003e Enum.to_list\n\n  Plot.hist(x, bins: 50, normed: 1, facecolor: :green, alpha: 0.75)\n  Plot.xlabel(\"Smarts\")\n  Plot.ylabel(\"Probability\")\n  Plot.title(\"IQ Scores\")\n  Plot.axis_set([40, 160, 0, 0.03])\n  Plot.grid(b: true)\n\n  Plot.show()\nend\n```\n![Histogram](images/histogram.png)\n\n### Subplots\n\n```elixir\ndefmodule SpectralExample do\n  alias Expyplot.Plot\n\n  dt = 0.01\n  fs = 1 / dt\n  t = Stream.unfold(0, fn(acc) -\u003e {acc, acc + dt} end) |\u003e Stream.take_while(\u0026(\u00261 \u003c 10)) |\u003e Enum.to_list\n  nse = t |\u003e Enum.map(fn(_) -\u003e Statistics.Distributions.Normal.rand() end) |\u003e Enum.to_list\n  r = t |\u003e Enum.map(\u0026(Statistics.Math.exp(- \u00261 / 0.05)))\n\n  cnse = nse |\u003e Enum.map(\u0026(\u00261 * Enum.random(r))) |\u003e Enum.take(length(t)) # fake convolution. I didn't feel like writing a functional convolution.\n  s = t |\u003e Enum.map(\u0026(:math.sin(2 * Statistics.Math.pi * \u00261))) |\u003e Enum.zip(cnse) |\u003e Enum.map(fn {el1, el2} -\u003e el1 + el2 end)\n\n  Plot.subplot([3, 2, 1])\n  Plot.plot([t, s])\n\n  Plot.subplot([3, 2, 1])\n  Plot.plot([t, s])\n\n  Plot.subplot([3, 2, 3])\n  Plot.magnitude_spectrum(s, _Fs: fs)\n\n  Plot.subplot([3, 2, 4])\n  Plot.magnitude_spectrum(s, _Fs: fs, scale: :dB)\n\n  Plot.subplot([3, 2, 5])\n  Plot.angle_spectrum(s, _Fs: fs)\n\n  Plot.subplot([3, 2, 6])\n  Plot.phase_spectrum(s, _Fs: fs)\n\n  Plot.show()\nend\n```\n![Subplots](images/subplots.png)\n\n### Zorder/Scatterplots\n\n```elixir\ndefmodule ZorderExample do\n  alias Expyplot.Plot\n\n  x = 1..20 |\u003e Enum.map(fn(_) -\u003e Statistics.Distributions.Normal.rand() end) |\u003e Enum.to_list\n  y = 1..20 |\u003e Enum.map(fn(_) -\u003e Statistics.Distributions.Normal.rand() end) |\u003e Enum.to_list\n\n  Plot.figure()\n  Plot.subplot([2, 1, 1])\n  Plot.plot([x, y, :r], [lw: 3])\n  Plot.scatter(x, y, [s: 120])\n  Plot.title(\"Lines on top of dots\")\n\n  Plot.subplot([2, 1, 2])\n  Plot.plot([x, y, :r], [zorder: 1, lw: 3])\n  Plot.scatter(x, y, [s: 120], [zorder: 2])\n  Plot.title(\"Dots on top of lines\")\n\n  Plot.show()\nend\n```\n![Zorder](images/zorder.png)\n\n### Bar Graph\n\n```elixir\ndefmodule BarExample do\n  alias Expyplot.Plot\n\n  men_means = [20, 35, 30, 35, 27]\n  women_means = [25, 32, 34, 20, 25]\n  men_std = [2, 3, 4, 1, 2]\n  women_std = [3, 5, 2, 3, 3]\n  ind = 0..4\n  width = 0.35\n  yticks = Stream.unfold(0, fn(acc) -\u003e {acc, acc + 10} end) |\u003e Stream.take_while(\u0026(\u00261 \u003c 81)) |\u003e Enum.to_list\n\n  Plot.bar(ind, men_means, [width: width], color: \"#d62728\", yerr: men_std, label: \"Men\")\n  Plot.bar(ind, women_means, [width: width, bottom: men_means], yerr: women_std, label: \"Women\")\n  Plot.ylabel(\"Scores\")\n  Plot.title(\"Scores by group and gender\")\n  Plot.xticks([ind, {\"G1\", \"G2\", \"G3\", \"G4\", \"G5\"}])\n  Plot.yticks([yticks])\n  Plot.legend()\n  Plot.show()\nend\n```\n![Bar Graph](images/bar.png)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMaxStrange%2Fexpyplot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMaxStrange%2Fexpyplot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMaxStrange%2Fexpyplot/lists"}