Improper assignment with rectangular empty matrix error - matlab

I have the following code (see below) which I hope is self-explanatory. When I run the code using VEC A1/B1 or VEC A2/B2 commenting out the relevant bits, the code works without issues. But when I use the arrays A and B which is what I actually intend to do, matlab gives me the following error:
Improper assignment with rectangular empty matrix.
It says that the error is in this line of code:
prePr(j,:)=a(a>B(j) & a<B((j+1)))
this suggests that it loops correctly for the condition when i=1 but gets stuck when i=2 which is something I am failing to understand. Would be a great help if someone can offer suggestion. Thank you.
RatePu=31.25;
RatePr=250;
ratioRate=RatePr/RatePu;
A=[1:3,5:11,13:19;2:8,10:16,18:20;];
B=[4,12,20;1,9,17;];
% A=[1:3,5:11,13:19;]; % VEC A1
% A=[2:8,10:16,18:20;]; % VEC A2
% B=[4,12,20;]; % VEC B1
% B=[1,9,17;]; % VEC B2
NumTP=size(A,1);
prePr=zeros(length(B),ratioRate-1);
for i=1:NumTP
a=A(i,:);
b=B(i,:);
if b(1)==1
for j=1:length(b)-1
prePr(j,:)=a(a>B(j) & a<B((j+1)))
end
elseif b(1)>1
for j=1:length(b)
if j==1
prePr(j,1:max(a(a<(b(1)))))=a(a<b(j)) ;
else
prePr(j,:)= a(a>b(j-1) & a<b((j-1)+1))
end
end
end
end

It is because for i=2 you have that prePr is an empty matrix.
I would suggest this:
x==a(a>B(j) & a<B((j+1)));
if numel(x)==0
prePr(j,:)=NaN;
else
prePr(j,:)=x;
end

Related

Plot Two arrays Values in Matlab

so, i have tried to Plot all of values of (h,rex)
but its plot just the last values of them.
i think must use array but i dont know how to do that. i hope to help me !
clc
Pr=1.05;
lam=0.167;
l=2;
rex=100;
while (rex<2900)
disp('rex');
disp(rex);
h=((0.664*Pr^(1/3)*lam)/l)*rex^(1/2) ;
disp('h');
disp(h);
rex=rex+100;
end
plot(rex,h);
You are not storing your intermediate values, hence rex and h are overwritten each time and only the values from the last iteration are available. Solve this by storing the values in an array:
Pr=1.05;
lam=0.167;
l=2;
rex=100;
rex_array = [];
h_array = [];
while (rex<2900)
h=((0.664*Pr^(1/3)*lam)/l)*rex^(1/2) ;
rex=rex+100;
% store values in array (appending)
rex_array(end+1) = rex;
h_array(end+1) = h;
end
figure(1); clf;
plot(rex_array,h_array);
This is not recommended though, since rex_array and h_array are increasing in size with every iteration. So instead you use a for loop.
rex = 100:100:2900; % or to give same result as the while loop: 100:100:2800
h = zeros(size(rex)); % initialize h to be a zero vector with the same size as rex
% loop over rex
for k = 1:numel(rex)
% store each value in h(k):
h(k)=((0.664*Pr^(1/3)*lam)/l)*rex(k)^(1/2) ;
end
figure(1); clf;
plot(rex,h);
The best option though is to avoid the loop completely, and use vectorization:
rex = 100:100:2900; % or to give same result as the while loop: 100:100:2800
h=((0.664*Pr^(1/3)*lam)/l)*rex.^(1/2);
By using .^ each element in rex will be squared element wise.

How do I adjust this code so that I can enter how many runs I want and it will store each run in a matrix?

