I want to change the colors of my stacked bar plot but I keep getting an error message
As I need specific colors in my stacked bar plot to match with another graph I set up the color vector: colori with RGB values which I then convert into values between 0 and 1 after creating the figuer I want to change colors of the 15 stacked bars like this:
for i = 1:15
barSNE(i,:).FaceColor = colori(i);
end
here a bit mor of the code:
...
colori = [139,0,0
255,160,122;
255,69,0;
255,165,0;
255,215,0;
154,205,50;
34,139,34;
50,205,50;
255,182,193;
106,90,205;
139,0,139;
32,178,170;
199,21,133;
30,144,255;
0,0,205];
colori = colori ./ 255;
ctMeansT = ctMeans.';
figure(2)
barSNE = bar(ctMeansT, 'stacked');
for i = 1:15
barSNE(i,:).FaceColor = colori(i);
end
However, I get following Error message:
Structure assignment to non-structure object.
Error in viSNE_stacked_bar_plot (line 41)
barSNE(i,:).FaceColor = colori(i);
Colors in the figuere are not changed as expected
Your did a wrong indexing of your arrays barSNE and colori. If I run the code as you posted it above and check the size of both arrays I get
>> size(barSNE)
ans =
1 15
>> size(colori)
ans =
15 3
So barSNE is a one-dimensional array, while colori is a matrix of size 15 x 3. However, you tread it in your code vice versa given your index notation. E.g. If you do colori(i) you do not get the first RGB triplet as desired, but the first single value of the array colori (in your case 139/256 = 0.5451).
Change the indexing within the loop as follows
for i = 1:15
barSNE(i).FaceColor = colori(i,:);
end
and it works. As an example with random numbers for ctMeans (since you haven't provided your original data) I get a bar chart like this
Related
I've created some Matlab code which anyone helping can run and see the problem.
When I run the following code, for each data point on my plot I seem to get all 15 labels instead of only 1 specific label.
So how do I get the Matlab data point labels correct for the following code?
Based on the the suggestions, I did the following:
I replaced these two lines of code:
labels = num2str(test_vector_label,'F%d');
labels_cell = cellstr(labels);
With this line of code as suggested:
labels_cell = strread(num2str(test_vector_label),'%s');
Now there are two follow-up questions:
1) A warning appears stating that I should use textscan instead of strread:
labels_cell = textscan(num2str(test_vector_label),'%s');
Then when I use textscan as in the above line of code above, I get an error?
"Error using text
Cell array of strings may only contain string and numeric
matrices"
"Error in Code_Test (line 46)
text(x_val,y_val,labels_cell,'horizontal','left',
'vertical','bottom')"
2) How do I put a letter in front of the number labels? For example, in the original code I had put letter F followed by a number?
%--------------Randomly select training and testing data.-----------
num_data = 35;
data_idx = 1:35;
train_data_idx_tmp = randsample(num_data,20)
train_dataRand_idx = sort(train_data_idx_tmp)
% Lia = ismember(A,B) returns an array the same size as A, containing 1 (true)
% where the elements of A are found in B, and 0 (false) elsewhere.
test_data_idx_tmp = ismember(data_idx,train_dataRand_idx)
test_dataRand_idx = data_idx(~test_data_idx_tmp)'
% Check to see if training and test data index are exclusive.
check_train_test_idx = ismember(train_dataRand_idx,test_dataRand_idx)
%--------------------------------------------------------------------------
% Testing stage.
test_vector = test_dataRand_idx; %Select randomly obtained testing data.
% Training stage.
train_vector = train_dataRand_idx; %Select randomly obtained training
x_val = [1:15];
y_val = 2*[1:15];
plot(x_val,y_val,'or','MarkerFaceColor','r')
grid on
%Put specific data point labels on plots.
test_vector_label = test_vector';
labels = num2str(test_vector_label,'F%d');
labels_cell = cellstr(labels);
text(x_val,y_val,labels_cell,'horizontal','left', 'vertical','bottom')
Your variable labels_cell is a 1x1 string cell not an array of strings. Replace
labels = num2str(test_vector_label,'F%d');
labels_cell = cellstr(labels);
with
labels_cell = strread(num2str(test_vector_label),'%s');
I am pretty new to Matlab and encountered a problem when working with images.
I want to get a pixel that is in a specific colour (blue) in the following image:
image
My current code looks something like this:
function p = mark(image)
%// display image I in figure
imshow(image);
%// first detect all blue values higher 60
high_blue = find(image(:,:,3)>60);
%cross elements is needed as an array later on, have to initialize it with 0
cross_elements = 0;
%// in this iteration the marked values are reduced to the ones
%where the statement R+G < B+70 applies
for i = 1:length(high_blue)
%// my image has the size 1024*768, so to access the red/green/blue values
%// i have to call the i-th, i+1024*768-th or i+1024*768*2-th position of the "array"
if ((image(high_blue(i))+image(high_blue(i)+768*1024))<...
image(high_blue(i)+2*768*1024)+70)
%add it to the array
cross_elements(end+1) = high_blue(i);
end
end
%// delete the zero element, it was only needed as a filler
cross_elements = cross_elements(cross_elements~=0);
high_vector = zeros(length(cross_elements),2);
for i = 1:length(cross_elements)
high_vector(i,1) = ceil(cross_elements(i)/768);
high_vector(i,2) = mod(cross_elements(i), 768);
end
black = zeros(768 ,1024);
for i = 1:length(high_vector)
black(high_vector(i,2), high_vector(i,1)) = 1;
end
cc = bwconncomp(black);
a = regionprops(cc, 'Centroid');
p = cat(1, a.Centroid);
%// considering the detection of the crosses:
%// RGB with B>100, R+G < 100 for B<150
%// consider detection in HSV?
%// close the figure
%// find(I(:,:,3)>150)
close;
end
but it is not optimized for Matlab, obviously.
So i was wondering if there was a way to search for pixels with specific values,
where the blue value is larger than 60 (not hard with the find command,
but at the same time the values in the red and green area not too high.
Is there a command I am missing?
Since English isn't my native language, it might even help if you gave me some suitable keywords for googling ;)
Thanks in advance
Based on your question at the end of the code, you could get what you want in a single line:
NewImage = OldImage(:,:,1) < SomeValue & OldImage(:,:,2) < SomeValue & OldImage(:,:,3) > 60;
imshow(NewImage);
for example, where as you see you provide a restriction for each channel using logical operators, that you can customize of course (eg. using | as logical OR). Is this what you are looking for? According to your code you seem to be looking for specific regions in the image like crosses or coins is that the case? Please provide more details if the code I gave you is completely off the track :)
Simple example:
A = imread('peppers.png');
B = A(:,:,3)>60 & A(:,:,2)<150 & A(:,:,1) < 100;
figure;
subplot(1,2,1);
imshow(A);
subplot(1,2,2)
imshow(B);
Giving this:
I want to plot bar plot in which bars are grouped like this:
I have tried this code but I am not getting this type of plot. Please guide me how can I generate plot like above:
load Newy.txt;
load good.txt;
one = Newy(:,1);
orig = good(:,1);
hold on
bar(one,'m');
bar(orig,'g');
hold off
set(gca,'XTickLabel',{'0-19','20-39','40-79','80-159','160-319','320-639','640-1279','1280-1500'})
In each text file there is a list of numbers. The list comprises of 8 values.
You can use histc to count the values within certain edges.
To group bars you can collect them in a single matrix (with the values in each column).
edges = [0 20 40 80 160 320 640 1280 1501];
edLeg = cell(numel(edges)-1,1);
for i=1:length(edLeg)
edLeg{i} = sprintf('%d-%d',edges(i),edges(i+1)-1);
end
n = histc([one,orig],edges);
bar(n(1:end-1,:));
set(gca,'XTickLabels',edLeg)
legend('One','Orig')
I used these as test data
one = ceil(1500.*rand(200,1));
orig = ceil(1500.*rand(200,1));
I got the way to achieve group bars:
I had to plot the data such that there are 8 groups of bars where each group consists of 3 bars.
For that I wrote the data in my each file like this:
Y = [30.9858 1.36816 38.6943
0.655176 6.44236 13.1563
1.42942 3.0947 0.621403
22.6364 2.80378 17.1299
0.621871 5.37145 1.87824
0.876739 5.97647 3.80334
40.6585 68.6757 23.0408
2.13606 6.26739 1.67559
];
bar(Y)
I have many data need to be plotted as waterfall in matlab. I have more than 10 columns of data, each column represents one data data set. I put all data in a big matrix such that the first data set put in the first row of matrix, the second data set will be in the second row ... etc. After all those data stored in a matrix, I use the waterfall to plot those data. For each column, it contains about 10,000 data points which corresponds to x variable ranged from -5 to 5. But in the waterfall, it shows 0 to 10, 000 instead of -5 to 5 in the x axis. How do I force matlab to show the correct range? thx
mydata = zeros(13, 10000);
mydata(1, :) = ... ; % first data set
mydata(2, :) = ... ; % second data set
...
mydata(13, :) = ... ; % last data set
waterfall(mydata)
If you look at the documentation for waterfall (you can do this easily by placing the cursor in the command in your editor and hitting F1), you will see that you can invoke the waterfall command with different syntax . .
% Syntax
waterfall(Z)
waterfall(X,Y,Z)
waterfall(...,C)
waterfall(axes_handles,...)
h = waterfall(...)
Rather than just call the waterfall plot with the data Z, supply it with the X and Y range data also. For example . . .
mydata = rand(13, 10000);
Y = 1:size(mydata,1);
X = linspace(-5, 5,size(mydata,2));
waterfall(X, Y , mydata)
I want to show the p value that was used to generate each curve next to each of the curves plotted. Note that since there is a plot of E and -E, the same p value should be next to both. I've been attempting this for a while and I have not come across anything super useful.
t = -3.1;%coupling
a = 1;%distance between r1 and r3
n = 5;%latice vector span in a1 direction
m = 1;%latice vector span in a2 direction
i = -7;%unique axial vector t_hat direction
j = 11;%unique axial vector c_hat direction
max_p = abs((n*(i+j/2)-j*(m+n/2)));%# of unique p values
La = sqrt(3)*sqrt(m^2+n*m+n^2)*a/gcd(2*n+m,2*m+n);%unit cell length
C = sqrt(n^2+n*m+m^2);%circumference of the nanotube
hold on;
for p=0:1:max_p
kt = -pi/La:.05:pi/La;
kc = 2*pi*p/C;
ka1 = kc*a*.5*(2*n+m)/C + kt*a*sqrt(3)*.5*m/C;
ka2 = kc*a*.5*(n+2*m)/C - kt*a*sqrt(3)*.5*n/C;
E = abs(t+t*exp(1i*ka2)+t*exp(1i*ka1));
title_ = sprintf('(%d,%d) Carbon Nanotube Dispersion Diagram',n,m);
title(title_);
xlabel('k_{t}a');
ylabel('Energy (eV)');
plot(kt,E);
plot(kt,-E);
end
There is a command named text that writes comments into the figures,
http://www.mathworks.se/help/techdoc/ref/text.html
with if you can't solve it with that and the to string operation i misunderstood the question
First, do you need to plot both E and -E? Since these are the same except for their sign you don't really add any information to the plot by having -E there as well. However, if you do need both lines, then just construct an array of strings for the legend, during the loop, which has each string included twice (once for E and once for -E).
... Initial calculations ...
hold on;
for p=0:1:max_p
kt = -pi/La:.05:pi/La;
kc = 2*pi*p/C;
ka1 = kc*a*.5*(2*n+m)/C + kt*a*sqrt(3)*.5*m/C;
ka2 = kc*a*.5*(n+2*m)/C - kt*a*sqrt(3)*.5*n/C;
E = abs(t+t*exp(1i*ka2)+t*exp(1i*ka1));
plot(kt,E);
plot(kt,-E);
% Construct array containing legend text
legend_text{2*(p+1)-1} = strcat('p=', num2str(p));
legend_text{2*(p+1)} = strcat('p=', num2str(p));
end
title_ = sprintf('(%d,%d) Carbon Nanotube Dispersion Diagram',n,m);
title(title_);
xlabel('k_{t}a');
ylabel('Energy (eV)');
legend(legend_text)
I am sure there is a more elegant way of constructing the legend text, but the above code works. Also, notice that I moved the calls to xlabel, ylabel and title to outside of the loop. This way they are only called once and not for each iteration of the loop.
Finally, you need to take care to ensure that each iteration of the loop plots with a different line colour or line style (see edit below). You could colour/style each pair of E and -E lines the same for a given iteration of the loop and just display the legend for E (or -E), which would obviously halve the number of legend entries. To do this you will need to hide one of line's handle visibility - this prevents it from getting an item in the legend. To do this use the following in your loop:
plot(kt, E);
plot(kt,-E, 'HandleVisibility', 'off');
% Construct array containing legend text
legend_text{p+1} = strcat('p=', num2str(p));
Finally, it is best to include clear all at the top of your Matlab scripts.
Edit: To have each plotted line use a different colour for each iteration of your loop use something like the following
... initial calculations ...
cmap = hsv(max_p); % Create a max_p-by-3 set of colors from the HSV colormap
hold on;
for p = 0:1:max_p
plot(kt, E, 'Color', cmap(p,:)); % Plot each pair of lines with a different color
plot(kt, -E, 'Color', cmap(p,:));
end