Interactivity in octave through uicontrol

  • We need to run each cell as a octave script using octave-gui
  • This is because uicontrol is not supported for octave-cli kernel which jupyter lab uses
  • Let us plot the function $y = \sin(2\pi k x)$
  • We'll vary the frequency k and the number of points N
  • We first set the default plot properties using the set command.
  • We then specify the qt toolkit for plotting.
  • Then we reduce the plot window to accomodate the various slider objects which will change the control parameters.
  • After that we begin our container function which includes the function to be plotted.
  • After the container functions we define the various labels and sliders that our GUI object will contain.
  • NOTE: We have normalized the slider between 0 and 1 so that we modify the range in the function itself. This way we can reuse the same slider definition
In [2]:
set(0, "defaultlinelinewidth", 2);
set (0, "defaulttextfontname", "TimesNewRoman")
set (0, "defaulttextfontsize", 20)
set (0, "DefaultAxesFontName", "TimesNewRoman")
set(0, 'DefaultAxesFontSize', 20)

close all
clear h

graphics_toolkit qt

h.ax = axes ("position", [0.05 0.4 0.5 0.5]); #reduce plot windows size to accomodate sliders

function update_plot (obj, init = false)
  ## gcbo holds the handle of the control
  h = guidata (obj);  
  replot = false;
  recalc = false;
  switch (gcbo)                   # If we make any change then we replot
    case {h.print_pushbutton}
      fn =  uiputfile ("*.png");
      print (fn);
    case {h.freq_slider}
      recalc = true;
    case {h.iter_slider}
      recalc = true;
  end

  if (recalc || init)
    k = 0.1+ 9.9*get (h.freq_slider, "value"); # change the range of frequency slider
    r = floor(20 + 180*get (h.iter_slider, "value")); # change the range of points slider
    x = linspace(0, 2*pi*k, r);                                    
     # set the labels sliders
    set (h.freq_label, "string", sprintf ("freq: %.1f", k)); 
    set (h.iter_label, "string", sprintf ("Points: %d", r));      

    y = sin(x);
    h.plot = plot(x, y);
    guidata (obj, h);
    else
      set (h.plot, "ydata", y);
   end
end

# specify the GUI plot properties like sliders and label formatting

## print figure
h.print_pushbutton = uicontrol ("style", "pushbutton",
                                "units", "normalized",
                                "string", "print plot\n(pushbutton)",
                                "callback", @update_plot,
                                "position", [0.6 0.45 0.35 0.09]);
## freq
h.freq_label = uicontrol ("style", "text",
                           "units", "normalized",
                           "string", "freq:",
                           "horizontalalignment", "left",
                           "position", [0.05 0.25 0.35 0.08]);

h.freq_slider = uicontrol ("style", "slider",
                            "units", "normalized",
                            "string", "slider",
                            "callback", @update_plot,
                            "value", 0.1,
                            "position", [0.05 0.20 0.35 0.06]);
                            
h.iter_label = uicontrol ("style", "text",
                           "units", "normalized",
                           "string", "Points:",
                           "horizontalalignment", "left",
                           "position", [0.05 0.15 0.35 0.08]);

h.iter_slider = uicontrol ("style", "slider",
                            "units", "normalized",
                            "string", "slider",
                            "callback", @update_plot,
                            "value", 0.5,
                            "position", [0.05 0.10 0.35 0.06]);



set (gcf, "color", get(0, "defaultuicontrolbackgroundcolor"))
guidata (gcf, h)
update_plot (gcf, true);
Inline plot failed, consider trying another graphics toolkit
error: __gnuplot_draw_figure__: unknown object class, uicontrol
error: called from
    _make_figures>safe_print at line 125 column 7
    _make_figures at line 49 column 13

The plot should look like this:

image.png

  • Let us now plot the fixed point iteration value and change the initial guess point and number of iterations
  • $y = \log(3) + 2\log(x)$
  • This time we define the function outside the container function
In [3]:
clear;
clc; close all;
function y= fx(x)
    y= log(3) + 2*log(x);
end

h.ax = axes ("position", [0.05 0.4 0.5 0.5]);  #reduce plot windows size to accomodate sliders
h.fcn = @(x) fx(x);

function update_plot (obj, init = false)
  ## gcbo holds the handle of the control
  h = guidata (obj);
  replot = false;
  recalc = false;
  switch (gcbo)                       # If we make any change then we replot
    case {h.print_pushbutton}
      fn =  uiputfile ("*.png");
      print (fn);
    case {h.guess_slider}
      recalc = true;
    case {h.iter_slider}
      recalc = true;
  end

  if (recalc || init)
    xg = 1+ 4*get (h.guess_slider, "value");
    Niter = floor(1 + 20*get (h.iter_slider, "value"));
    x = zeros(1,Niter);
    set (h.guess_label, "string", sprintf ("Guess: %.1f", xg));
    set (h.iter_label, "string", sprintf ("Niter: %d", Niter));      
    x(1) = xg;
      for i=2:Niter+1
        x(i) = h.fcn(x(i-1));
      end
      
      h.plot = plot(0:1:Niter, x);                  
     
      guidata (obj, h);
    else
      set (h.plot, "ydata", y);
   end
