|
| 1 | +# Jupyter Notebooks — ruby-libgd |
| 2 | + |
| 3 | +Mathematical function plotting in Ruby, running inside JupyterLab. |
| 4 | + |
| 5 | +These notebooks demonstrate the `Plot` class built on top of [ruby-libgd](https://rubygems.org/gems/ruby-libgd) — plotting explicit functions, implicit curves, and more, entirely in Ruby. |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Requirements |
| 10 | + |
| 11 | +- [Docker](https://www.docker.com/) |
| 12 | +- No local Ruby or Python installation needed — everything runs inside the container. |
| 13 | + |
| 14 | +--- |
| 15 | + |
| 16 | +## Quick start |
| 17 | + |
| 18 | +Build the image: |
| 19 | + |
| 20 | +```bash |
| 21 | +docker build -t ruby-jupyter . |
| 22 | +``` |
| 23 | + |
| 24 | +Run the container, mounting this folder as `/work`: |
| 25 | + |
| 26 | +```bash |
| 27 | +docker run -it -p 8888:8888 \ |
| 28 | + -v $(pwd):/work \ |
| 29 | + ruby-jupyter |
| 30 | +``` |
| 31 | + |
| 32 | +Open [http://localhost:8888](http://localhost:8888) in your browser, create a new notebook, and select the **Ruby** kernel. |
| 33 | + |
| 34 | +--- |
| 35 | + |
| 36 | +## Dockerfile |
| 37 | + |
| 38 | +```dockerfile |
| 39 | +FROM python:3.11 |
| 40 | + |
| 41 | +RUN apt-get update && apt-get install -y \ |
| 42 | + ruby-full \ |
| 43 | + build-essential \ |
| 44 | + libgd-dev \ |
| 45 | + libgd3 \ |
| 46 | + libgd-tools \ |
| 47 | + valgrind \ |
| 48 | + libzmq3-dev |
| 49 | + |
| 50 | +RUN printf "prefix=/usr\n\ |
| 51 | +exec_prefix=\${prefix}\n\ |
| 52 | +libdir=\${exec_prefix}/lib/x86_64-linux-gnu\n\ |
| 53 | +includedir=\${prefix}/include\n\ |
| 54 | +\n\ |
| 55 | +Name: gd\n\ |
| 56 | +Description: GD Graphics Library\n\ |
| 57 | +Version: 2.3\n\ |
| 58 | +Libs: -L\${libdir} -lgd\n\ |
| 59 | +Cflags: -I\${includedir}\n" \ |
| 60 | +> /usr/lib/x86_64-linux-gnu/pkgconfig/gd.pc |
| 61 | + |
| 62 | +RUN pip install jupyterlab |
| 63 | +RUN gem install iruby |
| 64 | +RUN iruby register --force |
| 65 | +RUN gem install ruby-libgd |
| 66 | + |
| 67 | +EXPOSE 8888 |
| 68 | +CMD ["jupyter", "lab", "--ip=0.0.0.0", "--port=8888", \ |
| 69 | + "--no-browser", "--allow-root", "--ServerApp.token="] |
| 70 | +``` |
| 71 | + |
| 72 | +> **ARM machines (Apple Silicon, AWS Graviton):** replace `x86_64-linux-gnu` with `aarch64-linux-gnu` in the `libdir` path. |
| 73 | +
|
| 74 | +--- |
| 75 | + |
| 76 | +## Notebooks |
| 77 | + |
| 78 | +| File | Description | |
| 79 | +|------|-------------| |
| 80 | +| `01_trig_functions.ipynb` | `sin(x)`, `cos(x)`, `tan(x)` with discontinuity detection | |
| 81 | +| `02_logarithms_roots.ipynb` | `log(x)`, `log10(x)`, `log2(x)`, `sqrt(x)`, `cbrt(x)` | |
| 82 | +| `03_implicit_circles_ellipses.ipynb` | `x²+y²=r²`, ellipses, shifted circles | |
| 83 | +| `04_polynomial.ipynb` | `(x+56)³` and other polynomial examples | |
| 84 | + |
| 85 | +--- |
| 86 | + |
| 87 | +## Basic usage |
| 88 | + |
| 89 | +```ruby |
| 90 | +require 'gd' |
| 91 | +# SafeMath and Plot class defined in the first cell |
| 92 | + |
| 93 | +plot = Plot.new(xmin: -10, xmax: 10, ymin: -10, ymax: 10) |
| 94 | + |
| 95 | +# Explicit: y = f(x) |
| 96 | +plot.add("sin(x)") |
| 97 | +plot.add("cos(x)") |
| 98 | +plot.add("log(x)") |
| 99 | +plot.add("tan(x)", steps: 6000) |
| 100 | + |
| 101 | +# Implicit: f(x, y) = 0 |
| 102 | +plot.add("x**2 + y**2 - 9", type: :implicit) |
| 103 | +plot.add("x**2/9.0 + y**2/4.0 - 1", type: :implicit) |
| 104 | + |
| 105 | +plot.render("/work/graph.png") |
| 106 | +``` |
| 107 | + |
| 108 | +--- |
| 109 | + |
| 110 | +## Supported functions |
| 111 | + |
| 112 | +| Category | Functions | |
| 113 | +|----------|-----------| |
| 114 | +| Trigonometric | `sin`, `cos`, `tan`, `asin`, `acos`, `atan` | |
| 115 | +| Hyperbolic | `sinh`, `cosh`, `tanh` | |
| 116 | +| Logarithmic | `log` / `ln` (natural), `log10`, `log2` | |
| 117 | +| Algebraic | `sqrt`, `cbrt`, `exp`, `abs` | |
| 118 | +| Rounding | `floor`, `ceil`, `round` | |
| 119 | +| Constants | `pi`, `e` | |
| 120 | + |
| 121 | +--- |
| 122 | + |
| 123 | +## Plot options |
| 124 | + |
| 125 | +```ruby |
| 126 | +Plot.new( |
| 127 | + width: 600, # canvas width in pixels |
| 128 | + height: 600, # canvas height in pixels |
| 129 | + xmin: -10.0, |
| 130 | + xmax: 10.0, |
| 131 | + ymin: -10.0, |
| 132 | + ymax: 10.0 |
| 133 | +) |
| 134 | +``` |
| 135 | + |
| 136 | +```ruby |
| 137 | +plot.add( |
| 138 | + "sin(x)", |
| 139 | + type: :explicit, # :explicit (default) or :implicit |
| 140 | + color: GD::Color.rgb(r,g,b),# optional — auto palette if omitted |
| 141 | + steps: 3000, # sample count for explicit curves |
| 142 | + threshold: 0.30 # zero-crossing tolerance for implicit |
| 143 | +) |
| 144 | +``` |
| 145 | + |
| 146 | +`add` is chainable: |
| 147 | + |
| 148 | +```ruby |
| 149 | +plot.add("sin(x)").add("cos(x)").add("x**2 + y**2 - 9", type: :implicit) |
| 150 | +``` |
| 151 | + |
| 152 | +--- |
| 153 | + |
| 154 | +## Links |
| 155 | + |
| 156 | +- Gem: [rubygems.org/gems/ruby-libgd](https://rubygems.org/gems/ruby-libgd) |
| 157 | +- Source: [github.com/ggerman/ruby-libgd](https://github.com/ggerman/ruby-libgd) |
| 158 | +- Article: [RubyStackNews](https://rubystacknews.com) |
0 commit comments