[cacsd] fix demo Graphics => Technical plots => bode
[scilab.git] / scilab / modules / cacsd / macros / bode.sci
index e1d4fb3..a9125dc 100644 (file)
@@ -1,6 +1,7 @@
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C)  1985-2010 - INRIA - Serge Steer
+// Copyright (C) 1985 - 2016 - INRIA - Serge Steer
 // Copyright (C) 2012 - 2016 - Scilab Enterprises
+// Copyright (C) 2018 - Samuel GOUGEON
 //
 // This file is hereby licensed under the terms of the GNU GPL v2.0,
 // pursuant to article 5.3.4 of the CeCILL v.2.1.
@@ -9,7 +10,7 @@
 // For more information, see the COPYING file which you should have received
 // along with this program.
 
-function [] = bode(varargin)
+function bode(varargin)
     rhs = size(varargin)
 
     if rhs == 0 then
@@ -44,8 +45,8 @@ function [] = bode(varargin)
     fname = "bode"; // For error messages
     fmax = [];
     discr = %f; // For Shannon limit
-    if or(typeof(varargin(1)) == ["state-space" "rational"]) then
-// sys, fmin, fmax [,pas] or sys, frq
+    if or(typeof(varargin(1)) == ["state-space" "rational" "zpk"]) then
+        // sys, fmin, fmax [,pas] or sys, frq
         refdim = 1; // for error message
         discr = varargin(1).dt<>"c";
         if rhs == 1 then // sys
@@ -53,7 +54,7 @@ function [] = bode(varargin)
         elseif rhs == 2 then // sys, frq
             if size(varargin(2), 2) < 2 then
                 error(msprintf(_("%s: Wrong size for input argument #%d: A row vector with length>%d expected.\n"), ..
-                               fname, 2, 1))
+                fname, 2, 1))
             end
             [frq, repf] = repfreq(varargin(1:rhs));
         elseif or(rhs == (3:4)) then // sys, fmin, fmax [,pas]
@@ -64,49 +65,48 @@ function [] = bode(varargin)
         [phi, d] = phasemag(repf);
         if rhs >= 3 then fmax = varargin(3); end
     elseif type(varargin(1)) == 1 then
-// frq, db, phi [,comments] or frq, repf [,comments]
+        // frq, db, phi [,comments] or frq, repf [,comments]
         refdim = 2;
         select rhs
-            case 2 then // frq,repf
-                frq = varargin(1);
-                if size(frq, 2) < 2 then
-                    error(msprintf(_("%s: Wrong size for input argument #%d: A row vector with length>%d expected.\n"), ..
-                                   fname, 1, 1))
-                end
-                if size(frq, 2) <> size(varargin(2), 2) then
-                    error(msprintf(_("%s: Incompatible input arguments #%d and #%d: Same column dimensions expected.\n"), ..
-                                   fname, 1, 2))
-                end
-                [phi, d] = phasemag(varargin(2));
-            case 3 then  // frq, db, phi
-                [frq, d, phi] = varargin(1:rhs);
-                if size(frq, 2) <> size(d, 2) then
-                    error(msprintf(_("%s: Incompatible input arguments #%d and #%d: Same column dimensions expected.\n"), ..
-                                   fname, 1, 2))
-                end
-                if size(frq, 2) <> size(phi, 2) then
-                    error(msprintf(_("%s: Incompatible input arguments #%d and #%d: Same column dimensions expected.\n"), ..
-                                   fname, 1, 3))
-                end
+        case 2 then // frq,repf
+            frq = varargin(1);
+            if size(frq, 2) < 2 then
+                error(msprintf(_("%s: Wrong size for input argument #%d: A row vector with length>%d expected.\n"), ..
+                fname, 1, 1))
+            end
+            if size(frq, 2) <> size(varargin(2), 2) then
+                error(msprintf(_("%s: Incompatible input arguments #%d and #%d: Same column dimensions expected.\n"), ..
+                fname, 1, 2))
+            end
+            [phi, d] = phasemag(varargin(2));
+        case 3 then  // frq, db, phi
+            [frq, d, phi] = varargin(1:rhs);
+            if size(frq, 2) <> size(d, 2) then
+                error(msprintf(_("%s: Incompatible input arguments #%d and #%d: Same column dimensions expected.\n"), ..
+                fname, 1, 2))
+            end
+            if size(frq, 2) <> size(phi, 2) then
+                error(msprintf(_("%s: Incompatible input arguments #%d and #%d: Same column dimensions expected.\n"), ..
+                fname, 1, 3))
+            end
         else
             error(msprintf(_("%s: Wrong number of input arguments: %d to %d expected.\n"), fname, 2, 4))
         end
     else
-        error(msprintf(_("%s: Wrong type for input argument #%d: Linear dynamical system or row vector of floats expected.\n"),fname,1))
+        ierr=execstr("%"+overloadname(varargin(1))+"_bode(varargin(:))","errcatch")
+        if ierr<>0 then
+            error(msprintf(_("%s: Wrong type for input argument #%d: Linear dynamical system or row vector of floats expected.\n"),fname,1))
+        end
+        return
     end
     frq = frq';
     d = d';
     phi = phi';
     [n, mn] = size(d);
 
