Supervisely
About SuperviselyEcosystemContact usSlack
  • 💻Supervisely Developer Portal
  • 🎉Getting Started
    • Installation
    • Basics of authentication
    • Intro to Python SDK
    • Environment variables
    • Supervisely annotation format
      • Project Structure
      • Project Meta: Classes, Tags, Settings
      • Objects
      • Tags
      • Image Annotation
      • Video Annotation
      • Point Clouds Annotation
      • Point Cloud Episode Annotation
      • Volumes Annotation
    • Python SDK tutorials
      • Images
        • Images
        • Image and object tags
        • Spatial labels on images
        • Keypoints (skeletons)
        • Multispectral images
        • Multiview images
        • Advanced: Optimized Import
        • Advanced: Export
      • Videos
        • Videos
        • Video and object tags
        • Spatial labels on videos
      • Point Clouds
        • Point Clouds (LiDAR)
        • Point Cloud Episodes and object tags
        • 3D point cloud object segmentation based on sensor fusion and 2D mask guidance
        • 3D segmentation masks projection on 2D photo context image
      • Volumes
        • Volumes (DICOM)
        • Spatial labels on volumes
      • Common
        • Iterate over a project
        • Iterate over a local project
        • Progress Bar tqdm
        • Cloning projects for development
    • Command Line Interface (CLI)
      • Enterprise CLI Tool
        • Instance administration
        • Workflow automation
      • Supervisely SDK CLI
    • Connect your computer
      • Linux
      • Windows WSL
      • Troubleshooting
  • 🔥App development
    • Basics
      • Create app from any py-script
      • Configuration file
        • config.json
        • Example 1. Headless
        • Example 2. App with GUI
        • v1 - Legacy
          • Example 1. v1 Modal Window
          • Example 2. v1 app with GUI
      • Add private app
      • Add public app
      • App Compatibility
    • Apps with GUI
      • Hello World!
      • App in the Image Labeling Tool
      • App in the Video Labeling Tool
      • In-browser app in the Labeling Tool
    • Custom import app
      • Overview
      • From template - simple
      • From scratch - simple
      • From scratch GUI - advanced
      • Finding directories with specific markers
    • Custom export app
      • Overview
      • From template - simple
      • From scratch - advanced
    • Neural Network integration
      • Overview
      • Serving App
        • Introduction
        • Instance segmentation
        • Object detection
        • Semantic segmentation
        • Pose estimation
        • Point tracking
        • Object tracking
        • Mask tracking
        • Image matting
        • How to customize model inference
        • Example: Custom model inference with probability maps
      • Serving App with GUI
        • Introduction
        • How to use default GUI template
        • Default GUI template customization
        • How to create custom user interface
      • Inference API
      • Training App
        • Overview
        • Tensorboard template
        • Object detection
      • High level scheme
      • Custom inference pipeline
      • Train and predict automation model pipeline
    • Advanced
      • Advanced debugging
      • How to make your own widget
      • Tutorial - App Engine v1
        • Chapter 1 Headless
          • Part 1 — Hello world! [From your Python script to Supervisely APP]
          • Part 2 — Errors handling [Catching all bugs]
          • Part 3 — Site Packages [Customize your app]
          • Part 4 — SDK Preview [Lemons counter app]
          • Part 5 — Integrate custom tracker into Videos Annotator tool [OpenCV Tracker]
        • Chapter 2 Modal Window
          • Part 1 — Modal window [What is it?]
          • Part 2 — States and Widgets [Customize modal window]
        • Chapter 3 UI
          • Part 1 — While True Script [It's all what you need]
          • Part 2 — UI Rendering [Simplest UI Application]
          • Part 3 — APP Handlers [Handle Events and Errors]
          • Part 4 — State and Data [Mutable Fields]
          • Part 5 — Styling your app [Customizing the UI]
        • Chapter 4 Additionals
          • Part 1 — Remote Developing with PyCharm [Docker SSH Server]
      • Custom Configuration
        • Fixing SSL Certificate Errors in Supervisely
        • Fixing 400 HTTP errors when using HTTP instead of HTTPS
      • Autostart
      • Coordinate System
      • MLOps Workflow integration
    • Widgets
      • Input
        • Input
        • InputNumber
        • InputTag
        • BindedInputNumber
        • DatePicker
        • DateTimePicker
        • ColorPicker
        • TimePicker
        • ClassesMapping
        • ClassesColorMapping
      • Controls
        • Button
        • Checkbox
        • RadioGroup
        • Switch
        • Slider
        • TrainValSplits
        • FileStorageUpload
        • Timeline
        • Pagination
      • Text Elements
        • Text
        • TextArea
        • Editor
        • Copy to Clipboard
        • Markdown
        • Tooltip
        • ElementTag
        • ElementTagsList
      • Media
        • Image
        • LabeledImage
        • GridGallery
        • Video
        • VideoPlayer
        • ImagePairSequence
        • Icons
        • ObjectClassView
        • ObjectClassesList
        • ImageSlider
        • Carousel
        • TagMetaView
        • TagMetasList
        • ImageAnnotationPreview
        • ClassesMappingPreview
        • ClassesListPreview
        • TagsListPreview
        • MembersListPreview
      • Selection
        • Select
        • SelectTeam
        • SelectWorkspace
        • SelectProject
        • SelectDataset
        • SelectItem
        • SelectTagMeta
        • SelectAppSession
        • SelectString
        • Transfer
        • DestinationProject
        • TeamFilesSelector
        • FileViewer
        • Dropdown
        • Cascader
        • ClassesListSelector
        • TagsListSelector
        • MembersListSelector
        • TreeSelect
        • SelectCudaDevice
      • Thumbnails
        • ProjectThumbnail
        • DatasetThumbnail
        • VideoThumbnail
        • FolderThumbnail
        • FileThumbnail
      • Status Elements
        • Progress
        • NotificationBox
        • DoneLabel
        • DialogMessage
        • TaskLogs
        • Badge
        • ModelInfo
        • Rate
        • CircleProgress
      • Layouts and Containers
        • Card
        • Container
        • Empty
        • Field
        • Flexbox
        • Grid
        • Menu
        • OneOf
        • Sidebar
        • Stepper
        • RadioTabs
        • Tabs
        • TabsDynamic
        • ReloadableArea
        • Collapse
        • Dialog
        • IFrame
      • Tables
        • Table
        • ClassicTable
        • RadioTable
        • ClassesTable
        • RandomSplitsTable
        • FastTable
      • Charts and Plots
        • LineChart
        • GridChart
        • HeatmapChart
        • ApexChart
        • ConfusionMatrix
        • LinePlot
        • GridPlot
        • ScatterChart
        • TreemapChart
        • PieChart
      • Compare Data
        • MatchDatasets
        • MatchTagMetas
        • MatchObjClasses
        • ClassBalance
        • CompareAnnotations
      • Widgets demos on github
  • 😎Advanced user guide
    • Objects binding
    • Automate with Python SDK & API
      • Start and stop app
      • User management
      • Labeling Jobs
  • 🖥️UI widgets
    • Element UI library
    • Supervisely UI widgets
    • Apexcharts - modern & interactive charts
    • Plotly graphing library
  • 📚API References
    • REST API Reference
    • Python SDK Reference
Powered by GitBook
On this page
  • Introduction
  • How to debug this tutorial
  • Import libraries
  • Init API client
  • Get variables from environment
  • Create new project and dataset
  • Upload volumes from local directory to Supervisely
  • Upload NRRD format volume
  • Upload volume as NumPy array
  • Upload DICOM series from local directory
  • Upload list of volumes from local directory
  • Get volume info from Supervisely
  • Get list of volumes infos from current dataset
  • Get single volume info by id
  • Get single volume info by name
  • Download volume from Supervisely to local directory
  • Get volume slices from local directory
  • Read NRRD file from local directory
  • Get slices from volume
  • Download slice from Supervisely
  • Save slice to local directory
  • Save slice as JPG

Was this helpful?

Edit on GitHub
  1. Getting Started
  2. Python SDK tutorials
  3. Volumes

Volumes (DICOM)

PreviousVolumesNextSpatial labels on volumes

Last updated 6 months ago

Was this helpful?

Introduction

In this tutorial we will focus on working with volumes using Supervisely SDK.

You will learn how to:

📗 Everything you need to reproduce : source code and demo data.

How to debug this tutorial

git clone https://github.com/supervisely-ecosystem/tutorial-volume.git

cd tutorial-volume

./create_venv.sh

Step 3. Open repository directory in Visual Studio Code.

code -r .

Step 4. Change workspace ID in local.env file by copying the ID from the context menu of the workspace.

WORKSPACE_ID=654 # ⬅️ change value

Step 6. Place downloaded files in the project structure as shown below:

tutorial-volume
├── .vscode
├── src
│     ├── upload
│     │     ├── MRHead_dicom        <-- sample dicom files
│     │     │   ├── 000000.dcm
│     │     │   ├── 000001.dcm
│     │     │   └── ...
│     │     └── nrrd
│     │         ├── CTACardio.nrrd  <-- sample NRRD
│     │         ├── CTChest.nrrd    <-- sample NRRD
│     │         └── MRHead.nrrd     <-- sample NRRD
│     └── main.py
├── .gitignore
├── create_venv.sh
├── local.env
├── README.md
└── requirements.txt

Step 7. Start debugging src/main.py.

Import libraries

import os

from dotenv import load_dotenv
from pprint import pprint
import supervisely as sly

Init API client

First, we load environment variables with credentials and init API for communicating with Supervisely Instance.

if sly.is_development():
    load_dotenv("local.env")
    load_dotenv(os.path.expanduser("~/supervisely.env"))

api = sly.Api()

Get variables from environment

workspace_id = sly.env.workspace_id()

Create new project and dataset

Create new project with ProjectType.VOLUMES type.

Source code:

project = api.project.create(
    workspace_id,
    "Volume tutorial",
    ProjectType.VOLUMES,
    change_name_if_conflict=True,
)

print(f"Project ID: {project.id}")

Output:

# Project ID: 16342

Create new dataset.

Source code:

dataset = api.dataset.create(project.id, "dataset_1")

print(f"Dataset ID: {dataset.id}")

Output:

# Dataset ID: 54698

Upload volumes from local directory to Supervisely

Upload NRRD format volume

Source code:

local_path = "src/upload/nrrd/MRHead.nrrd"

nrrd_info = api.volume.upload_nrrd_serie_path(
    dataset.id,
    "MRHead.nrrd",
    local_path,
)
print(f'"{nrrd_info.name}" volume uploaded to Supervisely with ID:{nrrd_info.id}')

Output:

# "NRRD_1.nrrd" volume uploaded to Supervisely with ID:18562981

Upload volume as NumPy array

Source code:

np_volume, meta = sly.volume.read_nrrd_serie_volume_np(local_path)

nrrd_info_np = api.volume.upload_np(
    dataset.id,
    "MRHead_np.nrrd",
    np_volume,
    meta,
)

print(f"Volume uploaded as NumPy array to Supervisely with ID:{nrrd_info_np.id}")

Output:

# Volume uploaded as NumPy array to Supervisely with ID:18562982

Upload DICOM series from local directory

Inspect you local directory and collect all dicom series.

Source code:

dicom_dir_name = "src/upload/MRHead_dicom/"

series_infos = sly.volume.inspect_dicom_series(root_dir=dicom_dir_name)

Upload DICOM series from local directory to Supervisely platform.

Source code:

for serie_id, files in series_infos.items():
    item_path = files[0]
    name = f"{sly.fs.get_file_name(path=item_path)}.nrrd"
    dicom_info = api.volume.upload_dicom_serie_paths(
        dataset_id=dataset.id,
        name=name,
        paths=files,
        anonymize=True,
    )
    print(f"DICOM volume has been uploaded to Supervisely with ID: {dicom_info.id}")

Set anonymize=True if you want to anonymize DICOM series and hide PatientID and PatientName fields.

Output:

# DICOM volume has been uploaded to Supervisely with ID: 18630608

Upload list of volumes from local directory

Source code:

local_dir_name = "src/upload/nrrd/"
all_nrrd_names = os.listdir(local_dir_name)
names = [f"1_{name}" for name in all_nrrd_names]
paths = [os.path.join(local_dir_name, name) for name in all_nrrd_names]

volume_infos = api.volume.upload_nrrd_series_paths(dataset.id, names, paths)
print(f"All volumes has been uploaded with IDs: {[x.id for x in volume_infos]}")

Output:

# All volumes has been uploaded with IDs: [18630605, 18630606, 18630607]

Get volume info from Supervisely

Get list of volumes infos from current dataset

Source code:

volume_infos = api.volume.get_list(dataset.id)

volumes_ids = [x.id for x in volume_infos]

print(f"List of volumes`s IDs: {volumes_ids}")

Output:

# List of volumes`s IDs: [18562986, 18562987, 18562988, 18562989, 18562990]

Get single volume info by id

Source code:

volume_id = volume_infos[0].id

volume_info_by_id = api.volume.get_info_by_id(id=volume_id)

print(f"Volume name:", volume_info_by_id.name)

Output:

# Volume name: NRRD_1.nrrd

Get single volume info by name

Source code:

volume_info_by_name = api.volume.get_info_by_name(dataset.id, name="MRHead.nrrd")

print(f"Volume name:", volume_info_by_name.name)

Output:

# Volume name: NRRD_1.nrrd

Download volume from Supervisely to local directory

Source code:

volume_id = volume_infos[0].id
volume_info = api.volume.get_info_by_id(id=volume_id)

download_dir_name = "src/download/"
path = os.path.join(download_dir_name, volume_info.name)
if os.path.exists(path):
    os.remove(path)

api.volume.download_path(volume_info.id, path)

if os.path.exists(path):
    print(f"Volume (ID {volume_info.id}) successfully downloaded.")

Output:

# Volume (ID 18630603) successfully downloaded.

Get volume slices from local directory

Read NRRD file from local directory

Read NRRD file from local directory and get meta and volume (as NumPy array).

Source code:

# read NRRD file from local directory
nrrd_path = os.path.join(download_dir_name, "MRHead.nrrd")
volume_np, meta = sly.volume.read_nrrd_serie_volume_np(nrrd_path)

pprint(meta)

Output:

# {
#     'ACS': 'RAS',
#     'channelsCount': 1,
#     'dimensionsIJK': {'x': 130, 'y': 256, 'z': 256},
#     'directions': (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0),
#     'intensity': {'max': 279.0, 'min': 0.0},
#     'origin': (-86.64489746093749, -121.07139587402344, -138.21430206298828),
#     'rescaleIntercept': 0,
#     'rescaleSlope': 1,
#     'spacing': (1.2999954223632812, 1.0, 1.0),
#     'windowCenter': 139.5,
#     'windowWidth': 279.0
# }

Get slices from volume

Get slices from current volume. In this example we will get sagittal slices.

Source code:

slices = {}

dimension = volume_np.shape[0]  # change index: 0 - sagittal, 1 - coronal, 2 - axial
for batch in sly.batched(list(range(dimension))):
    for i in batch:
        if i >= dimension:
            continue
        pixel_data = volume_np[i, :, :]  # sagittal
        # pixel_data = volume_np[:, i, :]  # coronal
        # pixel_data = volume_np[:, :, i]  # axial
        slices[i] = pixel_data

print(f"{len(slices.keys())} slices has been received from current volume.")

Output:

# 130 slices has been received from current volume.

Download slice from Supervisely

Download slice as NumPy from Supervisely by ID

Source code:

slice_index = 60

image_np = api.volume.download_slice_np(
    volume_id=volume_id,
    slice_index=slice_index,
    plane=sly.Plane.SAGITTAL,
)

print(f"Image downloaded as NumPy array. Image shape: {image_np.shape}")

Output:

# Image downloaded as NumPy array. Image shape: (256, 256, 3)

Save slice to local directory

✅ There is a built-in function supervisely.image.write which reads file extension from path and saves image (slice) with the desired format in local directory.

Example:

import supervisely as sly

sly.image.write("folder/slice.nrrd", image_np) # save as NRRD
sly.image.write("folder/slice.jpg", image_np) # save as JPG

Save slice as NRRD

Recommended way to save slice as NRRD file to preserve image quality (pixel depth)

Source code:

# save slice as NRRD file
save_dir = "src/download/"
nrrd_slice_path = os.path.join(save_dir, 'slice.nrrd')

sly.image.write(nrrd_slice_path, image_np)

Save slice as JPG

Source code:

# save slice as jpg
save_dir = "src/download/"
image_slice_path = os.path.join(save_dir, 'slice.jpg')

sly.image.write(jpg_slice_path, image_np)

Note:

save_dir = "src/download/"
slice_path = os.path.join(save_dir, 'slice.nrrd')

nrrd.write(slice_path, image_np, index_order='C')

Step 1. Prepare ~/supervisely.env file with credentials.

Step 2. Clone with source code and demo data and create .

Step 5. Download sample

In this tutorial, you will need an workspace ID that you can get from environment variables.

Now you can explore and label it in :

In case you save slice using nrrd library, it is to use C-order indexing.

🎉
Learn more here.
repository
Virtual Environment
volumes
Supervisely labeling tool
recommended
this tutorial is on GitHub
upload volume (NRRD) from local directory to Supervisely dataset
upload volume to Supervisely as NumPy matrix
upload DICOM series from local directory
upload list of volumes from local directory to Supervisely
get list of volume infos
get single volume info by id
get single volume info by name
download volume from Supervisely to local directory
read NRRD files from local directory
get volume slices from local directory
download slice as NumPy from Supervisely by ID
save slice as NRRD or JPG file
Learn more here