Skip to content

data analysis

Jian Tay edited this page Jun 15, 2021 · 3 revisions

Analyzing tracked data

This document will walk you through an analyzing data of growing bacteria cells.

[[TOC]]

Prerequisites

  • Completed the cell tracking example
  • Have a MAT-file named demodata.mat containing a TrackArray object named trackdata

Overview

After reviewing this document, you will be able to:

  1. Load saved track data
  2. Get data of a specific cell
  3. Plot cell length vs time
  4. Plot a lineage tree of the cells

Glossary

  • Tracks represent the data connected to individual objects across every frame of the timelapse video.
  • Track ID is a unique identifier (number) that is assigned to a track when it is created. For most functions, this is the identifier that should be used to refer to a track.
  • A TrackArray object is a concrete realization (instant) of the TrackArray class. For example:
    TA = TrackArray;
    TA will be a TrackArray object.
  • NaN - Not-A-Number is a specific data value that MATLAB recognizes as not being a number. This value will affect functions in different ways.

Step-by-step

Loading previously saved data

  1. Let's start by clearing variables in the workspace
    >> clearvars
  2. Load the MAT-file by double-clicking in the Current Folder panel or by typing in the Command Window
    >> load('demodata.mat')

The TrackArray object

We can get an overview of the trackdata variable by displaying it in the Command Window

>> trackdata
trackdata = 
  TrackArray with properties:

          Tracks: [1×7 struct]
    FileMetadata: []
       CreatedOn: '11-Apr-2020 12:20:43'
       NumTracks: 7
      Datafields: {5×1 cell}

In this example, the object has the following properties:

  • Tracks - a struct containing time series data (more this later).
  • FileMetadata - a struct containing file metadata. We did not set this in the previous example so it is empty here.
  • CreatedOn - a string showing the date and time the object was created.
  • NumTracks - number of tracks in the array.
  • Datafields - a cell string array with the names of the data fields in the tracks.

To see what data was tracked we can look at the Datafields property:

>> trackdata.Datafields
ans =
  3×1 cell array
    {'Centroid'       }
    {'MajorAxisLength'}
    {'PixelIdxList'   }

Working with tracks

You can access a track using the method getTrack(obj, trackID), where obj is the variable containing the TrackArray object and trackID is the unique identifier assigned to the track.

If you followed along with the cell tracking example, the cell IDs are the numbers displayed on the resulting GIF:

Tracked cells

As an example, to get track 1:

>> track1 = getTrack(trackdata, 1)
track1 = 
  struct with fields:

                 ID: 1
           MotherID: NaN
         DaughterID: [2 3]
             Frames: [1 2 3 4 5 6]
           Centroid: [6×2 double]
    MajorAxisLength: [6×1 double]
       PixelIdxList: {1×6 cell}

Retrieving track data

Note that the variable track1 is a normal MATLAB struct, which is a built-in data structure.

For example, to access a property such as the MajorAxisLength (cell length):

>> track1.MajorAxisLength
ans =
   43.3994
   45.8512
   49.4658
   53.4396
   58.1812
   63.1483

Note that the data fields will be concatenated into a matrix if they share the same number of elements. In this case, each row contains data belonging to a different frame.

To access data belonging to a specific element in the matrix, you can use standard indexing notation:

>> track1.MajorAxisLength(3)
ans =
   49.4658

If the data for each frame is not a matrix of the same size, the data is stored as a cell instead. In the example above, the PixelIdxList contains the linear indices of the pixels in the mask of each cell in each frame. Since the cell is constantly changing shape, the number of elements in the index list changes from frame to frame.

To access a specific cell, use the curly braces when indexing:

>> track1.PixelIdxList{3}

To learn more about indexing in MATLAB:

Track data structure

A track will always have the following fields:

  • ID: Unique number that identifies the track

  • MotherID: ID of mother track

  • DaughterID: ID of daughter tracks

  • Frames: Vector containing frame number that correspond to the data

    For example:

    >> track1.Frames
    ans =
      1     2     3     4     5     6

    shows that track 1 existed between frames 1 and 6 of the movie.

Plotting time series data

You can plot time series data using the Frames property. For example, to plot cell length over time:

%Convert frame to hours (conversion rate of 0.5 hour per frame was determined by microscope settings)
timeAxis = track1.Frames * 0.5;

%Convert cell length from pixels into microns (conversion is 0.065 um/pixel, 
%obtained from the microscope)
cellLength = track1.MajorAxisLength * 0.065;

plot(timeAxis, cellLength)
xlabel('Time (hours)')
ylabel('Cell length (\mum)')

Cell length over time

Links between tracks

In TrackArray, tracks are modelled as a binary linked list. Each track can have, at most, a link to a previous track in time, and two links to the next track. Since we wrote this code originally for tracking cells, the track IDs are tracked as MotherID and DaughterID.

For example, once again looking at track 1:

>> track1 = getTrack(trackdata, 1)
track1 = 
  struct with fields:

                 ID: 1
           MotherID: NaN
         DaughterID: [2 3]
             Frames: [1 2 3 4 5 6]
           Centroid: [6×2 double]
    MajorAxisLength: [6×1 double]
       PixelIdxList: {1×6 cell}

Since MotherID is NaN, track 1 is not linked to a previous track, which makes sense since we know that cell 1 existed prior to the start of the movie. The DaughterID of track 1 is [2 3], indicating that cell 1 divided into cells 2 and 3. From the last element of Frames, we know that division occured between frames 6 and 7.

Inspecting track 2, one of the the daughter cells:

>> track1 = getTrack(trackdata, 2)
track1 = 
  struct with fields:

                 ID: 2
           MotherID: 1
         DaughterID: [6 7]
             Frames: [7 8 9 10 11 12 13 14]
           Centroid: [8×2 double]
    MajorAxisLength: [8×1 double]
       PixelIdxList: {1×8 cell}

We can see that the data here is consistent as MotherID is 1 and the first element in Frames is 7, indicating that this track started in frame 7 of the movie.

Tree plots

These relationships can be plotted as a binary using the method treeplot(obj, rootID). rootID specifies the track ID at the root (bottom most node) of the tree

>> treeplot(trackdata, 1)
>> ylabel('Frames')

Tree plot with root node 1

The y-axis of the tree plot is frames

You can change where the tree starts by changing the root node. For example, to plot the subtree starting from cell 2:

>> treeplot(trackdata, 2)
>> ylabel('Frames')

Tree plot with root node 2

Conclusion

This document concludes the example case of tracking cells.

If you encountered any issues, please send us a ticket at biof-imaging@colorado.edu and we will be happy to help.

< Back to User Guide