I have created this code to generate a 1 set of lottery numbers, but I am trying to make it so that the user can enter how many sets they want (input n), and it will print out as one long matrix of size nX6? I was messing around with a few options from online suggestions, but to no avail. I put the initial for i=1:1:n at the beginning, but I do not know how to store each run into a growing matrix. Right now it still generates just 1 set.
function lottery(n)
for i=1:1:n
xlow=1;
xhigh=69;
m=5;
i=1;
while (i<=m)
lottonum(i)=floor(xlow+rand*(xhigh-xlow+1));
flag=0;
for j=1:i-1
if (lottonum(i)==lottonum(j))
flag=1;
end
end
if flag==0
i=i+1;
end
end
ylow=1;
yhigh=26;
m=1;
lottonum1=floor(ylow+rand*(yhigh-ylow+1));
z = horzcat(lottonum, lottonum1);
end
disp('The lotto numbers picked are')
fprintf('%g ',z)
disp (' ')
The problem is that you are not storing or displaying the newly generated numbers, only the last set. To solve this, initialize z with NaNs or zeros, and later index z to store each set in a row of z, by using z(i,:) = lottonum.
However, you are using i as iterator in the while loop already, so you should use another variable, e.g. k.
You can also set z as an output of the function, so you can use this matrix in some other part of a program.
function z = lottery(n)
% init z
z = NaN(n,6);
for k = 1:n
xlow=1;
xhigh=69;
m=5;
i=1;
while (i<=m)
lottonum(i)=floor(xlow+rand*(xhigh-xlow+1));
flag=0;
for j=1:i-1
if (lottonum(i)==lottonum(j))
flag=1;
end
end
if flag==0
i=i+1;
end
end
ylow=1;
yhigh=26;
lottonum1 = floor(ylow+rand*(yhigh-ylow+1));
z(k,:) = horzcat(lottonum, lottonum1); % put the numbers in a row of z
end
disp('The lotto numbers picked are')
disp(z) % prettier display than fprintf in this case.
disp (' ')
end
The nice answer from rinkert corrected your basic mistakes (like trying to modify your loop iterator i from within the loop => does not work), and answered your question on how to store all your results.
This left you with a working code, however, I'd like to propose to you a different way to look at it.
The porposed architecture is to divide the tasks into separate functions:
One function draw_numbers which can draw N numbers randomly (and does only that)
One function draw_lottery which call the previous function as many times as it needs (your n), collect the results and display them.
draw_lottery
This architecture has the benefit to greatly simplify your main function. It can now be as simple as:
function Draws = draw_lottery(n)
% define your draw parameters
xmin = 1 ; % minimum number drawn
xmax = 69 ; % maximum number drawn
nballs = 5 ; % number of number to draw
% pre allocate results
Draws = zeros( n , nballs) ;
for iDraw=1:1:n
% draw "nballs" numbers
thisDraw = draw_numbers(xmin,xmax,nballs) ;
% add them to the result matrix
Draws(iDraw,:) = thisDraw ;
end
disp('The lotto numbers picked are:')
disp (Draws)
disp (' ')
end
draw_numbers
Instead of using a intricated set of if conditions and several iterators (i/m/k) to branch the program flow, I made the function recursive. It means the function may have to call itself a number of time until a condition is satisfied. In our case the condition is to have a set of nballs unique numbers.
The function:
(1) draws N integer numbers randomly, using randi.
(2) remove duplicate numbers (if any). Using unique.
(3) count how many unique numbers are left Nu
(4a) if Nu = N => exit function
(4b) if Nu < N => Call itself again, sending the existing Nu numbers and asking to draw an additional N-Nu numbers to add to the collection. Then back to step (2).
in code, it looks like that:
function draw = draw_numbers(xmin,xmax,nballs,drawn_set)
% check if we received a partial set
if nargin == 4
% if yes, adjust the number of balls to draw
n2draw = nballs - numel(drawn_set) ;
else
% if not, make a full draw
drawn_set = [] ;
n2draw = nballs ;
end
% draw "nballs" numbers between "xmin" and "xmax"
% and concatenate these new numbers with the partial set
d = [drawn_set , randi([xmin xmax],1,n2draw)] ;
% Remove duplicate
drawn_set = unique(d) ;
% check if we have some more balls to draw
if numel(drawn_set) < nballs
% draw some more balls
draw = draw_numbers(xmin,xmax,nballs,drawn_set) ;
else
% we're good to go, assign output and exit funtion
draw = drawn_set ;
end
end
You can have both functions into the same file if you want.
I encourage you to look at the documentation of a couple of Matlab built-in functions used:
randi
unique

how to write cell array to text file MATLAB, error with dlmwrite

