Cubic spline implementation in Matlab - matlab

I have two vectors, x and y that are defined(at random) as follows:
x1=[1000 3000 5000 6000 4000 2000 500 0 -1000 -3000 -5000 -6000 -4000 -2000 -500 1 999 2999 4999];
y1=[5000 4999 4990 3500 2500 2499 2498 2497 2496 2495 2494 1000 -1000 -999 -998 -997 -996 -995 -994];
Following is the plot I obtained by simply typing in plot(x1,y1):
Is there a way to produce a smooth curve from the above data using the interp1 command? I have been told that I should use cubic splines to achieve the desired plot, however, since I am new to Matlab I am unaware of how to implement such a solution. Thanks in advance!
Edit: I have tried to implement it as follows, but I am getting a hideous looking plot!
x1_temp=-6000:100:6000;
pc=pchip(x1,y1,x1_temp);
plot(x1,y1,'o',x1_temp,pc,'-');
How should I modify this code to produce the right plot?

I think you are confused about what you are interpolating. You should interpolate x1 and y1 separately, and afterwards plot them against each other. The following example produces a smooth curve:
x1=[1000 3000 5000 6000 4000 2000 500 0 -1000 -3000 -5000 -6000 -4000 -2000 -500 1 999 2999 4999];
y1=[5000 4999 4990 3500 2500 2499 2498 2497 2496 2495 2494 1000 -1000 -999 -998 -997 -996 -995 -994];
s = [0,cumsum(sqrt(diff(x1).^2+diff(y1).^2))]
N = length(s);
figure();
plot(x1,y1);
hold on
s_fine = interp1(linspace(0,1,N),s,linspace(0,1,5*N));
pcx=interp1(s,x1,s_fine,'spline');
pcy=interp1(s,y1,s_fine,'spline');
plot(pcx,pcy,'r-');

Related

Matlab to calculate a spectral line parameter for each layer

I need to calculate a parameter defined as x,( this is defined in my code below) for the given spectral lines in each layer. My atmospheric profile has 10 layers. I know how to calculate x for just one layer. Then I get 5 values for x corresponding to each spectral line ( or wavelength) .
Suppose I want to do this for all 10 layers. Then my output should have 10 rows and 5 columns , size should be (10,5) , 10 represent number of the layer and 5 represent the spectral line. Any suggestion would be greatly appreciated
wl=[100 200 300 400 500]; %5 wavelengths, 5 spectral lines
br=[0.12 0.56 0.45 0.67 0.89]; % broadening parameter for each wavelength
p=[1 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 ]; % pressure for 10 layers
T=[101 102 103 104 105 106 107 108 109 110]; % temperature for 10 layers
%suppose I want to caculate a parameter, x for all the layers
% x is defined as,( wavelength*br*T)/p
%when I do the calculation for the first layer,I have to consider all the
%wavelengths , all the broadening parameters and only the first value of
%pressure and only the first value of temperature
for i=1:5;
x(i)= (wl(i)*br(i)*T(1))/p(1);
end
% x is the x parameter for all the wavelengths in the first layer
%Now I want to calculate the x parameter for all the wavelengths in all 10
%layers
%my output should have 10 rows for 10 layers and 5 columns , size= (10,5)
you don't need loops for this case
>> (T./p)'*(wl.*br)
ans =
1.0e+05 *
0.0121 0.1131 0.1364 0.2707 0.4495
0.0136 0.1269 0.1530 0.3037 0.5043
0.0155 0.1442 0.1738 0.3451 0.5729
0.0178 0.1664 0.2006 0.3982 0.6611
0.0210 0.1960 0.2362 0.4690 0.7788
0.0254 0.2374 0.2862 0.5682 0.9434
0.0321 0.2996 0.3611 0.7169 1.1904
0.0432 0.4032 0.4860 0.9648 1.6020
0.0654 0.6104 0.7358 1.4606 2.4253
0.1320 1.2320 1.4850 2.9480 4.8950

Matlab log2 graph scale

