Plotting surface in Octave results in non-uniform surface? - matlab

I'm trying to plot the attached data in octave. The 1st column is the X values, the 2nd is the Y value, and the last is the Z values.
I'm running this script:
xVec = reshape(mat(:,1),25,9);
yVec = reshape(mat(:,2),25,9);
zVec = reshape(mat(:,3),25,9);
surf(xVec,yVec,zVec);
axis([0.15 0.85 0.15 0.85]);
set(gca, 'XTick',0.20:0.05:0.80);
set(gca, 'YTick',0.20:0.05:0.80);
But I keep getting an uneven surface which is very hard to understand. Why is that? What am I missing?
The data:
0.15 0.15 40.802
0.15 0.2 40.673
0.15 0.25 40.526
0.15 0.3 40.83
0.15 0.35 40.862
0.15 0.4 40.652
0.15 0.45 40.924
0.15 0.5 40.774
0.15 0.55 41.088
0.15 0.6 40.749
0.15 0.65 41.099
0.15 0.7 41.753
0.15 0.75 41.607
0.15 0.8 41.911
0.15 0.85 41.537
0.2 0.15 39.809
0.2 0.2 39.884
0.2 0.25 40.595
0.2 0.3 40.497
0.2 0.35 40.863
0.2 0.4 41.325
0.2 0.45 40.916
0.2 0.5 40.431
0.2 0.55 40.583
0.2 0.6 40.858
0.2 0.65 40.548
0.2 0.7 41.668
0.2 0.75 41.863
0.2 0.8 41.499
0.2 0.85 41.903
0.25 0.15 39.894
0.25 0.2 39.686
0.25 0.25 40.227
0.25 0.3 40.625
0.25 0.35 40.572
0.25 0.4 41.034
0.25 0.45 40.828
0.25 0.5 40.802
0.25 0.55 40.196
0.25 0.6 40.493
0.25 0.65 41.265
0.25 0.7 40.963
0.25 0.75 41.023
0.25 0.8 41.396
0.25 0.85 41.596
0.3 0.15 39.546
0.3 0.2 40.216
0.3 0.25 39.535
0.3 0.3 39.945
0.3 0.35 40.108
0.3 0.4 40.726
0.3 0.45 40.187
0.3 0.5 41.279
0.3 0.55 40.747
0.3 0.6 41.122
0.3 0.65 40.91
0.3 0.7 40.292
0.3 0.75 41.04
0.3 0.8 41.287
0.3 0.85 42.023
0.35 0.15 38.693
0.35 0.2 40.269
0.35 0.25 40.561
0.35 0.3 40.536
0.35 0.35 40.268
0.35 0.4 39.947
0.35 0.45 40.259
0.35 0.5 40.146
0.35 0.55 41.048
0.35 0.6 40.263
0.35 0.65 40.875
0.35 0.7 41.281
0.35 0.75 40.836
0.35 0.8 41.322
0.35 0.85 41.734
0.4 0.15 39.321
0.4 0.2 39.103
0.4 0.25 39.694
0.4 0.3 40.529
0.4 0.35 40.272
0.4 0.4 39.826
0.4 0.45 40.224
0.4 0.5 40.808
0.4 0.55 40.66
0.4 0.6 40.003
0.4 0.65 41.626
0.4 0.7 41.549
0.4 0.75 41.523
0.4 0.8 41.408
0.4 0.85 41.545
0.45 0.15 39.428
0.45 0.2 39.53
0.45 0.25 39.988
0.45 0.3 40.039
0.45 0.35 40.075
0.45 0.4 40.206
0.45 0.45 40.946
0.45 0.5 41.027
0.45 0.55 41.214
0.45 0.6 40.98
0.45 0.65 40.874
0.45 0.7 41.483
0.45 0.75 41.151
0.45 0.8 41.123
0.45 0.85 40.528
0.5 0.15 39.477
0.5 0.2 39.62
0.5 0.25 40.265
0.5 0.3 39.61
0.5 0.35 40.109
0.5 0.4 40.232
0.5 0.45 40.212
0.5 0.5 40.861
0.5 0.55 39.665
0.5 0.6 41.225
0.5 0.65 40.577
0.5 0.7 40.62
0.5 0.75 41.244
0.5 0.8 40.977
0.5 0.85 41.753
0.55 0.15 39.033
0.55 0.2 39.769
0.55 0.25 40.164
0.55 0.3 40.351
0.55 0.35 40.592
0.55 0.4 40.227
0.55 0.45 40.14
0.55 0.5 40.734
0.55 0.55 40.429
0.55 0.6 40.701
0.55 0.65 40.849
0.55 0.7 40.596
0.55 0.75 41.481
0.55 0.8 41.27
0.55 0.85 40.755
0.6 0.15 38.944
0.6 0.2 39.76
0.6 0.25 39.051
0.6 0.3 40.009
0.6 0.35 39.84
0.6 0.4 40.072
0.6 0.45 41.282
0.6 0.5 40.606
0.6 0.55 40.98
0.6 0.6 41.141
0.6 0.65 40.111
0.6 0.7 41.627
0.6 0.75 41.798
0.6 0.8 41.196
0.6 0.85 41.35
0.65 0.15 39.457
0.65 0.2 39.38
0.65 0.25 40.26
0.65 0.3 40.142
0.65 0.35 39.935
0.65 0.4 40.496
0.65 0.45 39.862
0.65 0.5 40.665
0.65 0.55 40.187
0.65 0.6 40.955
0.65 0.65 39.834
0.65 0.7 40.641
0.65 0.75 41.162
0.65 0.8 41.028
0.65 0.85 41.54
0.7 0.15 38.938
0.7 0.2 39.803
0.7 0.25 39.485
0.7 0.3 39.8
0.7 0.35 39.459
0.7 0.4 39.895
0.7 0.45 40.203
0.7 0.5 40.222
0.7 0.55 40.176
0.7 0.6 41.01
0.7 0.65 41.433
0.7 0.7 41.651
0.7 0.75 41.018
0.7 0.8 41.185
0.7 0.85 41.216
0.75 0.15 39.182
0.75 0.2 38.856
0.75 0.25 39.992
0.75 0.3 40.005
0.75 0.35 39.613
0.75 0.4 39.526
0.75 0.45 40.232
0.75 0.5 40.45
0.75 0.55 41.157
0.75 0.6 40.578
0.75 0.65 41.106
0.75 0.7 41.252
0.75 0.75 40.773
0.75 0.8 41.207
0.75 0.85 42.219
0.8 0.15 39.33
0.8 0.2 39.463
0.8 0.25 39.435
0.8 0.3 40.252
0.8 0.35 39.819
0.8 0.4 39.826
0.8 0.45 40.506
0.8 0.5 41.031
0.8 0.55 40.666
0.8 0.6 41.306
0.8 0.65 40.674
0.8 0.7 41.489
0.8 0.75 40.956
0.8 0.8 41.61
0.8 0.85 41.099
0.85 0.15 39.247
0.85 0.2 38.983
0.85 0.25 39.051
0.85 0.3 39.098
0.85 0.35 39.617
0.85 0.4 40.541
0.85 0.45 40.091
0.85 0.5 40.435
0.85 0.55 40.55
0.85 0.6 40.204
0.85 0.65 40.682
0.85 0.7 40.965
0.85 0.75 41.063
0.85 0.8 41.113
0.85 0.85 41.577

