Code for analytical separation videos

My old videos about ana­lyt­i­cal sep­a­ra­tion processes should be added to this site. The scripts are still good and easy to mod­ify to sim­u­late dif­fer­ent sce­nario by chang­ing a few parameters.

When I first made them in 1996 and 1999, I saved them in mpeg1 for­mats. Nowa­days, other for­mats are more pop­u­lar, espe­cially MP4 that can run on prac­ti­cally 100% of the browsers includ­ing iPhone and iPad — and on any other browser — since Flash play­ers can han­dle that one as well. Just because I like the native Fire­fox for­mat, I added OGV files as well. The MATLAB scripts were set to dump uncom­pressed AVI files. The AVI files were con­verted to MP4 using Mpegstream­clip, and to OGV using fffmpeg2theora. The below code can be copied and mod­i­fied in MATLAB.

Open tubular chromatography simulation

% Chro­matog­ra­phy sim­u­la­tions, 1996 and 1999
% Cre­ate an empty dark window
fig­ure(1);
set(1,‘Posi­tion’,[69 601 620 66]);
clf;
col­ormap(‘gray’)
fill([0 0 5000 5000 0],[-200 200 200 -200 -200],‘k’)
% Video pic­ture, frame 1
axis([0 5000 -140 140]); axis(‘equal’); axis(‘off’);
text(500,100,‘Made by Mar­tin Ander­s­son, Dept. of Tech­ni­cal Ana­lyt­i­cal Chem­istry’,‘Color’,‘w’)
text(1500,-50,‘Lund Uni­ver­sity, Swe­den 1996’,‘Color’,‘w’)
mov=avifile(‘cromat.avi’,‘com­pres­sion’,‘none’);
% Para­me­ters for the simulation
flow=20; % Speed of the plug flow
dif­fu­sion=10; % Dif­fu­sio­nen
pA=0.2; % par­ti­tion OR propa­bil­ity for ana­lyte A
pB=1; % par­ti­tion OR propa­bil­ity for ana­lyte B
N=30; % Num­ber of mol­e­cules of each analyte
% Set up the plug of sam­ple, “inject” the sample
Startx=ones(10,1)*[20:20:200];
Starty=[-90:20:90]’*ones(1,10)*diag([1 -1 1 -1 1 -1 1 -1 1 -1]);
Apos=[Startx(1:2:N*2)’ Starty(1:2:N*2)];
Bpos=[Startx(2:2:N*2)’ Starty(2:2:N*2)];
% Draw the injected sample
hold off;
fill([0 0 5000 5000 0],[-200 -100 -100 -200 -200],‘y’)
hold on;
fill([0 0 5000 5000 0],[100 200 200 100 100],‘y’)
fill([0 0 5000 5000 0],[-100 100 100 -100 -100],‘w’);
plot(Apos(:,1),Apos(:,2),‘r.’,‘Mark­er­size’,10);
plot(Bpos(:,1),Bpos(:,2),‘b.’,‘Mark­er­size’,10);
axis([0 5000 -140 140]); axis(‘equal’); axis(‘off’);
fig­ure(gcf);
frame=getframe(gcf);
mov=addframe(mov,frame);
% t>0. Flow starts.
count=2;
while count count=count+1;
% Move ana­lytes A and B for­ward that are not attached to the wall
mobileA=find(abs(Apos(:,2)) Apos(mobileA,:)=Apos(mobileA,:)+dif­fu­sion*randn(size(Apos(mobileA,:)));
Apos(mobileA,1)=Apos(mobileA,1)+flow;
mobileB=find(abs(Bpos(:,2)) Bpos(mobileB,:)=Bpos(mobileB,:)+dif­fu­sion*randn(size(Bpos(mobileB,:)));
Bpos(mobileB,1)=Bpos(mobileB,1)+flow;
% If stuck at the walls, released accord­ing to prob­a­bil­ity of A and B
ind=find(Apos(:,2)> 80); Apos(ind,2)=130*ones(size(ind));
ind=ind(rand(size(ind))>pA); Apos(ind,2)=80*ones(size(ind));
ind=find(Apos(:,2) ind=ind(rand(size(ind))>pA); Apos(ind,2)=-90*ones(size(ind));
ind=find(Bpos(:,2)> 80); Bpos(ind,2)=130*ones(size(ind));
ind=ind(rand(size(ind))>pB); Bpos(ind,2)=80*ones(size(ind));
ind=find(Bpos(:,2) ind=ind(rand(size(ind))>pB); Bpos(ind,2)=-90*ones(size(ind))
% Draw walls and decorate
hold off;
fill([0 0 5000 5000 0],[-200 -100 -100 -200 -200],‘y’)
hold on;
fill([0 0 5000 5000 0],[100 200 200 100 100],‘y’)
fill([0 0 5000 5000 0],[-100 100 100 -100 -100],‘w’);
% Plot the sample
plot(Apos(:,1),Apos(:,2),‘r.’,‘Mark­er­size’,10);
plot(Bpos(:,1),Bpos(:,2),‘b.’,‘Mark­er­size’,10);
axis([0 5000 -140 140]); axis(‘equal’); axis(‘off’);
fig­ure(gcf);
drawnow;
frame=getframe(gcf);
mov=addframe(mov,frame);
end;
mov=close(mov);

Field flow fractionation separation simulation

clear all;
% Para­me­ters
Cross­Flow=-1;
Sdif­fu­sion=2 % dif­fu­sion of Small analyte;
Ldif­fu­sion=1; % dif­fu­sion of Large analyte
Lam­i­nar­Const=1.5; %LINEAR flow pro­file, “slope”=1.5
N=50; %Num­ber of mol­e­cules of each analyte
Width=100; % Chan­nel width
Length=1000; % Chan­nel length
%Print-size of molecules
mark­er­SizeL = 5*3;
mark­er­SizeS = 2*3;
mov=avifile(‘fff.avi’,‘com­pres­sion’,‘none’);
% t=0. Inject sam­ple at mid­dle of top.
% Large and Small positions.
Lpos=[ones(N,1)*Width/2 ones(N,1)*Width];
Spos=[ones(N,1)*Width/2 ones(N,1)*Width];
hold off;
plot([Lpos(:,1) ones(N,1)*NaN]’, [Lpos(:,2) ones(N,1)*NaN]’,’.m’,‘Mark­er­Size’,mark­er­SizeL);
hold on;
plot([Spos(:,1) ones(N,1)*NaN]’, [Spos(:,2) ones(N,1)*NaN]’,’.y’,‘Mark­er­Size’,mark­er­SizeS);
set(gcf,‘posi­tion’,[45 453 620 200]);
axis([-Width Length -5 Width]);
set(gca,‘ytick’,[]);
set(gca,‘xtick’,[]);
fig­ure(gcf);
frame=getframe(gcf);
mov=addframe(mov,frame);
% t>0. Cross­flow starts. Relax­ation & focusing.
count=1;
mL=Width;
mS=Width;
maxS=Inf;
while maxS>0.15*Width,
count=count+1
Lpos=Lpos+Ldiffusion*randn(size(Lpos));
Lpos(:,2)=Lpos(:,2)+Cross­Flow;
Spos=Spos+Sdiffusion*randn(size(Spos));
Spos(:,2)=Spos(:,2)+Cross­Flow;
% Bounce at the “walls” — focus­ing using ten­ta­tive walls.
ind=find(Lpos(:) ind=find(Spos(:) ind=find(Lpos(:)>Width+1); Lpos(ind)=Width+1-(Lpos(ind)-(Width+1));
ind=find(Spos(:)>Width+1); Spos(ind)=Width+1-(Spos(ind)-(Width+1));
hold off;
plot([Lpos(:,1) ones(N,1)*NaN]’, [Lpos(:,2) ones(N,1)*NaN]’,’.m’,‘Mark­er­Size’,mark­er­SizeL);
hold on;
plot([Spos(:,1) ones(N,1)*NaN]’, [Spos(:,2) ones(N,1)*NaN]’,’.y’,‘Mark­er­Size’,mark­er­SizeS);
maxS=max(Spos(:,2));
plot([-Width Length],[0 0],‘w-’)
set(gca,‘ytick’,[]);
set(gca,‘xtick’,[]);
axis([-Width Length -5 Width]);
text(0.2*Length,0.8*Width, ‘Relaxation/focusing. Cross­flow only’);
drawnow;
frame=getframe(gcf);
mov=addframe(mov,frame);
end;
% sep­a­ra­tion after focusing
while count count=count+1
Lpos=Lpos+Ldiffusion*randn(size(Lpos));
Lpos(:,2)=Lpos(:,2)+Cross­Flow;
Lpos(:,1)=Lpos(:,1)+(Lpos(:,2)+2)*Lam­i­nar­Const;
Spos=Spos+Sdiffusion*randn(size(Spos));
Spos(:,2)=Spos(:,2)+Cross­Flow;
Spos(:,1)=Spos(:,1)+(Spos(:,2)+2)*Lam­i­nar­Const;
% Bounce at the wall.
ind=find(Lpos(:) ind=find(Spos(:) hold off;
plot([Lpos(:,1) ones(N,1)*NaN]’, [Lpos(:,2) ones(N,1)*NaN]’,’.m’,‘Mark­er­Size’,mark­er­SizeL);
hold on;
plot([Spos(:,1) ones(N,1)*NaN]’, [Spos(:,2) ones(N,1)*NaN]’,’.y’,‘Mark­er­Size’,mark­er­SizeS);
% Draw dis­tri­b­u­tion curves…
% mL=[mean(Lpos(:,1)) mL(1)];
% mS=[mean(Spos(:,1)) mS(1)];
% sL=std(Lpos(:,1));
% sS=std(Spos(:,1));
% NL=exp(-([-Width:Length]-mL(1)).^2/2/sL/N)/sL;
% NS=exp(-([-Width:Length]-mS(1)).^2/2/sS/N)/sS;
% plot(-Width:Length,NL*1000,‘w-’)
% plot(-Width:Length,NS*2000,‘w:’)
% plot(mL(1)*[1 1],[0 Width],’-w’);
% plot(mS(1)*[1 1],[0 Width],’:w’);
Length],[0 0],‘w-’)
set(gca,‘ytick’,[]);
set(gca,‘xtick’,[]);
axis([-Width Length -5 Width]);
text(0.2*Length,0.8*Width,‘Sep­a­ra­tion process. Cross- & lon­gi­tu­dal flow’);
fig­ure(gcf);
frame=getframe(gcf);
mov=addframe(mov,frame);
end;
mov=close(mov);
disp(‘done’);

Field flow fractionation, demonstrating the flows

Down­load mat-file with the arrow images to be loaded before run­ning this script.

% Defin­ing the speeds of the lam­i­nar flow
step=[5.0 6 6.5 7 7.125];
mov=avifile(‘fl-fff.avi’,‘com­pres­sion’,‘none’);
% Show the lam­i­nar flow
for k=1:120,
shift=round(step*k);
for k=1:length(step);
r{k}=[r1(:,end-shift(k)+1:end,:) r1(:,1:end-shift(k),:)];
end
xx=[r{1};r{2};r{3};r{4};r{5};r{4};r{3};r{2};r{1}];
xx=[zeros(16,960,3)+128; xx;zeros(16,960,3)+128];
if k==1, % make a nice transition
for f=0:0.05:0.95,
imshow(uint8(dou­ble(xx(1:2:end,1:2:end,:))*f+0*(1-f)));
drawnow;
fig­ure(gcf);
frame=getframe(gcf);
mov=addframe(mov,frame);
end
end
imshow(xx(1:2:end,1:2:end,:));
if k drawnow;
fig­ure(gcf);
frame=getframe(gcf);
mov=addframe(mov,frame);
end
for f=0.05:0.05:1, % make a nice transition
imshow(uint8(dou­ble(xx(1:2:end,1:2:end,:))*(1-f)+255*f));
drawnow;
fig­ure(gcf);
frame=getframe(gcf);
mov=addframe(mov,frame);
end
% Show the cross flow
for k=1:90,
ccc=cc([end‑k+1:end 1:end‑k],:,:);
ccc=[zeros(16,960,3)+128; ccc;zeros(16,960,3)+128];
if k==1,% make a nice transition
for f=0:0.05:0.95,
imshow(uint8(dou­ble(ccc(1:2:end,1:2:end,:))*f+255*(1-f)));
drawnow;
fig­ure(gcf);
frame=getframe(gcf);
mov=addframe(mov,frame);
end
end
imshow(ccc(1:2:end,1:2:end,:));
if k drawnow;
fig­ure(gcf);
frame=getframe(gcf);
mov=addframe(mov,frame);
end
for f=0.05:0.05:1,% make a nice transition
imshow(uint8(dou­ble(ccc(1:2:end,1:2:end,:))*(1-f)+255*f));
drawnow;
fig­ure(gcf);
frame=getframe(gcf);
mov=addframe(mov,frame);
end
%Show both
for k=1:120,
shift=round(step*k);
for k=1:length(step);
r{k}=[r1(:,end-shift(k)+1:end,:) r1(:,1:end-shift(k),:)];
end
xx=[r{1};r{2};r{3};r{4};r{5};r{4};r{3};r{2};r{1}];
xx=[zeros(16,960,3)+128; xx;zeros(16,960,3)+128];
ccc=cc([end‑k+1:end 1:end‑k],:,:);
ccc=[zeros(16,960,3)+128; ccc;zeros(16,960,3)+128];
xc=min(xx,ccc);
if k==1,% make a nice transition
for f=0:0.05:0.95,
imshow(uint8(dou­ble(xc(1:2:end,1:2:end,:))*f+255*(1-f)));
drawnow;
fig­ure(gcf);
frame=getframe(gcf);
mov=addframe(mov,frame);
end,
end
imshow(xc(1:2:end,1:2:end,:));
if k drawnow;
fig­ure(gcf);
frame=getframe(gcf);
mov=addframe(mov,frame);
end
for f=0:0.05:0.95,% make a nice transition
imshow(uint8(dou­ble(xc(1:2:end,1:2:end,:))*(1-f)+0*f));
drawnow;
fig­ure(gcf);
frame=getframe(gcf);
mov=addframe(mov,frame);
end
mov=close(mov);

Leave a Comment

Your email address will not be published. Required fields are marked *

This website uses cookies. By continuing to use this site, you accept our use of cookies. 

Scroll to Top