total_Route = zeros(4,4);
tmp = evalin('base', 't'); % i initialise t in the Workspace with the value 1
if(tmp==5)
tmp=1;
end
total_Route(tmp,1) = Distance_Traveled_CM;
total_Route(tmp,2) = Hauptantrieb_Verbrauchte_Energie_CM;
total_Route(tmp,3) = Nebenaggregate_Verbrauch_Real_CM;
total_Route(tmp,4) = t;
Total_Distance_Traveled_CM = sum(total_Route(:,1));
set(handles.edit3, 'string',Total_Distance_Traveled_CM);
Total_Hauptantrieb_Verbrauchte_Energie_CM = sum(total_Route(:,2));
set(handles.edit4, 'string',Total_Hauptantrieb_Verbrauchte_Energie_CM);
Total_Nebenaggregate_Verbrauch_Real_CM = sum(total_Route(:,3));
set(handles.edit5, 'string',Total_Nebenaggregate_Verbrauch_Real_CM);
%% Index
set(handles.edit15, 'string',tmp);
assignin('base', 't', tmp + 1); % with this line i can increment "t" after each pass
guidata(hObject,handles);
Sorry that I did not explain my problem well.
#Sardar_Usama I want to run the loop only once but t should be incremented after each time I click on my Button.
# Sembei Norimaki end is at the end of my codes, have forgotten to write it in my question
#Patrik & #Dennis Jaheruddin let me explain my problem again
I created a Matrix with 4×4 Elements with the Goal to save the results of each my Variable (Total_Distance_Traveled_CM, Total_Hauptantrieb_Verbrauchte_Energie_CM etc...) after each Simulation in the element of my Matrix (See image below).
I want by pressing a button (on my GUI) to get always the sum of each Column.
Example
The first pass: t = 1--> Distance_Traveled(1,1) is 900 the GUI will take through clicking on the Button, the sum of the first column (which is 900+0+0+0) and write it in a static test.
The second pass t = 2--> Distance_traveled(2,1) is 800 the GUI will take the sum of the first column (which is 900+800+0+0) and write it in a static test and the same thing should happen with the other column.
This should continue until t = 4 i.e. until it does the same thing for each column, then it should reset.
I hope, I have explained my problem better this time and I apologize for my bad English.
I appreciate any help.
Based on your code fragment the for loop is only called once.
However, the contents of the for loop are ran for four times. (first for i=1 then for 1=2 etc..)
If you only want to run one of these options the solution is very simple:
i = 1
yourLoopContent
If i is always 0 the first time, and you always want to run it for the current i, it would also be simple:
yourLoopContent
i = i+1;
However if i may not be set properly the first time, things get messy. This is because i is by default defined as the square root of minus 1.
Therefore I would recommend you to use a different letter like t instead. Then you could do this:
if ~exists(t)
t=0;
end
yourLoopContent %Everywhere using t instead of i
t = t+1;
In general you may want to avoid i as an index to stay clear of complex number issues.
I'm not sure if I got your question correctly, but it seems to me that what you look for is a cumulative sum. This can be done either buy summing on 1:t or by using cumsum. I'm not sure why you use a loop, but if this is only for the summing then cumsum can replace that.
Here is some example in your code:
total_Route = zeros(4,4);
% I commented below what is not part of the question
for t = 1:4
total_Route(t,:) = [Distance_Traveled_CM,
Hauptantrieb_Verbrauchte_Energie_CM,
Nebenaggregate_Verbrauch_Real_CM,
t];
% the following line compute the comulative sum from the top of each
% column to every element in it, so cs_total_Route(3,2) is like
% sum(total_Route(1:3,2)):
cs_total_Route = cumsum(total_Route);
Total_Distance_Traveled_CM = cs_total_Route(t,1); % OR sum(total_Route(1:t,1))
% set(handles.edit3, 'string',Total_Distance_Traveled_CM);
Total_Hauptantrieb_Verbrauchte_Energie_CM = cs_total_Route(t,2); % OR sum(total_Route(1:t,2))
% set(handles.edit4, 'string',Total_Hauptantrieb_Verbrauchte_Energie_CM);
Total_Nebenaggregate_Verbrauch_Real_CM = cs_total_Route(t,3); % OR sum(total_Route(1:t,3))
% set(handles.edit5, 'string',Total_Nebenaggregate_Verbrauch_Real_CM);
% set(handles.edit15, 'string',t);
end
And here is a quick look on what cumsum does (with some random numbers for total_Route):
total_Route =
671 4.6012 1.0662 1
840 3.6475 0.58918 2
354 8.6056 2.1313 3
893 4.1362 2.0118 4
cs_total_Route =
671 4.6012 1.0662 1
1511 8.2487 1.6554 3
1865 16.854 3.7867 6
2758 20.991 5.7985 10
Is this what you looked for?
Related
I would like to divide a vector in many vectors and put all of them in a matrix. I got this error "Subscripted assignment dimension mismatch."
STEP = zeros(50,1);
STEPS = zeros(50,length(locate));
for i = 1:(length(locate)-1)
STEP = filtered(locate(i):locate(i+1));
STEPS(:,i) = STEP;
end
I take the value of "filtered" from (1:50) at the first time for example and I would like to stock it in the first row of a matrix, then for iterations 2, I take value of "filtered from(50:70) for example and I stock it in row 2 in the matrix, and this until the end of the loop..
If someone has an idea, I don't get it! Thank you!
As mentioned in the comments, to make it work you can edit the loopy code at the end with -
STEPS(1:numel(STEP),i) = STEP;
Also, output array STEPS doesn't seem to use the last column. So, the initialization could use one less column, like so -
STEPS = zeros(50,length(locate)-1);
All is good with the loopy code, but in the long run with a high level language like MATLAB, you might want to look for faster codes and one way to achieve that would be vectorized codes. So, let me suggest a vectorized solution using bsxfun's masking capability to process such ragged-arrays. The implementation to cover generic elements in locate would look something like this -
% Get differentiation, which represent the interval lengths for each col
diffs = diff(locate)+1;
% Initialize output array
out = zeros(max(diffs),length(locate)-1);
% Get elements from filtered array for setting into o/p array
vals = filtered(sort([locate(1):locate(end) locate(2:end-1)]));
% Use bsxfun to create a mask that are to be set in o/p array and set thereafter
out(bsxfun(#ge,diffs,(1:max(diffs)).')) = vals;
Sample run for verification -
>> % Inputs
locate = [6,50,70,82];
filtered = randi(9,1,120);
% Get extent of output array for number of rows
N = max(diff(locate))+1;
>> % Original code with corrections
STEP = zeros(N,1);
STEPS = zeros(N,length(locate)-1);
for i = 1:(length(locate)-1)
STEP = filtered(locate(i):locate(i+1));
STEPS(1:numel(STEP),i) = STEP;
end
>> % Proposed code
diffs = diff(locate)+1;
out = zeros(max(diffs),length(locate)-1);
vals = filtered(sort([locate(1):locate(end) locate(2:end-1)]));
out(bsxfun(#ge,diffs,(1:max(diffs)).')) = vals;
>> max_error = max(abs(out(:)-STEPS(:)))
max_error =
0
I am trying to concatenate several structs. What I take from each struct depends on a function that requires a for loop. Here is my simplified array:
t = 1;
for t = 1:5 %this isn't the for loop I am asking about
a(t).data = t^2; %it just creates a simple struct with 5 data entries
end
Here I am doing concatenation manually:
A = [a(1:2).data a(1:3).data a(1:4).data a(1:5).data] %concatenation function
As you can see, the range (1:2), (1:3), (1:4), and (1:5) can be looped, which I attempt to do like this:
t = 2;
A = [for t = 2:5
a(1:t).data
end]
This results in an error "Illegal use of reserved keyword "for"."
How can I do a for loop within the concatenate function? Can I do loops within other functions in Matlab? Is there another way to do it, other than copy/pasting the line and changing 1 number manually?
You were close to getting it right! This will do what you want.
A = []; %% note: no need to initialize t, the for-loop takes care of that
for t = 2:5
A = [A a(1:t).data]
end
This seems strange though...you are concatenating the same elements over and over...in this example, you get the result:
A =
1 4 1 4 9 1 4 9 16 1 4 9 16 25
If what you really need is just the .data elements concatenated into a single array, then that is very simple:
A = [a.data]
A couple of notes about this: why are the brackets necessary? Because the expressions
a.data, a(1:t).data
don't return all the numbers in a single array, like many functions do. They return a separate answer for each element of the structure array. You can test this like so:
>> [b,c,d,e,f] = a.data
b =
1
c =
4
d =
9
e =
16
f =
25
Five different answers there. But MATLAB gives you a cheat -- the square brackets! Put an expression like a.data inside square brackets, and all of a sudden those separate answers are compressed into a single array. It's magic!
Another note: for very large arrays, the for-loop version here will be very slow. It would be better to allocate the memory for A ahead of time. In the for-loop here, MATLAB is dynamically resizing the array each time through, and that can be very slow if your for-loop has 1 million iterations. If it's less than 1000 or so, you won't notice it at all.
Finally, the reason that HBHB could not run your struct creating code at the top is that it doesn't work unless a is already defined in your workspace. If you initialize a like this:
%% t = 1; %% by the way, you don't need this, the t value is overwritten by the loop below
a = []; %% always initialize!
for t = 1:5 %this isn't the for loop I am asking about
a(t).data = t^2; %it just creates a simple struct with 5 data entries
end
then it runs for anyone the first time.
As an appendix to gariepy's answer:
The matrix concatenation
A = [A k];
as a way of appending to it is actually pretty slow. You end up reassigning N elements every time you concatenate to an N size vector. If all you're doing is adding elements to the end of it, it is better to use the following syntax
A(end+1) = k;
In MATLAB this is optimized such that on average you only need to reassign about 80% of the elements in a matrix. This might not seam much, but for 10k elements this adds up to ~ an order of magnitude of difference in time (at least for me).
Bare in mind that this works only in MATLAB 2012b and higher as described in this thead: Octave/Matlab: Adding new elements to a vector
This is the code I used. tic/toc syntax is not the most accurate method for profiling in MATLAB, but it illustrates the point.
close all; clear all; clc;
t_cnc = []; t_app = [];
N = 1000;
for n = 1:N;
% Concatenate
tic;
A = [];
for k = 1:n;
A = [A k];
end
t_cnc(end+1) = toc;
% Append
tic;
A = [];
for k = 1:n;
A(end+1) = k;
end
t_app(end+1) = toc;
end
t_cnc = t_cnc*1000; t_app = t_app*1000; % Convert to ms
% Fit a straight line on a log scale
P1 = polyfit(log(1:N),log(t_cnc),1); P_cnc = #(x) exp(P1(2)).*x.^P1(1);
P2 = polyfit(log(1:N),log(t_app),1); P_app = #(x) exp(P2(2)).*x.^P2(1);
% Plot and save
loglog(1:N,t_cnc,'.',1:N,P_cnc(1:N),'k--',...
1:N,t_app,'.',1:N,P_app(1:N),'k--');
grid on;
xlabel('log(N)');
ylabel('log(Elapsed time / ms)');
title('Concatenate vs. Append in MATLAB 2014b');
legend('A = [A k]',['O(N^{',num2str(P1(1)),'})'],...
'A(end+1) = k',['O(N^{',num2str(P2(1)),'})'],...
'Location','northwest');
saveas(gcf,'Cnc_vs_App_test.png');
So far I have got this code:
clear all; % clears all variables from your workspace
close all; % closes all figure windows
clc; % clears command window
%%=============================================
%%define number of trials and subjects
%%=============================================
njump=81;
nsbj=6;
%%
%%==============================================
%%defining size of cell that will be created
%%==============================================
data=cell(njump,1);
%%
%%==============================================
%%defining gravity and frame rate per second (fps)
%%==============================================
fps=0.001; %frames per second
g=-9.81; %acceleration
%%
%%==============================================
%%read in excel data in CSV format
%%===============================================
for i=1:njump;
x=sprintf('Trial%02d.csv',i),sprintf('Trial%02d',i),'A1:E7000';;% jump data
data{i}=xlsread(x,'A1:E7000');
%%===============================================
%%defining total no. of frames and time of flight
%tnf=total number of frames equal to zero
%n = nnz(X) returns the number of nonzero elements in matrix X.
%%===============================================
% myMax(i) = nanmax(data{i}(:,5));
% vals = find(data{i}(:,5) > (myMax(i) - 10));
% pointsInAir = numel(vals,i);
tnf(i,1) = size(data{i,1},1) - nnz(data{i,1}(:,5)); %number of zeros
tof(i)=tnf(i)*fps; %Time of flight is equal to this
jh(i,1)=(-g*(tof(i).^2)/8); %defining jump height
%%=================================================
%%to find average power first use "find" function to find the first zero in
%%Fz, have the cell referenced
%%then use nanmean for average power(av_pwr)
%%use nanmin for peak power (peak_pwr)
%%=================================================
n = 1; % the following call to find retrieves only the n first element(s) found.
ref= find(data{i,1}(:,5)==0, n, 'first');
% ref=find(data(:,5)==0);
peak_pwr(i,1) = nanmin (data {i,1}(1:ref,5)); %preak power in coloumn E1 in all data with reference to cell found
av_pwr(i,1)=nanmean(data {i,1}(1:ref,5));%average power in coloumn E1 in all data with reference to cell found
%%==================================================
%%Plot the results onto a time vs jump height, time vs average power and
%%time vs peak power
However the part that is hard is trying to find the first zero in column E which is the 5th column to use as a reference cell. I want to use this reference cell so that I can do my average and peak power calcs. that use the numbers before this zero.
In this case ref is empty so you cannot access the first element.
If you think that ref should not be empty you need to go back further to see where things go wrong. Otherwise, you can use something like:
if any(ref)
%Do something
else
%Return the default value/do alternative action
end
It could help to have an example of what's in data. I have created one which might be similar to yours :
data{1,1}=magic(6)-10
Now in this matrix, column 5 actually does have a zero element so ref= find(data{1,1}(:,5)==0); ref(1) actually works and retrieves the first index of a zero element. However, if it didn't, you would be trying to access the first element of an empty matrix.
Try instead using the second (and perhaps third) arguments of find to achieve this :
n = 1;
% the following call to find retrieves only the n first element(s) found.
ref= find(data{1,1}(:,5)==0, n, 'first');
The rest of your code seems like it should work, although from the looks of it i have a feeling your loop (i take it you are using a loop for i) could maybe be vectorized.
Hope this helps :)
Tepp
Hi have this code and I don't know how to put the output result with every pixel.I think the output code are not well defined.
EDIT:
I'm going to try to explain the code:
% I have an image
imagen1=imread('recor.tif');
imagen2= double(imagen1);
band1= imagen2(:,:,1);
% I preallocate the result (the image size is 64*89*6)
yvan2= zeros(61,89,1);
% For every pixel of the image, I want to get one result (each one is different).
for i = 1 : nfiles
for j = 1 : nrows
for i = 1:numel(band1)
% I'm doing this because I've to multiply the results of this interpolation with that result a2ldb1y= ldcm_1(:,1). This vector has a length of 2151x1 and I need to muliply the result of the interpolation for (101:267) position on the vector, this is the reason because I'm doing the interpolation since 101 to 267 (also because I don't have that values).
interplan= interp1(van1,man2,t2,'spline');
ma(96) = banda1a(i); % I said 96, because I want to do an interpollation
end
van1= [101 96 266]';
mos1= ma(134);
van2= [0 pos1 0];
t= 101:267;
t2= t';
xi= 101:1:267;
xi2=xi';
interplan= interp1(van1,van2,t2,'spline');
% After this, I 'prepare' the vector.
out=zeros(2151,1)
out(101:267) = interplan;
% And then, I do all this operation (are important for the result)
a2ldb1y= ldcm_1(:,1);
a2ldsum_pesos1= sum(a2ldb1y);
a2l7dout1_a= a2ldb1y.*out;
a2l7dout1_b= a2l7dout1_a./a2ldsum_pesos1;
a2l7dout1_c= sum(a2l7dout1_b);
% And the result a2l7dout1_c I want it for every pixel (the results are different because every pixel has a different value...)
**yvan2(:,:,1)= [a2l7dout1_c];**
end
end
Thanks in advance,
I'm shooting in the dark here, but I think you're looking for:
yvan2(i, j, 1)= a2l7dout1_c;
instead of:
yvan2(:,:,1)= [a2l7dout1_c];
and thus your output should be stored in the variable yvan2 after the loops are done.
P.S
Some issues in your code:
Why do you have two loops using the same iteration variable i? Your calculations are probably incorrect since i is being modified by two for loops.
Why do you even need the second loop? Each iteration overruns the value of ma(134) set by the previous iteration. You can just replace the entire loop with:
ma(134) = banda1a(numel(band1))
You shouldn't be using the names i and j for loop variables. They are already reserved for the imaginary unit (that is, sqrt(-1)), so MATLAB needs extra processing time for name resolution. You'd rather use other loop variable names instead, even ii and jj.
Okay so this sounds easy but no matter how many times I have tried I still cannot get it to plot correctly. I need only 3 lines on the same graph however still have an issue with it.
iO = 2.0e-6;
k = 1.38e-23;
q = 1.602e-19;
for temp_f = [75 100 125]
T = ((5/9)*temp_f-32)+273.15;
vd = -1.0:0.01:0.6;
Id = iO*(exp((q*vd)/(k*T))-1);
plot(vd,Id,'r',vd,Id,'y',vd,Id,'g');
legend('amps at 75 F', 'amps at 100 F','amps at 125 F');
end;
ylabel('Amps');
xlabel('Volts');
title('Current through diode');
Now I know the plot function that is currently in their isn't working and that some kind of variable needs setup like (vd,Id1,'r',vd,Id2,'y',vd,Id3,'g'); however I really can't grasp the concept of changing it and am seeking help.
You can use the "hold on" function to make it so each plot command plots on the same window as the last.
It would be better to skip the for loop and just do this all in one step though.
iO = 2.0e-6;
k = 1.38e-23;
q = 1.602e-19;
temp_f = [75 100 125];
T = ((5/9)*temp_f-32)+273.15;
vd = -1.0:0.01:0.6;
% Convert this 1xlength(vd) vector to a 3xlength(vd) vector by copying it down two rows.
vd = repmat(vd,3,1);
% Convert this 1x3 array to a 3x1 array.
T=T';
% and then copy it accross to length(vd) so each row is all the same value from the original T
T=repmat(T,1,length(vd));
%Now we can calculate Id all at once.
Id = iO*(exp((q*vd)./(k*T))-1);
%Then plot each row of the Id matrix as a seperate line. Id(1,:) means 1st row, all columns.
plot(vd,Id(1,:),'r',vd,Id(2,:),'y',vd,Id(3,:),'g');
ylabel('Amps');
xlabel('Volts');
title('Current through diode');
And that should get what you want.