Well, as far as I can see in your data X values change every 15 points, so do Y and Z.
It seems you are reshaping incorrectly.
Try the next really small changes to your code:
xVec = reshape(data(:,1),15,15);
yVec = reshape(data(:,2),15,15);
zVec = reshape(data(:,3),15,15);
surf(xVec,yVec,zVec);
axis([0.15 0.85 0.15 0.85]);
set(gca, 'XTick',0.20:0.05:0.80);
set(gca, 'YTick',0.20:0.05:0.80);
Output:

(This is only true for matlab, so I don't know if octav is any different, but I don't think so.)
The problem is that surf needs a very specific input format, it does not work with vectors.
the function you would want is griddata which interpolates any 3D or 4D input data on an even grid (which would be the needed input of surf).
It works somewhat like this:
xVec=mat(:,1);
yVec=mat(:,2);
zVec=mat(:,3);
gridpoints = 100;
[xi, yi] = meshgrid(linspace(min(xVec),max(xVec),gridpoints),linspace(min(xVec),max(xVec),gridpoints));
zi = griddata(xVec,yVec,zVec,xi,yi);
surf(xi,yi,zi);

Related

Fitting a curve through scipy.optimize.curve_fit with endpoints fixed

The following script fits a curve bowing-like via curve_fit (from scipy.optimize), see below:
ydata = numpy.array[ 1.6504 1.63928044 1.62855028 1.6181874 1.60817119 1.59848249 1.58910347 1.58001759 1.57120948 1.56266487 1.55437054 1.54631424 1.5384846 1.53087109 1.52346397 1.5162542 1.5092334 1.50239383 1.4957283 1.48923013 1.48289315 1.47671162 1.4706802 1.46479393 1.45904821 1.45343874 1.44796151 1.44261281 1.43738913 1.43228723 1.42730406 1.42243677 1.4176827 1.41303936 1.40850439 1.40407561 1.39975096 1.39552851 1.39140647 1.38738314 1.38345695 1.37962642 1.37589018 1.37224696 1.36869555 1.36523487 1.36186389 1.35858169 1.35538741 1.35228028 1.34925958 1.34632469 1.34347504 1.34071015 1.33802957 1.33543295 1.33291998 1.33049042 1.32814407 1.32588081 1.32370057 1.32160331 1.31958908 1.31765795 1.31581005 1.31404556 1.31236472 1.3107678 1.30925513 1.30782709 1.30648411 1.30522666 1.3040553 1.30297062 1.30197327 1.30106398 1.30024355 1.29951286 1.29887287 1.29832464 1.29786933 1.29750821 1.29724268 1.29707426 1.29700463 1.29703564 1.29716927 1.29740773 1.2977534 1.29820885 1.29877688 1.29946049 1.3002629 1.30118751 1.30223793 1.30341792 1.30473139 1.30618232 1.30777475 1.30951267 1.3114 ]
xdata = numpy.array[ 0. 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.1 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.2 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.3 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.4 0.41 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.5 0.51 0.52 0.53 0.54 0.55 0.56 0.57 0.58 0.59 0.6 0.61 0.62 0.63 0.64 0.65 0.66 0.67 0.68 0.69 0.7 0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79 0.8 0.81 0.82 0.83 0.84 0.85 0.86 0.87 0.88 0.89 0.9 0.91 0.92 0.93 0.94 0.95 0.96 0.97 0.98 0.99 1. ]
sigma = np.ones(len(xdata))
sigma[[0, -1]] = 0.01
def function_cte(x, b):
return 1.31*x + 1.57*(1-x) - b*x*(1-x)
def function_linear(x, c1, c2):
return 1.31*x + 1.57*(1-x) - (c1+c2*x)*x*(1-x)
popt_cte, pcov_cte = curve_fit(function_cte, xdata, ydata, sigma=sigma)
popt_lin, pcov_lin = curve_fit(function_linear, xdata, ydata, sigma=sigma)
But I'm getting the plot in figure ,
i.e., the initial points from both functions disagree with the data to fit (xdata, ydata).
I would like a fit constrained on the endpoints (0.0, 1.57) and (1.0, 1.31) at the same point that minimize the error. Any idea based on this code or it is better taking another way?
thanks!

Calculate the mean values if the numbers are same

I want to calculate the mean value if the first column numbers are same. e.g:
M = [ 2 0.99 0.15 0.60 0.12 0.76 0.16 0.81 0.02 0.75 0.32
2 0.17 0.38 0.34 0.02 0.74 0.67 0.75 0.92 0.23 0.81
2 0.26 0.16 0.30 0.29 0.74 0.89 0.12 0.65 0.06 0.79
3 0.40 0.76 0.45 0.32 0.11 0.52 0.53 0.93 0.77 0.85
3 0.07 0.87 0.42 0.65 0.68 0.70 0.33 0.16 0.67 0.51
3 0.68 0.35 0.36 0.96 0.46 0.15 0.55 0.92 0.72 0.64
3 0.40 0.69 0.56 0.94 0.21 0.95 0.40 0.79 0.64 0.95
4 0.98 0.29 0.74 0.46 0.10 0.54 0.42 0.58 0.42 0.44
4 0.40 0.53 0.42 0.24 0.82 0.68 0.18 0.44 0.39 0.06
4 0.62 0.83 0.43 0.76 0.18 0.04 0.26 0.26 0.82 0.87 ]
Out=[ 2 0.47 0.23 0.41 0.15 0.75 0.57 0.56 0.53 0.35 0.64
3 0.39 0.67 0.45 0.72 0.37 0.58 0.45 0.70 0.70 0.74
4 0.67 0.55 0.53 0.49 0.37 0.42 0.28 0.43 0.54 0.46 ]
G = findgroups(M(:,1 ));
Out = [unique(M(:,1)) splitapply(#mean, M(:,2:end), G)]
G = findgroups(A) returns G, a vector of group numbers created from the grouping variable A. Here G = findgroups(M(:,1 )) means pick up the first column out the matrics.
Y = splitapply(func,X,G) splits X into groups specified by G and applies the function func to each group.

How to put a border around a tikz figure with tcbox?

The following code produces the figure I want but only when I remove the \tcbox. I'd like a border around the figure. What I have done below works with other tikz figures. The problem seems to be with the table data. Can anyone please advise?
\begin{figure}
\tcbox{
\begin{tikzpicture}
\begin{axis}[
legend pos=south east,
xlabel=Variable 1, % label x axis
ylabel=Variable 2, % label y axis
]
\addplot[
scatter, only marks,
scatter/classes={
a={mark=square*,blue},
b={mark=triangle*,red}
}
]
table[x=x,y=y,meta=label]{
x y label
0.1 0.35 a
0.2 0.4 a
0.25 0.35 a
0.3 0.4 a
0.3 0.35 a
0.4 0.3 a
0.45 0.3 a
0.4 0.4 a
0.6 0.7 b
0.65 0.55 b
0.65 0.55 b
0.7 0.6 b
0.75 0.65 b
0.8 0.75 b
0.9 0.6 b
0.7 0.6 b
0.5 0.7 b
0.5 0.55 b
0.6 0.8 b
};
\legend{}
\end{axis}
\end{tikzpicture}
}
\caption{CAP HERE}
\label{statsexample}
\end{figure}
The issue is with your row separator. You can use row sep=crcr instead:
\begin{figure}
\tcbox{
\begin{tikzpicture}
\begin{axis}[
legend pos=south east,
xlabel=Variable 1, % label x axis
ylabel=Variable 2, % label y axis
]
\addplot[
scatter, only marks,
scatter/classes={
a={mark=square*,blue},
b={mark=triangle*,red}
}
]
table[x=x,y=y,meta=label,row sep=crcr]{
x y label\\
0.1 0.35 a\\
0.2 0.4 a\\
0.25 0.35 a\\
0.3 0.4 a\\
0.3 0.35 a\\
0.4 0.3 a\\
0.45 0.3 a\\
0.4 0.4 a\\
0.6 0.7 b\\
0.65 0.55 b\\
0.65 0.55 b\\
0.7 0.6 b\\
0.75 0.65 b\\
0.8 0.75 b\\
0.9 0.6 b\\
0.7 0.6 b\\
0.5 0.7 b\\
0.5 0.55 b\\
0.6 0.8 b\\
};
\end{axis}
\end{tikzpicture}
}
\caption{CAP HERE}
\label{statsexample}
\end{figure}

Same transparency with overlapping patches

I have a geometric figure with a complex shape. However, it can be split into several simpler subfigures. I need to plot them with some transparency, so I use patches. However, in the overlapping areas the color is too dark, as (of course) the patches overlap.
MWE
patch([0.1 0.45 0.45 0.1], [0.65 0.65 0.85 0.85], 'black', 'EdgeAlpha', 0)
patch([0.35 0.55 0.55 0.35], [0.4 0.4 0.8 0.8], 'black', 'EdgeAlpha', 0)
alpha(0.6)
How do I achieve a uniform opacity? I am open to other approaches different from patches.
You can combine the patches however for complex shapes this may be hard to accomplish.
x=[0.1 0.45 0.45 0.55 0.55 0.35 0.35 0.1];
y=[0.85 0.85 0.8 0.8 0.4 0.4 0.65 0.65];
patch(x,y,'k','FaceAlpha',0.6,'LineStyle','none')

I need to program in Matlab do loops

I have four parameters Q1,Q2,Q3,Q4 and I want to increase the parameters sequentiality 0.05
I mean I want to start the four parameters with the value 0.1, then increase Q1 by 0.05 and keep the others as it 0.1. then keep Q1=0.15, increase the second one Q2 0.05 a
From what I understood, you want to generate all possible tuples from the four parameters, where each can go from 0.1 to some higher value (I am using 0.2) in 0.05 increases. If this is the case, you can use the NDGRID function:
[q1,q2,q3,q4] = ndgrid(0.1:0.05:0.2);
params = [q1(:) q2(:) q3(:) q4(:)]
The result as rows:
params =
0.1 0.1 0.1 0.1
0.15 0.1 0.1 0.1
0.2 0.1 0.1 0.1
0.1 0.15 0.1 0.1
0.15 0.15 0.1 0.1
0.2 0.15 0.1 0.1
0.1 0.2 0.1 0.1
0.15 0.2 0.1 0.1
0.2 0.2 0.1 0.1
0.1 0.1 0.15 0.1
0.15 0.1 0.15 0.1
0.2 0.1 0.15 0.1
0.1 0.15 0.15 0.1
0.15 0.15 0.15 0.1
0.2 0.15 0.15 0.1
0.1 0.2 0.15 0.1
0.15 0.2 0.15 0.1
0.2 0.2 0.15 0.1
0.1 0.1 0.2 0.1
0.15 0.1 0.2 0.1
0.2 0.1 0.2 0.1
0.1 0.15 0.2 0.1
0.15 0.15 0.2 0.1
0.2 0.15 0.2 0.1
0.1 0.2 0.2 0.1
0.15 0.2 0.2 0.1
0.2 0.2 0.2 0.1
0.1 0.1 0.1 0.15
0.15 0.1 0.1 0.15
0.2 0.1 0.1 0.15
0.1 0.15 0.1 0.15
0.15 0.15 0.1 0.15
0.2 0.15 0.1 0.15
0.1 0.2 0.1 0.15
0.15 0.2 0.1 0.15
0.2 0.2 0.1 0.15
0.1 0.1 0.15 0.15
0.15 0.1 0.15 0.15
0.2 0.1 0.15 0.15
0.1 0.15 0.15 0.15
0.15 0.15 0.15 0.15
0.2 0.15 0.15 0.15
0.1 0.2 0.15 0.15
0.15 0.2 0.15 0.15
0.2 0.2 0.15 0.15
0.1 0.1 0.2 0.15
0.15 0.1 0.2 0.15
0.2 0.1 0.2 0.15
0.1 0.15 0.2 0.15
0.15 0.15 0.2 0.15
0.2 0.15 0.2 0.15
0.1 0.2 0.2 0.15
0.15 0.2 0.2 0.15
0.2 0.2 0.2 0.15
0.1 0.1 0.1 0.2
0.15 0.1 0.1 0.2
0.2 0.1 0.1 0.2
0.1 0.15 0.1 0.2
0.15 0.15 0.1 0.2
0.2 0.15 0.1 0.2
0.1 0.2 0.1 0.2
0.15 0.2 0.1 0.2
0.2 0.2 0.1 0.2
0.1 0.1 0.15 0.2
0.15 0.1 0.15 0.2
0.2 0.1 0.15 0.2
0.1 0.15 0.15 0.2
0.15 0.15 0.15 0.2
0.2 0.15 0.15 0.2
0.1 0.2 0.15 0.2
0.15 0.2 0.15 0.2
0.2 0.2 0.15 0.2
0.1 0.1 0.2 0.2
0.15 0.1 0.2 0.2
0.2 0.1 0.2 0.2
0.1 0.15 0.2 0.2
0.15 0.15 0.2 0.2
0.2 0.15 0.2 0.2
0.1 0.2 0.2 0.2
0.15 0.2 0.2 0.2
0.2 0.2 0.2 0.2
If I understand this correctly, you want to increase your four parameters one at a time? How about you use a simple modulus statement, like this:
for (int i = 0; i < 100; i++) {
if (i % 4 == 0) {
Q1 += 0.05;
} else if (i % 4 == 1) {
Q2 += 0.05;
} else if (i % 4 == 2) {
Q3 += 0.05;
} else {
Q4 += 0.05;
}
}
That way, after one loop you will have:
Q1 = 0.15
Q2 = 0.10
Q3 = 0.10
Q4 = 0.10
But after two, you have:
Q1 = 0.15
Q2 = 0.15
Q3 = 0.10
Q4 = 0.10
And so on...
Also, with Matlab without for loop and if statements:
n=4;
step=0.05;
base=floor((2:1/4:n));
q=base*step;
q1=q(4:end);
q2=q(3:end-1);
q3=q(2:end-2);
q4=q(1:end-3);
Which produces:
0.10 0.15 0.15 0.15 0.15 0.20
0.10 0.10 0.15 0.15 0.15 0.15
0.10 0.10 0.10 0.15 0.15 0.15
0.10 0.10 0.10 0.10 0.15 0.15