{"id":15668306,"url":"https://github.com/devstopfix/gnuplot-elixir","last_synced_at":"2025-07-27T21:38:07.328Z","repository":{"id":56008082,"uuid":"175167995","full_name":"devstopfix/gnuplot-elixir","owner":"devstopfix","description":"Elixir interface to Gnuplot graphing utility","archived":false,"fork":false,"pushed_at":"2022-11-21T19:44:53.000Z","size":363,"stargazers_count":30,"open_issues_count":3,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-15T17:00:00.802Z","etag":null,"topics":["charts","elixir-library","graphs","plotting"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devstopfix.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":"2019-03-12T08:34:10.000Z","updated_at":"2024-05-19T12:41:46.000Z","dependencies_parsed_at":"2023-01-22T18:00:10.057Z","dependency_job_id":null,"html_url":"https://github.com/devstopfix/gnuplot-elixir","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devstopfix%2Fgnuplot-elixir","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devstopfix%2Fgnuplot-elixir/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devstopfix%2Fgnuplot-elixir/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devstopfix%2Fgnuplot-elixir/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devstopfix","download_url":"https://codeload.github.com/devstopfix/gnuplot-elixir/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249116231,"owners_count":21215142,"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":["charts","elixir-library","graphs","plotting"],"created_at":"2024-10-03T14:08:00.905Z","updated_at":"2025-04-15T17:00:12.443Z","avatar_url":"https://github.com/devstopfix.png","language":"Elixir","readme":"# Gnuplot Elixir\n\nA simple interface from [Elixir data][7] to the [Gnuplot graphing utility][1] that uses [Erlang Ports][5] to transmit data from your application to Gnuplot. Datasets are streamed directly to STDIN without temporary files and you can plot [1M points in 12.7 seconds](examples/stress.exs).\n\nPlease visit the [Gnuplot demos gallery](http://gnuplot.sourceforge.net/demo_5.3/) to see all the possibilities, the [manual which describes the grammar](http://www.gnuplot.info/docs_5.2/Gnuplot_5.2.pdf), and the [examples folder](examples/).\n\nThis is a conversion of the [Clojure Gnuplot library][4] by [aphyr][2]. This library has been tested on OS X, Ubuntu 16.04 and CentOS 7.6.\n\n[![Build Status](https://github.com/devstopfix/gnuplot-elixir/workflows/ci/badge.svg)](https://github.com/devstopfix/gnuplot-elixir/actions)\n[![Hex.pm](https://img.shields.io/hexpm/v/gnuplot.svg?style=flat-square)](https://hex.pm/packages/gnuplot)\n[![API Docs](https://img.shields.io/badge/api-docs-MediumPurple.svg?style=flat)](https://hexdocs.pm/gnuplot/Gnuplot.html)\n![Platforms](https://img.shields.io/badge/platform-osx%7Cubuntu%7Ccentos-black.svg)\n\n## Usage\n\nThe `plot` function takes two arguments:\n\n* a list of commands (each of which is a list of terms)\n* a list of Streams or Enumerable datasets (not required when plotting functions)\n\nCommands are lists of terms that normally start with an atom such as `:set`. They may be written as lists or [Word lists](https://elixir-lang.org/getting-started/sigils.html#word-lists) - the following lines are equivalent:\n\n* `[:set, :xtics, :off]`\n* `~w(set xtics off)a`\n\nand both convert to `set xtics off`.\n\nStrings are output inside double quotes, and charlists are output without modification. `[:plot, 'sin(x)', :title, \"Sine Wave\"]` becomes: `plot sin(x) title \"Sine Wave\"`\n\nA dataset is a list of points, each point is a list of numbers. A dataset can be a Stream.\n\n### Scatter plot with a single dataset\n\nLets compare the distributions of the [Erlang rand functions](http://erlang.org/doc/man/rand.html):\n\n```elixir\ndataset = for _ \u003c- 0..1000, do: [:rand.uniform(), :rand.normal()]\n{:ok, _cmd} = Gnuplot.plot([\n  [:set, :title, \"rand uniform vs normal\"],\n  [:plot, \"-\", :with, :points]\n  ], [dataset])\n```\n\nGnuplot will by default open a window containing your plot:\n\n![rand](docs/gnuplot.PNG)\n\nThe command string sent (`_cmd` above) can be manually inspected should the chart not appear as you expected. If the chart is not drawn due to an error then the result will be `{:error, cmd, errors}`.\n\n### PNG of two datasets\n\nWrite two datasets to a PNG file:\n\n```elixir\nimport Gnuplot\n\n{:ok, _cmd} = plot([\n  [:set, :term, :pngcairo],\n  [:set, :output, \"/tmp/rand.png\"],\n  [:set, :title, \"rand uniform vs normal\"],\n  [:set, :key, :left, :top],\n  plots([\n      [\"-\", :title, \"uniform\", :with, :points],\n      [\"-\", :title, \"normal\", :with, :points]\n      ])\n  ],\n  [\n        for(n \u003c- 0..100, do: [n, n * :rand.uniform()]),\n        for(n \u003c- 0..100, do: [n, n * :rand.normal()])\n  ])\n```\n\n![uniform-vs-rand](docs/rand.PNG)\n\nWhen we are plotting multiple datasets in the same chart we need a comma separated list for the `plot` command which is made with the `plots`, `splots` or `list` function.\n\nNB the `:png` terminal can also be used but it produces [rougher output](http://www.gnuplotting.org/output-terminals/).\n\n\n### Plot functions without datasets\n\n```elixir\nGnuplot.plot([[:plot, 'sin(x)', :title, \"Sine Wave\"]])\n```\n\n![rand](docs/sine.PNG)\n\n```elixir\nGnuplot.plot([\n        ~w(set autoscale)a,\n        ~w(set samples 800)a,\n        [:plot, -30..20, 'sin(x*20)*atan(x)']\n])\n```\n\nNB [ranges](https://hexdocs.pm/elixir/Range.html) can be used\n\n![rand](docs/atan_sin.PNG)\n\n### Multiplot\n\nThe `multiplot` mode places serveral plots on the same page:\n\n```elixir\nGnuplot.plot([\n  [:set, :multiplot, :layout, '2,1'],\n  [:plot, 'sin(x)/x'],\n  [:plot, 'cos(x)']\n  ])\n```\n\n## Installation\n\nThis library is [available in Hex](https://hex.pm/packages/gnuplot) with [documentation](https://hexdocs.pm/gnuplot/Gnuplot.html) and the package can be installed by adding `gnuplot` to your project:\n\n```elixir\ndef deps do\n  [\n    {:gnuplot, \"~\u003e 1.22\"}\n  ]\nend\n```\n\n## Testing\n\nSome tests create plots which require `gnuplot` to be installed. They can be be excluded with:\n\n    mix test --exclude gnuplot:true\n\n## Performance\n\nThe performance of the library on a MacBook Air is comparable to the Clojure version when `gnuplot` draws to a GUI. It is a little faster when writing directly to a PNG when running on a server. The times below are in milliseconds. Each plot was made in increasing order of the number of points and after a cold start of the VM. The last two columns show the refactoring from Enumerable to Streams.\n\n| Points | Clojure GUI | Elixir GUI | Elixir PNG | Elixir Enum   | Elixir Stream |\n| -----: | ----------: | ---------: | ---------: | ------------: | ------------: |\n|      1 |       1,487 |          5 |         18 |             4 |             5 |\n|     10 |       1,397 |         10 |          1 |            \u003c1 |             1 |\n|    1e2 |       1,400 |          4 |         12 |             1 |             1 |\n|    1e3 |       1,381 |         59 |         52 |             8 |            10 |\n|    1e4 |       1,440 |        939 |        348 |           211 |           211 |\n|    1e5 |       5,784 |      5,801 |      3,494 |         1,873 |         1,313 |\n|    1e6 |      49,275 |     43,464 |     35,505 |        19,916 |        12,775 |\n|        |     MacBook |    MacBook |    MacBook |  Ubuntu 16.04 |  Ubuntu 16.04 |\n|        |  2.5 GHz i5 | 2.5 GHz i5 | 2.5 GHz i5 | 3.3 GHz 2vCPU | 3.3 GHz 2vCPU |\n\n![performance](docs/perf.PNG)\n\n```elixir\npoints      = [1, 10, 100, 1_000, 10_000, 100_000, 1_000_000]\nclojure_gui = [1.487, 1.397, 1.400, 1.381, 1.440, 5.784, 49.275]\nelixir_gui  = [0.005, 0.010, 0.004, 0.059, 0.939, 5.801, 43.464]\nelixir_png  = [0.002, 0.010, 0.049, 0.040, 0.349, 4.091, 41.521]\nubuntu_t2m  = [0.004, 0.002, 0.001, 0.008, 0.211, 1.873, 19.916]\nubuntu_strm = [0.002, 0.001, 0.001, 0.009, 0.204, 1.279, 12.858]\ndatasets = for ds \u003c- [clojure_gui, elixir_gui, elixir_png, ubuntu_t2m, ubuntu_strm], do:\n  Enum.zip(points, ds)\n\nGnuplot.plot([\n  [:set, :title, \"Time to render scatter plots\"],\n  [:set, :xlabel, \"Points in plot\"],\n  [:set, :ylabel, \"Elapsed (s)\"],\n  ~w(set key left top)a,\n  ~w(set logscale xy)a,\n  ~w(set grid xtics ytics)a,\n  ~w(set style line 1 lw 2 lc '#63b132')a,\n  ~w(set style line 2 lw 2 lc '#2C001E')a,\n  ~w(set style line 3 lw 2 lc '#5E2750')a,\n  ~w(set style line 4 lw 2 lc '#E95420')a,\n  ~w(set style line 5 lw 4 lc '#77216F')a,\n  Gnuplot.plots([\n    [\"-\", :title, \"Clojure GUI\", :with, :lines, :ls, 1],\n    [\"-\", :title, \"Elixir GUI\", :with, :lines, :ls, 2],\n    [\"-\", :title, \"Elixir PNG\", :with, :lines, :ls, 3],\n    [\"-\", :title, \"Elixir t2.m\", :with, :lines, :ls, 4],\n    [\"-\", :title, \"Elixir Stream\", :with, :lines, :ls, 5]\n  ])],\n  datasets\n)\n```\n\n## Credits and licence\n\nOriginal design ©2015 [Kyle Kingsbury][2].\n\nElixir code ©2022 [DEVSTOPFIX LTD][3]. Contributions from [piisgaaf](https://github.com/piisgaaf)\n\nDistributed under the [Eclipse Public License v2][6].\n\n\n[1]: http://www.gnuplot.info/\n[2]: https://github.com/aphyr\n[3]: http://www.devstopfix.com/\n[4]: https://github.com/aphyr/gnuplot\n[5]: http://erlang.org/doc/reference_manual/ports.html\n[6]: https://www.eclipse.org/legal/epl-2.0/\n[7]: https://elixir-lang.org/getting-started/basic-types.html\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevstopfix%2Fgnuplot-elixir","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevstopfix%2Fgnuplot-elixir","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevstopfix%2Fgnuplot-elixir/lists"}