I understand that this is a recurrent topic, I have tried understanding the answers that people provided but none of them seemed easy to transfer to my particular problem as the solutions are usually for an implementation that is too far from what I'm trying to do
Could anyone help with the following.
When I run the code below I get:
Error using dlmwrite (line 118)
The input cell array cannot be converted to a matrix.
Error in GAVNeuroScan (line 25)
dlmwrite(outputfile, CondRowDone);
I give an example of what I want to achieve in the comments at the end of the code.
If someone can help me getting the contents of CondRowDone to a text file as exemplified in the comments that would be great!
studyname='TestGav';
subjects={'504','505'};
conditions={'HighLabel','LowLabel','HighSound','LowSound'};
nCond=4;
GFPorBMR='GFP';
for curCond=1:length(conditions)
for curSubject=1:length(subjects)
gavRow{curSubject}=[subjects(curSubject) '-' conditions{curCond} '-' GFPorBMR '.avg'];
end
CondRowDone{curCond,:}=['GROUPAVG' '{' gavRow '}' 'G Y 1 N N' conditions{curCond} 'avg.'];
end
outputfile = [studyname '_GAV_' curSubject '.txt'];
dlmwrite(outputfile, CondRowDone);
% What I want is a text file that would look exactly like that. I think I'm
% not far but it fails to write...
%
% GROUPAVG {{HighLabel-504-GFP.avg} {HighLabel-505-GFP.avg}} G Y 1 N N {HighLabel.avg}
% GROUPAVG {{LowLabel-504-GFP.avg} {LowLabel-505-GFP.avg}} G Y 1 N N {LowLabel.avg}
% GROUPAVG {{HighSound-504-GFP.avg} {HighSound-505-GFP.avg}} G Y 1 N N {HighSound.avg}
% GROUPAVG {{LowSound-504-GFP.avg} {LowSound-505-GFP.avg}} G Y 1 N N {LowSound.avg}
From what I have seen using the debugger, you have a little bit of confusion between the curly braces as text and the curly braces to handle MATLAB cell arrays.
Here is a re-write of your for-loop to produce the cell array of strings you have given in your code example. Also, to produce the exact output you specified, subject and condition have to be given in a different order:
for curCond=1:length(conditions)
gavRow = [];
for curSubject=1:length(subjects)
if (curSubject ~= 1)
gavRow = [gavRow ' '];
end
gavRow = [gavRow '{' [conditions{curCond} '-' subjects{curSubject} '-' GFPorBMR '.avg'] '}'];
end
CondRowDone{curCond}=['GROUPAVG ' '{' gavRow '} ' 'G Y 1 N N {' conditions{curCond} '.avg}'];
end
As for the task of writing the strings to disk, MATLAB is telling you that it cannot handle your cell array as a matrix. When it comes to write cell arrays to disk, I think you have to write it yourself using low-level functions, like this:
outputfile = [studyname '_GAV_' curSubject '.txt'];
fid = fopen(outputfile, 'w');
for i=1:length(CondRowDone)
fprintf(fid, '%s\n', CondRowDone{i});
end
fclose(fid);
dlmwrite only handles numeric data. One way around this, if you have Excel, would be to use xlswrite - it can take in (some kinds of) cell arrays directly.
xlswrite(outputfile, CondRowDone);
Then, do some batch xls to csv conversion (for example, see this question and answers). To get a text file directly you'll need to use lower level commands (as in blackbird's answer).

matlab - is there a function which echo text of file ?

Since it is not possible to have a script and a function definition in the same file , I thought to echo the function which I want to attach in the script such that I get a script with function code and then some usage with this function .
For example -
func1.m
function [result] = func1(x)
result=sqrt(x) ;
end
script1.m
echo(func1.m) ;
display(func1(9))
Desire output for script1.m
function [result] = func1(x)
result=sqrt(x) ;
end
display(func1(9))
3
Have you any idea for that ?
Since a convoluted solution was already proposed, why not stating the obvious?
Matlab has a built-in command that does exactly what you want. It is called type:
>> type('mean')
will give you this:
function y = mean(x,dim)
%MEAN Average or mean value.
% For vectors, MEAN(X) is the mean value of the elements in X. For
% matrices, MEAN(X) is a row vector containing the mean value of
% each column. For N-D arrays, MEAN(X) is the mean value of the
% elements along the first non-singleton dimension of X.
%
% MEAN(X,DIM) takes the mean along the dimension DIM of X.
%
% Example: If X = [0 1 2
% 3 4 5]
%
% then mean(X,1) is [1.5 2.5 3.5] and mean(X,2) is [1
% 4]
%
% Class support for input X:
% float: double, single
%
% See also MEDIAN, STD, MIN, MAX, VAR, COV, MODE.
% Copyright 1984-2005 The MathWorks, Inc.
% $Revision: 5.17.4.3 $ $Date: 2005/05/31 16:30:46 $
if nargin==1,
% Determine which dimension SUM will use
dim = min(find(size(x)~=1));
if isempty(dim), dim = 1; end
y = sum(x)/size(x,dim);
else
y = sum(x,dim)/size(x,dim);
end
You could use this:
function echo(mfile)
filename=which(mfile);
if isempty(filename)
fprintf('Invalid input - check you are inputting a string.');
return;
end
fid=fopen(filename,'r');
if (fid<0)
fprintf('Couldn''t open file.');
end
file=fread(fid,Inf);
fclose(fid);
fprintf('%s',file);
end
This will open a file, read it, and print it. Note that you need to provide the input as a string, i.e. with single quotes around it, and need to have '.m' at the end:
echo('fread.m')
Not
echo(fread.m) % This won't work
echo('fread') % This won't work
Just for completeness, there's also dbtype which prepends line numbers.

