Skip to main content

A Python Library for VISoR Image.

Reason this release was yanked:

hot-fix in 2025.8.1.post1

Project description

visor-py

A Python Library for VISoR Image.

[!NOTE] Since v2025.5.1, we've switched to Zarr v3, are using zarrs to speed up I/O, and have replaced dask since it has not yet optimized its I/O for sharded Zarr.

Usage

Install Module

pip install visor-py

Import Module

import visor

Examples

VSR

  • Construct VSR
vsr_path = 'path/to/VISOR001.vsr'
vsr:visor.VSR = visor.VSR(vsr_path)
  • Check vsr info
vsr.info() # return JSON
  • List images
vsr.images() # return JSON
# Filter images by image_type
#   get image_types from vsr.info()
vsr.images(image_type='raw')
  • List transforms
vsr.transforms() # return JSON
# Filter transforms by recon_version
#   get recon_versions from vsr.info()
vsr.transforms(recon_version='xxx_20250525')
  • Create vsr if not exist
new_vsr_path = 'path/to/VISOR002.vsr'
vsr = visor.VSR(new_vsr_path, create=True)

Image

  • Construct Image
vsr_path = 'path/to/VISOR001.vsr'
# v_img is an instance of visor.Image
v_img:visor.Image = visor.Image(
    vsr_path,
    image_type='raw',
    image_name='slice_1_10x',
)
  • Load array of resolution 0
# arr is a zarr.Array with 5-dimensions: vs,ch,z,y,x
# see more about array format at https://visor-tech.github.io/visor-data-schema
arr:zarr.Array = v_img.load(resolution='0')
  • Convert to numpy.ndarray
# below code loads the entire zarr.Array into memory as a numpy.ndarray
# Note:
#   zarr.Array supports lazy loading and is recommended for large arrays.
np_arr:numpy.ndarray = arr[:]
  • Or slice zarr.Array like numpy
# sub_arr is a numpy.ndarray with 5-dimensions: vs=1,ch=1,z,y,x
# Note:
#   The zarrs.py module requires dimensions to be preserved.
#   This operation also loads array into memory.
sub_np_arr:numpy.ndarray = arr[:1,:1,:,:,:]

# To get index by visor_stack(vs) or channel(ch) labels
s1_idx = v_img.label_to_index('stack', 'stack_1') # 0
s1_arr = arr[s1_idx:s1_idx+1,:,:,:,:]

c488_idx = v_img.label_to_index('channel', '488') # 1
c488_arr = arr[:,c488_idx:c488_idx+1,:,:,:]
  • Convert to dask.array.Array
# below code converts a zarr.Array to a dask.array.Array
# but will not load data into memory just yet
# Note:
#   We like Dask but do not recommend it for disk writing with Zarr v3 (sharded Zarr) for now, because it relies on zarr.py, which has 10× slower disk writing performance compared to zarrs.py.
import dask.array as da
da_arr = da.from_array(arr, chunks=arr.chunks)
  • Create Image
v_img = visor.Image(
    vsr_path,
    image_type='raw',
    image_name='slice_2_10x',
    create=True,
)
# Metadata
#   follow https://visor-tech.github.io/visor-data-schema/
#   .vsr/visor_{image_type}_images/{image_name}.zarr/zarr.json['attributes']
attrs = {...}
v_img.update_attrs(attrs)
# Generate a random array
new_arr_shape      = (2,2,4,4,4)
new_arr_shard_size = (1,1,4,4,4)
new_arr_chunk_size = (1,1,2,2,2)
dtype='uint16'
new_arr = numpy.random.randint(0, 255, size=new_arr_shape, dtype=dtype)
# Save array to disk
v_img.save(
    new_arr,
    resolution='0',
    dtype=dtype,
    shape=new_arr_shape,
    shard_size=new_arr_shard_size,
    chunk_size=new_arr_chunk_size,
    compressors=BloscCodec(cname="zstd", clevel=5),
)
  • Modify Image
