{"id":50973799,"url":"https://github.com/crystal-data/unicode_plot.cr","last_synced_at":"2026-06-19T05:32:57.511Z","repository":{"id":353496867,"uuid":"1218669297","full_name":"crystal-data/unicode_plot.cr","owner":"crystal-data","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-19T08:15:50.000Z","size":2493,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-19T10:37:53.024Z","etag":null,"topics":["crystal-lang"],"latest_commit_sha":null,"homepage":"https://crystal-data.github.io/unicode_plot.cr/","language":"Crystal","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/crystal-data.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-23T05:20:13.000Z","updated_at":"2026-05-19T08:15:24.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/crystal-data/unicode_plot.cr","commit_stats":null,"previous_names":["kojix2/unicode_plot","kojix2/unicode_plot.cr","crystal-data/unicode_plot.cr"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/crystal-data/unicode_plot.cr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crystal-data%2Funicode_plot.cr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crystal-data%2Funicode_plot.cr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crystal-data%2Funicode_plot.cr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crystal-data%2Funicode_plot.cr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/crystal-data","download_url":"https://codeload.github.com/crystal-data/unicode_plot.cr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/crystal-data%2Funicode_plot.cr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34519049,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["crystal-lang"],"created_at":"2026-06-19T05:32:56.492Z","updated_at":"2026-06-19T05:32:57.499Z","avatar_url":"https://github.com/crystal-data.png","language":"Crystal","funding_links":[],"categories":[],"sub_categories":[],"readme":"# unicode_plot.cr\n\n[![Test](https://github.com/kojix2/unicode_plot/actions/workflows/test.yml/badge.svg)](https://github.com/kojix2/unicode_plot/actions/workflows/test.yml)\n[![Lines of Code](https://img.shields.io/endpoint?url=https%3A%2F%2Ftokei.kojix2.net%2Fbadge%2Fgithub%2Fkojix2%2Funicode_plot%2Flines)](https://tokei.kojix2.net/github/kojix2/unicode_plot)\n\nUnicode terminal plots for Crystal, ported from Julia's [UnicodePlots.jl](https://github.com/JuliaPlots/UnicodePlots.jl).\n\n🚧 **UNDER CONSTRUCTION** 🚧\n\n- Before the first release, history may be rewritten (force-push).\n- API and behavior are still being aligned with UnicodePlots.jl.\n\n## Current coverage\n\nImplemented plot interfaces:\n\n- `lineplot`, `lineplot!`\n- `scatterplot`, `scatterplot!`\n- `barplot`\n- `histogram`\n- `boxplot`\n- `densityplot`, `densityplot!`\n- `heatmap`\n- `spy`\n- `polarplot`, `polarplot!`\n- `stairs`, `stairs!`\n- `contourplot`, `contourplot!` (experimental)\n\nSee [examples/](examples/) for runnable scripts.\n\n- Contour example: [examples/contourplot.cr](examples/contourplot.cr)\n\n## Installation\n\nAdd to your `shard.yml`:\n\n```yaml\ndependencies:\n  unicode_plot:\n    github: kojix2/unicode_plot.cr\n```\n\nThen run `shards install`.\n\n## Quick start\n\n```crystal\nrequire \"unicode_plot\"\ninclude UnicodePlot\n```\n\n### Line plot\n\n```crystal\nx = (0..62).map { |i| i * Math::PI / 31.0 }\ny = x.map { |v| Math.sin(v) }\nputs lineplot(x, y, title: \"sin(x)\", xlabel: \"x\", ylabel: \"sin(x)\", color: :blue)\n```\n\n### Scatter plot\n\n```crystal\nx1 = (1..15).map { Random.rand * 3.0 + 1.0 }\ny1 = (1..15).map { Random.rand * 3.0 + 1.0 }\nx2 = (1..15).map { Random.rand * 3.0 + 6.0 }\ny2 = (1..15).map { Random.rand * 3.0 + 6.0 }\n\np = scatterplot(x1, y1, name: \"cluster A\", color: :blue,\n  title: \"Two clusters\", xlim: {0.0, 11.0}, ylim: {0.0, 11.0})\nscatterplot!(p, x2, y2, name: \"cluster B\", color: :red)\nputs p\n```\n\n### Polar plot\n\n```crystal\ntheta = (0...40).map { |i| 4.0 * Math::PI * i.to_f64 / 39.0 }\nr = theta.map { |angle| angle / (2.0 * Math::PI) }\nputs polarplot(theta, r, title: \"Polar line\", color: :green)\n```\n\n### Bar plot\n\n```crystal\ncities  = [\"Tokyo\", \"Delhi\", \"Shanghai\", \"São Paulo\", \"Mexico City\"]\npopmill = [13.96, 16.79, 24.18, 12.33, 9.21]\nputs barplot(cities, popmill, title: \"City populations\", xlabel: \"population [mil]\")\n```\n\nYou can also pass a `Hash(String, Float64)` directly (sorted by key):\n\n```crystal\nputs barplot({\"Ruby\" =\u003e 95.0, \"Python\" =\u003e 98.0, \"Crystal\" =\u003e 72.0}, title: \"Scores\")\n```\n\n### Histogram\n\n```crystal\ndata = (1..500).map { Random.rand * 10.0 }\nputs histogram(data, title: \"Uniform [0, 10)\", nbins: 15)\n```\n\n### Add series incrementally (`!` variants)\n\nMost series-based plot types support a mutating `!` variant:\n\n```crystal\nx = (1..20).map(\u0026.to_f)\np = lineplot(x, x.map { |v| Math.sqrt(v) }, name: \"√x\", color: :green, title: \"Functions\")\nlineplot!(p, x, x.map { |v| Math.log(v) }, name: \"ln(x)\", color: :red)\nputs p\n```\n\n### Time x-axis (experimental)\n\n`lineplot` and `stairs` can accept `Array(Time)` for the x-axis. This API is experimental and currently requires an explicit Crystal `Time#to_s` format string:\n\n```crystal\ndates = (0..10).map { |i| Time.utc(2020, 1, 1) + i.days }\nputs lineplot(dates, dates.map_with_index { |_, i| i.to_f }, format: \"%F\")\n```\n\n### Options\n\n| Option              | Description                                                                             |\n| ------------------- | --------------------------------------------------------------------------------------- |\n| `title`             | Plot title                                                                              |\n| `xlabel` / `ylabel` | Axis labels                                                                             |\n| `xlim` / `ylim`     | Axis limits as `{min, max}` tuple                                                       |\n| `color`             | Line/point color (`:red`, `:blue`, `:green`, `:cyan`, `:magenta`, `:yellow`, `:normal`) |\n| `name`              | Series name (shown in legend)                                                           |\n| `xscale` / `yscale` | Scale function (`:log2`, `:log10`, or a `Proc(Float64, Float64)`)                       |\n| `width` / `height`  | Canvas size in characters                                                               |\n| `canvas`            | Canvas type (`:braille`, `:block`, `:ascii`)                                            |\n\n## Practical notes\n\n- This project prioritizes Julia compatibility in visible output.\n- Some interfaces may still differ while ports are in progress.\n- `spec/reference_spec.cr` compares output against Julia reference assets.\n\n## Development\n\nRun specs from repository root:\n\n```bash\ncrystal spec\n```\n\nReference fixtures are stored under [spec/fixtures/](spec/fixtures/).\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrystal-data%2Funicode_plot.cr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcrystal-data%2Funicode_plot.cr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcrystal-data%2Funicode_plot.cr/lists"}