Search code examples
for-loopanimationoctave

Octave using 'for' statement to show two animations simultaneously


I would like to make an animation of TOF-MS spectrometer (time-of-flight mass spectrometry) using the 'for' statement. I am able to make a script which animates the flight of ions inside the tube. This is the script:

%Definiranje konstanti
e = 1.609e-19;
u = 1.6605391e-27;
U = 15;
L = 1;
n = 1;

%Ulazni parametri i funkcije
m1 = 4; %He
m2 = 12; %C
m3 = 16; %O
T1 = L * sqrt( (m1 * u)/(2 * n * e * 1000 * U) );
v1 = L/T1;
T2 = L * sqrt( (m2 * u)/(2 * n * e * 1000 * U) );
v2 = L/T2;
T3 = L * sqrt( (m3 * u)/(2 * n * e * 1000 * U) );
v3 = L/T3;

%Opcije grafa
axis equal;
xlim ([0 1]);
ylim ([0 0.5]);
axis off;

%Linije spektrometra
rectangle ("position", [0.0, 0.0, 1, 0.3], 
           "curvature", [0.033, 0.1], 
           "linewidth", 1.5, 
           "facecolor", [0.9, 0.6, 0.4], 
           "facealpha", 0.1);
%Izvor iona           
rectangle ("position", [0.01, 0.13, 0.02, 0.04], 
           "curvature", [0, 0], 
           "linewidth", 1.5, 
           "facecolor", [0.5, 0.2, 0.8], 
           "facealpha", 0.1); 
%Napon
rectangle ("position", [0.04, 0.0, 0.025, 0.14], 
           "curvature", [0, 0], 
           "linewidth", 1.5, 
           "facecolor", [0.2, 0.2, 0.7], 
           "edgecolor", "none");
rectangle ("position", [0.04, 0.16, 0.025, 0.14], 
           "curvature", [0, 0], 
           "linewidth", 1.5, 
           "facecolor", [0.2, 0.2, 0.7], 
           "edgecolor", "none");
%Detektor
rectangle ("position", [0.99, 0.1, 0.01, 0.08], 
           "curvature", [0, 0], 
           "linewidth", 1.5, 
           "facecolor", [0.2, 0.2, 0.7], 
           "edgecolor", "none");          

%Tekst
text (-0.05, 0.15, "izvor \niona", "fontsize", 20);
text (0.05, 0.33, "ubrzavajuci \nnapon", "fontsize", 20);
text (0.99, 0.32, "detektor", "fontsize", 20);

%Legenda
%He
rectangle ("position", [0.3, 0.45, 0.01, 0.01], 
           "curvature", [1, 1], 
           "facecolor", [0.2, 0.8, 0.6], 
           "edgecolor", "none");
text (0.35, 0.455, "He^+", "fontsize", 20);
%C         
rectangle ("position", [0.2975, 0.40, 0.015, 0.015], 
           "curvature", [1, 1], 
           "facecolor", [0.4, 0.2, 0.8], 
           "edgecolor", "none");
text (0.35, 0.4075, "C^+", "fontsize", 20);
%O
rectangle ("position", [0.295, 0.35, 0.02, 0.02], 
           "curvature", [1, 1], 
           "facecolor", [0.8, 0.2, 0.4], 
           "edgecolor", "none");
text (0.35, 0.36, "O^+", "fontsize", 20);

