George Nyarangi

Tracking Cells: A project on Cell Biology

Abstract

yeast cells with marked nuclei

Yeast cells, Dept. of Genetics, Cell Biology and Development, UMN

Most genetic disorders are attributed to mutations in cells and efforts to study and understand these disorders entail the use of model organisms such as yeast. This project seeks to study yeast cells with a central goal of identifying, analyzing and tracking mutations in replicating cells. To accomplish this, a Digital Image Processing (DIP) based Matlab software application that will be used in Biological research performed by Judith Berman, Ph.D (University of Minnesota) will be designed and developed. This software application will utilize digital time-lapse images of replicating yeast cells to, in part; automate the tedious process of manually identifying and tracking mutations. The application will also be designed to produce exportable data reports for analysis and a Graphical User Interface (GUI) that allows switching between visual analysis and the reports will also be integrated into the design. System documentation will be provided along with the final product which will be adopted for studies and research focused on cancer at the University of Minnesota.



Current Development

View Matlab code:

function [] = tracking_cells()
global L X S output_file_name; %global variables

clear all; clc;

D = dir('*.jpg');  % or jpeg or whatever.
S.NAM = {D(:).name};  % Store the name of all items returned in D.

% Main UI
S.fh = figure('units','pixels',...
              'position',[100 50 800 800],...
              'menubar','none',...
              'name','Verify Password.',...
              'resize','off',...
              'numbertitle','off',...
              'name','Tracking Cells');
movegui(S.fh, 'center'); %center figure

% Loaded images ls title
S.ed1 = uicontrol('style','text',...
                 'unit','pix',...
                 'position',[580 760 50 15],...
                 'string','Images',...
                 'fontsize',9,'fontweight','bold',...
                 'HorizontalAlign','left');
% Output results ls title
S.ed2 = uicontrol('style','text',...
                 'unit','pix',...
                 'position',[30 40 100 190],...
                 'string','Output results',...
                 'fontsize',9,'fontweight','bold',...
                 'HorizontalAlign','left');

% Output results listbox
S.output = uicontrol('style','list',...
                 'unit','pix',...
                 'fontsize',10,'position',[30 20 512 195],...
                 'string','~~~~~~~~~~OUTPUT RESULTS WILL PRINT HERE~~~~~~~~~~',...
                 'HorizontalAlign','left');

% Output results file pushbutton
S.view_out = uicontrol('style','push',...
                 'units','pix',...
                 'position',[580 185 100 30],...
                 'backgroundcolor','w',...
                 'HorizontalAlign','left',...
                 'string','View output file',...
                 'fontsize',9,'fontweight','bold',...
                 'callback',{@view_output,S});

% Loaded imagest listbox
S.ls = uicontrol('style','list',...
                 'units','pix',...
                 'position',[580 640 200 120],...
                 'backgroundcolor','w',...
                 'string',S.NAM,...
                 'HorizontalAlign','right');

% Load image pushbutton
S.pb1 = uicontrol('style','push',...
                 'units','pix',...
                 'position',[580 600 100 30],...
                 'backgroundcolor','w',...
                 'HorizontalAlign','left',...
                 'string','Load Image',...
                 'fontsize',9,'fontweight','bold',...
                 'callback',{@pb1_call,S});

% Run detection push button
S.pb2 = uicontrol('style','push',...
                 'units','pix',...
                 'position',[580 550 100 30],...
                 'backgroundcolor','w',...
                 'HorizontalAlign','left',...
                 'string','Run Detection',...
                 'fontsize',9,'fontweight','bold',...
                 'callback',{@pb2_call,S});

% Reset push button
S.reset = uicontrol('style','push',...
                 'units','pix',...
                 'position',[580 500 100 30],...
                 'backgroundcolor','w',...
                 'HorizontalAlign','left',...
                 'string','Reset',...
                 'fontsize',9,'fontweight','bold',...
                 'callback',{@reset,S});

S.ax = axes('units','pixels',...
            'position',[30 250 512 512]);
set(S.ax,'xtick',[],'ytick',[]);  % Get rid of ticks.

function get_ls()
   L = get(S.ls,{'string';'value'});  % Get the editbox string
   L = L{1}{L{2}};  % Give it a name for the base workspace.
   X = imread(L); % Read the image.
end

function view_output(varargin)
   open(strcat(L, '.txt')); % Open output file
end

function [] = reset(varargin)
set(S.output, 'String','~~~~~~~~~~OUTPUT RESULTS WILL PRINT HERE~~~~~~~~~~');
cla reset; % Delete from the current axes all graphics objects
title(''); % Delete from the current axes all titles
clear all; clc; % Clear all variables, clear terminal
end

function [] = pb1_call(varargin)
% Callback for pushbutton.
S = varargin{3}; %variable length argument list
get_ls();
S.im = X;  % X from fuction get_ls()
S.R = image(S.im);  % Display the image on S.ax.
title('Original image');
end

function print_to_ls(str)
   str_part = str;
   old_str = get(S.output, 'String' );
   new_str = strvcat(old_str, str_part); %concatenation
   set(S.output, 'String', new_str)
end

function [] = pb2_call(varargin)
clc;
S = varargin{3}; %variable length argument list
get_ls();
I = X;
%
% DETECT FAMILIES
%
    I_Red = I(:,:,1);     % divides the image into its three channels
    I_Green = I(:,:,2);
    I_Blue = I(:,:,3);
    N = 512;                        % N = 512 for the 512 by 512 image
    I_edged = edge(I_Green,'canny',.35); % uses the blue channel detects edge

    %figure(1);
    %imshow(I_edged);

    %figure(2);
    %imshow(I);

    se1 = strel([1,1,1,1,1,1,1,1,1
        1,1,1,1,1,1,1,1,1
        1,1,1,1,1,1,1,1,1
        1,1,1,1,1,1,1,1,1
        1,1,1,1,1,1,1,1,1
        1,1,1,1,1,1,1,1,1
        1,1,1,1,1,1,1,1,1
        1,1,1,1,1,1,1,1,1
        1,1,1,1,1,1,1,1,1]);


    I_dialiated = imdilate(I_edged,se1); % dialtes image toward center

    %figure(3);
    %imshow(I_dialiated);

    I_filled = imfill(I_dialiated,'holes'); % fills holes in white up to certain size
    %figure(4);
    %imshow(I_filled);


    I_label = bwlabel(I_filled,8); % labels each white patch 1-num_fam

    d = max(I_label,[],2);          % searches through I_label and finds
    family = max(d);               % the number of family


    I_thresh = im2bw(I_Red,.22);     % thresholds the Red channel so only the nucli show up
    for h = 1:family;
    [R,C] = find(I_label == h);

    upper_lim_x = max(R);           %this set of for loops checks to make sure
    lower_lim_x = min(R);           %every family has at least one nuclei in it
    upper_lim_y = max(C);           %I had trouble with noise and this seemed to help
    lower_lim_y = min(C);
    x_dim = upper_lim_x - lower_lim_x;
    y_dim = upper_lim_y - lower_lim_y;
    cor = [ lower_lim_y  lower_lim_x    y_dim   x_dim ];
    I2 = imcrop(I_thresh,cor);
    D = find(I2 == 1);
    if(length(D) < 2);
    for A = 1:N
        for B = 1:N
            if(I_label(A,B) == h)
                I_label(A,B) = 0;
            end
        end
    end

    end
    end
    I_fam = bwlabel(I_label,8);
    e = max(I_fam,[],2);
    num_fam = max(e);

%
% Detect Cells
%
    I_Red = adapthisteq(I_Red, 'clipLimit',0.025,'Distribution','rayleigh');

    tic;
    [accum, circen, cirrad] = CircularHough_Grd(I_Red, [3 20], 10, 8, 1);
    toc

    if any(cirrad <= 0)
        inds = find(cirrad>0);
        cirrad = cirrad(inds);
        circen = circen(inds,:);
    end

%Get Nuclei

    im_yiq = rgb2ntsc(I);

    i_im = im_yiq(:,:,2);

    thresh_I = ~(i_im < 0.09);
    [I_nuclei, num_nuclei] = bwlabel(thresh_I);

    nuclei = zeros(num_nuclei,2);

    for i = 1:num_nuclei
        [R,C] = find(I_nuclei == i);
        nuclei(i, 1) = mean(C);
        nuclei(i, 2) =  mean(R);
    end
    %find family perimeters for numbering purposes
    BWoutline = bwperim(I_fam);
    s = regionprops(BWoutline, 'Centroid');

    S.im = I;
    S.R = image(S.im);  % Display the image on S.ax.
    title('Outlined original image')

    hold on;

    circen(:,2) = circen(:,2);
    plot(nuclei(:,1), nuclei(:,2), 'r+');

    %Get family boundaries
    set(S.output, 'String', ''); % clear output listbox first
    diary output.txt
    for i = 1:num_fam
        if i == 1
            my_str = strcat('Image processed:-->',L); % img processed
            fprintf(my_str);
            print_to_ls(my_str) %call print_to_ls function
            print_to_ls(sprintf('------------------------------'))
        end
       fprintf('\nFamily %d\r------------\n', i);
        %pring family output to GUI
        if i > 1 % nsert space after first family is printed
            F1 = sprintf('\n'); % print new blank line
            print_to_ls(F1) %call print_to_ls function
        end
        F2 = sprintf('Family %d', i);
        print_to_ls(F2) %call print_to_ls function
        F3 = sprintf('\r------------\n'); % print new blank line
        print_to_ls(F3) %call print_to_ls function
        % end print family output to GUI

        array(i,1) = i;
        fam = array;
        cell_count = 0;
        [R,C] = find(I_fam == i);
        upper_lim_x = max(C);
        lower_lim_x = min(C);
        upper_lim_y = max(R);
        lower_lim_y = min(R);
        x_dim = upper_lim_x - lower_lim_x;
        y_dim = upper_lim_y - lower_lim_y;

        rectangle('Position', [lower_lim_x, lower_lim_y, x_dim, y_dim],...
            'edgecolor', 'w', 'linewidth', 1);

        %start label families
            c = s(i).Centroid;
            text(upper_lim_x, upper_lim_y, sprintf('%d',i) , ...
            'VerticalAlignment', 'Bottom',...
            'HorizontalAlignment', 'Right', 'Color','white');
        %end label families
        for j=1:size(circen,1)
            cell_x = circen(j,1);
            cell_y = circen(j,2);
            cell_rad = cirrad(j);
            if((lower_lim_x <= cell_x) && (cell_x <= upper_lim_x) &&...
                    (lower_lim_y <= cell_y) && (cell_y <= upper_lim_y))
                cell_count = cell_count + 1;
                % plot cell
                rectangle('Position',[cell_x - cell_rad, cell_y - ...
                    cell_rad, 2*cell_rad, 2*cell_rad],...
                    'Curvature', [1,1], 'edgecolor', 'b', 'linewidth', 1);
                            %count nuclei per cell
                nuclei_count = 0;
                for k=1:size(nuclei,1)
                    %see if distance between cell and nuclei center is less than the radius of the current cell
                    if(sqrt((nuclei(k,1) - cell_x)^2 + (nuclei(k,2) - ...
                            cell_y)^2) < cell_rad)
                        nuclei_count = nuclei_count + 1;
                    end
                end
                fprintf('\tCell %d has %d nuclei\n', j, nuclei_count);

                % print cell output to GUI
                C = sprintf('\tCell %d has %d nuclei\n', j, nuclei_count);
                print_to_ls(C) %call print_to_ls function
                % end print cell output to GUI
            end
        end
    end
    diary off;
    movefile('output.txt', strcat(L, '.txt')); % trick to rename output.txt to include image_name
    delete output.txt;
    hold off;
end
end
yeast cells with marked nuclei

User Interface

So far we have been able to successfully detect clusters of families, the number of cells/family, and the number of nuclei/cell. We are also in the process of finishing the GUI design.