Search code examples
plotscilab

3D Ploting in Scilab: Weird plot behaviour


I want to plot a function in scilab in order to find the maximum over a range of numbers:

function y=pr(a,b)
  m=1/(1/270000+1/a);
  n=1/(1/150000+1/a);
  y=5*(b/(n+b)-b/(m+b))
endfunction

x=linspace(10,80000,50)
y=linspace(10,200000,50)
z=feval(x,y,pr)
surf(x,y,z);
disp( max(z))

For these values this is the plot:

enter image description here

It's obvious that increasing the X axis will not increase the maximum but Y axis will. However from my tests it seems the two axis are mixed up. Increasing the X axis will actually double the max Z value.

For example, this is what happens when I increase the Y axis by a factor of ten (which intuitively should increase the function value):

enter image description here

It seems to increase the other axis (in the sense that z vector is calculated for y,x pair of numbers instead of x,y)!

What am I doing wrong here?


Solution

  • Stephane's answer is correct, but I thought I'd try to explain better why / what is happening.

    From the help surf page (emphasis mine):

    X,Y:
    two vectors of real numbers, of lengths nx and ny ; or two real matrices of sizes ny x nx: They define the data grid (horizontal coordinates of the grid nodes). All grid cells are quadrangular but not necessarily rectangular. By default, X = 1:size(Z,2) and Y = 1:size(Z,1) are used.

    Z:
    a real matrix explicitly defining the heights of nodes, of sizes ny x nx.

    In other words, think of surf as surf( Col, Row, Z )

    From the help feval page (changed notation for convenience):

    z=feval(u,v,f):
    returns the matrix z such as z(i,j)=f(u(i),v(j))

    In other words, in your z output, the i become rows (and therefore u should represent your rows), and j becomes your columns (and therefore v should represent your columns).

    Therefore, you can see that you've called feval with the x, y arguments the other way round. In a sense, you should have designed pr so that it should have expected to be called as pr(y,x) instead, so that when passed to feval as feval(y,x,pr), you would end up with an output whose rows increase with y, and columns increase with x.

    Then you could have called surf(x, y, z) normally, knowing that x corresponds to columns, and y corresponds to rows.

    However, if you don't want to change your whole function just for this, which presumably you don't want to, then you simply have to transpose z in the call to surf, to ensure that you match x to the columns or z' (i.e, the rows of z), and y to the rows of z' (i.e. the columns of z).

    Having said all that, it would probably be much better to make your function vectorized, and just use the surf(x, y, pr) syntax directly.