xdot.py icon indicating copy to clipboard operation
xdot.py copied to clipboard

Add support for 'streaming mode' which draws animated graphs from stdin

Open emdash opened this issue 2 years ago • 5 comments

Essentially, it treats stdin as a stream of null-delimited frames. Each time a complete frame is read, the graph is updated. The effect is that changes to the graph are "animated". This also avoids touching the disk when the graph output is dynamically generated.

To make the effect less visually disorienting, I modified set_dotcode and friends to take an optional preserve_viewport parameter. This keeps the current scroll position and zoom ratio when the graph is updated. If the new frame is "sufficiently similar" to the old frame, the effect is quite seamless.

I added a test script tests/streaming.sh which demonstrates usage.

If there's interest, perhaps some scheme could be devised to help "pin" the "origin" of the image to a particular feature (node id, edge, subgraph), which might help keep you oriented across large structural changes to the graph, at the expense of some extra complexity.

A further enhancement would be to save up to the last n frames, and add some key bindings to allow seeking arbitrarily through the history.

emdash avatar May 06 '22 02:05 emdash

Another thought -- should --streaming-mode be renamed to -0, by analogy with xargs -0?

emdash avatar May 08 '22 08:05 emdash

Another enhancement: animate the changes between frames. Interpolate position, color, other attributes.

emdash avatar May 08 '22 08:05 emdash

Sorry for the silence. I finally spend some time looking into this proposal.

This is not an invasive change, so I have no objections in principle.

A few suggestions regarding the minutiae:

  • Instead of null character, I recommend that the separator is a single line form feed (ie, '\xc\n'). This allows an human to visually inspect the stream, and read the input a line at a time instead of byte at a time. It also means one can use sys.stdin as is.
  • Instead of first=True/False, just have preserve_viewport=False/True

jrfonseca avatar Sep 24 '22 10:09 jrfonseca

This is an interesting feature.

If I understand jrfonseca correctly, the printf '\0' statements in tests/streaming.sh would be updated to printf '\xc\n'.

(or printf '\f\n' as \f is an alias for \xc)

tlk avatar Sep 24 '22 11:09 tlk

Thanks for your interest! I've been dog-fooding this for a while and it's been working really great for my use-case: a command-line driven mind-mapping tool. But I can see this being great for debugging, data science, and any other situation where you want to watch graphs evolving through time.

I am currently experimenting with "closing the loop" around user interaction, by printing data to stdout in response to user clicks.

The form-feed character is a good thing to know about. I had forgotten about it, and I had not thought about using that, but at first glance it seems like it should work.

On the other hand, using sys.stdin "as is" is never really enough thanks to I/O buffering. I was imagining was more like proper use of asyncio, select, or other non-blocking read rather than spawning a thread. I just didn't want to take the time unless there was interest. Ideally I would leave the choice of delimiter up to the user.

emdash avatar Sep 24 '22 15:09 emdash