2012-06-22 14 views
8

私は5000x5000のグリッドを持っています。私はMATLABで単純なガン分化モデルを実装しようとしています。最初は、ランダムな点(x、y)を選択し、そのセルを癌細胞にします。最初の反復では、それは分割されます - 親セルはその場所にとどまり、娘セルは任意の隣接セルにランダムに割り当てられます。
これまでのところ簡単です。グリッド上の癌細胞のモデル分割

私の問題はこれです:逐次反復では、しばしば娘細胞がに癌細胞を有する細胞に割り当てられることになります。この場合、私は娘細胞がその場所を取って、そこにある細胞を隣接細胞に「衝突」させたい。その隣接セルが空であれば、それは満たされ、プロセスは停止する。そうでない場合は、その場所に既にあるセルは突き当てられ、最後のセルが空のスペースを見つけてプロセスが停止するまで続きます。

これは単純なはずですが、コード化する方法と使用するループの種類はわかりません。
私はプログラマーではなく物理的な科学者ですので、私をシンプトンのように扱ってください!

+1

)の接続に応じて、ロードに時間がかかります娘細胞を置くために? –

+0

ループの代わりに再帰的な解決に役立つ問題のように思えます。 – slayton

+0

@HighPerformanceMarkあなたの質問は元の質問で答えられます:_ "...もしそうでなければ、その場所に既にあるセルは突き当てられ、最後のセルが空のスペースを見つけてプロセスが停止するまで続きます。 –

答えて

4

ここで私がまとめた機能は、あなたが提供した仕様にほぼ合致しています。

がん細胞の数が多くなるにつれて、私は減速します。

は、基本的に私はいくつかの変数、

Iを反復することができる点のベクトル(既存のMATLAB関数の名前は、私はこのグリッドとしてplate呼び出し)セル位置のグリッドを表すN×Nのマトリックスを有しますすばやく私はシード位置を選び、グリッドがいっぱいになるまでwhileループを実行します。各ループ反復で

Iがセル毎に以下を実行する:

  • そのセルが
  • は最初のオープンプレートを探す
  • を分割するランダムな方向を生成分けるべきかどうかを決定するために乱数を生成しその方向の位置
  • 私はエクステそれをテストしていない、その位置に

の移入それはうまくいくようです。

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 

注:代わりに細胞を押す思考のは、私は彼らが現在のセルを出て、行/列の最後に新しいセルを作成した方法でこれをコード化されました。意味論的には異なるが、論理的には世代を気にしない限り同じ最終結果を持つ。

+0

私は無意味ですが、今は実行しようとしていますが、gridSize(つまり:5000) pDivideとは何ですか? – DRG

+0

グリッドが5000x5000の場合、 'plateSize'は5000です。' pDivide'は、与えられたセルが各世代を分割する確率です。 1に設定すると、各セルが常に分割されます。 .1に設定すると、各セルは各世代を分割する確率が10%になります。 – slayton

+0

乾杯 - それは本当にうまくいっていますが、 "divide> = pDivide"という考え方では、入力引数が十分ではないということを教えてくれます。 – DRG

2

another questionに触発されましたが、このシミュレーションを実装するために画像処理技術を使用しましたが、具体的には、morphological dilationを使用して癌細胞を広げることができます。

中心が固定され、そして他の 1は、他の8つの残りの位置のいずれかにランダムに配置されている
1 0 0 
0 1 0 
0 0 0 

アイデアは、のように見える構造要素を用いて各ピクセルを拡張することです。これは、その方向にピクセルを効果的に拡張する。

拡張の方法は、1つのピクセルセットだけの空白イメージを作成し、単純なOR操作を使用してすべての結果を累積することです。

私たちは、すべてのピクセルを考慮する必要はなく、癌細胞のクラスターによって形成される現在のブロックの周囲にあるものだけを考慮する必要がありません。内側のピクセルはすでにガン細胞に囲まれており、拡張されても効果はありません。

さらに高速化するため、1回の呼び出しで同じ方向に拡張されるように選択されたすべてのピクセルに対して拡張を実行します。したがって、すべての反復において、最大で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 

私も10個のランダムな初期癌細胞(警告と500×500のグリッド上のシミュレーション、アニメーションの作成:.GIF画像をサイズは約1MBです、そうかもしれません)すでにブロブ分裂の中心に3×3とする細胞である癌ブロブを持っている場合は、ルール(または何のルールがあるとは何か

simulation_animation

関連する問題