Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi series sharing 1 x-axis with d3fc using WebGL #1752

Open
stereokai opened this issue Jun 11, 2022 · 21 comments
Open

Multi series sharing 1 x-axis with d3fc using WebGL #1752

stereokai opened this issue Jun 11, 2022 · 21 comments

Comments

@stereokai
Copy link

I'm researching charting libraries for the project in the picture below. The design calls for between 10-25 line charts that share the same time series x-axis. Each line chart can have up to 3,500,000 data points reaching a total of 90,000,000 points. Mousewheel zoom and panning are a requirement as well.

Is it possible to develop such a UI with the WebGL d3fc today? Emphasis on WebGL here – ideally, we would like to avoid "paginating" the chart data before passing it to d3fc. So far we have implemented demos using SVG, Canvas, and WebGL based chart libraries. In our experience, canvas and SVG based libraries were more than able to render such massive datasets, but when it came to user interactions (zoom, pan, etc.) they struggled to the point of being unusable even before the 1M datapoints mark. Above that number, only the single WebGL alternative could actually cut it, and it did so rather impressively well.

If some features are missing, what would it take to develop them? We'll be willing to contribute these features back to d3fc if we can estimate the work. Thanks!

image

@stereokai
Copy link
Author

@ColinEberhardt any chance for your feedback on this? Really appreciate your time!

@ColinEberhardt
Copy link
Member

HI @stereokai - a chart with up to 90m points, that is fully interactive, without using any form of downsampling is going to be a challenge in my opinion.

If I take one of the current interactive D3FC examples, canvas zoom, convert it to WebGL using the line series, on my machine it is OK with 1m points, but starts to get really quite laggy (when panning and zooming) at 10m points:

https://codepen.io/ColinEberhardt/pen/WNMPwra

The only commercial chart I know of that has good performance with >1m datapoints is SciCharts.

@stereokai
Copy link
Author

stereokai commented Jun 14, 2022

@ColinEberhardt Thank you so much for your reply!

And thanks very much for taking the time to pull up that example so quickly. Of course downsampling would be necessary in this case – but to clarify my original question, we would prefer to rely on a proven and "battle tested" (excuse the buzzword) downsampling algorithm hopefully as part of the rendering library (most in not all charting libraries offer something like that). Does d3fc come with any downsampling algorithm built-in?

Going back to the image I provided, if we ignore the performance constraints for a moment, can this UI be developed today using the webgl version of d3fc?

@ColinEberhardt
Copy link
Member

Going back to the image I provided, if we ignore the performance constraints for a moment, can this UI be developed today using the webgl version of d3fc?

Yes, absolutely

@stereokai
Copy link
Author

stereokai commented Jun 16, 2022

Thanks for your answer! I would greatly appreciate it if you could help me out here and elaborate, because even after days of research, I could not piece together this UI from the tens and tens of d3fc examples I studied, and I'm completely stuck

@johncardiologs
Copy link

Hi @stereokai, hopefully you've checked out this example made by Colin? I have a similar use case and it's been helpful for me! https://github.com/ColinEberhardt/d3fc-webgl-hathi-explorer

@stereokai
Copy link
Author

@johncardiologs thanks a lot for the link!

I have seen it, but unfortunately, the example in this link has a completely different UI than what I need to build (like in the picture at the top of this topic). In other words: I need to render multiple line series, each with an independent Y-Axis, that all share a single, synced X-Axis, using WebGL (due to the great amount of data). Do you know any example of how to use the APIs of d3fc to achieve that? Thanks a lot!

@johncardiologs
Copy link

