clear;

% 2D-Golgi model
% units: length micrometer, time: seconds

% SETTINGS:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% cisternae:
nC=6; % number of cisternae
dC=1.5; % diameter

% tubules:
nT=1; % (max.) number of tubules between two cisternae
pT_step=10; % number of time steps between probability calculations
ChoT=0.2; % s; average opening time of each tubule
ChcT=0.2; % s; average closing time of each tubule
dT=.03; % diameter
lT=.10; % length

% box:
res=25; % resolution in pix/um

% simulation
t_end=100000*10^-3; % duration
t_dt=1000*10^-8; % time step 
t_keep=1000; % keep every

% diffusion constant
Cdiff=10; % um^2/s

% initial concentration:
conc_1st_0=10;   
conc_all_0=0;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% new directory
newdir=['C1st' num2str(conc_1st_0+conc_all_0) '_Call' num2str(conc_all_0) '_D10h' num2str(log10(Cdiff))];
if exist(newdir)~=0
    n=1;
    while exist([newdir '_' num2str(n)])~=0, n=n+1; end
    newdir=[newdir '_' num2str(n)];
end
mkdir(newdir);
cd(newdir);
 
% generation of box and geometry
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% box size
pix_S=1/res;
Sx=nC*dC+(nC-1)*lT+2*pix_S;  
Sy=dC+2*pix_S;

% number of pixels
Nx=ceil(Sx/pix_S);
Ny=ceil(Sy/pix_S);

% number of time steps
Nt=ceil(t_end/t_dt/t_keep)+1;

% create empty box
boxC=newim(Nx,Ny,nC);

% cisternae
box1C=newim(Ny,Ny);
box1C=testobject(box1C,'ellipsoid',1,dC/pix_S/2,[1 1]); box1C=box1C>.5;
for n=1:nC
    boxC((n-1)*((dC+lT)/pix_S):(n-1)*((dC+lT)/pix_S)+Ny-1,:,n-1)=box1C; 
end
boxCall=squeeze(sum(boxC,[],3)>.5); 
boxC=boxC>.5;

% pixel per cisterna
NpixC=sum(boxC(:,:,0));

% tubules
pix_lT=ceil(res*lT); pix_dT=ceil(res*dT);
boxT=newim(Nx,Ny,nT*(nC-1));
boxT2=newim(Nx,Ny,nT*(nC-1));
for n=1:nC-1
    for m=1:nT
        shT=(m-.5*(nT+1))*(pix_dT+1);
        boxT(round((n-1)*((dC+lT)/pix_S)+dC/pix_S+1):round((n-1)*((dC+lT)/pix_S)+dC/pix_S+pix_lT),round(dC/pix_S/2+shT):round(dC/pix_S/2+pix_dT-1+shT),(n-1)*nT+(m-1))=1;
        boxT2(round((n-1)*((dC+lT)/pix_S)+dC/pix_S):round((n-1)*((dC+lT)/pix_S)+dC/pix_S+pix_lT+1),round(dC/pix_S/2+shT):round(dC/pix_S/2+pix_dT-1+shT),(n-1)*nT+(m-1))=1;
    end
end

% boxTall=sum(boxT,[],3);
boxTends=boxT2-boxT; boxTends=boxTends>.5;
boxT=boxT>.5;

% define concentration matrices
Mzeros=newim(Nx,Ny);
M=newim(Nx,Ny,Nt);

% initial condition: first cisternae filled
M0=Mzeros;
M0=M0+squeeze(conc_1st_0*boxC(:,:,0)); 
M0=M0+conc_all_0*boxCall; 
M(:,:,0)=M0;
Ntot(1)=sum(M0); % total concentration ...
Mlast(1)=double(M0(round((5*(dC+lT)+dC/2)/pix_S+1),round(dC/2/pix_S+1))); % concentration in the last cisterna
for n=1:nC, IC(n,1)=sum(M0*squeeze(boxC(:,:,n-1)))/NpixC; end % mean concentration per cisterna

% lifetimes
NCho=0; 
NChc=0;
sumCho=0;
sumChc=0;
ltCh=dip_image(zeros(1,nT*(nC-1)));
LTCh=dip_image(zeros(1,nT*(nC-1)));
Pt0=dip_image(rand(1,nT*(nC-1)))<=(ChoT/(ChoT+ChcT));
Pt1=dip_image(zeros(1,nT*(nC-1)));
for n=1:nT*(nC-1)
    p=rand;
    if Pt0(n-1)==1
        NCho=NCho+1;
        LTCh(n-1)=-ChoT*log(p);
    else
        NChc=NChc+1;
        LTCh(n-1)=-ChcT*log(p);       
    end