# Update partial data to an existing zarr array on disk
# where 
#   arr is a zarr.Array
#   new_arr is a numpy.ndarray
v_img = visor.Image(
    vsr_path,
    image_type='raw',
    image_name='slice_2_10x',
    create=True,
)
arr = v_img.load(resolution='0')
arr[:1,:,:,:,:] = new_arr[:1,:,:,:,:]

# Update metadata
attrs = v_img.attrs
attrs['visor']['visor_stacks'].append(
    {
        "index": 1,
        "label": "stack_2",
        "position": [20.2647, 63.2581]
    }
)
v_img.update_attrs(attrs)

ROI

  • Construct and Load ROI
# v_roi is an instance of visor.ROI
v_roi:visor.ROI = visor.ROI(
    image_path=v_img.path, # :str|Path
    resolution='0',        # :str|int
    ranges=(1,1,slice(2,3),slice(None),slice(None)),
    # :tuple[slice|int, ...], ch,st,z,y,x
)
# np_arr is a numpy.ndarray
np_arr:numpy.ndarray = v_roi.load()

Transform

  • Construct Transform
# v_xfm is an instance of visor.Transform
v_xfm = visor.Transform(
    vsr_path,
    recon_version='xxx_20250525',
    slice_name='slice_1_10x',
)
  • Load Transform
# Function load() could be polymorphic based on transform type (e.g. affine) and file format (e.g. tfm), for example
# raw_to_ortho is an affine transform stored as SimpleITK tfm format
#   below load transform for stack index 0 and channel index 0
#   where indices cooresponding to raw image
# t_raw_to_ortho is an instance of SimpleITK.Transform
t_raw_to_ortho = v_xfm.load(
    from_space='raw',
    to_space='ortho',
    params=[0,0],
)
  • Create Transform
v_xfm = visor.Transform(
    vsr_path,
    recon_version='xxx_20250525',
    slice_name='slice_1_10x',
    create=True,
)

raw_to_ortho_mat = [0, np.sin(45) * 1.03, 0,
                    0, 0, 1.03,
                    3.5, np.cos(45) * 1.03, 0]

offset_vec = [0,0,0]
stack_idx = 0
channel_idx = 0
params = [stack_idx] + [channel_idx] + raw_to_ortho_mat + offset_vec,
# another example could be
# params = [stack_idx] + [channel_idx] + model_params,

# Save transform to disk
# PATH: version/slice_/space_to_space/stack/channel/type.format
# see more about transform type / format at https://visor-tech.github.io/visor-data-schema
t_type = 'affine'
t_format = 'tfm'
v_xfm.save(
    from_space='raw',
    to_space='ortho',
    t_type=t_type,
    t_format=t_format,
    params=params,
)
v_xfm.update_meta(
    trans = {
        'name'  : f'{from_space}_to_{to_space}',
        'type'  : t_type,
        'format': t_format,
    }
)

References

VISoR Image Schema

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

visor_py-2025.8.1.tar.gz (13.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

visor_py-2025.8.1-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

File details

Details for the file visor_py-2025.8.1.tar.gz.

File metadata

  • Download URL: visor_py-2025.8.1.tar.gz
  • Upload date:
  • Size: 13.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.7

File hashes

Hashes for visor_py-2025.8.1.tar.gz
Algorithm Hash digest
SHA256 62eacb3314f1bb3d7f4de32ddaf05d0f213de955a4fbaf4611c91fba0fd7ef66
MD5 acd89f68d5272c15ba58d79bd42e8f61
BLAKE2b-256 67967e93bbaeafb9e619658861ecd1a816a36a8cba019161e57bf38637e4992c

See more details on using hashes here.

File details

Details for the file visor_py-2025.8.1-py3-none-any.whl.

File metadata

  • Download URL: visor_py-2025.8.1-py3-none-any.whl
  • Upload date:
  • Size: 14.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.7

File hashes

Hashes for visor_py-2025.8.1-py3-none-any.whl
Algorithm Hash digest
SHA256 613332cd44bf48d535e1ccb3a2da3f8964dd6678d2881b4e508427cd06944ce8
MD5 c1fa798d115453f0814931f31abab323
BLAKE2b-256 3db78a0694257e4c32b53c97a9f5dd3ed7ae395a5009914a8d41dd113ca59bc9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page