Ah I see -- I thought you were trying to make a scatterplot. I unfortunately don't have any examples, although I'd imagine you could have multiple plots / charts (from the D3FC api) which use webgl, and you can pass the scales you want to these -- so perhaps a common xScale, and individual yScales for each plot/chart (you'd need to give redraw, zoom and chart the scales each needs). I haven't tried it myself so that's just a theory.
As for the zooming portion of code in the example, I'm using raw d3.zoom rather than d3fc.zoom.
Sorry I can't be of more help, good luck!

@stereokai
Copy link
Author

Thanks. I scoured the internet and took a deep dive into almost every line-series d3fc content available, including the official docs here on GitHub. Unfortunately, there is not 1 single example of this UI implemented with d3fc using WebGL, and I couldn't put all the pieces together myself. There is simply not enough information available. You "have to know to know". I really wish someone from @ColinEberhardt team would chime in, but they're not even answering emails :(

@ibrahimuslu
Copy link

Hello @stereokai
I don't know if you are still working on this project, but for the help of your project others who would need to try this, I can confirm that it is quite working very good as @johncardiologs explained in his comment with total 1million data on charts.

as @johncardiologs explained a common xScale with different charts and individual yScales

about the performance up to 14 different charts it can be rendered after 14 context
WARNING: Too many active WebGL contexts. Oldest context will be lost
warning occuring on console.

and up to 1million and slightly over it like 1.2 million datapoints it is rendering 4 or 5 fps so it gives quite enough ux
BUT it is important to emphasize that it is not for each chart but the total datapoints on all charts.

I havent apply any performance tweak as described in https://blog.scottlogic.com/2021/10/15/efficiently-loading-massive-d3-datasets-using-apache-arrow.html

And as an experience, 3 million points can not be visualize on a line meaningfully. It will be squeezed on window. Even 100.000 data point line chart can not be seen meaningfully.

Ah I see -- I thought you were trying to make a scatterplot. I unfortunately don't have any examples, although I'd imagine you could have multiple plots / charts (from the D3FC api) which use webgl, and you can pass the scales you want to these -- so perhaps a common xScale, and individual yScales for each plot/chart (you'd need to give redraw, zoom and chart the scales each needs). I haven't tried it myself so that's just a theory. As for the zooming portion of code in the example, I'm using raw d3.zoom rather than d3fc.zoom. Sorry I can't be of more help, good luck!

@stereokai
Copy link
Author

@ibrahimuslu Thank you so much for your encouraging message :)

The impressive examples of d3fc that are available online are very convincing in terms of performance, so, I have no doubt in that regard. Unfortunately, I am really clueless about how to implement the particular layout as in the example screenshot. I have tried following the tutorials and code examples, but I couldn't put everything together. I am not sure that d3fc-webgl currently supports this layout configuration.

@ibrahimuslu
Copy link

If i understand correctly what you are saying about particular layout. I have implemented similar to that. Check my demo app on https://ibrahimuslu.github.io/d3fc-shared-x/

@stereokai
Copy link
Author

@ibrahimuslu That's fantastic! I really appreciate you sharing that. Nice work!

Is there any reason why each graph is rendered in a dedicated canvas instance instead of all of them rendering in a single canvas?

@ibrahimuslu
Copy link

@ibrahimuslu That's fantastic! I really appreciate you sharing that. Nice work!

Is there any reason why each graph is rendered in a dedicated canvas instance instead of all of them rendering in a single canvas?

I am afraid d3fc does not support more than 1 chart at one canvas.

@stereokai
Copy link
Author

@ibrahimuslu I see. Unfortunately, if that's true, it rules out d3fc for me, because of the 14 canvases per webpage limitation.

@ColinEberhardt Are there plans to support multiple charts in a single canvas?

@ibrahimuslu
Copy link

@ibrahimuslu I see. Unfortunately, if that's true, it rules out d3fc for me, because of the 14 canvases per webpage limitation.

@ColinEberhardt Are there plans to support multiple charts in a single canvas?

Yes in my tests at one view youncan see only 14 due to webgl limitations. If you want to see mutliple charts at one canvas you have to do so many custom development. D3fc architecture is not suitable for that, afaik d3 is not suitable for that.

@chrisprice
Copy link
Contributor

chrisprice commented Sep 9, 2022 via email

@stereokai
Copy link
Author

@chrisprice thanks so much for chiming in. Is that all it would take? Write a decorator that would set the gl.viewport property of each sub-chart to the same canvas element? Or will this change also require configuring the layout in some other way or using different API?

Is there a decorator example somewhere that would be easy to understand and derive from?

@chrisprice
Copy link
Contributor

Unfortunately it's not quite that simple. Changing the gl.viewport for a webgl series would only grant control of the bounding box (within the bounds of the canvas) into which the series renders. It would still require bespoke code to produce the appropriate bounding boxes for each series, appropriate bounding boxes for each axis (remembering the axes render using SVG) and the glue code to bring it all together (the role played by defc-chart typically).

@stereokai
Copy link
Author

@chrisprice Thanks for expanding on your previous tip. What do you mean by "remembering the axes render using SVG"?

@chrisprice
Copy link
Contributor

They don't use canvas for rendering, so you'll need at least one SVG element positioned used CSS relative to the canvas.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants