网格上癌细胞的模型划分

时间:2012-06-22 13:42:01

标签: matlab loops recursion while-loop simulation

我有一个5000x5000网格,我正在尝试在MATLAB中实现一个简单的癌症分区模型。最初,它选择一个随机点(x,y)并使该细胞成为癌细胞。在第一次迭代中,它划分 - 父单元格保留在其位置,子单元格被随机分配给任何相邻单元格。
很容易到目前为止。

我的问题是:在连续迭代中,子细胞通常会被分配到已经有癌细胞的细胞。在这种情况下,我希望子单元取代它并将已经存在的单元“撞击”到相邻单元。如果该相邻单元格为空,则将其填充并且该过程停止。如果没有,则已经在该位置的单元格被撞击,依此类推,直到最后一个单元格找到空白空间并且该过程停止。

这应该很简单,但我不知道如何编写它以及使用什么类型的循环。
我是一个物理科学家而不是程序员,所以请像对待我一样对待我!

2 个答案:

答案 0 :(得分:4)

这是我一起破解的功能,大致符合您提供的规格。

随着癌细胞数量的增加,我的确会减慢。

基本上我有一些变量,NxN矩阵表示单元格位置的网格(我称之为plate,因为grid是现有matlab函数的名称)

我可以快速迭代的点矢量。我选择种子位置,然后运行while循环,直到网格已满。

在每次循环迭代中,我为每个单元格执行以下操作:

  • 生成一个随机数以确定该单元格是否应该划分
  • 生成随机方向划分
  • 找到该方向的第一个开放式位置
  • 填充该位置

我没有对它进行过广泛的测试,但似乎有效。

function simulateCancer(plateSize, pDivide)

plate = zeros(plateSize, plateSize);
nCells = 1;
cellLocations = zeros(plateSize*plateSize,2);

initX = randi(plateSize);
initY = randi(plateSize);

cellLocations(nCells,:) = [initX, initY];

plate(initX, initY) = 1;

f = figure;
a = axes('Parent', f);
im = imagesc(plate, 'Parent', a);


while(nCells < (plateSize * plateSize))
    currentGeneration = currentGeneration+1;
    for i = 1:nCells
        divide = rand();
        if divide <= pDivide
            divideLocation = cellLocations(i,:);
            divideDir = randi(4);
            [x, y, v] = findNewLocation(divideLocation(1), divideLocation(2), plate, divideDir);
            if (v==1)
                nCells = nCells+1;
                plate(x,y) = 1;
                cellLocations(nCells,:) = [x,y];
            end
        end
    end
    set(im,'CData', plate);
    pause(.1);
end

end

function [x,y, valid] = findNewLocation(xin, yin, plate, direction)   
    x = xin;
    y = yin;
    valid = 1;
    % keep looking for new spot if current spot is occupied
    while( plate(x, y) == 1)
       switch direction
            case 1 % divide up
                y = y-1;
            case 2 % divide down
                y = y+1;
            case 3 % divide left
                x = x-1;
            case 4 % divide down
                x = x+1;
            otherwise
            warning('Invalid direction')
            x = xin;
            y = yin;
        return;
       end

       %if there has been a collision with a wall then just quit
       if y==0 || y==size(plate,2)+1 || x==0 || x==size(plate,1)+1 % hit the top
           x = xin; %return original values to say no division happend
           y = yin;
           valid = 0;
           return;
       end

    end


end

注意:我没有考虑推送单元格,而是以一种将单元格保留在当前位置的方式对其进行编码,并在行/列的末尾创建新单元格。在语义上它的不同但在逻辑上它具有相同的最终结果,只要你不关心几代人。

答案 1 :(得分:2)

受到another question的启发,我使用图像处理技术来实现此模拟。具体来说,我们可以使用morphological dilation来传播癌细胞。

我们的想法是使用类似于以下内容的结构元素扩展每个像素:

1 0 0
0 1 0
0 0 0

中心固定,另一个1随机放置在其他八个位置之一。这将有效地在该方向上扩展像素。

执行扩张的方法是创建一个空白图像,只有一个像素集,然后使用简单的OR运算累积所有结果。

为了加快速度,我们不需要考虑每个像素,只需考虑由癌细胞簇形成的当前块周边的那些像素。内部的像素已经被癌细胞包围,如果扩张则没有效果。

为了进一步加快速度,我们对所有选择在一次调用中以相同方向扩展的像素进行扩张。因此,每次迭代,我们最多执行8次扩张操作。

这使得代码相对较快(我测试了高达1000x1000网格)。此外,它在所有迭代中保持相同的时序(当网格开始填满时不会减速)。

这是我的实施:

%# initial grid
img = false(500,500);

%# pick 10 random cells, and set them as cancerous
img(randi(numel(img),[10 1])) = true;

%# show initial image
hImg = imshow(img, 'Border','tight', 'InitialMag',100);

%# build all possible structing elements
%# each one dilates in one of the 8 possible directions
SE = repmat([0 0 0; 0 1 0; 0 0 0],[1 1 8]);
SE([1:4 6:9] + 9*(0:7)) = 1;

%# run simulation until all cells have cancer
BW = false(size(img));
while ~all(img(:)) && ishandle(hImg)
    %# find pixels on the perimeter of all "blocks"
    on = find(bwperim(img,8));

    %# percentage chance of division
    on = on( rand(size(on)) > 0.5 );    %# 50% probability of cell division
    if isempty(on), continue; end

    %# decide on a direction for each pixel
    d = randi(size(SE,3),[numel(on) 1]);

    %# group pixels according to direction chosen
    dd = accumarray(d, on, [8 1], @(x){x});

    %# dilate each group of pixels in the chosen directions
    %# to speed up, we perform one dilation for all pixels with same direction
    for i=1:8
        %# start with an image with only those pixels set
        BW(:) = false;
        BW(dd{i}) = true;

        %# dilate in the specified direction
        BW = imdilate(BW, SE(:,:,i));

        %# add results to final image
        img = img | BW;
    end

    %# show new image
    set(hImg, 'CData',img)
    drawnow
end

我还在500x500网格上创建了​​一个模拟动画,其中包含10个随机初始癌细胞(警告:.gif图像大小约为1MB,因此根据您的连接可能需要一些时间加载)

simulation_animation