end

% simulation
tic
for nt=1:ceil(t_end/t_dt)
    t=nt*t_dt;
    M1=Mzeros;
    % open / close tubules
    if mod(nt-1,pT_step)==0
        % open / close times
        for n=1:nT*(nC-1)
            if Pt0(n-1)==0
                if ltCh(n-1)>LTCh(n-1) % tubule opens
                    Pt1(n-1)=1;
                    NCho=NCho+1;
                    LTCh(n-1)=-ChoT*log(rand);
                    sumChc=sumChc+ltCh(n-1);
                    ltCh(n-1)=0;
                else % tubule remain closed
                    Pt1(n-1)=0;
                    ltCh(n-1)=ltCh(n-1)+t_dt*pT_step;
                end
            else
                if ltCh(n-1)>LTCh(n-1) % tubule closes
                    Pt1(n-1)=0;
                    NChc=NChc+1;
                    LTCh(n-1)=-ChcT*log(rand);
                    sumCho=sumCho+ltCh(n-1);
                    ltCh(n-1)=0;
                else % tubule remain open
                    Pt1(n-1)=1;
                    ltCh(n-1)=ltCh(n-1)+t_dt*pT_step;
                end
            end
        end
        % define box
        box=boxCall;
        for n=1:nT*(nC-1)
            if Pt1(n-1)==1
                box=box+squeeze(boxT(:,:,n-1)); 
            end
        end
        % increase total concentration by proteins in disappearing tubules;
        if nt>1
            for n=1:nT*(nC-1)
                if Pt1(n-1)==0 && Pt0(n-1)==1
                    concT=sum(M0*squeeze(boxT(:,:,n-1))); % proteins in tubule
                    M0=M0*(1-squeeze(boxT(:,:,n-1)))+concT/sum(squeeze(boxTends(:,:,n-1)))*squeeze(boxTends(:,:,n-1));
                end
            end
        end
    end
    
    % count neighboring pixels where particles can diffuse; this can change
    % at any timestep due to opening/closing of tubules
    Cbox1=0*newim(Nx,Ny,4);
    Cbox1(0:Nx-2,:,0)=box(1:Nx-1,:);
    Cbox1(1:Nx-1,:,1)=box(0:Nx-2,:);
    Cbox1(:,0:Ny-2,2)=box(:,1:Ny-1);
    Cbox1(:,1:Ny-1,3)=box(:,0:Ny-2);
    CboxA=squeeze(sum(Cbox1,[],3));
    
    % diffusional step    
    Mlap1=0*newim(Nx,Ny,4);
    Mlap1(0:Nx-2,:,0)=M0(1:Nx-1,:);
    Mlap1(1:Nx-1,:,1)=M0(0:Nx-2,:);
    Mlap1(:,0:Ny-2,2)=M0(:,1:Ny-1);
    Mlap1(:,1:Ny-1,3)=M0(:,0:Ny-2);
    MlapA=squeeze(sum(Mlap1,[],3));
    M1=box*(M0+t_dt*Cdiff*(MlapA-CboxA.*M0)/(pix_S^2));
    
    % save frame
    if nt/t_keep==round(nt/t_keep)
        Ntot(nt/t_keep+1)=sum(M1);
        Mlast(nt/t_keep+1)=M1(round((5*(dC+lT)+dC/2)/pix_S+1),round(dC/2/pix_S+1));
        M(:,:,nt/t_keep)=M1;
        for n=1:nC, IC(n,nt/t_keep+1)=sum(M1*squeeze(boxC(:,:,n-1)))/NpixC; end % mean concentration per cisterna
        disp(['time: t = ' num2str(t) ' sec']); toc; tic
    end
    M0=M1; 
    Pt0=Pt1;
end

% statistics
for n=1:nT*(nC-1)
    if Pt1(n-1)==1
        sumCho=sumCho+ltCh(n-1);
        ltCh(n-1)=0;
    elseif Pt1(n-1)==1
        sumChc=sumChc+ltCh(n-1);
        ltCh(n-1)=0;
    end
end
ltCho_avg=sumCho/NCho,
ltChc_avg=sumChc/NChc,

% analysis
tim=(0:t_dt*t_keep:t_end)';

% figures
figure; plot(tim,IC) % intensity in 6 cisternae
figure; plot(tim,Ntot) 
figure; plot(tim,Mlast)

savemat=[tim Mlast'];
save('Mlast_flick2_2_1.5min.dat','savemat','-ascii') % saves concentration in last cisternae to file
