I am doing an iteration to find the corresponding latitude/longitude at a height (h_intercept). My code works perfectly for a single height value. However, I want to find the lat/long of 79 heights (1x79 matrix) and therefore have an output that is a 3x79 matrix (llh_test). I've tried a for loop but I can't seem to get the results I want. I am probably doing something stupid.
Basically, I need to modify it so it will run with rng_sat, u_sat and h_intercept all being 1x79 matrices. It needs to step through the entire iteration before moving to the next values of rng_sat, u_sat and h_intercept
Also, I want to store all of the llh_test values (3x79 matrix)
rng_sat= sat_look_tcs_pass1(3,1)/2e2;
u_sat=[sat_look_tcs_pass1(1,1)/sat_look_tcs_pass1(3,1);sat_look_tcs_pass1(2,1)/sat_look_tcs_pass1(3,1);sat_look_tcs_pass1(3,1)/sat_look_tcs_pass1(3,1)];
h_intercept=sat_look_pass1_llh(3,1)/2e3;
h_test=0;
rng_test_min=0;
rng_test_max=rng_sat;
err=0.01;
while abs(h_test-h_intercept)>err
rng_test=(rng_test_min+rng_test_max)/2;
tcs_test=u_sat*rng_test;
llh_test=tcs2llhT(tcs_test,station_llh);
h_test=llh_test(3,:);
if h_test>=h_intercept;
rng_test_max=rng_test;
else
rng_test_min=rng_test;
end
end
The easiest thing to do here would be to encapsulate this into a single for loop, and change the way you're accessing the core variables so that you're using the loop index instead. Looking at your code, I'm assuming that sat_look_tcs_pass1 is a 3 x 79 matrix. I'm also going to assume that the output height h_test is a single value because when you're doing h_test = llh_test(3,:), h_test will actually become a vector, as you are trying to get all of the columns for the third row. I'm going to assume that this is a single value, rather than an array.
To modify this code, this actually will take no effort at all, so here's where you need to modify. Anywhere you see %// NEW is where I modified and anything else is your original code:
llh_test = zeros(3,79); %// Preallocate
for k = 1 : 79 %// You have 79 values to go through
rng_sat = sat_look_tcs_pass1(3,k)/2e2; %// NEW Change to k
u_sat = [sat_look_tcs_pass1(1,k)/sat_look_tcs_pass1(3,k); ...
sat_look_tcs_pass1(2,k)/sat_look_tcs_pass1(3,k);...
sat_look_tcs_pass1(3,k)/sat_look_tcs_pass1(3,k)]; %// NEW - Change to k
h_intercept = sat_look_pass1_llh(3,k)/2e3; %// NEW - Change to k
rng_test_min=0;
rng_test_max=rng_sat;
err=0.01;
while abs(h_test-h_intercept) > err
rng_test=(rng_test_min+rng_test_max)/2;
tcs_test=u_sat*rng_test;
llh_test(:,k) = tcs2llhT(tcs_test,station_llh); %// NEW - llh_test is now a matrix
h_test = llh_test(3,k); %// NEW - Changed the way we are accessing llh_test
if h_test >= h_intercept
rng_test_max=rng_test;
else
rng_test_min=rng_test;
end
end
end
Take a look at the general pattern of your code. You essentially are changing all of the points where you were accessing the first column with the kth column. Also, llh_test is a matrix, and so for each iteration in your loop, you want to access the kth column. llh_test should now be a 3 x 79 matrix as per your specifications.
Good luck!
Related
I would like your suggestions to make my code faster (and elegant). In particular, sub2ind (and the if-loop) slow it down dramatically according to the matlab profiler. I will try to explain what I need from my code as simply as I can.
Assuming I have the following problem, for simplicity.
Every citizen of every city has a car of a specific brand and a specific color.
What I would like to have is a 4D multidimensional array Data_4D(City,Citizen,Car_brand,Car_color) that I can manipulate (read and modify) using as indexes only these four dimensions.
Then, I want to reshape my multidimensional array into a 1D array Data_1D with
length(Data_1D)=(City*Citizen*Car_brand*Car_color)
The order of the elements must follow an indexing rule:
Example assuming City=2, Citizen=2, Car_brand=2, Car_color=2;
Data_1D(1)=Data_4D(1,1,1,1)
Data_1D(2)=Data_4D(1,1,1,2)
Data_1D(3)=Data_4D(1,1,2,1)
Data_1D(4)=Data_4D(1,1,2,2)
Data_1D(5)=Data_4D(1,2,1,1)
Data_1D(6)=Data_4D(1,2,1,2)
Data_1D(7)=Data_4D(1,2,2,1)
Data_1D(8)=Data_4D(1,2,2,2)
Data_1D(9)=Data_4D(2,1,1,1)
Data_1D(10)=Data_4D(2,1,1,2)
Data_1D(11)=Data_4D(2,1,2,1)
Data_1D(12)=Data_4D(2,1,2,2)
Data_1D(13)=Data_4D(2,2,1,1)
Data_1D(14)=Data_4D(2,2,1,2)
Data_1D(15)=Data_4D(2,2,2,1)
Data_1D(16)=Data_4D(2,2,2,2)
After that I will get this 1D array, shaped as above, I need to create a matrix Matrix_Final( NRows,length(Data_1D)) in which every row is an array Data_1D. In every row NRows, the array Data_1D will have the same amount of elements but with different values.
The amount of rows depends also on some (or all) of the four the dimensions City,Citizen,Car_brand,Car_color (respecting the same indexing rule as for Data_1D) and the array built in each line must be manipulated according also to the value of the matrix row (by using the four indexes, which is the common rule for both NRows and Data_1D).
Example:
Assuming City=2, Citizen=2, Car_brand=2, Car_color=2;
Assuming NRows depends on all the four dimensions.
I will have Matrix_Final( length(DATA_1D), length(DATA_1D)).
I want that all the data of my array DATA_1D are zeros, except one element, which has to be the element that has the same indexes values(City,Citizen,Car_brand,Car_color) as NRows(City,Citizen,Car_brand,Car_color)
So at the row NRows(1), only Data_1D(1) is non-zero. For this example, the result is an eye matrix.
clc
clear all
%Dimensions Definition
City=2;
Citizen=2;
Car_brand=2;
Car_color=2;
%Length of Data
Length_Data_1D=City*Citizen*Car_brand*Car_color;
%preallocation Matrix_Final
Matrix_Final=zeros(City*Citizen*Car_brand*Car_color, Length_Data_1D);
%indexes of the dimensions
indexes_array_carcolor=repmat(repelem([1:Car_color], 1), [1 City*Citizen*Car_brand]);
indexes_array_carbrand=repmat(repelem([1:Car_brand], Car_color), [1 City*Citizen]);
indexes_array_citizen=repmat(repelem([1:Citizen],Car_brand*Car_color),[1 City]);
indexes_array_city=repmat(repelem([1:City],Citizen*Car_brand*Car_color),[1 1]);
%Initializing loop variable
column_Matrix_final=1;
for CITY_selected=1:City
for CITIZEN_selected=1:Citizen
for CAR_BRAND_selected=1:Car_brand
for CAR_COLOR_selected=1:Car_color
%Data_4D Construction
Data_4D=zeros(City,Citizen,Car_brand,Car_color);
for city=1:length(indexes_array_city)
for citizen=1:length(indexes_array_citizen)
for car_brand=1:length(indexes_array_carbrand)
for car_color=1:length(indexes_array_carcolor)
if (indexes_array_city(city)==CITY_selected && indexes_array_citizen(citizen)==CITIZEN_selected ...
&& indexes_array_carbrand(car_brand)==CAR_BRAND_selected && ...
indexes_array_carcolor(car_color)==CAR_COLOR_selected)
Data_4D(sub2ind(size(Data_4D),indexes_array_city(city),indexes_array_citizen(citizen),...
indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color)))=1;
end
end
end
end
end
%Data_4D transformation into array Data_1D
Data_1D=zeros(1,City*Citizen*Car_brand*Car_color);
tic=1;
for city=1:City
for citizen=1:Citizen
for car_brand=1:Car_brand
for car_color=1:Car_color
Data_1D(tic)=Data_4D(city,citizen,car_brand,car_color);
tic=tic+1;
end
end
end
end
%Adding Data_1D to the next for of Matrix_Final
Matrix_Final(column_Matrix_final,:)=Data_1D;
column_Matrix_final=column_Matrix_final+1;
%Display of the four most external loops indexes to show code
%advancement
CAR_COLOR_selected
end
CAR_BRAND_selected
end
CITIZEN_selected
end
CITY_selected
end
spy(Matrix_Final)
If you add e.g.
&& indexes_array_carcolor(car_color)==2
in the if loop, only the elements of Data_1D(City,Citizen,Car_brand,Car_color=2) in NRows(City,Citizen,Car_brand,Car_color=2) will be non-zero.
I would like to know if there are faster ways to set up the problem, but keeping the same ability to manipulate Data_1D an Matrix_Final using the four indexes (City,Citizen,Car_brand,Car_color) and the ability to correlate NRows and the elements of Data_1D using these four indexes.
Thank you for your help!
This is how you have coded it
if (indexes_array_city(city)==CITY_selected && indexes_array_citizen(citizen)==CITIZEN_selected ...
&& indexes_array_carbrand(car_brand)==CAR_BRAND_selected && ...
indexes_array_carcolor(car_color)==CAR_COLOR_selected)
Data_4D(sub2ind(size(Data_4D),indexes_array_city(city),indexes_array_citizen(citizen),...
indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color)))=1;
end
Another way 1
if (indexes_array_city(city)==CITY_selected && indexes_array_citizen(citizen)==CITIZEN_selected ...
&& indexes_array_carbrand(car_brand)==CAR_BRAND_selected && ...
indexes_array_carcolor(car_color)==CAR_COLOR_selected)
Data_4D(indexes_array_city(city),indexes_array_citizen(citizen),...
indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color))=1;
end
Another way 2
Data_4D(indexes_array_city(city),indexes_array_citizen(citizen),...
indexes_array_carbrand(car_brand), indexes_array_carcolor(car_color))=double((indexes_array_city(city)==CITY_selected)& ...
(indexes_array_citizen(citizen)==CITIZEN_selected)& ...
(indexes_array_carbrand(car_brand)==CAR_BRAND_selected)& ...
(indexes_array_carcolor(car_color)==CAR_COLOR_selected));
All three of them will yield same result. Try which is faster and use it.
%% Data_4D transformation into array Data_1D
Data_4D_size=size(Data_4D);
Data_1D_size=prod(Data_4D_size);
temp = permute(Data_4D, [4 3 2 1]);
Data_1D=reshape(temp,Data_1D_size,1);
Use this for 4D to 1D convertion
If still need more speed. Compile it to mex. Compiled code runs faster.
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
I'm looking for a way to update certain elements in a vector [nx113] for every full rotation of my system.
%% # Iterate through timesteps
for tt = 1:nTimeSteps
% # Initialise ink on transfer roller
rollers(2).ink = [zeros(1,98),ones(1,5),zeros(1,113)];
% # Rotate all rollers
for ii = 1:N
rollers(ii).ink(:) = ...
circshift(rollers(ii).ink(:),rollers(ii).rotDirection);
end
% # Update all roller-connections
for ii = 1:N
for jj = 1:nBins(ii)
if(rollers(ii).connections(jj) ~= 0)
index1 = rollers(ii).connections(jj);
index2 = find(ii == rollers(index1).connections);
ink1 = rollers(ii).ink(jj);
ink2 = rollers(index1).ink(index2);
rollers(ii).ink(jj) = (ink1+ink2)/2;
rollers(index1).ink(index2) = (ink1+ink2)/2;
end
end
end
% # Calculate average amount of ink on each roller
for ii = 1:N
averageAmountOfInk(tt,ii) = mean(rollers(ii).ink);
end
rollers(18).TakeOff = averageAmountOfInk*0.6;
end
the vector rollers(2).ink is the vector i'd like to update. currently the vector is populated only once so i have ones from row 98:103. I would like this range of elements to be populated for each 'rotation' of my system not just the first time.
The reason - I'm trying to show ink being added intermittently from only a small section of the roller surface, hence the need for only five cells to be populated.
i thought that if i iterated from 1 to the number of timesteps, in steps size nBins-Max in the loop:
for tt = 1:nBins_max:nTimeSteps
this doesn't seem to be what i'm after.
I'm also hoping to remove ink from the system at the end. for every revolution i would like to be able to remove a percentage of ink on each rotation so it does not stay in the system (as if it was being printed onto a sheet and taken away).
Hopefully someone can understand this and perhaps offer some advice on how to proceed on either or both of my issues.
Your explanation doesn't quite match your code (or vice-versa if you prefer) so I'm not entirely sure what you want to do, but the following may help you towards a solution or towards expressing your problem more clearly.
The vector rollers(2).ink has 1 row and 216 columns, so an operation such as rollers(2).ink(98:103) = something is not updating rows 98 through to 103. Note also that element 98 of that vector is initialised to 0, it's not included in the elements which are initialised to 1.
You write that you want to update a range of the elements in that vector, then write a loop statement for tt = 1:nBins_max:nTimeSteps which strides over a vector of time steps. Surely you want to write something like rollers(2).ink(99:103) = new_values.
As for removing ink from the rollers at every rotation, you could just execute a line such as rollers(2).ink = rollers(2).ink * 0.975 every rotation; obviously you'll want to replace the removal rate of 2.5% every rotation that I have chosen with whatever is right for your simulation.
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.
I want to mark each value that comes out of my loop with a value.
Say I have a variable number of values that come out of each iteration. I want those values to be labeled by which iteration they came out of.
like
1-1,
2-1,
3-1,
1-2,
2-2,
3-2,
4-2,
etc.
where the first number is the value from the loop and the second is counting which iteration it came from.
I feel like there is a way I just cant find it.
ok so here is some code.
for c=1:1:npoints;
for i=1:1:NN;
if ((c-1)*spacepoints)<=PL(i+1) && ((c-1)*spacepoints)>=PL(i);
local(c)=((c)*spacepoints)-PL(i);
end
if ((c-1)*spacepoints)>=PL(NN);
local(c)=((c)*spacepoints)-PL(NN);
element(i)=NN;
end
end
I want to mark each local value with the iteration it came from for the i:NN. PL is a vector and the output is a set of vectors for each iteration.
For this sort of quick problem I like to create a cell array:
for k = 1:12
results{k} = complicated_function(...);
end
If the output is really complicated, then I return a struct with fields relating to the outputs:
for k = 1:12
results{k}.file = get_filename(...);
results{k}.result = ...;
end
Currently as it is right now, in your inner 1:NN loop, your local(c) variable is being updated or overwritten. You never apply the previous value of local, so it is not some iterative optimization algorithm(?)...
Perhaps an easy solution is to change the size/type of local from a vector to a matrix. Let's say that local is of size [npoints 1]. Instead you make it of size [npoints NN]. It is now a 2d-array (a matrix of npoints rows and NN columns). use the second dimension to store each (assumed column) vector from the inner loop:
local = zeros([npoints NN]);
%# ... code in bewteen ...
for c=1:1:npoints;
for i=1:1:NN;
if ((c-1)*spacepoints)<=PL(i+1) && ((c-1)*spacepoints)>=PL(i);
local(c, i)=((c)*spacepoints)-PL(i);
end
if ((c-1)*spacepoints)>=PL(NN);
local(c, i)=((c)*spacepoints)-PL(NN);
element(i)=NN;
end
end
end
The c'th row of your local matrix will then corresponds to the NN values from the inner loop. Please note that I have assumed your vector to be a column vector - if not, just change the order of the sizes.