numbat icon indicating copy to clipboard operation
numbat copied to clipboard

Basic plotting support

Open sharkdp opened this issue 1 year ago • 7 comments

This is a draft for adding basic plotting support to Numbat. Contrary to the first attempt in #147, we now implement the basic data preprocessing step in Numbat itself, using the new struct and List data types. We can now also implement this as a normal function, instead of having to introduce a new command.

We can now write something like:

let A0 = 3 cm
let ω = 20 Hz
let λ = 1.5 s

fn amplitude(t) = A0 exp(-t/λ) cos(ω t)

line_plot(amplitude, 0 s, 8 s) |>
  xlabel("Time") |>
  ylabel("Amplitude") |>
  show

and get the following plot. The xlabel/ylabel calls are optional. Note how the units here are inferred and added to the axis descriptions:

image

Similarly, we can create a simple bar chart:

let names = ["Iron", "Copper", "Silver", "Gold", "Platinum"]
let elements = map(element, names)

fn density(e: ChemicalElement) -> MassDensity = e.density

let densities = map(density, elements)

bar_chart(densities) |>
  xlabels(names) |>
  value_label("Density") |>
  show

image

Open points:

  • This would be much more powerful if we had #452. This would allow us to rewrite line_plot(amplitude, 0 s, 8 s) into line_plot(amplitude) |> xlim(0 s, 8 s), for example. It would also allow us to implement ylim(…, …). We could also store the function inside the LinePlot struct instead of storing all the data points. We would only convert to data points before passing it to the FFI
  • It would be nice to be able to move the |> reverse-apply operators in the example above to the next line. To have it look like
    line_plot(amplitude, 0 s, 8 s)
      |> xlabel("Time")
      |> ylabel("Amplitude")
      |> show
    

sharkdp avatar Jun 11 '24 21:06 sharkdp

For CLI usage, I wonder if we could hook it up to ratatui's canvas or chart widgets. This probably wouldn't be all that useful in practice, but might be fun anyway :)

eminence avatar Jun 12 '24 01:06 eminence

For CLI usage, I wonder if we could hook it up to ratatui's canvas or chart widgets. This probably wouldn't be all that useful in practice, but might be fun anyway :)

Cool. Hadn't heard about ratatui. But yeah, I think a file-based backend and maybe an actual GUI backend might be more useful options.

sharkdp avatar Jun 15 '24 20:06 sharkdp

This changeset now uses plotly, which allows us to open interactive plots in the browser. This is also much lighter in terms of dependencies (but see https://github.com/plotly/plotly.rs/issues/176). And it would also integrate with the web version naturally.

image

sharkdp avatar Jul 01 '24 22:07 sharkdp

@irevoire I had a new idea for the API. It's a bit hacky, but could be enough for a first draft. I'm now using your enhanced reverse-apply operator to add optional arguments like xlabel and ylabel. Please see the updated PR description for details, and let me know what you think, if you're interested.

sharkdp avatar Aug 05 '24 21:08 sharkdp

Oh yes we can now do a builder pattern quite easily! IMO, that's nicer than having a « Default » implementation for the structure 🤔

On another subject, I’m really starting to think that we may need scopes earlier than I expected:

Plot.line_plot(amplitude, 0 s, 8 s)
  |> Plot.xlabel("Time")
  |> Plot.ylabel("Amplitude")
  |> Plot.show

Something like that seems easier to understand, and it will free up a lot of symbols for the users.

irevoire avatar Aug 05 '24 21:08 irevoire

On another subject, I’m really starting to think that we may need scopes earlier than I expected:

Yes, absolutely. It's a problem already since I can't reuse things like ylabel for other plot types. I added a slightly hacky solution for now in order to be able to have just one show function for both line plots and bar plots. The latter of which are now also supported (see PR description).

sharkdp avatar Aug 08 '24 15:08 sharkdp

This is now in a state where it could be merged. A drawback is that the binary size increases by about 4 MiB, which is probably mostly due to https://github.com/plotly/plotly.rs/issues/176

sharkdp avatar Aug 09 '24 11:08 sharkdp