22
33## Installation
44
5+ ### Full Installation (with napari GUI plugin)
6+
57``` bash
68pip install napari-fast4dreg
79```
810
11+ ### API-Only Installation (lightweight, no GUI dependencies)
12+
13+ ``` bash
14+ pip install napari-fast4dreg[api-only]
15+ ```
16+
17+ Use the API-only installation if you only need programmatic access and want to avoid installing napari and its dependencies.
18+
919## Three Ways to Use Fast4DReg
1020
1121### 1. napari GUI (Interactive)
@@ -46,21 +56,42 @@ xy_drift = result['xy_drift']
4656``` python
4757from napari_fast4dreg import register_image_from_file
4858
59+ # TIFF file (ImageJ format)
4960result = register_image_from_file(
5061 " my_image.tif" ,
5162 axis_order = " TZCYX" , # ImageJ format
5263 ref_channel = 1 ,
5364 output_dir = " ./results"
5465)
66+
67+ # NumPy binary file
68+ result = register_image_from_file(
69+ " my_image.npy" ,
70+ axis_order = " CZYX" ,
71+ ref_channel = 0 ,
72+ output_dir = " ./results"
73+ )
74+
75+ # Zarr file (chunked)
76+ result = register_image_from_file(
77+ " my_image.zarr" ,
78+ axis_order = " CTZYX" ,
79+ ref_channel = 0 ,
80+ output_dir = " ./results"
81+ )
82+
83+ # Output is always same shape as input shape
84+ registered = result[' registered_image' ]
85+ xy_drift = result[' xy_drift' ]
5586```
5687
5788## Common Parameters
5889
5990| Parameter | Type | Default | Description |
6091| -----------| ------| ---------| -------------|
6192| ` image ` | ndarray/dask | required | Image in specified axis order |
62- | ` axis_order ` | str | "CTZYX" | Axis order: CTZYX, TZYX, ZYX, ZCYX, etc . Missing axes auto-added |
63- | ` ref_channel ` | int/str | 0 | Reference channel(s): int (e.g., ` 0 ` ), comma-separated (e.g., ` "0,1" ` ) |
93+ | ` axis_order ` | str | "CTZYX" | Axis order: CTZYX, TZCYX, TZYX, ZYX, CZYX, CYX, TYX, or YX . Missing axes auto-added |
94+ | ` ref_channel ` | int/str/list/tuple | 0 | Reference channel(s): int (e.g., ` 0 ` ), list (e.g., ` [0,1,5] ` ), comma-separated string (e.g., ` "0,1,5" ` ), space-separated (e.g., ` "0 1 5 "` ) |
6495| ` output_dir ` | str/Path | "./fast4dreg_output" | Output directory |
6596| ` correct_xy ` | bool | True | Apply XY drift correction |
6697| ` correct_z ` | bool | True | Apply Z drift correction |
@@ -78,16 +109,37 @@ result = register_image_from_file(
78109Dictionary containing:
79110``` python
80111{
81- ' registered_image' : np.ndarray, # Registered image (same axis order as input)
82- ' xy_drift' : np.ndarray, # XY drift values
83- ' z_drift' : np.ndarray, # Z drift values
112+ ' registered_image' : dask.array.Array, # Registered image (dask array, lazy-loaded)
113+ # For register_image: same axis order as input
114+ # For register_image_from_file: always CTZYX
115+ ' xy_drift' : np.ndarray, # XY drift values (T, 2)
116+ ' z_drift' : np.ndarray, # Z drift values (T, 2)
84117 ' rotation_xy' : np.ndarray, # XY rotation angles
85118 ' rotation_zx' : np.ndarray, # ZX rotation angles
86119 ' rotation_zy' : np.ndarray, # ZY rotation angles
87120 ' output_path' : Path # Path to saved Zarr
88121}
89122```
90123
124+ ### Working with the Registered Image
125+
126+ The ` registered_image ` is a ** dask array** , meaning it's lazy-loaded from Zarr storage:
127+
128+ ``` python
129+ result = register_image(image, ... }
130+ registered = result[' registered_image' ] # dask.array, not in RAM
131+
132+ # Convert to numpy if needed (loads into memory, make sure it fits)
133+ registered_np = registered.compute()
134+
135+ # Or work with it directly for out-of-memory processing
136+ mip_projection = registered.max(axis = 2 ).compute()
137+
138+ # Or save chunks back to disk
139+ import dask.array as da
140+ da.to_zarr(registered, " path/to/output.zarr" )
141+ ```
142+
91143# # Supported Axis Orders
92144
93145The `axis_order` parameter accepts flexible axis specifications:
@@ -100,8 +152,8 @@ The `axis_order` parameter accepts flexible axis specifications:
100152| `CZYX ` | (C, Z, Y, X) | 4D , single timepoint |
101153| `ZYX ` | (Z, Y, X) | 3D single timepoint + channel |
102154| `TYX ` | (T, Y, X) | Time series 2D |
103- | ` CYX ` | (C, Y, X) | Multi-channel 2D image |
104- | ` YX ` | (Y, X) | Single 2D image |
155+ | `CYX ` | (C, Y, X) | Multi- channel 2D image (included for pipeline savety) |
156+ | `YX ` | (Y, X) | Single 2D image (included for pipeline savety) |
105157
106158Missing dimensions are automatically inserted as singletons during processing and removed in the output.
107159
@@ -175,16 +227,43 @@ result = register_image(
175227# ## Multi-Channel Reference
176228
177229```python
178- # Use multiple channels - comma or space-separated
230+ # Multiple ways to specify multiple reference channels:
231+
232+ # Option 1: List of integers
233+ result = register_image(
234+ image,
235+ ref_channel = [0 , 3 , 5 ], # List of channel indices
236+ normalize_channels = True ,
237+ projection_type = ' max'
238+ )
239+
240+ # Option 2: Tuple of integers
179241result = register_image(
180242 image,
181- ref_channel = " 0,3,5" , # Use channels 0, 3, and 5 (comma-separated)
182- # OR: ref_channel="0 3 5" # Space-separated also works
243+ ref_channel = (0 , 3 , 5 ), # Tuple - same as list
244+ normalize_channels = True ,
245+ projection_type = ' max'
246+ )
247+
248+ # Option 3: Comma-separated string
249+ result = register_image(
250+ image,
251+ ref_channel = " 0,3,5" , # Comma-separated string
252+ normalize_channels = True ,
253+ projection_type = ' max'
254+ )
255+
256+ # Option 4: Space-separated string
257+ result = register_image(
258+ image,
259+ ref_channel = " 0 3 5" , # Space-separated string
183260 normalize_channels = True ,
184261 projection_type = ' max'
185262)
186263```
187264
265+ All formats above produce the same result: channels 0 , 3 , and 5 are summed together for drift detection.
266+
188267# ## Integration into Workflow
189268
190269```python
@@ -216,12 +295,32 @@ print(f"Maximum drift: {max_drift:.2f} pixels")
216295```python
217296from napari_fast4dreg import register_image_from_file
218297
298+ # ImageJ format (TZCYX) - Output will be TZCYX
219299result = register_image_from_file(
220300 " timelapse.tif" ,
221- axis_order = " TZCYX" , # ImageJ: Time, Z, Channel, Y, X
301+ axis_order = " TZCYX" , # Time, Z, Channel, Y, X (default for TIFF)
222302 ref_channel = 1 ,
223303 output_dir = " ./results"
224304)
305+ registered = result[' registered_image' ] # Shape: (T, Z, C, Y, X)
306+
307+ # Single channel TIFF (TZYX) - Output will be TZYX
308+ result = register_image_from_file(
309+ " timelapse.tif" ,
310+ axis_order = " TZYX" , # Time, Z, Y, X
311+ ref_channel = 0 ,
312+ output_dir = " ./results"
313+ )
314+ registered = result[' registered_image' ] # Shape: (T, Z, Y, X)
315+
316+ # NumPy array file (.npy)
317+ result = register_image_from_file(
318+ " image_stack.npy" ,
319+ axis_order = " CZYX" , # Channels, Z, Y, X
320+ ref_channel = " 0,1" ,
321+ output_dir = " ./results"
322+ )
323+ registered = result[' registered_image' ] # Shape: (C, Z, Y, X)
225324```
226325
227326# ## Batch Processing
@@ -249,39 +348,75 @@ for tif_file in input_dir.glob("*.tif"):
249348
250349# # Axis Order Formats
251350
252- Fast4DReg expects ** CTZYX** format (Channels, Time, Z, Y, X) .
351+ Fast4DReg processes images in ** CTZYX ** format internally, but input and output formats are flexible .
253352
254- Common conversions:
255- - ** ImageJ/Fiji** (` TZCYX ` ): Use ` axis_order="TZCYX" ` in ` register_image_from_file() `
256- - ** Single channel** (` TZYX ` ): Use ` axis_order="TZYX" ` - channel dimension is added automatically
257- - ** Already CTZYX** : Use ` axis_order="CTZYX" ` or pass directly to ` register_image() `
353+ # ## Input/Output Axis Orders
354+ - ** register_image()** : Input in format X, output in format X (same as input )
355+ - ** register_image_from_file()** : Input in format X, output in format X (same as input file )
356+
357+ # ## Supported Formats
358+ - `CTZYX ` - Standard 5D (Channels, Time, Z, Y, X)
359+ - `TZCYX ` - ImageJ/ Fiji format (Time, Z, Channels, Y, X) [DEFAULT for register_image_from_file]
360+ - `TZYX ` - Single channel time series (Time, Z, Y, X)
361+ - `CZYX ` - Multi- channel single timepoint (Channels, Z, Y, X)
362+ - `ZYX ` - Single timepoint single channel volume (Z, Y, X)
363+ - `CYX ` - Multi- channel 2D image (Channels, Y, X)
364+ - `TYX ` - 2D time series (Time, Y, X)
365+ - `YX ` - Single 2D image
366+
367+ Missing dimensions (C, T, Z) are automatically inserted as singletons during processing.
368+
369+ # ## Example: Axis Order Preservation
258370
259- Manual conversion:
260371```python
372+ from napari_fast4dreg import register_image, register_image_from_file
261373import numpy as np
262374
263- # TZCYX → CTZYX
264- image_ctzyx = np.moveaxis(image_tzcyx, [0 , 1 , 2 ], [1 , 2 , 0 ])
375+ # register_image preserves input format
376+ image_tzyx = np.load(" data.npy" ) # Shape: (T, Z, Y, X)
377+ result = register_image(image_tzyx, axis_order = " TZYX" )
378+ output = result[' registered_image' ] # Still TZYX: (T, Z, Y, X)
379+
380+ # register_image_from_file preserves file format
381+ # File is TZCYX, output is TZCYX
382+ result = register_image_from_file(" data.tif" , axis_order = " TZCYX" )
383+ output = result[' registered_image' ] # TZCYX: (T, Z, C, Y, X)
265384
266- # TZYX → CTZYX (add channel dim)
267- image_ctzyx = image_tzyx[:, np.newaxis, ... ]
385+ # Custom format also preserved
386+ result = register_image_from_file(" data.npy" , axis_order = " CZYX" )
387+ output = result[' registered_image' ] # CZYX: (C, Z, Y, X)
268388```
269389
270390# # Output Files
271391
272392When registration completes, you' ll find:
273- - ` registered.zarr/ ` - Final registered image (Zarr format)
393+ - `registered.zarr/ ` - Final registered image (Zarr format , dask- accessible)
394+ - Format matches your input ' s axis_order
395+ - For TZCYX input : output is TZCYX
396+ - For CZYX input : output is CZYX
397+ - etc.
274398- `tmp_data_* .zarr/ ` - Temporary stores (deleted unless `keep_temp_files=True ` )
275399
276- Load the output in napari or Python :
400+ Load and work with the output :
277401```python
278- # In napari
279- viewer.open(" ./results/registered.zarr" )
402+ # From the result dictionary
403+ result = register_image_from_file(" data.tif" , axis_order = " TZCYX" )
404+ registered = result[' registered_image' ] # dask.array in TZCYX format
280405
281- # In Python
406+ # Or load manually from disk
282407import dask.array as da
283- import zarr
284- registered = da.from_zarr(" ./results/registered.zarr" )
408+ registered = da.from_zarr(" ./results/registered.zarr" ) # Format matches input
409+
410+ # Convert to numpy for analysis
411+ registered_np = registered.compute()
412+
413+ # Or process chunks without loading all into RAM
414+ mean = registered.mean().compute()
415+ max_val = registered.max().compute()
416+
417+ # View in napari (napari accepts dask arrays directly)
418+ import napari
419+ viewer = napari.view_image(registered)
285420```
286421
287422# # Tips
@@ -296,13 +431,13 @@ registered = da.from_zarr("./results/registered.zarr")
296431
297432# # GPU Acceleration (Optional)
298433
299- Fast4DReg ** automatically detects and enables GPU acceleration** when available using [ pyclesperanto] ( https://github.com/clEsperanto/pyclesperanto_prototype ) for all transformation operations (translations and rotations).
434+ Fast4DReg ** automatically detects and enables GPU acceleration** when available using [pyclesperanto](https:// github.com/ clEsperanto/ pyclesperanto ) for all transformation operations (translations and rotations).
300435
301436# ## Installation
302437
303438```bash
304439# Install pyclesperanto for GPU support
305- pip install pyclesperanto-prototype
440+ pip install pyclesperanto
306441```
307442
308443# ## Automatic Detection
0 commit comments