Matlab cell to array not working - matlab

I have this cell (16x1) in MATLAB:
eventIDs =
'explosion'
'light'
'darkness'
'atomic'
...
..
now I want to use this :
%First bar plotting!
bar(duration_vector);
d = size(duration_vector);
labels = cell2mat(eventIDs);
xticklabel_rotate([1:d],45,eventIDs,'interpreter','none');
set(gca, 'XTick', 1:d, 'XTickLabel', labels);
I want to plot a bar graph but my events I too long, and I want them rotated to look good!
but when I run the code
I get this:
??? Error using ==> cat
CAT arguments dimensions are not consistent.
Error in ==> cell2mat at 85
m{n} = cat(1,c{:,n});
Error in ==> extract_data at 52
labels = cell2mat(eventIDs);

You don't need to do cell2mat. That tries to create a 2D matrix of characters (which fails because your strings are different lengths).
You also don't need the set(... line because xticklabel_rotate already sets the labels.

cell2mat in Matlab only works if your cell has a consistent number of columns in all rows. That is so because Matlab can't handle normal arrays with a variable number of columns per row, and that's generally the case of string matrices.
That said, cell manipulations is almost equal to matrix manipulation, the only difference being the indexation method: matrices use square brackets ([) and cells use curly brackets.
I googled the code of this function you're using, the xticklabel_rotate, and found the fileexchange link to the function here. There, the example given by the author uses a cell, instead of a matrix.
So I'm guessing that you can drop this cell2mat off because I thik you don't need to set the Xticks with the set function you're using. The xticklabel_rotate should do that.
I think you should try this:
%First bar plotting!
bar(duration_vector);
d = size(duration_vector);
xticklabel_rotate([1:d],45,eventIDs,'interpreter','none');

Related

Append legends. Whats wrong with my code?

I'm trying to add legends the plot when it adds a curve. I can't see whats wrong with my code, can someone please help? I'm using matlab r2015a on ubuntu.
x=1:5;
v=1:5;
plot(x,v)
[~,~,plots,str] = legend('1');
hold on
for i=4:10
pl=plot(x,v*i);
[~,~,plots,str]=legend([plots;pl],str,num2str(i))
end
when i run it i get:
plots =
1x2 Line array:
Line Line
str =
'1' '4'
Error using vertcat
Dimensions of matrices being
concatenated are not
consistent.
So its means it works the first lap but not the second.
As discussed in the comment, the way Matlab handles legends is different than in earlier releases; they are now legend objects.
In any case, to solve your problem, which is a dimension mismatch problem, you can simply concatenate vertically the outputs you get using the transpose operator, because Matlab returns a horizontal array of line and text objects whereas you want a vertical array. Therefore, using plots.' and pl.' works fine. Also, it's good practice not to use i as a loop counter since it represents the imaginary unit.
clear
clc
close all
x=1:5;
v=1:5;
plot(x,v)
[~,~,plots,str] = legend('1');
hold on
for k=4:10
pl=plot(x,v*k);
[LegendObject,~,plots,str]=legend([plots.';pl.'],str,num2str(k));
end
%// Use the legend object to modify its properties/location
set(LegendObject,'Location','NorthWest');
Output:

The appearance of a dashed line in matlab is not even

The appearance of a dashed line in matlab is not even. For example:
x = [121.2802 112.5784 115.0855 109.0412 99.1158 103.9001];
y = [-25.8392 -24.9378 -25.1976 -24.5714 -23.5433 -24.0389];
plot(x,y,'--k','linewidth',1.2)
print -r600 -dtiff test.tif
The dashes do not appear separate in some parts of the line. Is this because the points are not evenly distributed? Any suggestions? Thanks.
No the problem isn't matlab it is your variables. Matlab is conecting (x(i),y(i)) with (x(i+1),y(i+1)) with a dashed line. But your data isn't sorted.
The only thing happening here is that you draw 2 lines above each other which results in your non dashed parts. If you want only dashed line try sorting your data before plotting it.
Edit 1
z= [x' ,y'];
z= (sortrows(z))';
x2=fliplr(z(1,:));
y2=fliplr(z(2,:));
plot(x2,y2,'--k','linewidth',1.2)
Here is a way to sort your data. What i am doing is i am conecting x,y rowwise in z. Then i use sortrows to sort all rows according to the first one. Then i transpose the resulting matrix so that you have new coloumn vectors. After that i use fliplr to flip the first to last element and so on (inverting your data, since your original data went from 120 to 100and i don't know if you want to use the data later on). And then i plot it.
Hope that helps
Edit 2
As posted by Dennis:
z= [x' ,y'];
z= (sortrows(z))';
z=flipud(z);
plot(x2,y2,'--k','linewidth',1.2)

Error using ' Transpose on ND array is not defined?

I am getting error for my below code: temp=reshape(img',irow*icol,1);
Error message:Error using '
Transpose on ND array is not defined.
What is solution for this. I think I have to use permute(A,order) command. But I dont know how to use this command in my code. Do you know any solution?
for i=1:M
str=strcat(int2str(i),'.jpg'); %concatenates two strings that form the name of the image
eval('img=imread(str);');
subplot(ceil(sqrt(M)),ceil(sqrt(M)),i)
imshow(img)
if i==3
title('Training set','fontsize',18)
end
drawnow;
[irow icol]=size(img); % get the number of rows (N1) and columns (N2)
temp=reshape(img',irow*icol,1); %creates a (N1*N2)x1 matrix
S=[S temp]; %X is a N1*N2xM matrix after finishing the sequence
%this is our S
end
I assume the code was designed for grey scale images. For matrices with more than two dimensions, you have to use permute. One solution could be:
[irow icol d]=size(img);
temp=reshape(permute(img,[2,1,3]),[irow*icol,d]);
Which results in a nx3 matrix, each column corresponding to one colour. You have to change the last line as well, but I don't know what you are expecting. Maybe take a look at cat

Diffusion outer bounds

I'm attempting to run this simple diffusion case (I understand that it isn't ideal generally), and I'm doing fine with getting the inside of the solid, but need some help with the outer edges.
global M
size=100
M=zeros(size,size);
M(25,25)=50;
for diffusive_steps=1:500
oldM=M;
newM=zeros(size,size);
for i=2:size-1;
for j=2:size-1;
%we're considering the ij-th pixel
pixel_conc=oldM(i,j);
newM(i,j+1)=newM(i,j+1)+pixel_conc/4;
newM(i,j-1)=newM(i,j-1)+pixel_conc/4;
newM(i+1,j)=newM(i+1,j)+pixel_conc/4;
newM(i-1,j)=newM(i-1,j)+pixel_conc/4;
end
end
M=newM;
end
It's a pretty simple piece of code, and I know that. I'm not very good at using Octave yet (chemist by trade), so I'd appreciate any help!
If you have concerns about the border of your simulation you could pad your matrix with NaN values, and then remove the border after the simulation has completed. NaN stands for not a number and is often used to denote blank data. There are many MATLAB functions work in a useful way with these values.
e.g. finding the mean of an array which has blanks:
nanmean([0 nan 5 nan 10])
ans =
5
In your case, I would start by adding a border of NaNs to your M matrix. I'm using 'n' instead of 'size', since size is an important function in MATLAB, and using it as a variable can lead to confusing errors.
n=100;
blankM=zeros(n+2,n+2);
blankM([1,end],:) = nan;
blankM(:, [1,end]) = nan;
Now we can define 'M'. N.B that the first column and row will be NaNs so we need to add an offset (25+1):
M = blankM;
M(26,26)=50;
Run the simulation through,
m = size(blankM, 1);
n = size(blankM, 2);
for diffusive_steps=1:500
oldM = M;
newM = blankM;
for i=2:m-1;
for j=2:n-1;
pixel_conc=oldM(i,j);
newM(i,j+1)=newM(i,j+1)+pixel_conc/4;
newM(i,j-1)=newM(i,j-1)+pixel_conc/4;
newM(i+1,j)=newM(i+1,j)+pixel_conc/4;
newM(i-1,j)=newM(i-1,j)+pixel_conc/4;
end
end
M=newM;
end
and then extract the area of interest
finalResult = M(2:end-1, 2:end-1);
One simple change you might make is to add a boundary of ghost cells, or halo, around the domain of interest. Rather than mis-use the name size I've used a variable called sz. Replace:
M=zeros(sz,sz)
with
M=zeros(sz+2,sz+2)
and then compute your diffusion over the interior of this augmented matrix, ie over cells (2:sz+1,2:sz+1). When it comes to considering the results, discard or just ignore the halo.
Even simpler would be to simply take what you already have and ignore the cells in your existing matrix which are on the N,S,E,W edges.
This technique is widely used in problems such as, and similar to, yours and avoids the need to write code which deals with the computations on cells which don't have a full complement of neighbours. Setting the appropriate value for the contents of the halo cells is a problem-dependent matter, 0 isn't always the right value.

Matlab boxplot for multiple fields

I have this matlab file which has a field called "data". In "data" I have lots of fields for different bonds (x5Q12... etc).
I am trying to produce ONE box plot that contains ONE column from each of the fields (i.e. a box diagram with 36 boxes in it). I tried this code (e.g. to plot a box for column 2 in all of the bonds) but it does't work for me:
boxplot(gilts_withoutdates.data.:(:,2));figure(gcf);
I know my understanding of calling different levels in a structure is a problem here. Any suggestions, please? Many thanks.
You can use STRUCTFUN to extract the data from a particular column of all fields of a structure.
col2plot = 2; %# this is the column you want to plot
%# return, for each field in the structure, the specified
%# column in a cell array
data2plot = structfun(#(x){x(:,col2plot)},gilts_withoutdates.data);
%# convert the cell array into a vector plus group indices
groupIdx = arrayfun(#(x)x*ones(size(data2plot{x})),1:length(data2plot),'uni',0);
groupIdx = cat(1,groupIdx{:});
data2plot = cat(1,data2plot{:});
%# create a compact boxplot
boxplot(data2plot,groupIdx,'plotStyle','compact','labels',labels)
If you're interested in the distribution of the data, I can recommend my function distributionPlot.
B=gilts_withoutdates.data;
b=fieldnames(B);
for a=1:numel(b)
boxplot(B.(b{a})); fig;
end
To plot a boxplot for each of the 5 columns of data for each field you could do this:
pos=1;
for i = 1:numel(b)
for ii=1:5
subplot(numel(b),5,pos);boxplot(B.(b{i})(:,ii));pos=pos+1;
end
end