Cellocity Tutorial¶
Step-by-step guide¶
This tutorial will show you how to:
- Load a file and create a
cellocity.channel.Channelobject. - Preprocess the
Channelobject. - Prepare for analysis by creating an
cellocity.analysis.Analyzerobject from theChannelobject. - Extract data by creating an
cellocity.analysis.Analysisobject.
Load a file and create a Channel object¶
from cellocity.channel import Channel import tifffile my_filename = "2_channel_micromanager_timelapse.ome.tif" chToAnalyze = 0 # 0-based indexing of channels #safely load file with tifffile.TiffFile(my_filename, multifile=False) as tif: #strips ome.tif from filename label = my_filename.split(".")[0] channelName = label + "_Ch" + str(chToAnalyze + 1) channel_0 = Channel(chToAnalyze, tif, name=channelName)Warning
Cellocity assumes that it can hold all Channel data in RAM.
A
Tifffiledoes not load all its image data into RAM when created, however upon accessing data duringChannelcreation some of it will be cached, thus increasing its size somewhat.Channelobjects store all image data in RAM and can get quite hefty for long time lapses.
Preprocess Channel object¶
First, we will check if the frame interval stated in the metadata is in agreement with
the time stamps of the individual frames in the channel (within 1%). This is done with the
Channel.doFrameIntervalSanityCheck(maxDiff=0.01) method. If there is an discrepancy between
the actual frame intervals and the intended, if can be fixed by calling the
Channel.fixFrameInterval() method, which overwrites the intended frame interval with the actual
average frame interval.
if not channel_0.doFrameIntervalSanityCheck(): channel_0.fixFrameInterval()Note
Checking and fixing the frame interval is currently only possible on MicroManager ome.tif files. Individual frame timestamps are lost when saving .tif files in ImageJ.
Channel objects have convenient preprocessing methods, such as trimming frames
and temporal median filtering. Let’s start by trimming our newly created channel to
frames 10-60, meaning we discard frames 0-9 and from frame 60 onward to the end.
#Trim channel to include frame 10-59 channel_0.trim(10,60)
Now let’s employ a temporal median filter, meaning we do a median filtering over time.
This will have the effect of filtering out fast moving free-floating debris, thus
greatly reducing the noise in the final analysis. This is done by creating a child cellocity.channel.MedianChannel
object. Median filtering can be done with a gliding window (default), or by binning the frames.
MedianChannel takes care of properly recalculating frame intervals in either case. The default
frame sampling interval is 3.
from cellocity.channel import MedianChannel
gliding_median_channel_0 = MedianChannel(channel_0)
binned_4frame_median_channel_0 = MedianChannel(channel_0,
doGlidingProjection=False,
frameSamplingInterval=4)
MedianChannel objects can also be created by calling the .getTemporalMedianChannel() method on a Channel.
The following code gives identical results to the above example:
arguments ={doGlidingProjection = True,
frameSamplingInterval=3,
startFrame=0,
stopFrame=None
}
gliding_median_channel_0 = channel_0.getTemporalMedianChannel(arguments)
arguments = {doGlidingProjection = False,
frameSamplingInterval=4,
startFrame=0,
stopFrame=None}
binned_4frame_median_channel_0 = channel_0.getTemporalMedianChannel(arguments)
Prepare for Analysis by creating an Analyzer object¶
Now let’s perform an optical flow analysis of our preprocessed Channel. This is done
by instantiating an Analyzer object with a Channel as argument. In this case we
will perform an optical flow analysis using the Farenback flow analysis from OpenCV. This
is handled by a FarenbackAnalyzer, which is a specific subtype FlowAnalyzer of Analyzer.
FarenbackAnalyzer takes two arguments, one Channel and one unit. unit is a string
indicating the unit that we want the output to be in. Currently only “um/s”, “um/min”, and “um/h” are
implemented. Cellocity handles all unit conversions automatically in the background.
from cellocity.analysis import FarenbackAnalyzer
fb_analyzer_ch0 = FarenbackAnalyzer(channel = gliding_median_channel_0, unit = "um/h")
fb_analyzer_ch0.doFarenbackFlow()
Note
Quite a lot of effort has gone in to selecting sensible default parameters that work well for microscopy data for the FlowAnalyzer objects FarenbackAnalyzer and OpenPivAnalyzer, as is demonstrated in the Validation of the Cellocity Software section.
Extract data by creating an Analysis object.¶
Great, now we have calculated the optical flow of channel_0 with the default parameters. Now its
time to extract data. This is done by creating Analysis objects. In our case we want to analyse
the flow speeds of our channel. To do this we can utilize the FlowSpeedAnalysis class, which works on
FlowAnalyzer objects.
from cellocity.analysis import FlowSpeedAnalysis
speed_analysis_ch0 = FlowSpeedAnalysis(fb_analyzer_ch0)
speed_analysis_ch0.calculateSpeeds()
speed_analysis_ch0.calculateAverageSpeeds()
When speeds have been calculated the results can be stored either as a 32-bit tif, where pixel values represent flow speeds in the location of the pixel, or the average speed of each frame can be saved as a .csv file for further processing.
from pathlib import Path
savepath = Path("path/to/save/folder")
speed_analysis_ch0.saveArrayAsTif(outdir=savepath):
speed_analysis_ch0.saveCSV(outdir=savepath, fname="mySpeeds.csv", tunit="s")
That’s it! If you want more detailed information, please check the The Cellocity API Reference , the Validation of the Cellocity Software contains more examples of different Analysis objects in use, and the Developer Information contains information on how to submit a bug report.