[Scilab-users] Plots on second Y axis

mathias_magdowski mathias.magdowski at ovgu.de
Tue Mar 28 09:51:46 CEST 2017


I have extended the given example in a way that the left and right y axis get
some kind of intelligent equal scaling, so that a joined grid for both axes
would fit. If one of the axes includes the value of y = 0, both axes will
also share the same "base line".

Here is the function:

// Function for plotting a diagram with two y axes
// Input:
//  x  - x values -> vector
//  y1 - y values for the  for the left y axis -> vector
//  y2 - y values for the right y axis -> vector
// Output:
//  a1, a2         - axes -> handle
function [a1,a2]=plotyy(x,y1,y2)
    // example for a diagram with two y axes
    // see:
https://commons.wikimedia.org/wiki/File:Trace_ln_sqrt_1_2_deux_echelles_scilab.svg
    // and:  
http://mailinglists.scilab.org/Scilab-users-Plots-on-second-Y-axis-td4025895.html
    // generation of the right y axis
    a1=newaxes();
    a1.tight_limits=["on","off","off"];
    // plot of the first function
    plot(x,y1);
    // generation of the right y axis
    a2=newaxes();
    // no background for this plot
    a2.filled="off";
    // hide second x axis
    a2.axes_visible(1)="off";
    a2.y_location = "right";
    a2.tight_limits = "on";
    // plot of the second function
    plot(x,y2,"r");
    // set font size
    a1.font_size=3;
    a2.font_size=3;
    // delete tick marks of the first x axis
    a1.x_ticks=tlist(["ticks","locations","labels"],[],[])
    // add a grid
    a1.grid=[1,1];
    a2.grid=[1,1];
    // end of plotting
    // algorithm to equally scale the axes
    // minimum of the first function -> scalar
    y1min=min(y1);
    // maximum of the first function -> scalar
    y1max=max(y1);
    // minimum of the second function -> scalar
    y2min=min(y2);
    // maximum of the second function -> scalar
    y2max=max(y2);
    // divider for the first function -> scalar
    division1=find_division(y1min,y1max);
    // divider for the second function -> scalar
    division2=find_division(y2min,y2max);
    // lower axis left y axis the first function (normalized) -> scalar
    y1axismin=floor(y1min/division1)
    // upper axis left y axis the first function (normalized) -> scalar
    y1axismax=ceil(y1max/division1)
    // lower axis left y axis the second function (normalized) -> scalar
    y2axismin=floor(y2min/division2)
    // upper axis left y axis the second function (normalized) -> scalar
    y2axismax=ceil(y2max/division2)
    // distinction of cases
    if y1axismin*y1axismax>0 & y2axismin*y2axismax>0 then
        // both axes don't go over the value of zero
        // preset variable
        addupper=1;
        // start a loop, until both axes have the same number of dividers
        while y1axismax-y1axismin>y2axismax-y2axismin
            // left y axis has more dividers than the right y axis
            if addupper==1 & y2axismax~=-1
                // move the upper limit of the right y axis up
                y2axismax=y2axismax+1;
            end
            if addupper==-1 & y2axismin~=1
                // move the lower limit of the right y axis down
                y2axismin=y2axismin+1;
            end
            // toggle variable
            addupper=adduper*(-1);
        end
        // preset variable
        addupper=1;
        // start a loop, until both axes have the same number of dividers
        while y1axismax-y1axismin<y2axismax-y2axismin
            // left y axis hat weniger optimum rounded divider als right y
axis
            if addupper==1 & y1axismax~=-1
                // move the upper limit of the left y axis up
                y1axismax=y1axismax+1;
            end
            if addupper==-1 & y1axismin~=1
                // move the lower limit of the left y axis down
                y1axismin=y1axismin+1;
            end
            // toggle variable
            addupper=adduper*(-1);
        end
        // rescale axes
        // lower limit of the left y axis
        a1.data_bounds(1,2)=y1axismin*division1;
        // lower limit of the left y axis
        a1.data_bounds(2,2)=y1axismax*division1;
        // lower limit of the left y axis
        a2.data_bounds(1,2)=y2axismin*division2;
        // lower limit of the left y axis
        a2.data_bounds(2,2)=y2axismax*division2;
    else
        // at least one of the axes goes over zero, or starts or ends at
zero
        // find joint lower limit of both axes -> scalar
        ymin=min(y1axismin,y2axismin);
        // find joint upper limit of both axes -> scalar
        ymax=max(y1axismax,y2axismax);
        // rescale axes
        // lower limit of the left y axis
        a1.data_bounds(1,2)=ymin*division1;
        // lower limit of the left y axis
        a1.data_bounds(2,2)=ymax*division1;
        // lower limit of the left y axis
        a2.data_bounds(1,2)=ymin*division2;
        // lower limit of the left y axis
        a2.data_bounds(2,2)=ymax*division2;
    end
endfunction

// Function to find a good division for the grid of a diagram
// Input:
//  axismin: minimum of the data to display -> scalar
//  axismax: maximum of the data to display -> scalar
// Output:
//  division: optimum rounded divider to divide the axis into 5 to 10 parts
function division=find_division(axismin,axismax)
    // distance between maximum and minimum -> scalar
    distance=axismax-axismin;
    // preset exponent -> scalar
    exponent=0;
    // loop, until the distance is between 1 and 10
    while 1
        if distance>10 then
            // decrease distance -> scalar
            distance=distance/10;
            // increase exponent -> scalar
            exponent=exponent+1;
        elseif distance<1 then
            // increase distance -> scalar
            distance=distance*10;
            // decrease exponent -> scalar
            exponent=exponent-1;
        else
            // exit loop
            break;
        end
    end
    // distinction of cases, so that there will be 5 to 10 dividers at the
end
    if distance==1 then
        // optimum rounded divider -> scalar
        division=0.1;
    elseif distance<=2 then
        // optimum rounded divider -> scalar
        division=0.2;
    elseif distance<=5 then
        // optimum rounded divider -> scalar
        division=0.5;
    else
        // optimum rounded divider -> scalar
        division=1;
    end
    // adjust the scaling -> scalar
    division=division*10^exponent;
endfunction



--
View this message in context: http://mailinglists.scilab.org/Scilab-users-Plots-on-second-Y-axis-tp4025895p4036055.html
Sent from the Scilab users - Mailing Lists Archives mailing list archive at Nabble.com.



More information about the users mailing list