Reintroduce dislocation segmentation & MultiVolumeViewer workflow (rebased after revert after PR 105) #107
Merged
Merged
Conversation
added 20 commits
February 3, 2026 18:50
Base updated to latest dev to fully integrate the analysis workflow with the current package version.
This commit significantly extends the MultiVolumeViewer widget into a
ParaView-like interactive 3D visualization tool for Jupyter environments.
Key additions and changes:
- Introduced a unified layer system supporting raw, slice, plane, and clip layers
- Slice layers:
* Axis-aligned slicing with adjustable position and thickness
* Independent layers, decoupled from the source after creation
- Plane layers:
* Arbitrary planes defined by physical-space normal and origin
* Optional slab thickness and finite spatial extent
* Robust in-plane basis construction and correct physical sampling
- Clip layers:
* Half-space clipping of raw volumes using a plane (normal + origin)
* Selectable side relative to the plane normal (up / down)
* Geometry extraction via marching cubes with clean planar cuts
* Coloring sampled from the original (unclipped) source volume
- Flexible coloring:
* Color by self, other raw layers, spatial coordinates, or constants
* Independent colorbars per visible layer
- Robust NaN handling:
* Per-layer NaN policy (none / mean / zero / min / max)
* For slice and plane layers with NaN policy = "none":
- NaN regions rendered as true holes (opacity = 0)
- Behavior consistent with ParaView-style NaN hiding
* Consistent handling of NaN and ±inf across all layer types
- UI and UX improvements:
* Contextual “Create layer” workflow
* Two-column layout for plane and clip normal/origin controls
* Independent edit panels per selected layer
* Removal of unused UI components
* Improved slider range synchronization
- Rendering and consistency:
* Full support for anisotropic voxel sizes
* All geometry defined and rendered in physical (x, y, z) space
* Lighting controls preserved for mesh-based layers
- Code quality:
* Refactored for clarity and separation of concerns
* Formatted with ruff (line length 79)
* All ruff checks pass with no violations
This completes the core functionality of MultiVolumeViewer as a
self-contained, notebook-native 3D visualization tool for scientific
volume data exploration (e.g. BCDI, tomography, FEM fields).
…ogic, and add robust async animation export
This commit introduces a substantial refactor and feature expansion of MultiVolumeViewer, focusing on UI stability,
deterministic color handling, and scalable animation export.
1. Color-range and color_by handling (major behavioral fix)
- Reset range slider bounds when color_by changes instead of only expanding bounds.
- Track the active reference field via _range_ref_color_by to detect color_by transitions.
- On color_by change:
* Recompute min/max from the newly selected scalar field.
* Reset the slider window to the full valid range unless the user explicitly overrides it.
- Prevents stale or misleading color scaling when switching between __self__, other layers,
spatial coordinates (__x__, __y__, __z__), or constants.
- Ensures cmin/cmax always reflect the active coloring source.
Impact: fixes long-standing UI inconsistency and ensures physically meaningful color interpretation.
2. NaN handling consistency for derived layers
- Clear separation between base data (data2d_base, NaNs preserved) and displayed data (policy-applied).
- Slice and plane layers now:
* Respect nan_policy="none" by producing true transparency holes.
* Match ParaView-like NaN masking behavior.
- Geometry NaNs and color-intensity NaNs are handled independently and deterministically.
3. Observer lifecycle management (UI performance and correctness)
- Explicit unobserve / re-observe logic for slice and plane panels.
- Observers are stored per panel (_slice_obs, _plane_obs) and safely detached before rebuild.
- Prevents duplicate callbacks, refresh storms, and memory leaks during repeated UI edits.
4. Layer rename UX fix
- Introduced _EDIT_PLACEHOLDER="__choose_layer__" and _suspend_rename_autofill_once flag.
- Rename textbox auto-fills only when appropriate.
- Prevents overwriting user input when switching layers.
- Fixes regression causing confusing rename behavior.
5. Rendering and animation export architecture
- Added configurable rendering backend:
rendering_mode ∈ {"safe", "fast", "process"}.
- Introduced render_workers and render_in_flight controls.
- Implemented async / parallel animation export:
* Geometry/materialization remains sequential and UI-safe.
* PNG rendering may run in a process pool.
* Frames are streamed and written in order without large in-memory buffers.
- Added _render_fig_json_to_png helper to decouple Plotly rendering from UI state.
Impact: enables stable high-resolution MP4/GIF export without freezing the notebook or breaking widgets.
6. Global rendering safety controls
- Added force_fixed_color_range flag to disable auto-ranging globally.
- Guarantees deterministic color scaling for publications and animations.
7. Miscellaneous UI and layout improvements
- Grid visibility toggle respected during theme updates.
- Camera reset and forced relayout after exports.
- More robust colorbar placement logic.
- Minor cleanup of colormap discovery and option exposure.
Summary:
This refactor upgrades MultiVolumeViewer into a robust, production-grade visualization and export engine
with correct color semantics, stable UI behavior under heavy interaction, and scalable animation export.
- Restrict layers input to dict[str, np.ndarray] - Forward viewer-specific options via `layers_kwargs` - Update docstrings to reflect current behavior
- Align arguments with new Plotter and MultiVolumeViewer APIs - No functional changes
This enables reliable MP4 animation export via imageio on all platforms, by ensuring the FFmpeg backend required by imageio is available. Notes: - This does NOT install a system ffmpeg binary. - GIF export continues to rely on an external ffmpeg executable and is handled separately in code with explicit runtime checks.
Owner
|
I had a quick look at the PR which is nice as in introduces new features. Can you address the following points:
|
Collaborator
Author
|
ok. i agree with the sub package for dislocation. |
added 5 commits
March 5, 2026 11:33
- create cdiutils.analysis.dislocation subpackage - split large dislo.py into modular modules: _strain_map, _clustering, _geometry, _ring, _theory, _phase_decomp, _plotting - expose public API via dislocation.__init__ - improve maintainability and readability
…cation_identification notebook
added 7 commits
March 5, 2026 12:07
…e UI This commit introduces several improvements to the MultiVolumeViewer interactive 3D viewer, focusing on better spatial control of layers, clearer axis representation, and improved UI structure. 1. Per-layer rigid transformations ---------------------------------- A new transform system allows each layer to be visually manipulated independently. New capabilities: - Rotation controls: Rx, Ry, Rz - Translation controls: Tx, Ty, Tz - Transformations are applied only at the rendering stage, meaning: * the underlying voxel data remain unchanged * transformations affect only the displayed geometry Implementation details: - Transform state stored per layer (self._layer_transform) - Applied in the rendering pipeline before plotting - Default transform state initialized when layers are created - New layers start with zero transform This enables spatial comparison of volumes and derived layers without modifying the original data. 2. Axis unit support -------------------- An optional 'unit' parameter was added to allow axis labeling with physical units. Example: X (nm), Y (nm), Z (nm) Behavior: - unit=None -> axis labels remain X, Y, Z - unit="nm" -> axis labels become X (nm), Y (nm), Z (nm) Implementation: - new argument in MultiVolumeViewer - helper method used when configuring Plotly scene axes - forwarded via layers_kwargs in Plotter 3. Expanded transform ranges ---------------------------- Translation sliders (Tx, Ty, Tz) now scale with the physical extent of the dataset. Range is derived from the dataset physical size based on voxel_size and volume dimensions. This allows moving layers significantly outside the volume if needed. 4. Slice panel improvements --------------------------- The slice UI logic was corrected to ensure consistent behavior. Key fixes: - Slice position handled consistently - Prevents empty slices caused by invalid position values - Axis change correctly updates slider limits - Center button restores the mid-slice position These fixes restore robust slice rendering while maintaining compatibility with the interpolation pipeline. 5. Improved edit panel structure -------------------------------- The right-side editing panel was reorganized. Changes: - Lighting and Transform controls moved into collapsible sections - Implemented via a collapsible UI helper - Improves readability of the layer editor - Reduces vertical clutter when editing multiple parameters 6. Documentation updates ------------------------ Module documentation was updated to reflect new functionality: - Added description of the transform system - Documented axis unit feature - Updated feature list - Updated Plotter documentation for layers_kwargs Result ------ The viewer now supports: - independent spatial manipulation of layers - clearer axis labeling with physical units - improved UI organization - more robust slice handling while maintaining compatibility with the existing rendering and animation export system.
…e new files appear to be foramtted after updatting the ruff version from 0.1.14 to 0.15.4
…nd fix traitlets deprecation
This commit introduces unit test coverage for the dislocation analysis module and the MultiVolumeViewer 3D interface,
and fixes a traitlets/ipywidgets deprecation warning related to ButtonStyle usage.
1. Dislocation module testing
Added a comprehensive pytest suite for the dislocation analysis module.
New test file:
tests/test_dislocation.py
Covered functionality includes:
* Geometry utilities
* extract_structure
* fit_line_3d
* generate_filled_cylinder
* circular mask generation
* phase extraction around dislocations
* Ring analysis utilities
* center angle computation
* removal of large angular jumps
* phase ring processing pipeline
* Phase decomposition
* validation of cos² / sin² phase recovery
* Strain map utilities
* map_min_gradient behavior
* shape and range validation
* Clustering pipeline
* clusters_dislo_strain_map smoke test
* Theory utilities
* vector operations
* rotation matrix correctness
* dislocation phase model properties
These tests ensure that the main computational routines of the dislocation module execute correctly and return outputs with expected structure and physical properties.
2. MultiVolumeViewer 3D testing
Added a test suite for the interactive 3D multi-volume visualization system.
New test file:
tests/test_multiviewer_3d.py
Covered functionality includes:
* Input validation for dict_data
* Raw layer registration and management
* NaN handling policies
* preserve
* mean
* zero
* min
* max
* Mesh trace generation for volumetric layers
* Slice layer creation and registration
* Basic rendering pipeline smoke tests
These tests validate the internal logic of the viewer without requiring a graphical interface.
3. Traitlets / ipywidgets deprecation fix
Resolved a DeprecationWarning triggered by passing an unsupported argument to ButtonStyle.
Previous pattern:
widgets.Button(
...,
style={"description_width": "60px"}
)
This caused the warning:
DeprecationWarning: Passing unrecognized arguments to
super(ButtonStyle).**init**(description_width='60px')
Resolution:
* Removed description_width from ButtonStyle usage
* When sizing was required, replaced with Layout-based sizing
Example fix:
widgets.Button(
...,
layout=widgets.Layout(width="60px")
)
This ensures compatibility with newer versions of:
traitlets
ipywidgets
4. Test robustness improvements
All tests were verified under strict deprecation enforcement:
pytest -W error::DeprecationWarning
This confirms the codebase no longer triggers traitlets deprecation warnings.
Dislocation tests:
pytest tests/test_dislocation.py
→ all tests passed
MultiVolumeViewer tests:
pytest tests/test_multiviewer_3d.py
→ all tests passed
Strict warning mode:
pytest -W error::DeprecationWarning
→ all tests passed
* Improves reliability and maintainability of the dislocation analysis code.
* Adds regression protection for interactive visualization logic.
* Ensures forward compatibility with modern traitlets and ipywidgets versions.
* Provides a foundation for future extension of visualization and analysis features.
Collaborator
Author
|
Done all features and test units. |
clatlan
reviewed
Mar 7, 2026
| self.title = title | ||
| self.layers_kwargs = layers_kwargs or {} | ||
|
|
||
| # 🔒 STRICT: MultiVolumeViewer only accepts dict |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reintroduce dislocation segmentation & MultiVolumeViewer workflow (rebased after revert)
This PR reintroduces the dislocation segmentation, analysis, and interactive 3D visualization workflow originally proposed in #105, which was merged and then reverted in #106 to allow for a proper review.
Since the revert, the feature branch has been:
dev,--reapply-cherry-picksto correctly handle the merge → revert history.The feature logic is preserved; no functional content was dropped during the rebase.
Main contributions
1) Dislocation segmentation and analysis
New module:
src/cdiutils/analysis/dislo.pyEnd-to-end workflow based on strain / phase-gradient features:
Includes plotting utilities for experimental vs theoretical phase profiles.
2) MultiVolumeViewer extensions
Extended interactive 3D visualization in
src/cdiutils/interactive/multiviewer_3d.pyKey features:
Public
plot="layers"entry point integrated viaplotter.py.3) Documentation and example workflow
Reproducible tutorial:
src/cdiutils/templates/dislocation_identification.ipynbdocs/tutorials/dislocation_identification.rstDemonstrates the full workflow from segmentation to theory comparison.
Notes
dev.Relation to previous PRs