PCA with colorbar - matlab

I have this data of which I want to make a principal component analysis.
In particular for each data point I want to associate a color.
This is my code:
for ii=1:size(SBF_ens,1)
SBF(ii) = SBF_ens(ii, max(find(SBF_ens(ii,:)~=0)) ); %value at the moment of the measurement
end
%matrix of data
toPCA =[
wind_trend_72h_ens-nanmean(wind_trend_72h_ens);
wind_trend_24h_ens-nanmean(wind_trend_24h_ens);
wind_trend_12to18h_ens-nanmean(wind_trend_12to18h_ens);
wind_trend_0to12h_ens-nanmean(wind_trend_0to12h_ens);
wind_trend_last6h_ens-nanmean(wind_trend_last6h_ens);
Mwind12h_ens-nanmean(Mwind12h_ens);
Mwind24h_ens-nanmean(Mwind24h_ens);
SBF-nanmean(SBF)]';
variables = { 'wt72h','wt24h','wt12to18h','wt0to12h','wtLast6h','Mw12h', 'Mw24h', 'SBF'}; %labels
%PCA algorithm
C = corr(toPCA,toPCA);
w = 1./var(toPCA);
[wcoeff,score,latent,tsquared,explained] = pca(toPCA,'VariableWeights',w);
coefforth = diag(sqrt(w))*wcoeff;
metric=decstd_ens; %metric for colorbar
hbi=biplot(coefforth(:,1:2),'scores',score(:,1:2),'varlabels',...
variables,'ObsLabels', num2str([1:length(toPCA)]'),...
'markersize', 15);
%plotting
cm = autumn;
colormap(cm);
for ii = length(hbi)-length(toPCA):length(hbi)
userdata = get(hbi(ii), 'UserData');
if ~isempty(userdata)
indCol = ceil( size(cm,1) * abs(metric(userdata))/max(abs(metric)) );%maps decstd between 0 and 1 and find the colormap index
if indCol==0 %just avoid 0
indCol=1;
end
col = cm(indCol,:); %color corresponding to the index
set(hbi(ii), 'Color', col); %modify the dot's color
end
end
for ii = 1:length(hbi)-length(toPCA)-1 %dots corresponding to the original dimensions are in black
set(hbi(ii), 'Color', 'k');
end
c=colorbar;
ylabel(c,'decstd') %is this true?
xlabel(['1^{st} PCA component ', num2str(explained(1)), ' of variance explained'])
ylabel(['2^{nd} PCA component ', num2str(explained(2)), ' of variance explained'])
The resulting figure is the following:
Everything is fine except for the colorbar range. In fact decstd has values between 0 and 2. Actually I do not understand at all what the values on the colorbar are.
Does anyone understand it?
Is it possible to rethrive the data in the colorbar? So to understand what they are?

size(autumn)
shows you that the default length of the autumn colourmap (actually of all the colourmaps) is 64. When you call colorbar, by default it will use tick labels from 1 to n where n is the length of your colourmap, in this case 64.
If you want the mapping of the colourbar ticklabels to match the mapping that you used to get your data to fit between 1 and 64 (i.e. this line of yours indCol = ceil( size(cm,1) * abs(metric(userdata))/max(abs(metric)) );), then you will need to set that yourself like this
numTicks = 6;
cAxisTicks = linspace(min(metric), max(metric), numTicks); % or whatever the correct limits are for your data
caxis([min(metric), max(metric)]);
set(c,'YTick', cAxisTicks );

Related

Modify multiple XTick values at once

I want to make a matrix of scatterplots in Matlab (version R2014b), and have only two ticks (minimum and maximum) for each x and y axis because the real world example has more plots and that will be easier to read. Here is an example, and as you can see, the second for loop isn't working as intended to edit the ticks. Also, is there a way to set this without a for loop?
% Example data
example = [ -5.2844 5.0328 307.5500
-12.0310 5.1611 237.9000
-15.9510 7.5500 290.7600
-11.5500 13.6850 285.8400
-1.9356 9.4700 273.2600
-9.2622 4.7456 232.6000
-6.5639 5.2272 265.3800
-4.4795 14.8320 281.1300
-2.1474 13.0690 288.7300
-3.7342 11.7450 265.2200
-11.9040 10.9660 286.5700
-2.1789 6.7442 258.9700
-2.8316 11.8210 281.7500
-2.6170 7.4740 244.8600
-6.8770 1.6623 116.9800
-10.2210 5.7575 300.2200
-3.9430 5.9715 253.6000
-3.3690 5.6530 230.9700
2.6090 3.2750 236.8700
-5.1430 8.4060 273.9600
-7.9360 2.7855 254.8200
-2.8665 2.0241 176.0600
-0.0960 3.3165 228.6800
-8.8465 10.3240 289.2100
-8.1930 16.4070 289.7000
-6.5840 13.4010 283.2600
2.2405 8.4625 270.1000
-2.2505 7.5555 285.9100
-4.6955 6.2985 279.2000
-0.7610 12.5210 283.2000
-0.7510 9.9470 279.9100
1.7120 8.5990 285.5700
-0.6245 7.6905 251.9100
-19.2320 6.8545 306.2700
-4.1255 9.8265 298.2000
2.9486 3.8881 250.2100
1.7333 5.5000 240.7300
-6.5881 3.9152 234.3800
-7.9543 8.0771 276.8000
-6.9641 8.8573 284.2800
-10.3280 7.4768 291.8700
-8.0818 5.1250 250.6600
-10.1490 3.9427 271.0000
-2.7786 3.7673 213.6500
-14.5410 11.1500 288.9100
-6.8118 11.0210 280.2000
-2.6459 6.5127 213.2600
1.4036 4.2023 253.9400
-5.0014 9.3900 267.0600
-9.7382 12.0990 290.8800]
% Labels for data
data_labels = {'Variable1','Variable2',...
'Variable3'};
% Make scatterplot matrix with histogram on diagonal
figure()
[H,AX]= plotmatrix(example(:,:));
% label the axes of the plots (rotated) works fine
for i = 1:length(AX)
ylabel(AX(i,1),data_labels{i},'Rotation',0,'HorizontalAlignment','right',...
'FontSize',12);
xlabel(AX(end,i),data_labels{i},'Rotation',60,'HorizontalAlignment','right',...
'FontSize',12);
end
% Set ticks (not working yet)
NumTicks = 2;
for i = 1:length(AX)
L = get(AX(i,i),'XLim');
set(AX(i,i),'XTick',linspace(L(1),L(2),NumTicks));
% set y ticks here too
end
You are incorrectly using i or both subscripts when indexing into AX.
AX(i) % Rather than AX(i,i)
Also, it's better to use numel than length and use a variable rather than i as your loop variable (since that's a MATLAB built-in for 0 + 1i). Also, you can use a single linear index into AX rather than specifying row and column subscripts.
for k = 1:numel(AX)
L = get(AX(k),'XLim');
set(AX(k),'XTick',linspace(L(1),L(2),NumTicks));
end
If you want to do this witnout a loop, you could technically do it using cellfun and the fact that you can set the same property in multiple plot objects using the following syntax
set(array_of_plot_handles, {'Property'}, array_of_values_to_set)
So applied to your problem, it would be something like
% Get all XLims as a cell array
oldlims = get(AX, 'XLim');
% Compute the new xlims
newlims = cellfun(#(x)linspace(x(1), x(2), NumTicks), oldlims, 'UniformOutput', false);
% Now set the values
set(AX, {'XTick'}, newlims);
Or if you really want it to be one line
set(AX, {'XTick'}, cellfun(#(x)linspace(x(1),x(2),NumTicks), get(AX, 'Xlim'), 'UniformOutput', false))

How to force MATLAB function area to hold on in figure

I'm working on this function which gets axis handler and data, and is supposed to plot it correctly in the axis. The function is called in for loop. It's supposed to draw the multiple data in one figure. My resulted figure is shown below.
There are only two correctly plotted graphs (those with four colors). Others miss areas plotted before the final area (red area is the last plotted area in each graph). But the script is same for every axis. So where can be the mistake? The whole function is written below.
function [] = powerSpectrumSmooth(axis,signal,fs)
N= length(signal);
samplesPer1Hz = N/fs;
delta = int16(3.5*samplesPer1Hz); %last sample of delta frequncies
theta = int16(7.5*samplesPer1Hz); %last sample of theta frequncies
alpha = int16(13*samplesPer1Hz); %last sample of alpha frequncies
beta = int16(30*samplesPer1Hz); %last sample of beta frequncies
x=fft(double(signal));
powerSpectrum = 20*log10(abs(real(x)));
smoothPS=smooth(powerSpectrum,51);
PSmin=min(powerSpectrum(1:beta));
y1=[(smoothPS(1:delta)); zeros(beta-delta,1)+PSmin];
y2=[zeros(delta-1,1)+PSmin; (smoothPS(delta:theta)); zeros(beta-theta,1)+PSmin];
y3=[zeros(theta-1,1)+PSmin; (smoothPS(theta:alpha)); zeros(beta-alpha,1)+PSmin];
y4=[zeros(alpha-1,1)+PSmin; (smoothPS(alpha:beta))];
a1=area(axis,1:beta,y1);
set(a1,'FaceColor','yellow')
hold on
a2=area(axis,1:beta,y2);
set(a2,'FaceColor','blue')
a3=area(axis,1:beta,y3);
set(a3,'FaceColor','green')
a4=area(axis,1:beta,y4);
set(a4,'FaceColor','red')
ADDED
And here is the function which calls the function above.
function [] = drawPowerSpectrum(axesContainer,dataContainer,fs)
size = length(axesContainer);
for l=1:size
powerSpectrumSmooth(axesContainer{l},dataContainer{l},fs)
set(axesContainer{l},'XTickLabel','')
set(axesContainer{l},'YTickLabel','')
uistack(axesContainer{l}, 'top');
end
ADDED 29th July
Here is a script which reproduces the error, so you can run it in your computer. Before running it again you might need to clear variables.
len = 9;
axesContainer = cell(len,1);
x = [0.1,0.4,0.7,0.1,0.4,0.7,0.1,0.4,0.7];
y = [0.1,0.1,0.1,0.4,0.4,0.4,0.7,0.7,0.7];
figure(1)
for i=1:len
axesContainer{i} = axes('Position',[x(i),y(i),0.2,0.2]);
end
dataContainer = cell(len,1);
N = 1500;
for i=1:len
dataContainer{i} = rand(1,N)*100;
end
for l=1:len
y1=[(dataContainer{l}(1:N/4)) zeros(1,3*N/4)];
y2=[zeros(1,N/4) (dataContainer{l}(N/4+1:(2*N/4))) zeros(1,2*N/4)];
y3=[zeros(1,2*N/4) (dataContainer{l}(2*N/4+1:3*N/4)) zeros(1,N/4)];
y4=[zeros(1,3*N/4) (dataContainer{l}(3*N/4+1:N))];
axes=axesContainer{l};
a1=area(axes,1:N,y1);
set(a1,'FaceColor','yellow')
hold on
a2=area(axes,1:N,y2);
set(a2,'FaceColor','blue')
hold on
a3=area(axes,1:N,y3);
set(a3,'FaceColor','green')
hold on
a4=area(axes,1:N,y4);
set(a4,'FaceColor','red')
set(axes,'XTickLabel','')
set(axes,'YTickLabel','')
end
My result of this script is plotted below:
Again only one picture contains all areas.
It looks like that every call to plot(axes,data) deletes whatever was written in axes.
Important note: Do not use a variable name the same as a function. Do not call something sin ,plot or axes!! I changed it to axs.
To solve the problem I just used the classic subplot instead of creating the axes as you did:
len = 9;
axesContainer = cell(len,1);
x = [0.1,0.4,0.7,0.1,0.4,0.7,0.1,0.4,0.7];
y = [0.1,0.1,0.1,0.4,0.4,0.4,0.7,0.7,0.7];
figure(1)
dataContainer = cell(len,1);
N = 1500;
for i=1:len
dataContainer{i} = rand(1,N)*100;
end
for l=1:len
y1=[(dataContainer{l}(1:N/4)) zeros(1,3*N/4)];
y2=[zeros(1,N/4) (dataContainer{l}(N/4+1:(2*N/4))) zeros(1,2*N/4)];
y3=[zeros(1,2*N/4) (dataContainer{l}(2*N/4+1:3*N/4)) zeros(1,N/4)];
y4=[zeros(1,3*N/4) (dataContainer{l}(3*N/4+1:N))];
axs=subplot(3,3,l);
a1=area(axs,1:N,y1);
set(a1,'FaceColor','yellow')
hold on
a2=area(axs,1:N,y2);
set(a2,'FaceColor','blue')
hold on
a3=area(axs,1:N,y3);
set(a3,'FaceColor','green')
hold on
a4=area(axs,1:N,y4);
set(a4,'FaceColor','red')
set(axs,'XTickLabel','')
set(axs,'YTickLabel','')
axis tight % this is to beautify it.
end
As far as I know, you can still save the axs variable in an axescontainer and then modify the properties you want (like location).
I found out how to do what I needed.
len = 8;
axesContainer = cell(len,1);
x = [0.1,0.4,0.7,0.1,0.4,0.7,0.1,0.4];
y = [0.1,0.1,0.1,0.4,0.4,0.4,0.7,0.7];
figure(1)
for i=1:len
axesContainer{i} = axes('Position',[x(i),y(i),0.2,0.2]);
end
dataContainer = cell(len,1);
N = 1500;
for i=1:len
dataContainer{i} = rand(1,N)*100;
end
for l=1:len
y1=[(dataContainer{l}(1:N/4)) zeros(1,3*N/4)];
y2=[zeros(1,N/4) (dataContainer{l}(N/4+1:(2*N/4))) zeros(1,2*N/4)];
y3=[zeros(1,2*N/4) (dataContainer{l}(2*N/4+1:3*N/4)) zeros(1,N/4)];
y4=[zeros(1,3*N/4) (dataContainer{l}(3*N/4+1:N))];
axes=axesContainer{l};
Y=[y1',y2',y3',y4'];
a=area(axes,Y);
set(axes,'XTickLabel','')
set(axes,'YTickLabel','')
end
The area is supposed to work with matrices like this. The tricky part is, that the signal in every next column is not plotted absolutely, but relatively to the data in previous column. That means, if at time 1 the data in first column has value 1 and data in second column has value 4, the second column data is ploted at value 5. Source: http://www.mathworks.com/help/matlab/ref/area.html

why cant i display both the colorbar's title and ticks simultaneously?

gamma=20;
P=0.1;
N=P.*gamma;
lamdazero=1550;
[lamdapump,lamdasignal] = meshgrid(1540:0.1:1580,1520:0.1:1580);
beta3=0.06;
beta4=-2*10^-4;
c=2*pi*3*10^8;
L=1;
A0=(1./lamdapump) -(1./lamdazero);
B0=(1./lamdapump) -(1./lamdasignal);
Third0=10^-9.*beta3.*(c.^3).*A0.*(B0.^2);
Fourth0=10^-12.*beta4.*(1./2).*c.^4.*(A0.^2).*(B0.^2);
Fourorder=(10^-12).*c.^4.*beta4.*(1/12).*(B0).^4;
deltabeta=Third0+Fourth0+Fourorder;
test2 = deltabeta;
test2(~(deltabeta<=0 & deltabeta>=-4*N)) = nan;
[C,h]=contourf(lamdapump,lamdasignal,test2,[-(4*N):N/2:0],'ShowText','off');
caxis([-8 0]);
xlabel('\lambda_p_u_m_p')
ylabel('\lambda_s_i_g_n_a_l')
title('Contour representing linear phase mismatch in terms of pump and signal wavelength ')
colorbar('YTickLabel',{'-4','-3.5','-3','-2.5','-2','-1.5','-1','-0.5','0'})
h2=colorbar;
HandleOfTitle = get(h2,'Title');
set(HandleOfTitle,'String','\Delta \beta (\gamma P_F_W_M)');
%If i remove the color yticklabel i get my colorbar title and viceversa
%need to know what to do
%The code works just fine
You are creating two colorbars, the second overwrites the first.
colorbar('YTickLabel',{'-4','-3.5','-3','-2.5','-2','-1.5','-1','-0.5','0'})
Creates a colorbar.
h2=colorbar;
Creates another colorbar and removes the first. Get the handle from the first call and remove the second:
h2 = colorbar('YTickLabel',{'-4','-3.5','-3','-2.5','-2','-1.5','-1','-0.5','0'});
Then use the handle to set the title as before.

Most efficient way of drawing grouped boxplot matlab

I have 3 vectors: Y=rand(1000,1), X=Y-rand(1000,1) and ACTid=randi(6,1000,1).
I'd like to create boxplots by groups of Y and X corresponding to their group value 1:6 (from ACTid).
This is rather ad-hoc and looks nasty
for ii=
dummyY(ii)={Y(ACTid==ii)};
dummyX(ii)={X(ACTid==ii)}
end
Now I have the data in a cell but can't work out how to group it in a boxplot. Any thoughts?
I've found aboxplot function that looks like this but I don't want that, I'd like the builtin boxplot function because i'm converting it to matlab2tikz and this one doesn't do it well.
EDIT
Thanks to Oleg: we now have a grouped boxplot... but the labels are all skew-whiff.
xylabel = repmat({'Bleh','Blah'},1000,1); % need a legend instead, but doesn't appear possible
boxplot([Y(:,end); cfu], {repmat(ACTid,2,1), xylabel(:)} ,'factorgap',10,'color','rk')
set(gca,'xtick',1.5:3.2:50)
set(gca,'xticklabel',{'Direct care','Housekeeping','Mealtimes','Medication','Miscellaneous','Personal care'})
>> ylabel('Raw CFU counts (Y)')
How to add a legend?
I had the same problem with grouping data in a box plot. A further constraint of mine was that different groups have different amounts of data points. Based on a tutorial I found, this seems to be a nice solution I wanted to share with you:
x = [1,2,3,4,5,1,2,3,4,6];
group = [1,1,2,2,2,3,3,3,4,4];
positions = [1 1.25 2 2.25];
boxplot(x,group, 'positions', positions);
set(gca,'xtick',[mean(positions(1:2)) mean(positions(3:4)) ])
set(gca,'xticklabel',{'Direct care','Housekeeping'})
color = ['c', 'y', 'c', 'y'];
h = findobj(gca,'Tag','Box');
for j=1:length(h)
patch(get(h(j),'XData'),get(h(j),'YData'),color(j),'FaceAlpha',.5);
end
c = get(gca, 'Children');
hleg1 = legend(c(1:2), 'Feature1', 'Feature2' );
Here is a link to the tutorial.
A two-line approach (although if you want to retain two-line xlables and center those in the first line, it's gonna be hackish):
Y = rand(1000,1);
X = Y-rand(1000,1);
ACTid = randi(6,1000,1);
xylabel = repmat('xy',1000,1);
boxplot([X; Y], {repmat(ACTid,2,1), xylabel(:)} ,'factorgap',10)
The result:
EDIT
To center labels...
% Retrieve handles to text labels
h = allchild(findall(gca,'type','hggroup'));
% Delete x, y labels
throw = findobj(h,'string','x','-or','string','y');
h = setdiff(h,throw);
delete(throw);
% Center labels
mylbl = {'this','is','a','pain','in...','guess!'};
hlbl = findall(h,'type','text');
pos = cell2mat(get(hlbl,'pos'));
% New centered position for first intra-group label
newPos = num2cell([mean(reshape(pos(:,1),2,[]))' pos(1:2:end,2:end)],2);
set(hlbl(1:2:end),{'pos'},newPos,{'string'},mylbl')
% delete second intra-group label
delete(hlbl(2:2:end))
Exporting as .png will cause problems...

Kmean plotting in matlab

I am on a project thumb recognition system on matlab. I implemented Kmean Algorithm and I got results as well. Actually now I want to plot the results like here they done. I am trying but couldn't be able to do so. I am using the following code.
load training.mat; % loaded just to get trainingData variable
labelData = zeros(200,1);
labelData(1:100,:) = 0;
labelData(101:200,:) = 1;
k=2;
[trainCtr, traina] = kmeans(trainingData,k);
trainingResult1=[];
for i=1:k
trainingResult1 = [trainingResult1 sum(trainCtr(1:100)==i)];
end
trainingResult2=[];
for i=1:k
trainingResult2 = [trainingResult2 sum(trainCtr(101:200)==i)];
end
load testing.mat; % loaded just to get testingData variable
c1 = zeros(k,1054);
c1 = traina;
cluster = zeros(200,1);
for j=1:200
testTemp = repmat(testingData(j,1:1054),k,1);
difference = sum((c1 - testTemp).^2, 2);
[value index] = min(difference);
cluster(j,1) = index;
end
testingResult1 = [];
for i=1:k
testingResult1 = [testingResult1 sum(cluster(1:100)==i)];
end
testingResult2 = [];
for i=1:k
testingResult2 = [testingResult2 sum(cluster(101:200)==i)];
end
in above code trainingData is matrix of 200 X 1054 in which 200 are images of thumbs and 1054 are columns. actually each image is of 25 X 42. I reshaped each image in to row matrix (1 X 1050) and 4 other (some features) columns so total of 1054 columns are in each image. Similarly testingData I made it in the similar manner as I made testingData It is also the order of 200 X 1054. Now my Problem is just to plot the results as they did in here.
After selecting 2 features, you can just follow the example. Start a figure, use hold on, and use plot or scatter to plot the centroids and the data points. E.g.
selectedFeatures = [42,43];
plot(trainingData(trainCtr==1,selectedFeatures(1)),
trainingData(trainCtr==1,selectedFeatures(2)),
'r.','MarkerSize',12)
Would plot the selected feature values of the data points in cluster 1.