-    if comments == [] then
-        hx = 0.48;
-    else
-        if size(comments, "*") <> mn then
-            error(mprintf(_("%s: Incompatible input arguments #%d and #%d: Same number of elements expected.\n"), ...
-                          fname, refdim, rhs+1))
-        end
-        hx = 0.43;
+    if comments <> [] & size(comments, "*") <> mn then
+        msg = _("%s: Incompatible input arguments #%d and #%d: Same number of elements expected.\n")
+        error(mprintf(msg, fname, refdim, rhs+1))
     end
 
     fig = gcf();
@@ -117,12 +117,14 @@ function [] = bode(varargin)
     axes = sciCurAxes;
     wrect = axes.axes_bounds;
 
-
-// Magnitude
-    axes.axes_bounds = [wrect(1)+0, wrect(2)+0, wrect(3)*1.0, wrect(4)*hx*0.95];
+    // Magnitude plot
+    // --------------
+    axes.axes_bounds = [wrect(1), wrect(2), wrect(3), wrect(4)*0.5];
     axes.data_bounds = [min(frq), min(d); max(frq), max(d)];
     axes.log_flags = "lnn";
     axes.grid = color("lightgrey")*ones(1, 3);
+    axes.grid_style = [8 8];
+    axes.sub_ticks(1) = 8;
     axes.axes_visible = "on";
     axes.clip_state = "clipgrf";
     if size(d, 2) > 1 & size(frq, 2) == 1 then
@@ -130,7 +132,7 @@ function [] = bode(varargin)
     else
         xpolys(frq, d, 1:mn);
     end
-// Set datatips info
+    // Set datatips info
     e = gce();
 
     for i=1:size(e.children, "*")
@@ -143,13 +145,17 @@ function [] = bode(varargin)
         e.foreground = 5;
     end
     xtitle("", _("Frequency (Hz)"), _("Magnitude (dB)"));
+    axesM = axes;
 
-// Phase
+    // Phase plot
+    // ----------
     axes = newaxes();
-    axes.axes_bounds = [wrect(1)+0, wrect(2)+wrect(4)*hx, wrect(3)*1.0, wrect(4)*hx*0.95];
+    axes.axes_bounds = [wrect(1), wrect(2)+wrect(4)*0.5, wrect(3), wrect(4)*0.5];
     axes.data_bounds = [min(frq), min(phi); max(frq), max(phi)];
     axes.log_flags = "lnn";
     axes.grid = color("lightgrey")*ones(1, 3);
+    axes.grid_style = [8 8];
+    axes.sub_ticks(1) = 8;
     axes.axes_visible = "on";
     axes.clip_state = "clipgrf";
     if size(phi, 2) > 1 & size(frq, 2) == 1 then
@@ -158,7 +164,7 @@ function [] = bode(varargin)
         xpolys(frq, phi, 1:mn);
     end
     ephi = gce();
-// Set datatips info
+    // Set datatips info
     for i=1:size(ephi.children, "*")
         ephi.children(i).display_function = "formatBodePhaseTip";
     end
@@ -169,19 +175,38 @@ function [] = bode(varargin)
         e.foreground = 5;
     end
     xtitle("", _("Frequency (Hz)"), _("Phase (degree)"));
-// Create legend
+
+    // Create legend
+    // -------------
     if comments <> [] then
         c = captions(ephi.children, comments, "lower_caption");
         c.background = get(gcf(), "background");
     end
+
+    // Rendering
     fig.immediate_drawing = immediate_drawing;
-// Return to the previous scale
-    set("current_axes", sciCurAxes);
 
+    // Post-tuning the vertical distribution of Bode plots
+    // ---------------------------------------------------
+    // (only after rendering, otherwise the legend position is [0 0] (bug))
+    if comments <> [] then
+        LgH = (1-c.position(2))*wrect(4)*0.5; // Legend height
+        // Ah = Magnitude axes height.
+        // Ah + Ah+LgH*Ah/0.5 = wrect(4)  => Ah (1 + 1 + 2*LgH) = wrect(4)
+        Ah = wrect(4)/(2+2*LgH);
+        axes.axes_bounds([2 4]) = [wrect(2)+Ah, wrect(4)-Ah];
+        axesM.axes_bounds(4) = Ah*1.05;  // Magnitude plot
+    end
+
+    // Returns to the initial axes
+    sca(sciCurAxes);
+
+    // rad/s mode
+    // ----------
     if rad == %t then
-// This function modifies the Bode diagrams for a rad/s display instead of Hz.
-// h is a hanlde of a figure containing Bode diagrams.
-// Ref: http://forge.scilab.org/index.php/p/cpge/source/tree/HEAD/macros/bode_Hz2rad_2.sci
+        // This function modifies the Bode diagrams for a rad/s display instead of Hz.
+        // h is a hanlde of a figure containing Bode diagrams.
+        // Ref: http://forge.scilab.org/index.php/p/cpge/source/tree/HEAD/macros/bode_Hz2rad_2.sci
         labels = [_("Phase (degree)"); _("Magnitude (dB)")];
         pos_h = [9, 5];
         for k=1:2