end

# specify the GUI plot properties like sliders and label formatting

## print figure
h.print_pushbutton = uicontrol ("style", "pushbutton",
                                "units", "normalized",
                                "string", "print plot\n(pushbutton)",
                                "callback", @update_plot,
                                "position", [0.6 0.45 0.35 0.09]);
## guess
h.guess_label = uicontrol ("style", "text",
                           "units", "normalized",
                           "string", "Guess:",
                           "horizontalalignment", "left",
                           "position", [0.05 0.25 0.35 0.08]);

h.guess_slider = uicontrol ("style", "slider",
                            "units", "normalized",
                            "string", "slider",
                            "callback", @update_plot,
                            "value", 0.1,
                            "position", [0.05 0.20 0.35 0.06]);
                    
h.iter_label = uicontrol ("style", "text",
                           "units", "normalized",
                           "string", "Iteration:",
                           "horizontalalignment", "left",
                           "position", [0.05 0.15 0.35 0.08]);

h.iter_slider = uicontrol ("style", "slider",
                            "units", "normalized",
                            "string", "slider",
                            "callback", @update_plot,
                            "value", 0.5,
                            "position", [0.05 0.10 0.35 0.06]);

set (gcf, "color", get(0, "defaultuicontrolbackgroundcolor"))
guidata (gcf, h)
update_plot (gcf, true);
Inline plot failed, consider trying another graphics toolkit
error: __gnuplot_draw_figure__: unknown object class, uicontrol
error: called from
    _make_figures>safe_print at line 125 column 7
    _make_figures at line 49 column 13

image.png

  • Now let us look at the iteration diagram
In [2]:
clear all;
clc;
function y= fx(x)
    y= log(3) + 2*log(x);
end

h.ax = axes ("position", [0.05 0.4 0.5 0.5]);  #reduce plot windows size to accomodate sliders
h.fcn = @(x) fx(x);

function update_plot (obj, init = false)

  ## gcbo holds the handle of the control
  h = guidata (obj);
  replot = false;
  recalc = false;
  switch (gcbo)                     # If we make any change then we replot
    case {h.print_pushbutton}
      fn =  uiputfile ("*.png");
      print (fn);
    case {h.guess_slider}
      recalc = true;
    case {h.iter_slider}
      recalc = true;
  end

  if (recalc || init)
    x = linspace (0.3, 5);
    xg = 1+ 4*get (h.guess_slider, "value");
    Niter = floor(1 + 20*get (h.iter_slider, "value"));
    set (h.guess_label, "string", sprintf ("Guess: %.1f", xg));
    set (h.iter_label, "string", sprintf ("Niter: %d", Niter));
    y = h.fcn (x);
      h.plot = plot (x, y, "b");
      hold on;
      h.plot = plot(x, x, "r");
      for i=1:Niter
        xn = h.fcn(xg);
        h.plot = plot(xg, h.fcn(xg), 'ok', markersize=2);
        x2 = xn; y2 = x2;
        h.plot = plot(x2, y2, 'ok', markersize=2 );
        h.plot = plot([xg, x2], [h.fcn(xg), y2],'Color', 'black' );
        h.plot = plot([x2, x2], [y2, h.fcn(x2)], 'Color','red' );
        xg = xn;
      end
      
      guidata (obj, h);
      hold off;
    else
      set (h.plot, "ydata", y);
   end
end

# specify the GUI plot properties like sliders and label formatting

## print figure
h.print_pushbutton = uicontrol ("style", "pushbutton",
                                "units", "normalized",
                                "string", "print plot\n(pushbutton)",
                                "callback", @update_plot,
                                "position", [0.6 0.45 0.35 0.09]);
## guess
h.guess_label = uicontrol ("style", "text",
                           "units", "normalized",
                           "string", "Guess:",
                           "horizontalalignment", "left",
                           "position", [0.05 0.25 0.35 0.08]);

h.guess_slider = uicontrol ("style", "slider",
                            "units", "normalized",
                            "string", "slider",
                            "callback", @update_plot,
                            "value", 0.1,
                            "position", [0.05 0.20 0.35 0.06]);
                            
h.iter_label = uicontrol ("style", "text",
                           "units", "normalized",
                           "string", "Iteration:",
                           "horizontalalignment", "left",
                           "position", [0.05 0.15 0.35 0.08]);

h.iter_slider = uicontrol ("style", "slider",
                            "units", "normalized",
                            "string", "slider",
                            "callback", @update_plot,
                            "value", 0.5,
                            "position", [0.05 0.10 0.35 0.06]);

set (gcf, "color", get(0, "defaultuicontrolbackgroundcolor"));
guidata (gcf, h);
update_plot (gcf, true);
Inline plot failed, consider trying another graphics toolkit
error: __gnuplot_draw_figure__: unknown object class, uicontrol
error: called from
    _make_figures>safe_print at line 125 column 7
    _make_figures at line 49 column 13

image.png

In [ ]: