Constructing structure for wind data - matlab

I have been trying to construct a structure for wind data in matlab using the struct function:
struct(fieldname1,value1,fieldname2,value2,......).
I have wind speed and direction at different heights such as 40,50,80,90 meters. The problem is I don't understand how to represent the 'value', for my big data.
wind_data=struct(ws40,[],ws50,[],ws80,[],ws90,[],wd40,[],wd50,[],wd80,[],wd90,[])
ws=wind speed. wd=wind direction and each of them are vectors.

You can allocate structs by hand:
wind_data.ws40 = [1, 2, 3];
wind_data.wd40 = [4, 5, 6];
wind_data.ws50 = [11, 22, 33];
wind_data.wd50 = [44, 55, 66];
or dynamically:
heights = [40, 50, 80, 90];
ws = round(10*rand(4,3));
wd = round(10*rand(4,3));
for hh = 1:numel(heights)
wind_data.( [ 'ws' num2str(heights(hh)) ] ) = ws(hh,:)
wind_data.( [ 'wd' num2str(heights(hh)) ] ) = wd(hh,:)
end
or directly allocate them, you have to put the fieldname in '' as Ed Smith already said:
heights = [40, 50, 80, 90];
ws = round(10*rand(4,3));
wd = round(10*rand(4,3));
wind_data = struct('ws40', ws(1,:), ...
'wd40', wd(1,:), ...
'ws50', ws(2,:), ...
'wd50', wd(2,:) );

Related

Standing waves in Maple

How do I create The following in three dimensions? (one more extra dimension to what I already have)
with(plots):
animate(sin(Pi*(t-x))*Heaviside(t-x)-sin(Pi*(t+x))*Heaviside(t+x),x=-6..0,t=-5.99..12,frames=200,numpoints=200,color=red);
Thank you
You can use the plots[animate] command. Something like the following:
plots[animate](plot3d, [sin(Pi*(t-x))*Heaviside(t-x)-sin(Pi(t+x))*Heaviside(t+x), x = -6 .. 0, y = -6 .. 0], t = -5.99 .. 12, frames = 200, numpoints = 200, color = red, orientation = [75, 75, 0])

A method to vectorise a call to prod() for lots of arrays of varying length?

So my problem is, I'd like to do this without the for loop. Geting the prod() of multiple vectors but of different lengths.
I am dealing with rays intersecting voxels. I typically have 1e6 rays and 1e5 voxels, but this can vary.
intxRays is a list of rays that have intersected voxels.
gainList is a one dimensional vector, each element has a value that corresponds to a specific ray voxel intersection calculated previously (actually with the help of you lovely lot here).
rayIntxStart and rayIntxEnd are vectors of indices for, where in the gainlist array, each ray's corresponding values start and end (they're all in order).
Here is the code and some examples and expected outputs.
gainSum = zeros(1, 5);
% only interested in the intx uniques
intxSegCtr = 1;
% loop through all of the unique segments
for rayCtr = 1:max(intxRays)
if rayCtr == intxRays(intxSegCtr)
startInd = rayIntxStart(intxSegCtr);
endInd = rayIntxEnd(intxSegCtr);
% find which rows correspoond to those segements
gainVals = gainList(startInd:endInd);
gainProd = prod(gainVals);
% get the product of the gains for those voxels
gainSumIdx = intxRays(intxSegCtr);
gainSum(gainSumIdx) = gainProd;
% increment counter
intxSegCtr = intxSegCtr + 1;
end
end
Example data for five rays and nine voxels. Assume the voxel gain array looked like this (for simplicity) for nine voxels (used in previous step).
voxelGains = 10:10:90;
Now say rays 1 and 3 don't hit anything, ray 2 hits voxels 1 and 2, ray 4 hits voxels 2:7
and ray 5 hits voxels 6:9
intxRays = [2, 4, 5];
gainList = [10, 20, 20, 30, 40, 50, 60, 70, 60 70, 80, 90];
rayIntxStart = [1, 3, 9];
rayIntxEnd = [2, 8, 12];
For these numbers the above code would give as a result:
gainSum = [0, 200, 0, 5.0400e+09, 3.024e+07];
I hope this all makes sense.
When I developed it I was using far smaller ray and voxel numbers and it worked fine. As I'm moving up though, the major bottleneck in my code is this loop. Actually just the gainVals and gainProd assignment is like 80% and 15% of my runtime on their own.
This is the only method I can find that works, padding and the like won't work due to the sizes involved.
Is there a way to get the value I want, without this loop?
Many thanks!
ok this is a very small performance boost, but it might help. for testing the matrix way without the loop a bigger data sample is needed.
These are 3 soultions, your original, an optimized and the optimized way as a oneliner. could you please try if this is already doing something for you?
clear all
% orignial loop through all Rays
intxRays = [2, 4, 5];
gainList = [10, 20, 20, 30, 40, 50, 60, 70, 60 70, 80, 90];
rayIntxStart = [1, 3, 9];
rayIntxEnd = [2, 8, 12];
gainSum = zeros(1, 5);
tic
% only interested in the intx uniques
intxSegCtr = 1;
% loop through all of the unique segments
for rayCtr = 1:max(intxRays)
if rayCtr == intxRays(intxSegCtr)
startInd = rayIntxStart(intxSegCtr);
endInd = rayIntxEnd(intxSegCtr);
% find which rows correspoond to those segements
gainVals = gainList(startInd:endInd);
gainProd = prod(gainVals);
% get the product of the gains for those voxels
gainSumIdx = intxRays(intxSegCtr);
gainSum(gainSumIdx) = gainProd;
% increment counter
intxSegCtr = intxSegCtr + 1;
end
end
toc
clear all
%loop insted of every single one to max just through the intxRays
intxRays = [2, 4, 5];
gainList = [10, 20, 20, 30, 40, 50, 60, 70, 60 70, 80, 90];
rayIntxStart = [1, 3, 9];
rayIntxEnd = [2, 8, 12];
gainSum = zeros(1, 5);
tic
for rayCtr=1:length(intxRays)
%no if as you just go through them
%intxRays(rayCtr) is the corresponding element
startInd = rayIntxStart(rayCtr);
endInd = rayIntxEnd(rayCtr);
% find which rows correspoond to those segements
gainVals = gainList(startInd:endInd);
gainProd = prod(gainVals);
% get the product of the gains for those voxels and set them to the ray
gainSum(intxRays(rayCtr)) = gainProd;
end
%disp(gainSum);
toc
clear all
%same as above, but down to 1 line so no additional values are generated
intxRays = [2, 4, 5];
gainList = [10, 20, 20, 30, 40, 50, 60, 70, 60 70, 80, 90];
rayIntxStart = [1, 3, 9];
rayIntxEnd = [2, 8, 12];
gainSum = zeros(1, 5);
tic
for rayCtr=1:length(intxRays)
gainSum(intxRays(rayCtr))=prod(gainList(rayIntxStart(rayCtr):rayIntxEnd(rayCtr)));
end
toc

Derive Matlab value matrix from Matlab key matrix and lookup vector

I have a Matlab object of integer keys in the range 1:1:7 e.g.
[3, 1, 4, 5, 6]
I also have a size 7 vector containing an associated value for each integer key, e.g.
vals = (10, 20, 30, 4000, 50, 60, 70)
what is the most efficient way to create a matrix of the values using the keys as indices, e.g. a matrix
[30, 10, 4000, 50, 60]
(in reality the key object is 6D). Must I loop?
For the case of a 1D matrix a general approach could be:
keys=[3, 1, 4, 5, 6];
vals = [10, 20, 30, 4000, 50, 60, 70]
m=vals(keys)
With this approach you use the values stored in the keys array as indices of the vals array. You can find more information about array insdexing here.
In a more general case in which keys has n rows (3 in the following example):
keys=[3, 1, 4, 5, 6;
1 3 2 4 6 ;
7 6 5 4 3];
vals = [10, 20, 30, 4000, 50, 60, 70]
m=reshape(vals(keys(:)),size(keys))
Hope this helps.
Qapla'
I think this should work. If I got the question.
inds = [3, 1, 4, 5, 6];
vals = inds;
vals(vals==1) = 10;
vals(vals==2) = 20;
vals(vals==3) = 30;
vals(vals==4) = 4000;
vals(vals==5) = 50;
vals(vals==6) = 60;
Is it like that?

Different combinations of getting a total number with x amount of different smaller numbers MATLAB

im basically trying to create a list that represents the different ways "change" (as in money) can be given my example is this
printCells(exchange([1,3,10],20))
and have the output be
ans =
<0,0,2>
<1,3,1>
<2,6,0>
<4,2,1>
<5,5,0>
<7,1,1>
<8,4,0>
<10,0,1>
<11,3,0>
<14,2,0>
<17,1,0>
<20,0,0>
The cells in the output represent how many times each indicie is used in that combination. Im trying to use recursion with this and i really don't know where to start
Thanks in advance,
Well, I programmed some recursion and I got the following:
function [] = change()
% specify inputs here
options = [1,3,10];
target = 20;
global solutions; solutions = [zeros(1, size(options,2))];
sum_up(options, target);
end
function [] = sum_up(options, target)
clc;
recursive_sum(options, target, []);
end
function [] = recursive_sum(options, target, partial)
global solutions;
s = 0;
for i=1:size(partial,2)
s = s + partial(i);
end
if s == target
entry = [];
for i=1:size(options, 2)
entry = [entry sum(partial == options(i))];
end
if ~sum(ismember(solutions(:,:), entry, 'rows'))
fprintf('%d, ', entry);
solutions = [solutions; entry];
fprintf('= %d\n', sum(partial));
end
end
if s >= target
return;
end
for i=1:size(options,2)
recursive_sum(options, target, [partial options(i)]);
end
end
With output:
20, 0, 0, = 20
17, 1, 0, = 20
14, 2, 0, = 20
11, 3, 0, = 20
10, 0, 1, = 20
8, 4, 0, = 20
7, 1, 1, = 20
5, 5, 0, = 20
4, 2, 1, = 20
2, 6, 0, = 20
1, 3, 1, = 20
0, 0, 2, = 20
Note: your matlab .m file should be called change.m.
I hope I helped you out :)
Code Golf
And just for fun, here's an extremely small version:
function[]=change()
o=[1,3,10]; t=20;
global l; l=[zeros(1,size(o,2))];
rs(o,t,[]); disp(l(2:end, :));
end
function[]=rs(o,t,p)
global l; s=0;
for i=1:size(p,2); s=s+p(i); end
if s==t; e=[];
for i=1:size(o, 2); e=[e sum(p==o(i))]; end
if ~sum(ismember(l(:,:),e,'rows')); l=[l; e]; end
end
if s>=t; return; end
for i=1:size(o,2); rs(o,t,[p o(i)]); end
end

Matlab creating a design of experiment list

I have a range of conditions I want to run through a Matlab code,
Var1 = {'A1', 'B1'};
Var2 = {'A2', 'B2', 'C2', 'D2'};
Var3 = {2.5, 3, 3.5, 4, 4.5};
Var4 = {2E-6, 5E-6, 10E-6, 0.25E-3, 0.5E-3, 1E-3, 2E-3};
Var5 = {5, 10, 15, 20, 25, 30, 40, 50, 60, 70, 80, 90, 100, 125, 150, 200};
Is there an easy way I can create a matrix (or cell array) that has all the 2*4*5*7*16 combinations?
The result needs to be a cell array, because a matrix can't contain numbers and strings simultaneously.
This question and its answers achieve what you want but with vector inputs (as opposed to cell array inputs). So you can
Transform each of your input variables into a numeric vector, to be used as index;
Generate all combinations;
Convert back by indexing.
Code:
%// Step 1:
vectors = {1:numel(Var1), 1:numel(Var2), 1:numel(Var3), 1:numel(Var4), 1:numel(Var5)};
%// Step 2:
n = numel(vectors);
combs = cell(1,n);
[combs{end:-1:1}] = ndgrid(vectors{end:-1:1});
combs = cat(n+1, combs{:});
combs = reshape(combs,[],n);
%// Step 3:
result = [Var1(combs(:,1)).' Var2(combs(:,2)).' Var3(combs(:,3)).' ...
Var4(combs(:,4)).' Var5(combs(:,5)).'];
In your example, this produces the following 4480x5 cell array:
result =
'A1' 'A2' [2.5000] [2.0000e-006] [ 5]
'A1' 'A2' [2.5000] [2.0000e-006] [ 10]
'A1' 'A2' [2.5000] [2.0000e-006] [ 15]
...
'B1' 'D2' [4.5000] [ 0.0020] [150]
'B1' 'D2' [4.5000] [ 0.0020] [200]