how to use inputdlg with for loop in matlab - matlab

have tried searching but can't find anything to help, maybe my problem is too simple! Anyway, I'm running a nested FOR loop, but the array I save my results to only keeps the last "run" of results. Can someone please help me to store/concatenate the results ?
clc
clear
n = 2;
for aa = 1:n
aa = inputdlg({'Depth from','Depth to','Outer Diameter','Nominal Weight'},'1',[1 7;1 7;1 30;1 30]);
x = [str2num(aa{1}),str2num(aa{2}),str2num(aa{3}),str2num(aa{4})]
end
and the results
x =
1 2 3 4
x =
5 6 7 8
I cannot use the first one,
want to save all the results and save every iteration in a single variable

That is not the way to save the result into an array in a for loop; separate the looping variable and the array you are storing values in:
clc
clear
n = 2;
x = zeros(n, 4);
for k = 1:n
aa = inputdlg({'Depth from','Depth to','Outer Diameter','Nominal Weight'},'1',[1 7;1 7;1 30;1 30]);
x(k, :) = [str2double(aa{1}),str2double(aa{2}),str2double(aa{3}),str2double(aa{4})];
end
Then if you display x you get something like:
x =
1 2 3 4
5 6 7 8
Assuming you entered 1 to 4 and then 5 to 8 in the dialog.

Related

Exporting matrix with Logical indexing in Matlab

I trying to export logical 1 indices of a matrix to another variable without altering their position. Below I am trying to explain my doubt using a example:
l = logical([1 0 1 1 ;...
1 1 1 0]);
A = [1 2 3 4;...
5 6 7 8];
B = zeros(size(A));
B = A(l)
produces:
B =
1
5
6
3
7
4
But what I am interested in getting is
B =
1 0 3 4
5 6 7 0
Can anyone help me? Thanks
While you could use #tim's approach for this specific example, a more general solution is to use the logical array to index both the thing you're retrieving values from and the array you're assigning into. This grabs the values in A at the TRUE locations in I and places them into the corresponding positions in B.
I = logical([1 0 1 1; 1 1 1 0]);
A = [1 2 3 4; 5 6 7 8];
B = zeros(size(A));
B(I) = A(I);
The element-wise multiplication approach won't work if you want the "default" values in B to be anything other than 0. For example.
% Initialize B to an array of 100's
B = 100 * ones(size(A));
% Replace the elements specified by the logical array
B(I) = A(I);
% 1 100 3 4
% 5 6 7 100
Alternately, if you just want to zero-out the values in A you can also use logical indexing to do this.
A(~I) = 0;
As a sidenote, try to avoid using l for a variable name as it is very difficult to distinguish l from the number 1.
l = logical([1 0 1 1 ;...
1 1 1 0]);
A = [1 2 3 4;...
5 6 7 8];
A .* l % element-wise multiplication
no prob, you are welcome ;-) Accept, question closed! xD
EDIT
I'm afraid Stackoverflow became a page where everyone tries to beat other's answers by trying to make a longer and more detailed answer, even though not related to WHAT WAS ORIGINALLY ASKED. And not the one's which give a quick, easy, simple solution within a small amount of time, to exactly that SPECIFIC QUESTION. Suever immediately becomes an upvote by answering a question which was NOT asked, just because it is longer.
I'll also play the game and edit my answer: If you want to have other default options then 0, one could also adopt my solution and use:
~l*default_value + A.*l
I just want to say: It IS possible.
EDIT2
tic;
for i = 1:1000000
B = A.*l;
end;
toc
>> Elapsed time is 2.18214 seconds.
tic;
for i = 1:1000000
B=zeros(size(A));
B(l)=A(l);
end;
toc
>>Elapsed time is 13.9691 seconds.
Choose for yourself.
EDIT3 (Default value != 0)
>> tic; for i = 1:1e6; B = A.*l+100*(~l); end; toc
Elapsed time is 4.17261 seconds.
>> tic; for i = 1:1e6; B=100*ones(size(A)); B(l)=A(l); end; toc
Elapsed time is 14.2126 seconds.

Matlab: How do I use two nested for-loops to generate a consecutive list of numbers in ascending order?