I have been trying to put my graphic axis in log2 scale but something quite odd appears on the figure. The first data 63 appears at the beggining and the end of the x-scale and for some reason the first point does not appear. Also the points are not exactly centered on the x-ticks... do you have any idea why ?
Thanks in advance for you help !!!
clear all; clc;
%% Vectors
freq=[63 125 250 500 1000 2000 4000 8000 16000]
logfreq=log2(freq);
Lp1=[93.9 93.9 93.8 93.8 93.8 93.6 93.3 91.8 87.8]
Lp2=[93.9 93.9 93.8 93.8 94 94.1 94.4 94.6 95.3]
Lp3=[93.9 93.9 93.9 93.8 94.1 94.4 95.2 97.2 100.9]
%% Plot
figure
plot(log2(freq),Lp1,'+-','linewidth',1.7)
hold on; grid on;
plot(log2(freq),Lp2,'+-','linewidth',1.7)
plot(log2(freq),Lp3,'+-','linewidth',1.7)
set(gca,'fontsize',20)
set (gca, 'XTickLabel', logfreq);
set(gca,'XTickLabel',
{'63','125','250','500','1000','2000','4000','8000','16000'})
xlabel('Frequency [Hz]','fontsize',20)
ylabel('Pressure Level [dB]','fontsize',20)
leg=legend({'Sin correcion','Campo libre','Incidencia aleatoria'},'fontsize',18)
And here is the figure :
You want
set(gca,'XTick',logfreq);
instead of set(gca,'XTickLabel',logfreq)
With your incorrect code, the 63 appears at the start and the end because there are (incorrectly) 10 x tick locations but you are specifying only 9 labels, and hence the first one is repeated. (If you'd only specified 8 then the first 2 would be repeated, etc.)

Percentiles either side of the mean across a matrix - MATLAB

I have a matrix of data in this form:
5400 5700 6200 5200 6100 5500
5500 5900 7000 5900 6200 6000
6100 10300 7500 6200 6500 6600
6800 10900 7900 9400 9600 6600
7300 12500 10600 13000 10000 7900
7300 15700 10600 13200 14000 9200
11700 16200 11000 14900 14600 10800
12500 16500 11800 18100 14600 12900
13400 17000 19200 19300 16900 17100
14000 18700 20900 19700 17700 17700
14600 18800 22900 20200 17900 18500
15000 20800 24400 20800 19900 18700
15700 21100 25400 21500 22300 19700
16800 22000 26400 21700 22300 23300
The actual matrix is much larger.
I want to calculate two values for each row that describe the range of variation from the mean in terms of a percentile i.e. "95% of all values above the mean fall below X, and 95% of all value below the mean fall above Y".
What is the best method to do this?
Something like:
a = prctile(tcIED',0.90)
Produces only one value - which also appear to be inaccurate (lower than expected).
Your approach is correct , but prctile expects percentages (between 0 and 100). So:
a = prctile(tcIED.', 90);
Or, equivalently, use quantile with proportions (between 0 and 1):
a = quantile(tcIED.', 0.9);
For example, with your data you get
>> a(1)
ans =
6190
which means that about 90% of the values row 1 of your data matrix are less than or equal to 6190.

Limited Sum in Matlab

Hi lets say that i have matrix size 5x5.
B=[1 2 3 4 5; 10 20 30 40 50; 100 200 300 400 500; 1000 2000 3000 4000 5000; 10000 20000 30000 40000 50000];
How do i use function sum, to sum rows between 2 and 4 and have result:
A = [1110;2220;3330;4440]
You'll find some useful information about matrix indexing in the documentation at http://www.mathworks.co.uk/help/matlab/math/matrix-indexing.html
To illustrate your example, you can use B(2:4,:) to retreive the following:
ans =
10 20 30 40 50
100 200 300 400 500
1000 2000 3000 4000 5000
You can then use the sum function as follows to achieve your desired result:
A = sum(B(2:4,:))
I hope this helps!
All the best,
Matt
MATLAB>> sum(B(2:4,1:4))
ans =
1110 2220 3330 4440
If you want to transpose the result, add ' at the end.

X axis scaling with matlab plotting

My data is sparse therefore when I plot my graph I get the following result
As you can see the first x axis tick starts at 500(s), but most of my data is around 30(s). Can I change the scaling of the x axis?
How about this?
X = [1 3 6 10 25 30 235 678 1248];
Y = [0.4 0.45 0.5 0.55 0.6 0.65 0.7 0.8 0.9];
plot(X,Y,'-b.')
figure
semilogx(X,Y,'-b.')
I see the following output:
If you want to display data from 0 to 30s only you can either plot only those like this:
idcs=Xdata <30; %# find indices where X is less than 30s
plot(Xdata(idcs),Ydata(idcs),'b'); %#plot only these data.
or you can just express XLimits on the figure.
plot(Xdata,Ydata,'b'); %# plot everything
set(gca,XLim,[0 30]); %# limit display on X axis