Migration Guide: FURY 0.12.0 → v2.0.0#
This document catalogs all user-level API changes introduced between FURY
0.12.x and the master branch (targeting FURY v2.0.0). Every
entry is grounded in the actual source code and the official release notes
spanning v2.0.0a1 through v2.0.0a7. No changes are documented here
unless verified against the live codebase.
Warning
FURY master is a ground-up rewrite. The rendering backend has
switched from VTK to PyGfx / WGPU. All VTK objects
(vtkActor, vtkPolyData, vtkMapper, etc.) have been removed
from the public API. Scripts that import or manipulate VTK objects
directly will break without migration.
1. Rendering Backend: VTK → PyGfx#
Summary (Ref: PR #993, PR #953, PR #946, PR #978)
All VTK imports have been removed from the library. FURY now exposes
PyGfx WorldObject sub-classes as its actor types.
# FURY 0.12.x (VTK-based)
import fury
actor = fury.actor.sphere(centers, colors=colors)
# Users often interacted directly with the underlying VTK object:
prop = actor.GetProperty() # VTK method - BREAKS in master!
prop.SetOpacity(0.5)
# FURY master (PyGfx-based)
import fury
actor = fury.actor.sphere(centers, colors=colors)
# Actors are now PyGfx-backed; use native properties instead:
actor.opacity = 0.5 # Native PyGfx property
Action: Remove all direct VTK method calls (like GetProperty(), GetMapper()) and import vtk calls from user scripts.
Interact with actors exclusively through the FURY public API or PyGfx
WorldObject properties.
2. Color API and Normalization#
Summary (Ref: PR #965, PR #1120, PR #1097)
All actor creation functions and
actor_from_primitiveaccept colors in [0, 1] float or [0, 255] int ranges. Values> 1.0are divided by255automatically viafury.colormap.normalize_colors.Hex strings (
"#FF0000") are accepted everywhere colors are expected.Bug fixed: opacity / alpha transparency was not applied in primitive actors when RGBA colors were passed — now resolved.
Bug fixed:
pointactor failed whencolors=Nonewas passed — now defaults to red.
# Both forms now accepted
fury.actor.sphere(centers, colors=(255, 0, 0)) # 0-255 — auto-normalised
fury.actor.sphere(centers, colors=(1.0, 0.0, 0.0)) # 0-1 preferred form
fury.actor.sphere(centers, colors="#FF0000") # hex accepted
Action: Prefer float [0, 1] colors in new code. Legacy integer
colors will still work but are normalized internally.
3. Actor Base Class and Per-Actor Transform API#
Summary (Ref: PR #1063)
A new fury.actor.core.Actor base class mixin exposes spatial
transforms directly on every actor object. There is no longer a need for
fury.transform module calls with an explicit actor argument (though
those still exist).
New methods on every actor:
# FURY 0.12.x (VTK-based transforms)
import fury
from fury.transform import euler_matrix
actor = fury.actor.sphere(centers)
# Spatial transforms required manual VTK matrix composition:
rot_matrix = euler_matrix(0.5, 0, 0) # radians, returns 4x4 ndarray
# No single-step convenience method existed on the actor object itself
# FURY master (Native transforms on every actor)
import fury
actor = fury.actor.sphere(centers)
# Every actor now inherits rotate/translate/scale/transform directly:
actor.rotate((30, 0, 0)) # degrees, XYZ Euler (not radians!)
actor.translate((1.0, 0.0, 0.0)) # world-space offset
actor.scale(2.0) # uniform; or (2, 1, 0.5) per-axis
actor.transform(matrix_4x4) # raw 4×4 numpy matrix
actor.opacity = 0.5 # native property
The fury.transform module functions rotate(), translate(),
and scale() remain available as free functions when an actor is not
involved or a transformation matrix is needed independently.
New actor-group helpers (in fury.actor.utils):
fury.actor.set_opacity(actor, 0.5)
fury.actor.set_group_opacity(group, 0.5)
fury.actor.set_group_visibility(group, True)
fury.actor.apply_affine_to_actor(actor, affine_4x4)
fury.actor.apply_affine_to_group(group, affine_4x4)
4. Actor Module Restructuring#
Summary (Ref: PR #1014)
The monolithic fury/actor.py has been refactored into a package with
the following sub-modules:
Sub-module |
Contents |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Action: Always import from fury.actor (the public __init__
facade). Avoid deep internal imports like
from fury.actor.curved import sphere.
5. actor_from_primitive API#
Summary (Ref: PR #962, PR #1125)
actor_from_primitive is the canonical way to create custom mesh actors.
Its signature is:
fury.actor.actor_from_primitive(
vertices,
faces,
centers,
*,
colors=(1, 0, 0),
scales=(1, 1, 1),
directions=(1, 0, 0),
opacity=None,
material="phong", # "phong" or "basic"
smooth=False,
enable_picking=True,
repeat_primitive=True,
have_tiled_verts=False,
wireframe=False,
wireframe_thickness=1.0,
)
Bug fixed: a redundant local.position offset was being applied when
len(centers) > 1, causing actors to be double-positioned. This is now
corrected. (Ref: #1124, PR #1125)
6. New and Rewritten Actors in master#
New actors — these have no 0.12.x counterpart:
Actor |
PR reference |
|---|---|
|
|
|
|
|
|
|
(slicer sub-module) |
|
New specialized impostor variant built on |
|
Renamed / rewritten actors — these existed in 0.12.x (VTK-based), were removed during the VTK-strip rewrite (Ref: PR #993, PR #953, PR #946, PR #978), and were reintroduced on PyGfx under the same or a renamed API. They are not new capabilities:
Actor |
0.12.x name / PR reference |
|---|---|
|
Same name in 0.12.x; GPU shader-based rewrite PR #1038 |
|
Renamed from 0.12.x’s |
|
Renamed from 0.12.x’s |
|
|
|
Same name in 0.12.x; rewritten on PyGfx PR #1053 |
|
Generalizes/replaces 0.12.x’s |
The actor.image actor now supports directional parameters.
(Ref: PR #1001)
7. Slicer API: get_slices / show_slices#
Summary (Ref: PR #996, PR #1068, PR #1075)
Slicer actors (volume_slicer, data_slicer) return a Group
object. Two helper utilities act on these groups:
slicer_group = fury.actor.volume_slicer(data)
positions = fury.actor.get_slices(slicer_group) # returns ndarray
fury.actor.show_slices(slicer_group, (x, y, z)) # moves slices
Blend-mode is now available on the slicer actor. (Ref: PR #1068) Slicer flickering in nearest interpolation mode is fixed. (Ref: PR #1075)
8. fury.window Module#
Summary (Ref: PR #955, PR #969, PR #1047, PR #1054, PR #1060)
The window module has been rewritten around PyGfx canvas types.
``Scene`` constructor signature (replaces old Scene):
# FURY 0.12.x (VTK-based scene)
import fury
scene = fury.window.Scene()
scene.background((0, 0, 0)) # method call (not a property)
scene.add(actor) # mapped to VTK AddActor() internally
# FURY master (PyGfx-based scene)
import fury
scene = fury.window.Scene(
background=(0, 0, 0, 1), # RGBA float [0,1] — now in constructor
skybox=None, # pygfx Texture cubemap
lights=None, # list of gfx Light objects
)
scene.add(actor)
scene.remove(actor)
scene.background = (0.1, 0.1, 0.1, 1.0) # now a settable property
scene.set_skybox(cube_map_texture)
scene.clear()
``ShowManager`` constructor (new / changed parameters):
show_m = fury.window.ShowManager(
scene=scene,
title="My App",
size=(800, 600),
window_type="default", # "default","glfw","qt","jupyter","offscreen"
pixel_ratio=1.25,
camera_light=True,
screen_config=None, # NEW: multi-screen layout config
enable_events=True,
qt_app=None, # NEW: existing QApplication instance
qt_parent=None, # NEW: existing QWidget parent
show_fps=False, # NEW: on-screen FPS overlay
max_fps=60, # NEW: cap render rate
imgui=False, # NEW: enable ImGui integration
imgui_draw_function=None,# NEW: ImGui per-frame draw callback
)
show_m.start() # blocking render loop
show_m.render() # non-blocking single-frame request
show_m.snapshot(fname=fname) # save PNG of current frame
show_m.close()
Callback system (Ref: PR #1047):
# Actual signature: register_callback(func, time, repeat, name, *args)
show_m.register_callback(my_func, 0.1, True, "my_cb")
show_m.cancel_callback("my_cb")
show_m.resize_callback(func)
show_m.cancel_resize_callback()
Multi-screen layout via screen_config:
# Two vertical columns: left has 1 row, right has 2 rows
show_m = fury.window.ShowManager(screen_config=[1, 2])
# Access individual screens:
left_scene = show_m.screens[0].scene
right_top = show_m.screens[1].scene
right_bottom = show_m.screens[2].scene
9. Drag Events (POINTER_DRAG)#
Summary (Ref: PR #1046)
A new EventType.POINTER_DRAG is dispatched during pointer-move events
while a pointer button is held down. This enables per-object drag handling:
# FURY 0.12.x (VTK observers)
import fury
show_m = fury.window.ShowManager(scene)
def vtk_on_drag(obj, event):
print("Dragging...")
# Bound to the entire interactor window, not specific objects:
show_m.iren.AddObserver("MouseMoveEvent", vtk_on_drag)
# FURY master (PyGfx event system)
import fury
from fury.lib import EventType
def on_drag(event):
print(event.x, event.y, event.target)
# Bound directly to the target actor:
actor.add_event_handler(on_drag, EventType.POINTER_DRAG)
10. ImGui Integration#
Summary (Ref: PR #1060)
ShowManager now supports ImGui for immediate-mode GUI panels rendered
on top of the 3D scene.
from imgui_bundle import imgui
def draw_gui():
imgui.begin("Debug")
imgui.text("Hello from ImGui")
imgui.end()
show_m = fury.window.ShowManager(imgui=True,
imgui_draw_function=draw_gui)
show_m.start()
# Or enable / change at runtime:
show_m.enable_imgui(imgui_draw_function=draw_gui)
show_m.set_imgui_render_callback(new_draw_func)
show_m.disable_imgui()
11. Axes / Orientation Gizmo#
Summary (Ref: PR #1141)
A navigable axes gizmo can be overlaid on any screen. Clicking an axis disk re-aligns the camera to that axis.
show_m.show_axes_gizmo(
screen=0,
size=30,
thickness=2,
position=None, # defaults to bottom-left (60, 60)
labels=["-X","+X","-Y","+Y","-Z","+Z"],
click_callback=my_callback, # receives axis direction ndarray
)
12. UI Sub-system#
Summary (Ref: PR #998, PR #999, PR #1043, PR #1052, PR #1056, PR #1118)
The UI system has been rebuilt from scratch on PyGfx. A few 0.12.x
components remain temporarily disabled (DrawPanel, FileMenu2D,
GridUI, SpinBox) while the migration is in progress. Legacy
backward-compatibility code was explicitly removed. (Ref: PR #1043)
Currently available UI components:
fury.ui.Rectangle2Dfury.ui.Disk2Dfury.ui.TextBlock2D(Ref: PR #1052)fury.ui.Panel2D,fury.ui.TabPanel2D,fury.ui.TabUI(Ref: PR #999)fury.ui.ImageContainer2Dfury.ui.TexturedButton2D,fury.ui.TextButton2D(Ref: PR #1056)fury.ui.LineSlider2D(Ref: PR #1118)fury.ui.LineDoubleSlider2Dfury.ui.RingSlider2Dfury.ui.RangeSliderfury.ui.TextBox2Dfury.ui.ComboBox2Dfury.ui.ListBox2D,fury.ui.ListBoxItem2Dfury.ui.Card2Dfury.ui.Checkbox,fury.ui.RadioButton(Ref: PR #1305)fury.ui.PlaybackPanel
Action: DrawPanel, FileMenu2D, GridUI, and SpinBox
remain unavailable pending their PyGfx port; if you relied on those,
consider an ImGui panel as a temporary substitute until they are ported.
All other 0.12.x UI components have a PyGfx-backed equivalent listed
above.
13. FPS Display and Control#
Summary (Ref: PR #1054)
Frame-rate control is now first-class:
show_m = fury.window.ShowManager(show_fps=True, max_fps=60)
current_fps = show_m.get_fps()
14. GPU Buffer Readback#
Summary (Ref: PR #1098)
Read GPU buffer contents back to a NumPy array:
data = fury.actor.read_buffer(buffer, sync_cpu=True)
# Returns np.ndarray (float32) matching the buffer's shape.
15. fury.io.save_image TIFF Compression Fix#
Summary (Ref: PR #1163, #1162)
In 0.12.x, passing compression_type to save_image() for TIFF
files was silently ignored. This is now corrected:
fury.io.save_image(array, "output.tiff", compression_type="lzw")
16. fury.colormap Changes#
Summary (Ref: PR #1103)
boys2rgb: a long-standing bug in thez4term was corrected (z4 = z2*z2, notz*z2). (Ref: #857)colormap_lookup_table(VTK-based) has been removed — it is commented out in the source.normalize_colorsis now a public API and handles hex strings, int/float RGB/RGBA, and tiling automatically.
17. fury.window.snapshot Function#
Summary (Ref: PR #1050)
The free function fury.window.snapshot wraps an offscreen
ShowManager and saves a PNG. Its signature:
array = fury.window.snapshot(
scene=scene, # or actors=list_of_actors
actors=None,
screen_config=None,
fname="output.png",
return_array=True,
)
18. Removed / Commented-Out APIs#
The following modules and symbols exist in 0.12.x but are not in the master public API (either removed or temporarily commented out pending v2.0.0 stabilization):
Removed / commented out |
Notes |
|---|---|
|
Optional; pending PyGfx port |
|
VTK interactor; removed with VTK |
|
Grid/horizontal/vertical layouts pending port |
|
Pending port |
|
VTK pick manager removed |
|
Streaming module pending port |
|
VTK LUT removed |
|
VTK polydata I/O removed |
|
VTK polydata I/O removed |
|
Pending UI port |
|
Pending UI port |
|
Pending UI port |
|
Pending UI port |
Dependency Changes#
Dependency |
Change |
|---|---|
|
Removed |
|
Added (≥ 0.16.0) |
|
Added (== 0.2.0) |
|
Optional (Jupyter) |
|
Optional |
|
Optional |