Usage Examples

Volumetric Data

Creating a Project

Programmatic creation of projects can be useful for rapid viewing of data after collection.

In this example, we’ll create a project file from a series of TIFFs.

from syglass import pyglass
import syglass as sy
import time

# create a project by specifing a path and the name of the project to be created. In this case, we'll call the project autoGenProject.
project = pyglass.CreateProject(pyglass.path("C:\\syGlassProjects"), "autoGenProject")

# create a DirectoryDescriptor to search a folder for TIFFs that match a pattern
dd = pyglass.DirectoryDescription()

# show the directoryDescriptor the first image of the set, and it will create a file list of matching slices
dd.InspectByReferenceFile("C:\\raw_data\\example0000.tif")

# create a DataProvider to the dataProvider the file list
dataProvider = pyglass.OpenTIFFs(dd.GetFileList(), False)

# indicate which channels to include; in this case, all channels from the file
includedChannels = pyglass.IntList(range(dataProvider.GetChannelsCount()))
dataProvider.SetIncludedChannels(includedChannels)

# spawn a ConversionDriver to convert the data
cd = pyglass.ConversionDriver()

# set the ConversionDriver input to the data provider
cd.SetInput(dataProvider)

# set the ConversionDriver output to the project previously created
cd.SetOutput(project)

# start the job!
cd.StartAsynchronous()

# report progress
while cd.GetPercentage() != 100:
        print(cd.GetPercentage())
        time.sleep(1)
print("Finished!")

Adding Mask Data to Projects

Segmentations or masks can be added to a project, provided that they are stored in image files with the same dimensions as the project.

In this example, we’ll add a segmentation layer to an existing project.

from syglass import pyglass
import syglass as sy
import time

# the mask data is stored in a syGlass project format with a special .syk extension
project = pyglass.CreateProject(pyglass.path("C:\\pathToExistingProject\\"), "projectName.syk", True)

# create a DirectoryDescriptor to search a folder for TIFFs that match a pattern
dd = pyglass.DirectoryDescription()

# show the directoryDescriptor the first image of the set, and it will create a file list of matching slices
dd.InspectByReferenceFile("C:\\maskData\\maskData_Z-00000.tiff")

# create a DataProvider to the dataProvider the file list
dataProvider = pyglass.OpenTIFFs(dd.GetFileList(), False)

# indicate which channels to include; in this case, all channels from the file
includedChannels = pyglass.IntList(range(dataProvider.GetChannelsCount()))
dataProvider.SetIncludedChannels(includedChannels)

# spawn a ConversionDriver to convert the data
cd = pyglass.ConversionDriver(True)

# set the ConversionDriver input to the data provider
cd.SetInput(dataProvider)

# set the ConversionDriver output to the project previously created
cd.SetOutput(project)

# start the job!
cd.StartAsynchronous()

# report progress
while cd.GetPercentage() != 100:
        print(cd.GetPercentage())
        time.sleep(1)
print("Finished!")

Traversing the Volume

Iterating over the entire volume is a common task. Most projects have multiple resolution levels, where higher levels are split into more and more “blocks”.

In this example, we’ll determine how many resolution levels are in our volume, select the highest one, and iterate over each of its blocks.

import syglass as sy

project = sy.get_project("C:/path/to/project_file.syg")

# Get a dictionary showing the number of blocks in each level
resolution_map = project.get_resolution_map()

# Calculate the index of the highest resolution level
max_resolution_level = len(resolution_map) - 1

# Determine the number of blocks in this level
block_count = resolution_map[max_resolution_level]

# Retrieve a block at each index
for i in range(block_count):

# Because this image volume is static, we'll always use timepoint 0
block = project.get_block(0, max_resolution_level, i)

# The offset between the volume's origin and the block's origin
print(block.offset)

# The volumetric data as a numpy array (z, y, x, channel)
print(block.data)

Retrieving Volumetric Data Around Points

You may, in some cases, be interested in analyzing the volumetric data around points. Typically these points come from annotations. For example, the image data surrounding some counting points could be used as input for a machine learning model, with the goal of automatically counting the remaining structures.

The function get_custom_block() can be used to get a block of data of any size, at any location. It is more flexible than get_block() and get_block_by_point(), which retrieve blocks of predetermined sizes and positions.

In this example, we retrieve a (100, 100, 100) voxel cube of the volume for each counting point. Each cube is centered around its corresponding annotation.

import syglass as sy
import numpy as np