I would like to obtain an array of consecutive numbers from 1 to the product of the limits of two nested loops. I hope the example below will clarify the question. If I have the nested loop:
for i = 1:limit_loop_1
for j = 1:limit_loop_2
a = ???;
disp(a)
end
end
I would like to obtain a = (1:(limit_loop_1*limit_loop_2))'
For example, having:
for i = 1:3
for j = 1:5
a = ????;
disp(a)
end
end
I would like to get:
a=
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
I found similar questions for Java (like here), but nothing for Matlab. Thanks in advance.
Edit: I need this particular procedure because I will use the index to refer to another array. So, if I have for example a 3D array A of size (100,1,15) within the nested loops, I want to consider each one of the 15 elements of the array at each iteration. In code this would be:
for k = 1:100
for i = 1:3
for j = 1:5
something = A (k,1,????)
end
end
end
That is why ????? should go from 1 to 15. Hope this clarify my issue.
Obviously the solution you already provided (a = (1:(limit_loop_1*limit_loop_2))') is correct and absolutely nice. However if you must use a nested loop, just treat a as an external counter
a=0;
for i = 1:3
for j = 1:5
a = a+1;
disp(a)
end
end
This basically counts how many iteration are made by using the nested loop (3*5 in this case).
Or if you want to exploit the indices i and j you can re-adapt the Java example in Matlab by taking into account that in Matlab the indices start at 1 whereas in Java they start at 0:
for i = 1:3
for j = 1:5
c =1+(j-1)*1+(i-1)*(5);
disp(c)
end
end
I have no idea why you'd want to do it this way, but I'll take you at your word. This will give you the results you require:
for ii = 1:3
for jj = 1:5
a = 5*(ii-1)+jj;
disp(a)
end
end
(I changed your loop variables from i and j because they're the imaginary unit variables by default, and some folks get upset if you overwrite them.)
Results:
>> loop15
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Fill in vector with new values and shift to the left

I am trying to make a permanent vector and add new values (scalars) until the vector is full. Then all new values x will replace the last one and shift left all the others by 1 so the first value of the vector gets out of it. At the beginning the vector is empty.
UPDATE
So at the beginning the vector is empty []
When I run the function the first time it would be like this (x=1): 1
After running the function 10 times will be like this: 1 2 3 4 5 6 7 8 9 10
Next time will be like this: 2 3 4 5 6 7 8 9 10 11
and so on: 3 4 5 6 7 8 9 10 11 12
x is just a new value not progressive as above.
This is what I have done so far but I get errors
function [ b ] = buffer( x )
persistent A;
A = int16.empty(10,0); % preallocate
for pos=1:10
[ A(1:pos) x A((pos+1):end) ];
b=A
end
Error: Index exceeds matrix dimensions. Error in buffer (line 14) [
A(1:pos) x A((pos+1):end) ];
Since I have gray hair this is not homework but curiosity in learning something new on my own. Some help to sort this out will be appreciated.
If I understood right then this code will help,
function b = buffer(x)
persistent A;
if isempty(A)
A = int16.empty(1,0); % preallocate
end
A = [A x];
if length(A) > 10
A(1 : length(A) -10) = [];
end
b = A;
end
A simpler way would be this,
function b = buffer(x)
persistent A;
if isempty(A)
A = zeros(1,10); % preallocate
end
A = [A(2:end) x];
b = A;
end
if you don't mind the zeros while A is not filled.

How to display sequence numbers in Matlab in a better way?

For example, I have an array:
a=[1:5 8:10];
If I display it using:
disp(['a = ' num2str(a)]);
The result would be something like
a = 1 2 3 4 5 8 9 10
It's quite too long than I need. How can I let Matlab to display as same as the way I defined it or as close as is?
Be more specific, if I defined the variable in an "informal" way like:
a=[1:3 4:6 8:10]
(should be normally 1:6 instead of 1:3 4:6)
I just want Matlab to display in either way:
1:3 4:6 8:10 or 1:6 8:10
I also not care about whether it displays the variable name or square brackets.
Searched but didn't find anything useful. Considered to manually parse it but doesn't sounds like a clever way.
Any suggestion would be great helpful, thanks a lot.
The only way to do this would be to create your own function to display the arrays in the format you want. For example, if you want to display monotonically-increasing portions of your array in a condensed fashion, you could use a function like this:
function display_array(array)
str = cellfun(#(n) {num2str(n)}, num2cell(array));
index = (diff(array) == 1) & ([1 diff(array, 2)] == 0);
str(index) = {':'};
str = regexprep(sprintf(' %s', str{:}), '( :)+\s*', ':');
disp([inputname(1) ' = [' str(2:end) ']']);
end
And you would use it like so:
>> a = [1:5 7 9:11] %# Define a sample array
a =
1 2 3 4 5 7 9 10 11 %# Default display
>> display_array(a)
a = [1:5 7 9:11] %# Condensed display
>> b = [1 2 3 4 4 4 3 2 1]; %# Another sample array
>> display_array(b)
b = [1:4 4 4 3 2 1] %# Note only the monotonically increasing part is replaced
For this, I use vec2str from the Matlab file exchange. For example:
str = vec2str([1 3 5 5 9 8 7 6 5])
ans =
[1:2:5,5,9:-1:5]
>> eval(str)
ans =
1 3 5 5 9 8 7 6 5
Impossible. Matlab throws away your definition very quickly. The "object" a has no knowledge of that definition at all.

extract every n row in a matrix to another matrix in a loop

I'm a total beginner to matlab and I'm currently writing a script for extracting data from a thermographic video.
Firstly the video is cut in separate frames. The first frame is opened as a sample picture to define the coordinates of sampling points. The goal is then to select the rgb values of those defined coordinates from a set of frames and save them into a matrix.
Now I have a problem separating the matrix to n smaller matrices.
e.g I'm defining the number of points to be selected to n=2 , with a picture count of 31. Now it returns a matrix stating the rgb codes for 31 pictures, each at 2 points, in a 62x3 double matrix...
Now I want to extract the 1st, 3rd, 5th....etc... row to a new matrix...this should be done in a loop, according to the number of n points...e.g 5 points on each picture equals 5 matrices, containing values of 31 pictures....
this is an extract of my code to analyse the pictures, it returns the matrix 'values'
files = dir('*.jpg');
num_files = numel(files);
images = cell(1, num_files);
cal=imread(files(1).name);
n = input('number of selection points?: ');
imshow(cal);
[x,y] = ginput(n);
eval(get(1,'CloseRequestFcn'))
%# x = input('x-value?: '); manual x selection
%# y = input('y-value?: '); manual y selection
for k = 1:num_files
images{k} = imread(files(k).name);
end
matrix=cell2mat(images);
count=(0:size(matrix,1):size(matrix,1)*num_files);
for k = 1:num_files
a(k)= mat2cell(impixel(matrix,x+count(k),y));
end
values = cat(1,a{:})
Easy fix
Do you mean that if you have:
n = 2;
k = 2; % for example
matrix = [1 2 3;
4 5 6;
7 8 9;
8 7 6];
you want it to become
b{1} = [1 2 3;
7 8 9];
b{2} = [4 5 6;
8 7 6];
This can be easily done with:
for ii = 1:n
b{ii} = matrix(1:n:end,:);
end
Better fix
Of course it's also possible to just reshape your data matrix and use that instead of the smaller matrices: (continuing with my sample data ^^)
>> d=reshape(matrix',3,2,[]);
>> squeeze(d(:,1,:))
ans =
1 7
2 8
3 9
>> squeeze(d(:,2,:))
ans =
4 8
5 7
6 6
Good practice
Or, my preferred choice: save the data immediately in an easy to access way. Here I think it will be an matrix of size: [num_files x num_points x 3]
If you want all the first points:
rgb_data(:,1,:)
only the red channel of those points:
rgb_data(:,1,1)
and so on.
I think this is possible with this:
rgb_data = zeros(num_files, num_points, 3);
for kk = 1:num_files
rgb_data(kk,:,:) = impixel(images{kk},x+count(k),y);
end
But I don't understand the complete meaning of your code (eg: why matrix=cell2mat(images) ??? and then of course:
count=(0:size(matrix,1):size(matrix,1)*num_files);
is just count=0:num_files;
so I'm not sure what would come out of impixel(matrix,x+count(k),y) and I used images{k} :)