Cellocity Tutorial¶
Step-by-step guide¶
This tutorial will show you how to:
- Load a file and create a
cellocity.channel.Channel
object. - Preprocess the
Channel
object. - Prepare for analysis by creating an
cellocity.analysis.Analyzer
object from theChannel
object. - Extract data by creating an
cellocity.analysis.Analysis
object.
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
Tifffile
does not load all its image data into RAM when created, however upon accessing data duringChannel
creation some of it will be cached, thus increasing its size somewhat.Channel
objects 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.