%Ioni
t = 0 : 4d-8 : T3;
for k = 1 : length (t)
  
  %Ioni m1,v1
  h11 = rectangle ("position", [0.05 + v1 * t(k), 0.145, 0.01, 0.01], 
                  "curvature", [1, 1], 
                  "facecolor", [0.2, 0.8, 0.6], 
                  "edgecolor", "none");
  h12 = rectangle ("position", [0.04 + v1 * t(k), 0.148, 0.01, 0.01], 
                  "curvature", [1, 1], 
                  "facecolor", [0.2, 0.8, 0.6], 
                  "edgecolor", "none"); 
  h13 = rectangle ("position", [0.03 + v1 * t(k), 0.143, 0.01, 0.01], 
                  "curvature", [1, 1], 
                  "facecolor", [0.2, 0.8, 0.6], 
                  "edgecolor", "none");                  
  %Ioni m2,v2
  h21 = rectangle ("position", [0.05 + v2 * t(k), 0.1425, 0.015, 0.015], 
                  "curvature", [1, 1], 
                  "facecolor", [0.4, 0.2, 0.8], 
                  "edgecolor", "none"); 
  h22 = rectangle ("position", [0.04 + v2 * t(k), 0.1455, 0.015, 0.015], 
                  "curvature", [1, 1], 
                  "facecolor", [0.4, 0.2, 0.8], 
                  "edgecolor", "none");
  h23 = rectangle ("position", [0.025 + v2 * t(k), 0.1405, 0.015, 0.015], 
                  "curvature", [1, 1], 
                  "facecolor", [0.4, 0.2, 0.8], 
                  "edgecolor", "none");               
  %Ioni m3,v3
  h31 = rectangle ("position", [0.05 + v3 * t(k), 0.14, 0.02, 0.02], 
                  "curvature", [1, 1], 
                  "facecolor", [0.8, 0.2, 0.4], 
                  "edgecolor", "none");
  h32 = rectangle ("position", [0.06 + v3 * t(k), 0.142, 0.02, 0.02], 
                  "curvature", [1, 1], 
                  "facecolor", [0.8, 0.2, 0.4], 
                  "edgecolor", "none");
  h33 = rectangle ("position", [0.035 + v3 * t(k), 0.138, 0.02, 0.02], 
                  "curvature", [1, 1], 
                  "facecolor", [0.8, 0.2, 0.4], 
                  "edgecolor", "none");                  

  %Pauza izmedu dvije iteracije petlje
  pause (0.001);
  %Nakon svake iteracije, obrisati sliku iona iz prethodne
  delete (h11);
  delete (h12);
  delete (h13);
  delete (h21);
  delete (h22);
  delete (h23);
  delete (h31);
  delete (h32);
  delete (h33);
  
endfor

%Print slike
print primjer_tof_ms2.png

Now I would also like to add a spectrum which plots as the ions fly and hit the detector. The spectrum is the sum of Lorentz functions which have the peaks at time moments when the specific ion hits the detector. I made a script which animates this plot alone:

%Definiranje konstanti
e = 1.609e-19;
u = 1.6605391e-27;
U = 15;
L = 1;
n = 1;

%Ulazni parametri i funkcije
m1 = 4; %He
m2 = 12; %C
m3 = 16; %O
T1 = L * sqrt( (m1 * u)/(2 * n * e * 1000 * U) );
v1 = L/T1;
T2 = L * sqrt( (m2 * u)/(2 * n * e * 1000 * U) );
v2 = L/T2;
T3 = L * sqrt( (m3 * u)/(2 * n * e * 1000 * U) );
v3 = L/T3;

x01 = T1;
x02 = T2;
x03 = T3;
fwhm = 1d-7;
t = 0 : 0.4d-7 : 3d-6;
%Spektar = zbroj Lorentz-ovih funkcija (lf)
lf = ((fwhm^2)./((t-x01).^2 + fwhm^2))/(pi * fwhm) + ...
     ((fwhm^2)./((t-x02).^2 + fwhm^2))/(pi * fwhm) + ...
     ((fwhm^2)./((t-x03).^2 + fwhm^2))/(pi * fwhm);

for k = 1:length(t)
axes ("position", [0.5, 0.67, 0.2, 0.17]);          
plot (t(1:k), lf(1:k), "linewidth", 2);
axis ([0 3d-6 0 5d6])
legend ("off");
set (gca, "xtick", []);
set (gca, "ytick", []);
ht = title(['t = ' num2str(t(k)) ' s']);
pause (0.001);
delete (ht);
endfor
title(['t = ' num2str(t(k))]);

But when I try to combine these two codes, after the first iteration, only the spectrum plot continues to animate until the end, while the figure with ions as graphical objects stops. I tried to place both plots in the same 'for' loop:

%Definiranje konstanti
e = 1.609e-19;
u = 1.6605391e-27;
U = 15;
L = 1;
n = 1;

%Ulazni parametri i funkcije
m1 = 4; %He
m2 = 12; %C
m3 = 16; %O
T1 = L * sqrt( (m1 * u)/(2 * n * e * 1000 * U) );
v1 = L/T1;
T2 = L * sqrt( (m2 * u)/(2 * n * e * 1000 * U) );
v2 = L/T2;
T3 = L * sqrt( (m3 * u)/(2 * n * e * 1000 * U) );
v3 = L/T3;

%Opcije grafa
axis equal;
xlim ([0 1]);
ylim ([0 0.5]);
axis off;

%Linije spektrometra
rectangle ("position", [0.0, 0.0, 1, 0.3], 
           "curvature", [0.033, 0.1], 
           "linewidth", 1.5, 
           "facecolor", [0.9, 0.6, 0.4], 
           "facealpha", 0.1);
%Izvor iona           
rectangle ("position", [0.01, 0.13, 0.02, 0.04], 
           "curvature", [0, 0], 
           "linewidth", 1.5, 
           "facecolor", [0.5, 0.2, 0.8], 
           "facealpha", 0.1); 
%Napon
rectangle ("position", [0.04, 0.0, 0.025, 0.14], 
           "curvature", [0, 0], 
           "linewidth", 1.5, 
           "facecolor", [0.2, 0.2, 0.7], 
           "edgecolor", "none");
rectangle ("position", [0.04, 0.16, 0.025, 0.14], 
           "curvature", [0, 0], 
           "linewidth", 1.5, 
           "facecolor", [0.2, 0.2, 0.7], 
           "edgecolor", "none");
%Detektor
rectangle ("position", [0.99, 0.1, 0.01, 0.08], 
           "curvature", [0, 0], 
           "linewidth", 1.5, 
           "facecolor", [0.2, 0.2, 0.7], 
           "edgecolor", "none");          

%Tekst
text (-0.05, 0.15, "izvor \niona", "fontsize", 20);
text (0.05, 0.33, "ubrzavajuci \nnapon", "fontsize", 20);
text (0.99, 0.32, "detektor", "fontsize", 20);

%Legenda
%He
rectangle ("position", [0.3, 0.45, 0.01, 0.01], 
           "curvature", [1, 1], 
           "facecolor", [0.2, 0.8, 0.6], 
           "edgecolor", "none");
text (0.35, 0.455, "He^+", "fontsize", 20);
%C         
rectangle ("position", [0.2975, 0.40, 0.015, 0.015], 
           "curvature", [1, 1], 
           "facecolor", [0.4, 0.2, 0.8], 
           "edgecolor", "none");
text (0.35, 0.4075, "C^+", "fontsize", 20);
%O
rectangle ("position", [0.295, 0.35, 0.02, 0.02], 
           "curvature", [1, 1], 
           "facecolor", [0.8, 0.2, 0.4], 
           "edgecolor", "none");
text (0.35, 0.36, "O^+", "fontsize", 20);