project = sy.get_project("C:/path/to/project_file.syg")

# Determine the index of the highest resolution level
resolution = len(project.get_resolution_map()) - 1

# Define a side length and dimensions for our cube
side_length = 100
dimensions = np.full(3, side_length)

# Iterate over each point in each color series for the default experiment
counts = project.get_counting_points()
for color in counts:
        for point in counts[color]:

                # Calculate the offset to each cube based on point position
                offset = np.maximum(point.astype(int) - side_length / 2, np.zeros(3))

                # Retrieve a full-resolution cube from the volume
                block = project.get_custom_block(0, resolution, offset, dimensions)

Counting

Changing Colors of Counting Points

Once retrieved, the color and position of counting points can be changed. Here we change the color of all of the red counting points in an experiment to green.

import syglass as sy
import numpy as np

project = sy.get_project("C:/path/to/project_file.syg")

# Get counting points for the default experiment
counts = project.get_counting_points()

# Copy red points to the green series, clear the red points
counts["Green"] = np.append(counts["Green"], counts["Red"], axis = 0)
counts["Red"] = np.empty((0, 3))

# Save result as the new counting points for the default experiment
project.set_counting_points(counts)

Get and Set the Multi-tracking Points for a Project

import syglass as sy
import numpy as np
import pprint

# get the syGlass project
project = sy.get_project("C:/path/to/project_file.syg")

# load the multi tracking points into a dict
pts = project.get_multitracking_points()

# add two new points to the dict. One orange point and one violet point
pts['Orange'].append([np.array([30.02, 23.02, 19.02]), 235, 3]) # [[z,y,x], frame, series number]
pts['Violet'].append([np.array([45.02, 22.042, 5.03]), 600, 4]) # [[z,y,x], frame, series number]

# set the projects new and updated multi tracking points
project.set_multitracking_points(pts)

# retrieve the updated points
out = project.get_multitracking_points()

# display the dict with pretty print for organization
pp = pprint.PrettyPrinter(indent=4)
pp.pprint(out)

Tracings (SWCs)

Importing SWC Files

Import a series of SWC files for viewing inside of a syGlass project.

import syglass as sy
import glob

project = sy.get_project("E:/empty/empty.syg")
l = glob.glob("C:/swcs/*.swc")
outcome = project.import_swcs(l, "default")

Export and Analyze

Export tracings as SWC files, and analyze their morphology with the python module NeuroM.

import syglass as sy
import glob

# get the syGlass project
project = sy.get_project("E:/empty/empty.syg")

# save the tracings (will export each disconnected component as a separate SWC file)
project.save_tracings()

# find all the SWC files
matchingFiles = glob.glob("*.swc")
print(matchingFiles)
# output: ['output00000.swc', 'output00001.swc', 'output00002.swc']

# get first SWC and load into NeuroM
import neurom as nm
nrn = nm.load_neuron(matchingFiles[0])
nrnSegLen = nm.get('segment_lengths', nrn)
print(sum(nrnSegLen))
# total length: 111945.68

# calculate Sholl Analysis
nrnSholl = nm.get('sholl_frequency', nrn)
print(nrnSholl)
# sholl output: [  0.  8.  24.  33.  39.  52.  69.  68.  69.  79.  84.  78.  69.  78.  61. ... ]

Meshes (OBJ)

Import

Import a list of mesh files in the OBJ file format:

import syglass as sy
import glob

# get the syGlass project
project = sy.get_project("C:/syGlass Projects/thor/thorlabs.syg")
l = glob.glob("C:/meshes/*.obj")
project.import_meshes(l, "default")

ROIs

Importing and Exporting ROI Data

Export ROI data to numpy arrays and import an ROI to syGlass:

import numpy as np
import tifffile
import syglass as sy

# get the syGlass project
project = sy.get_project("C:/path/to/project_file.syg")

roi_index = 1

# get the raw ROI data block
roi_block = project.get_roi_data(roi_index)

# save the ROI data as a tiff file
tifffile.imsave("C:/path/to/roiraw_tiff_file.tiff", roi_block.data)

# get the mask block of the ROI
mask_block = project.get_mask(roi_index)

# save the mask data as a tiff file
tifffile.imsave("C:/path/to/mask_tiff_file.tiff", mask_block.data)

# import an ROI mask numpy array (z,y,x,channel count)
incoming_mask = np.ones(100,100,100, 1)
project.import_mask(incoming_mask, roi_index)