[cacsd] fix demo Graphics => Technical plots => bode
[scilab.git] / scilab / modules / cacsd / macros / bode.sci
index d63b832..a9125dc 100644 (file)
@@ -1,12 +1,16 @@
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C)  1985-2010 - INRIA - Serge Steer
-// This file must be used under the terms of the CeCILL.
-// This source file is licensed as described in the file COPYING, which
-// you should have received as part of this distribution.  The terms
-// are also available at
-// http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
-
-function [] = bode(varargin)
+// 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.
+// This file was originally licensed under the terms of the CeCILL v2.1,
+// and continues to be available under such terms.
+// For more information, see the COPYING file which you should have received
+// along with this program.
+
+function bode(varargin)
     rhs = size(varargin)
 
     if rhs == 0 then
@@ -41,7 +45,7 @@ function [] = bode(varargin)
     fname = "bode"; // For error messages
     fmax = [];
     discr = %f; // For Shannon limit
-    if or(typeof(varargin(1)) == ["state-space" "rational"]) then
+    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";
@@ -89,21 +93,20 @@ function [] = bode(varargin)
             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();
@@ -114,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
@@ -140,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
@@ -166,48 +175,60 @@ function [] = bode(varargin)
         e.foreground = 5;
     end
     xtitle("", _("Frequency (Hz)"), _("Phase (degree)"));
+
     // 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);
 
-    if rad == %t then
-        bode_Hz2rad_2(fig);
+    // 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
 
-endfunction
+    // Returns to the initial axes
+    sca(sciCurAxes);
 
-function [] = bode_Hz2rad_2(h)
-    // 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
-
-    // k = 1 phase, k = 2 gain
-    labels = ["Phase (degree)"; "Magnitude (dB)"];
-    pos_h = [9, 5];
-    for k=1:2
-        for i=1:size(h.children(k).children, 1)
-            if h.children(k).children(i).type == "Compound"
-                for j=1:size(h.children(k).children(i).children, 1)
-                    h.children(k).children(i).children(j).data(:, 1) = h.children(k).children(i).children(j).data(:, 1)*2*%pi;
+    // 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
+        labels = [_("Phase (degree)"); _("Magnitude (dB)")];
+        pos_h = [9, 5];
+        for k=1:2
+            for i=1:size(fig.children(k).children, 1)
+                if fig.children(k).children(i).type == "Compound"
+                    for j=1:size(fig.children(k).children(i).children, 1)
+                        fig.children(k).children(i).children(j).data(:, 1) = fig.children(k).children(i).children(j).data(:, 1)*2*%pi;
+                    end
+
+                    // h.children(k).title.text = h.children(k).y_label.text;
+                    xmin1 = fig.children(k).data_bounds(1)*2*%pi;
+                    xmax1 = fig.children(k).data_bounds(2)*2*%pi;
+                    ymin1 = fig.children(k).data_bounds(3);
+                    ymax1 = fig.children(k).data_bounds(4);
+
+                    rect = [xmin1, ymin1, xmax1, ymax1];
+                    nb_dec = log(xmax1/xmin1)/log(10);
+                    fig.children(k).x_label.text = _("Frequency (rad/s)");
+                    fig.children(k).x_location = "bottom";
+                    fig.children(k).y_label.text = labels(k);
+                    replot(rect, fig.children(k));
                 end
-
-                // h.children(k).title.text = h.children(k).y_label.text;
-                xmin1 = h.children(k).data_bounds(1)*2*%pi;
-                xmax1 = h.children(k).data_bounds(2)*2*%pi;
-                ymin1 = h.children(k).data_bounds(3);
-                ymax1 = h.children(k).data_bounds(4);
-
-                rect = [xmin1, ymin1, xmax1, ymax1];
-                nb_dec = log(xmax1/xmin1)/log(10);
-                h.children(k).x_label.text = "Frequency (rad/s)";
-                h.children(k).x_location = "bottom";
-                h.children(k).y_label.text = labels(k);
-                replot(rect, h.children(k));
             end
         end
     end