Skip to main content

A Python Library for VISoR Image.

Reason this release was yanked:

missing simpleitk

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.post1.tar.gz (13.5 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.post1-py3-none-any.whl (14.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: visor_py-2025.8.1.post1.tar.gz
  • Upload date:
  • Size: 13.5 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.post1.tar.gz
Algorithm Hash digest
SHA256 69c54c500ab1eb6a1feda64ac04111bf30aa98c9f420e4d87e8cc8293be2881c
MD5 2c71c158e02404043efcfeb7115d2348
BLAKE2b-256 79826d36baae04c26061cfd0e6e7c8b774722bf75e931610c3b9b462e2f3ec60

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for visor_py-2025.8.1.post1-py3-none-any.whl
Algorithm Hash digest
SHA256 0626b1e569b6536074de85f5200abf88daf7b11e2b76835fb68c476bf3047105
MD5 ec634ab7380c7b563c7b7d2be2f13c15
BLAKE2b-256 a1a7de86691451fb0289a08bc4f5f80fdeb3a4d1618c89484c473ed835f9e3e9

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