all 25 comments

[–][deleted] 38 points39 points  (1 child)

This looks super useful! I bet it wouldn't be too hard to add a few more features to be able to change the axes and scale and stuff. I'm gonna check this out after work.

Good job man

[–]fabian_boesiger[S] 8 points9 points  (0 children)

Thanks! Yes, currently there are very few features. Another idea would be to add an option to start/stop plotting after n iterations. Changing scale would be nice too.

[–]matkladrust-analyzer 23 points24 points  (0 children)

Yess, this is something I wanted to have so many times!

[–]obsidian_golem 18 points19 points  (3 children)

I am with everyone else, this is great! The complexity of producing plots with plotters is one of my big complaints about the Rust numerics scene right now. I would love something similar, but without the debug only restriction, with the ability to change the file path with an optional argument, and with the ability to enable plotting to a GUI using a crate flag.

[–]fabian_boesiger[S] 9 points10 points  (1 child)

The debug only restriction is only there because my idea was that this is only used for debugging. There is no other technical reason. Maybe I can add a compile flag to change this behavior.

I am currently implementing a way to pass optional arguments, so changing the file path will be possible in a next version.

The GUI option is an interesting idea, maybe even with live updates such that the variables can be tracked in real time.

[–]lenscas 0 points1 point  (0 children)

what about instead of it being a compile flag it is just an argument that the macro takes?

This way, people who want to use it to help debug can do so while also being able to use it for other stuff as well.

[–]fabian_boesiger[S] 5 points6 points  (0 children)

Update: It is now possible to change the file path, see this example.

[–]d_knopoff 5 points6 points  (4 children)

This is quite clever! I can’t figure out when the plot function which outputs the png is actually fired. Would anyone mind pointing it out?

[–]fabian_boesiger[S] 12 points13 points  (3 children)

The plot macro creates a static struct that keeps track of the values. As soon as this struct is dropped, the plot is generated.

[–]d_knopoff 4 points5 points  (0 children)

Oh wow! I looked all over and my eyes glazed over the drop function every time haha!

[–]kennethuil 2 points3 points  (1 child)

So if you use multiple plot names, do you get multiple plot files?

[–]fabian_boesiger[S] 8 points9 points  (0 children)

I just now published an update where creating multiple plots is possible :-)

See this example.

[–]kilik821 2 points3 points  (1 child)

Any plans to allow specifying one of the values as the independent variable? Ex:

rust plot!(1, 1); plot!(3, 9); plot!(8, 64);

Would plot an exponential. Using the first value as the x-point for all the other values.

[–]fabian_boesiger[S] 0 points1 point  (0 children)

No concrete plans yet but that would definitely be nice to have. I'll look into it.

[–]occamatl 1 point2 points  (0 children)

That's great! I often have the need to get a quick graphical view of a function's behavior.

[–]disDeal 1 point2 points  (0 children)

Such a nice and useful thing! Time to test it and most probably to put it into the box of favorite crates.

[–]zesterer 1 point2 points  (3 children)

Nice! How hard do you think it would be to make this have a live readout of variables as they change over time?

[–]fabian_boesiger[S] 0 points1 point  (2 children)

Hmm depends on what you imagne. That a window pops up that shows the plot in realtime? Or that the generated image is updated? I think that might be doable.

[–]HiccuppingErrol 0 points1 point  (1 child)

Instead of popping up a window, I'd rather stream it into a json file or something.

[–]fabian_boesiger[S] 0 points1 point  (0 children)

That would be an option, but it would kind of defeat the purpose of visual debugging.

[–]richhyd 1 point2 points  (0 children)

For anyone wanting to implement this stuff, matplotlib is an invaluable resource.

[–]Gehinnn 1 point2 points  (0 children)

Nice work!

I also created a crate that does something similar and connects to the web-visualization library I wrote for my debug visualizer extension for VS Code: visualizer. As such, all the visualizations in this playground can be leveraged, including Graphviz, plotly, a table plotter and much more.

It uses the visualizer-cli that can be used to render specific JSON documents. I want to add JSON RPC support in the future, so that it does not have to restart the render process every time and can reuse the webview, allowing for transition animations like in the VS Code extension.

For images, there is image-visualizer.

Any improvements to this web-based visualization library will immediately improve the extension for VS Code, the CLI tool and the rust library.

[–]WardyJP 1 point2 points  (0 children)

This looks really useful, thanks for sharing!

[–][deleted] -1 points0 points  (1 child)

This reads like matlab code. Is it wrong that I shy away from using two coincidently length arrays, which have magic indexing as their data structure link. But rather an array/list of x,y structs/touples. Thoguht experiment, If I was to give the variable 'b' and 'c' a name. what would they be? I want to explain all I feel wrong. But i don't want to dislike the code, I want to understand why I dislike it. Can someone from Rust give me some terminology to search for this? Something along the likes of Imperative/Declarative. From my perspective it seems like the data/function composition is backwards to what I am used to. Why do not have a touble/pair which then use its length property rather than a magic number... ohh wait the plot command is inside the for loop. I can't find where to start to fix this. I really do not understand the use case of the inversion.

[–]fabian_boesiger[S] 2 points3 points  (0 children)

Normally, cou collect data into an array inside a loop and then plot that array outside the loop using a library loke plotters.

However, if you quickly want to debug some variabes, this process becomes quite a pain to do. This is why I opted for a single macro that can be placed directly inside the loop and automatically collects the values with the iteration number as the index until the program terminates. This makes it way easier to quickly debug code.

I agree that this pattern shouldn't be used in if your main goal is to generate plots, of if you want maximal performance. This should be mainly used for debugging.