cellcanvas / cellcanvas/cellier
Goals and principles of cellier
- Dominant language
- Python
- Stars
- 9
- Forks
- 2
- Avg merge
- 3d 11h
- Merged PRs (30d)
- 4
Description
This issue discusses the goals and principles of `cellier`
## Goals
The overarching goal of `cellier` is to experiment with architectures for rich visualization of multiscale data. The idea is to provide a toolkit for visualization using `pygfx` as a backend.
A few goals:
- visualize nD data
- support rendering of large meshes and point clouds
- multicanvas support
- oblique slicing
- render to desktop- and browser-based GUIs
- it should be easy to serialize and deserialize the full viewer state. I want it to be easy to share views of data (ideally even between different viewers)
A few non-goals:
- build a fully featured application that is a one-stop shop for visualization and analysis. If done well, `cellier` would be a foundation for such a tool, but it is not a goal of `cellier` itself.
- support all visualization backends. while I hope that the architecture makes it easy to implement other backends, this is not a driving requirement.
## Principles
### Data flow
I think it is important that a dataset can be easily visualized with multiple representations without copying data. Below is a figure for a way I think data can flow through the viewer that supports this. I have started to work on this in #4

### Slicing and transformation

In practice the following happens when the dims are changed. This is currently synchronous. Also a redraw is triggered each time a visual is updated. For small numbers of visuals this is probably fine, but we might want to wait until all are updated before redrawing.
1. All dims events are connected to the DataSlicer._on_dims_update()` callback method. This method triggers reslicing of the specific scene the dims object is a member of. https://github.com/kevinyamauchi/cellier/blob/8c7d158dd6d50fd782896f8076b110ea59efb34f/src/cellier/slicer/slicer.py#L48
2. The `_on_dims_update()` method calls the [`DataSlicer.reslice_scene()` method](https://github.com/kevinyamauchi/cellier/blob/8c7d158dd6d50fd782896f8076b110ea59efb34f/src/cellier/slicer/slicer.py#L69). This method makes a [`DataSliceRequest`](https://github.com/kevinyamauchi/cellier/blob/8c7d158dd6d50fd782896f8076b110ea59efb34f/src/cellier/slicer/data_slice.py#L12-L59) for each visual in the scene. The slice request is processed by the `DataSlicer.get_slice()` method, which makes the appropriate requests to the data streams/stores and gets the `SliceResult`, which contains all data required to render the new slice. Each `SliceResult` is emitted as a [`new_slice` event](https://github.com/kevinyamauchi/cellier/blob/8c7d158dd6d50fd782896f8076b110ea59efb34f/src/cellier/slicer/slicer.py#L99)
3. The `RenderManager._on_new_slice()` callback takes the `SliceResult` from the `new_slice` event and updates the `pygfx` objects. Once completed, the `RenderManager` emits a [`redraw_canvas` event](https://github.com/kevinyamauchi/cellier/blob/8c7d158dd6d50fd782896f8076b110ea59efb34f/src/cellier/render/render_manager.py#L189).
4. The `redraw_canvas` event triggers the [`ViewerController._on_canvas_redraw_event()` method](https://github.com/kevinyamauchi/cellier/blob/8c7d158dd6d50fd782896f8076b110ea59efb34f/src/cellier/viewer_controller.py#L69-L74), which makes the canvases udpate.
Some notes about the construction:
- The events coordinating the slicing/rendering updates are connected here: https://github.com/kevinyamauchi/cellier/blob/8c7d158dd6d50fd782896f8076b110ea59efb34f/src/cellier/viewer_controller.py#L61-L66
- The dims update is connected in the DataSlicer: https://github.com/kevinyamauchi/cellier/blob/8c7d158dd6d50fd782896f8076b110ea59efb34f/src/cellier/slicer/slicer.py#L48
### Viewer state is serializable
The viewer state should be serializable. A (very) rough draft of how the viewer model could be structured to support the data flow shown above.

Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.