olavolav / uniplot

Lightweight plotting to the terminal. 4x resolution via Unicode.
MIT License
343 stars 16 forks source link

Reduce time delay between header and rest of the plot. #29

Closed PabloRuizCuevas closed 1 month ago

PabloRuizCuevas commented 1 month ago

While this may be strictly less efficient, it makes the header to be plotted roughly at the same time to the rest of the plot, which makes seamless transitions when updating the chart by just re-plotting on top. (otherwise you see the title for a split of a second and then the rest).

When plotting with a loop and a complex enough chart (with title) it should be apparent, you fit the terminal to be exactly on the size of the plot, expecting a clean update, but you get a tittle first and then the rest, breaking the stream-like plotting experience.

olavolav commented 1 month ago

Hi @PabloRuizCuevas thanks for the PR! 😄

I like the idea, especially if I imagine streaming the output to a log analysis platform like Splunk, then you would like all the lines in the plot to have exactly the same time stamp, not just a similar one.

Let me think about the best way to do this, with the least amount of code duplication. (Your code breaks interactive mode, I think, but I will test.)

PabloRuizCuevas commented 1 month ago

Nice, I made very cool looking plots of market order books so far, with this change it looks fantastic how they update without you to realize that the entire new plot is being generated, maybe i find the way of uploading a gif here.

Untitled

There is a small amount of hacking in this plot for getting the colors etc right.

Thinking it a bit more, I see that you are already erasing the previous lines in the interactive mode, which may open the door to update the data of the plot without generating more and more plots in the terminal. What I was doing now is fitting the terminal to the size to ensure I don't see the old ones, but with a clean update, the size of the terminal won't matter.

Tell me if I can help implementing any of this things.

PabloRuizCuevas commented 1 month ago

Hi, I m was looking at the code and the issue you raised with the interactive mode, so I reworked it, made a new commit and tested that the interactive mode still works fine.

Also changed a bit the structure that may facilitate a bit a possible update/ generator function.

PabloRuizCuevas commented 1 month ago

I let it out the updater for this pr as is getting long, but a possible updater function (generator) would look like this, using the functions of this branch:

def plot_gen(**kwargs):
    """

    """
    ys, xs, n_kwargs = yield
    while True:
        series: MultiSeries = MultiSeries(xs=xs, ys=ys)
        options: Options = validate_and_transform_options(series=series, kwargs=kwargs)
        print(_generate_plot_str(series, options))
        ys, xs, n_kwargs = yield
        if n_kwargs:
            kwargs.update(n_kwargs)
        _erase_previous_lines(options)

gen = plot_gen(title='test')
next(gen)
gen.send([1,2,5,3,2])
gen.send([1,2,5,3,2], {'title'='new title'})
olavolav commented 1 month ago

I finally had a look and think I found a way to make your idea work without loss of efficiency / duplicate computation. It's now live as v0.12.8. Feel free to take a look!

Thanks so much again for the idea and initiative! Sorry that I did not end up using the actual commits, but all credit to you!