首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >网格上癌细胞的模型分裂

网格上癌细胞的模型分裂
EN

Stack Overflow用户
提问于 2012-06-22 13:42:01
回答 2查看 876关注 0票数 8

我有一个5000x5000网格,我试图在MATLAB中实现一个简单的癌症部门模型。最初,它选择一个随机点(x,y),使该细胞成为癌细胞。在第一次迭代中,它被划分-父单元留在它的位置,子单元被随机分配到任何相邻的单元。

到目前为止很容易。

我的问题是:在连续的迭代中,一个子细胞通常被分配给一个已经有癌细胞的细胞。在这种情况下,我希望子细胞取代它的位置,并将已经在那里的细胞“撞”到一个相邻的细胞。如果相邻单元格为空,则填充该单元格并停止处理。否则,已经位于该位置的单元格会被颠簸等等,直到最后一个单元格找到一个空空间,进程停止为止。

这应该很简单,但我不知道如何对其进行编码,以及使用什么样的循环。

我是一个物理科学家,而不是一个程序员,所以请把我当作一个傻瓜!

EN

回答 2

Stack Overflow用户

发布于 2012-06-22 14:38:33

这是一个函数,我黑客在一起,大致符合您提供的规格。

随着癌细胞数量的增加,我确实放慢了脚步。

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

一个点的向量,我可以快速地迭代。我选择一个种子位置,然后运行一个while循环,直到网格满了为止。

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

  • 生成一个随机数,以确定该细胞是否应该分裂
  • 生成一个随机方向进行除法
  • 在那个方向找到第一个开板位置。
  • 填充那个位置

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

代码语言:javascript
复制
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

注意:我没有考虑推送单元格,而是将单元格保留在当前位置,并在行/列的末尾创建新单元格。在语义上它是不同的,但逻辑上它有相同的最终结果,只要你不关心世世代代。

票数 4
EN

Stack Overflow用户

发布于 2012-06-23 01:09:44

另一个问题的启发,我想使用图像处理技术来实现这个模拟。具体来说,我们可以使用形态扩张来传播癌细胞。

这样做的目的是使用如下结构元素来扩展每个像素:

代码语言:javascript
复制
1 0 0
0 1 0
0 0 0

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

展开的方式是创建一个空白图像,只有一个像素集,然后使用一个简单的OR操作来累积所有结果。

为了加快速度,我们不需要考虑每一个像素,只有那些在当前块周围形成的癌细胞集群。里面的像素已经被癌细胞包围了,如果扩张的话就没有效果了。

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

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

以下是我的实现:

代码语言:javascript
复制
%# 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,因此可能需要一些时间来加载,这取决于您的连接)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11157349

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档