Create image from Huffman code - Matlab

I have a project about image compression in Matlab. So far i have successfully implemented Huffman encoding to the image which gives me a vector of binary codes. After that i run Huffman decoding and i get a vector which contains the elements of the image compressed. My problem is that i can find how is possible from this vector to reconstruct the image and create the image file.
Any help would be grateful
Update
Based on Ben A. help i have made progress but i still have some issues.
To be more exact. I have an image matrix. After finding unique symbols(elements) on this image matrix, i calculate the probabilities and then with this function:
function [h,L,H]=Huffman_code(p,opt)
% Huffman code generator gives a Huffman code matrix h,
% average codeword length L & entropy H
% for a source with probability vector p given as argin(1)
zero_one=['0'; '1'];
if nargin>1&&opt>0, zero_one=['1'; '0']; end
if abs(sum(p)-1)>1e-6
fprintf('\n The probabilities in p does not add up to 1!');
end
M=length(p); N=M-1; p=p(:); % Make p a column vector
h={zero_one(1),zero_one(2)};
if M>2
pp(:,1)=p;
for n=1:N
% To sort in descending order
[pp(1:M-n+1,n),o(1:M-n+1,n)]=sort(pp(1:M-n+1,n),1,'descend');
if n==1, ord0=o; end % Original descending order
if M-n>1, pp(1:M-n,n+1)=[pp(1:M-1-n,n); sum(pp(M-n:M-n+1,n))]; end
end
for n=N:-1:2
tmp=N-n+2; oi=o(1:tmp,n);
for i=1:tmp, h1{oi(i)}=h{i}; end
h=h1; h{tmp+1}=h{tmp};
h{tmp}=[h{tmp} zero_one(1)];
h{tmp+1}=[h{tmp+1} zero_one(2)];
end
for i=1:length(ord0), h1{ord0(i)}=h{i}; end
h=h1;
end
L=0;
for n=1:M, L=L+p(n)*length(h{n}); end % Average codeword length
H=-sum(p.*log2(p)); % Entropy by Eq.(9.1.4)
i calculate the huffman codes for the image.
Now i use this function:
function coded_seq=source_coding(src,symbols,codewords)
% Encode a data sequence src based on the given (symbols,codewords).
no_of_symbols=length(symbols); coded_seq=[];
if length(codewords)<no_of_symbols
error('The number of codewords must equal that of symbols');
end
for n=1:length(src)
found=0;
for i=1:no_of_symbols
if src(n)==symbols(i), tmp=codewords{i}; found=1; break; end
end
if found==0, tmp='?'; end
coded_seq=[coded_seq tmp];
end
where in src i put my image (matrix) and i get a coded sequence for my image.
Last is this function:
function decoded_seq=source_decoding(coded_seq,h,symbols)
% Decode a coded_seq based on the given (codewords,symbols).
M=length(h); decoded_seq=[];
while ~isempty(coded_seq)
lcs= length(coded_seq); found=0;
for m=1:M
codeword= h{m};
lc= length(codeword);
if lcs>=lc&codeword==coded_seq(1:lc)
symbol=symbols(m); found=1; break;
end
if found==0, symbol='?'; end
end
decoded_seq=[decoded_seq symbol];
coded_seq=coded_seq(lc+1:end);
end
Which is used to decode the coded sequence. The problem is that finally as coded sequence i get a 1x400 matrix where i should get a 225x400 which is my image dimensions.
Am i missing something? Maybe should i replace something because i have a matrix and not a number sequence (for which the code is written)?
You might want to take a look at this:
http://www.mathworks.com/matlabcentral/answers/2158-huffman-coding-and-decoding-for-image-jpeg-bmp
This seems like it's right up your alley. It should ultimately lead you to here:
http://www.mathworks.com/matlabcentral/fileexchange/26384-ppt-for-chapter-9-of-matlabsimulink-for-digital-communication