%Ioni
t = 0 : 4d-8 : T3;
for k = 1 : length (t)
  
  %Ioni m1,v1
  h11 = rectangle ("position", [0.05 + v1 * t(k), 0.145, 0.01, 0.01], 
                  "curvature", [1, 1], 
                  "facecolor", [0.2, 0.8, 0.6], 
                  "edgecolor", "none");
  h12 = rectangle ("position", [0.04 + v1 * t(k), 0.148, 0.01, 0.01], 
                  "curvature", [1, 1], 
                  "facecolor", [0.2, 0.8, 0.6], 
                  "edgecolor", "none"); 
  h13 = rectangle ("position", [0.03 + v1 * t(k), 0.143, 0.01, 0.01], 
                  "curvature", [1, 1], 
                  "facecolor", [0.2, 0.8, 0.6], 
                  "edgecolor", "none");                  
  %Ioni m2,v2
  h21 = rectangle ("position", [0.05 + v2 * t(k), 0.1425, 0.015, 0.015], 
                  "curvature", [1, 1], 
                  "facecolor", [0.4, 0.2, 0.8], 
                  "edgecolor", "none"); 
  h22 = rectangle ("position", [0.04 + v2 * t(k), 0.1455, 0.015, 0.015], 
                  "curvature", [1, 1], 
                  "facecolor", [0.4, 0.2, 0.8], 
                  "edgecolor", "none");
  h23 = rectangle ("position", [0.025 + v2 * t(k), 0.1405, 0.015, 0.015], 
                  "curvature", [1, 1], 
                  "facecolor", [0.4, 0.2, 0.8], 
                  "edgecolor", "none");               
  %Ioni m3,v3
  h31 = rectangle ("position", [0.05 + v3 * t(k), 0.14, 0.02, 0.02], 
                  "curvature", [1, 1], 
                  "facecolor", [0.8, 0.2, 0.4], 
                  "edgecolor", "none");
  h32 = rectangle ("position", [0.06 + v3 * t(k), 0.142, 0.02, 0.02], 
                  "curvature", [1, 1], 
                  "facecolor", [0.8, 0.2, 0.4], 
                  "edgecolor", "none");
  h33 = rectangle ("position", [0.035 + v3 * t(k), 0.138, 0.02, 0.02], 
                  "curvature", [1, 1], 
                  "facecolor", [0.8, 0.2, 0.4], 
                  "edgecolor", "none");                  

  hold on;                  
                    
  x01 = T1;
  x02 = T2;
  x03 = T3;
  fwhm = 1d-7;
  %Spektar = zbroj Lorentz-ovih funkcija (lf)
  lf = ((fwhm^2)./((t-x01).^2 + fwhm^2))/(pi * fwhm) + ...
       ((fwhm^2)./((t-x02).^2 + fwhm^2))/(pi * fwhm) + ...
       ((fwhm^2)./((t-x03).^2 + fwhm^2))/(pi * fwhm);
  
  axes ("position", [0.5, 0.67, 0.2, 0.17]);          
  plot (t(1:k), lf(1:k), "linewidth", 2);
  axis ([0 3d-6 0 5d6])
  legend ("off");
  set (gca, "xtick", []);
  set (gca, "ytick", []);
  ht = title(['t = ' num2str(t(k)) ' s']);
  delete (ht);
  title(['t = ' num2str(t(k))]);                  
                  
  %Pauza izmedu dvije iteracije petlje
  pause (0.001);
  %Nakon svake iteracije, obrisati sliku iona iz prethodne
  delete (h11);
  delete (h12);
  delete (h13);
  delete (h21);
  delete (h22);
  delete (h23);
  delete (h31);
  delete (h32);
  delete (h33);

hold off; 
endfor

%Print slike
print primjer_tof_ms2.png

How to animate these two groups of objects on the same figure?


Solution

  • You are creating axes on each iteration of the loop with this line

    axes ("position", [0.5, 0.67, 0.2, 0.17]); 
    

    This also sets them as current ones. Then, when you do your rectangle thingy, those rectangles are drawn in the small axes you've created for spectrum, which is instantly covered by new ones you create. The first axes that you've created implicitly with axis equal; stay unused for the whole time.

    Instead you should create your graphic objects outside the loop and use references to them inside. Most drawing functions can accept a handle to an axes as their first argument. Or you can explicitly set current axes before calling drawing functions. The minimal exsample is:

    h = figure;
    ax1 = axes('position',[.1,.5,.4,.4]);
    ax2 = axes('position',[.5,.1,.4,.4]);
    
    v = -10; 
    wmin = 0; dw=0.1; Wmax = 6*pi();
    w = [wmin:dw:Wmax];
    t0 = 0; dt = 0.01; T = 10;
    for t = t0:dt:T;
        x = w/Wmax .*cos(w+t*v);
        y = w/Wmax .*sin(w+t*v);
        plot(ax1,x,y);%specificaly plot to ax1 (also sets it as current)
        axes(ax2)%set ax2 as current axis 
        plot(w,x,w,y);%plot to the current axis
        pause(0.1)
    end
    

    Then there's also an number of caveats, unexpected behaviors or bugs that depend on chosen graphic toolkit and octave version. One I've run into while trying your code is that title object gets destroyed by plot, so you have to recreate it instead of updating it's text property. I vaguely recall having to resort to other workarounds in other situations related to drawing stuff in octave before. So, an understanding of how it is supposed to work probably helps a bit, giving the documentation a read might be worth it in the long run. I'd recommend something else but that's all I've got.


    Since I've started answering by trying your code, you can have a slightly more working version of it. No warranty though.

    %Definiranje konstanti
    e = 1.609e-19;
    u = 1.6605391e-27;
    U = 15;
    L = 1;
    n = 1;
    
    %Ulazni parametri i funkcije
    m1 = 4; %He
    m2 = 12; %C
    m3 = 16; %O
    T1 = L * sqrt( (m1 * u)/(2 * n * e * 1000 * U) );
    v1 = L/T1;
    T2 = L * sqrt( (m2 * u)/(2 * n * e * 1000 * U) );
    v2 = L/T2;
    T3 = L * sqrt( (m3 * u)/(2 * n * e * 1000 * U) );
    v3 = L/T3;
    
    %Opcije grafa
    ax1 = axes();%create axes for particles 
    axis equal;
    xlim ([0 1]);
    ylim ([0 0.5]);
    axis off;
    
    ax2 = axes ("position", [0.5, 0.67, 0.2, 0.17]);%create axes for spectrum (also activates them)
    axis ([0 3d-6 0 5d6])
    legend ("off");
    set (ax2, "xtick", []);
    set (ax2, "ytick", []);
    
    axes(ax1)%activate axes for particles 
    %Linije spektrometra
    rectangle ("position", [0.0, 0.0, 1, 0.3], 
               "curvature", [0.033, 0.1], 
               "linewidth", 1.5, 
               "facecolor", [0.9, 0.6, 0.4], 
               "facealpha", 0.1);
    %Izvor iona           
    rectangle ("position", [0.01, 0.13, 0.02, 0.04], 
               "curvature", [0, 0], 
               "linewidth", 1.5, 
               "facecolor", [0.5, 0.2, 0.8], 
               "facealpha", 0.1); 
    %Napon
    rectangle ("position", [0.04, 0.0, 0.025, 0.14], 
               "curvature", [0, 0], 
               "linewidth", 1.5, 
               "facecolor", [0.2, 0.2, 0.7], 
               "edgecolor", "none");
    rectangle ("position", [0.04, 0.16, 0.025, 0.14], 
               "curvature", [0, 0], 
               "linewidth", 1.5, 
               "facecolor", [0.2, 0.2, 0.7], 
               "edgecolor", "none");
    %Detektor
    rectangle ("position", [0.99, 0.1, 0.01, 0.08], 
               "curvature", [0, 0], 
               "linewidth", 1.5, 
               "facecolor", [0.2, 0.2, 0.7], 
               "edgecolor", "none");          
    
    %Tekst
    text (-0.05, 0.15, "izvor \niona", "fontsize", 20);
    text (0.05, 0.33, "ubrzavajuci \nnapon", "fontsize", 20);
    text (0.99, 0.32, "detektor", "fontsize", 20);
    
    %Legenda
    %He
    rectangle ("position", [0.3, 0.45, 0.01, 0.01], 
               "curvature", [1, 1], 
               "facecolor", [0.2, 0.8, 0.6], 
               "edgecolor", "none");
    text (0.35, 0.455, "He^+", "fontsize", 20);
    %C         
    rectangle ("position", [0.2975, 0.40, 0.015, 0.015], 
               "curvature", [1, 1], 
               "facecolor", [0.4, 0.2, 0.8], 
               "edgecolor", "none");
    text (0.35, 0.4075, "C^+", "fontsize", 20);
    %O
    rectangle ("position", [0.295, 0.35, 0.02, 0.02], 
               "curvature", [1, 1], 
               "facecolor", [0.8, 0.2, 0.4], 
               "edgecolor", "none");
    text (0.35, 0.36, "O^+", "fontsize", 20);
    
    %Ioni
    t = 0 : 4d-8 : T3;
    for k = 1 : length (t)
      axes(ax1)%activate axes for particles
      %Ioni m1,v1
      h11 = rectangle ("position", [0.05 + v1 * t(k), 0.145, 0.01, 0.01], 
                      "curvature", [1, 1], 
                      "facecolor", [0.2, 0.8, 0.6], 
                      "edgecolor", "none");
      h12 = rectangle ("position", [0.04 + v1 * t(k), 0.148, 0.01, 0.01], 
                      "curvature", [1, 1], 
                      "facecolor", [0.2, 0.8, 0.6], 
                      "edgecolor", "none"); 
      h13 = rectangle ("position", [0.03 + v1 * t(k), 0.143, 0.01, 0.01], 
                      "curvature", [1, 1], 
                      "facecolor", [0.2, 0.8, 0.6], 
                      "edgecolor", "none");                  
      %Ioni m2,v2
      h21 = rectangle ("position", [0.05 + v2 * t(k), 0.1425, 0.015, 0.015], 
                      "curvature", [1, 1], 
                      "facecolor", [0.4, 0.2, 0.8], 
                      "edgecolor", "none"); 
      h22 = rectangle ("position", [0.04 + v2 * t(k), 0.1455, 0.015, 0.015], 
                      "curvature", [1, 1], 
                      "facecolor", [0.4, 0.2, 0.8], 
                      "edgecolor", "none");
      h23 = rectangle ("position", [0.025 + v2 * t(k), 0.1405, 0.015, 0.015], 
                      "curvature", [1, 1], 
                      "facecolor", [0.4, 0.2, 0.8], 
                      "edgecolor", "none");               
      %Ioni m3,v3
      h31 = rectangle ("position", [0.05 + v3 * t(k), 0.14, 0.02, 0.02], 
                      "curvature", [1, 1], 
                      "facecolor", [0.8, 0.2, 0.4], 
                      "edgecolor", "none");
      h32 = rectangle ("position", [0.06 + v3 * t(k), 0.142, 0.02, 0.02], 
                      "curvature", [1, 1], 
                      "facecolor", [0.8, 0.2, 0.4], 
                      "edgecolor", "none");
      h33 = rectangle ("position", [0.035 + v3 * t(k), 0.138, 0.02, 0.02], 
                      "curvature", [1, 1], 
                      "facecolor", [0.8, 0.2, 0.4], 
                      "edgecolor", "none");                  
    
      hold on;                  
                        
      x01 = T1;
      x02 = T2;
      x03 = T3;
      fwhm = 1d-7;
      %Spektar = zbroj Lorentz-ovih funkcija (lf)
      lf = ((fwhm^2)./((t-x01).^2 + fwhm^2))/(pi * fwhm) + ...
           ((fwhm^2)./((t-x02).^2 + fwhm^2))/(pi * fwhm) + ...
           ((fwhm^2)./((t-x03).^2 + fwhm^2))/(pi * fwhm);
      
      plot (ax2,t(1:k), lf(1:k), "linewidth", 2);%plot on spectrum axes (activates them)
    
            legend ("off");
            set (ax2, "xtick", []);%these properties are reset by each plot, need to set them in loop
            set (ax2, "ytick", []);
            title(['t = ' num2str(t(k))]);                  
                      
      %Pauza izmedu dvije iteracije petlje
      pause (0.001);
      %Nakon svake iteracije, obrisati sliku iona iz prethodne
      delete (h11);
      delete (h12);
      delete (h13);
      delete (h21);
      delete (h22);
      delete (h23);
      delete (h31);
      delete (h32);
      delete (h33);
    
    hold off; 
    endfor