I have data recorded from a device (250-Hz sampling device, ~100K measurements total so about 400 seconds worth). I want to create (overlapping) windows of 512 (~2 seconds) or 1024 (~4 seconds) measurements each, perhaps in ~0.5 second intervals. I'm using Matlab.
Is there a particular way to accomplish this goal? I imagine I want to use a filter to accomplish this goal? Would it change if I wanted to apply, say, a Hann window as well?
Thanks for the help!
Let your data be a row vector. You can use blockproc if you:
choose the "blockSize" argument as [1 S], where S is window step;
use the 'BorderSize' option to set borders [0 B]. Window length will be S+2*B;
set the 'TrimBorder' property to false;
define an appropriate function to apply to each window data.
For example, say you a length-5 window with step 3, and you want the sum of all elements in each window:
>> x = 1:12;
>> y = blockproc(x, [1 3], #(t) sum(t.data), 'Bordersize', [0 1], 'TrimBorder', false)
y =
10 25 40 42
where
%// 0+1+2+3+4 = 10
%// 3+4+5+6+7 = 25
%// 6+7+8+9+10 = 40
%// 9+10+11+12+0 = 42
Note the zero padding at the initial and final windows. To avoid that, include an adequate amount of initial zeros in the data, choose data size appropriately, and discard initial and final output values:
>> x = 1:14;
>> y = blockproc([0 0 x], [1 3], #(t) sum(t.data), 'Bordersize', [0 1], 'TrimBorder', false)
y =
3 15 30 45 60 27
where
%// 1+2+3+4+5 = 15
%// 4+5+6+7+8 = 30
%// 7+8+9+10+11 = 45
%// 10+11+12+13+14 = 60
Related
I have a 2000x2 matrix, and "for each 10x2 segment of this matrix", I need to calculate the maximum of corresponding values (second column) of repetitive values (first column) in the matrix. Like if the 3rd 10x2 segment of the matrix is this:
...
[2 20;
2 30;
2 40;
7 100;
7 110;
7 120;
7 130;
7 140;
15 240;
15 260]
...
I want to get this:
...
[2 40;
7 140;
15 260]
...
And so on. I have written the following but it gives me the maximum of repetitive elements through the "whole matrix":
[uv,~,idx] = unique(A(:,1));
B = [uv accumarray(idx,A(:,2),[],#max)];
But again, I need to do this "for each separate 10x2 segments of the matrix", and then store the results in a 'whatever x 2' sized matrix! Does anyone have any ideas how I could do this?
Instead of using A(:,2) as the argument to accumarray you can use indices of values and use them to extract elements in the function handle.
A = randi(5,50,2);
val = (1:size(A,1)).';
B = accumarray( ...
[A(:,1) ceil(val/10)], val, [], ...
#(x){[ A(x(1), 1) max(A(x, 2)) ]} ...
);
result = vertcat(B{:});
Suppose the following:
A = [1;2;3;4;5;6;7];
A1 = table(A);
The following sums current and 2 following cells beneath:
A2 = movsum(A1{:, 1:end}, [0 2], 'Endpoints', 'fill');`
What I want is the sum of what above movsum() does, but without
considering the current cell (0 in [0 2]). The very first value of this calculation (= first row in new table) should be 5 (2+3), the second 7 (3+4) etc.
How do I have to adapt my following code for it to do the intended calculations?
A3 = movsum(A1{:, 1:end}, [1 2], 'Endpoints', 'fill');
... because A3 returns:
I'm not sure movsum supports this, as the help reads as
Y = movsum(X,[NB NF]) [...] returning the local sum of the previous
NB elements, the current element, and the next NF elements of X.
However, a simple solution would be to subtract the unwanted current cell via
A2 = movsum(A1{:, 1:end}, [0 2], 'Endpoints', 'fill') - A1{:, 1:end};
Testing it gives
movsum(1:7,[0,2],'EndPoints','fill') - (1:7)
ans =
5 7 9 11 13 NaN NaN
Is that what you want?
I want to select a random subset of a vector, much like datasample(data,k), but I want them in order.
I have an ODE which has [t,y] as output and it's the y that I want a subset of. I cannot just do a sort because y is not linear and so I somehow have to sort it with respect to t.
Any ideas how I can to this?
If I understand correctly, you want to sample the elements maintaining their original order. You can do it this way:
randomly sample the indices rather than the values;
sort the sampled indices;
use them to access the selected values;
that is:
result = data(sort(randsample(numel(data), k)));
The above uses the randsample function from the Statistics Toolbox. Alternatively, in recent Matlab versions you can use the two-input form of randperm:
result = data(sort(randperm(numel(data), k)));
For example, given
data = [61 52 43 34 25 16];
k = 4;
a possible result is
result =
61 43 34 25
This can be solved using a combination of randperm and intersect:
function q40673112
% Create a vector:
v = round(sin(0:0.6:6),3); disp(['v = ' mat2str(v)]);
% Set the size of sample we want:
N = 5;
% Create the random indices:
inds = intersect(1:numel(v), randperm(numel(v),N)); disp(['inds = ' mat2str(inds)]);
% Sample from the vector:
v_samp = v(inds); disp(['v_samp = ' mat2str(v_samp)]);
Example output:
% 1 2 3 4 5 6 7 8 9 10 11
v = [0 0.565 0.932 0.974 0.675 0.141 -0.443 -0.872 -0.996 -0.773 -0.279]
inds = [4 6 9 10 11]
v_samp = [0.974 0.141 -0.996 -0.773 -0.279]
I am trying to write some code which feeds a function with an unknown number of parameters. The idea is to feed the function the minimum, middle and maximum value within the possible range of values.
For example:
If the function takes 3 parameters
Parameter 1 can accept a range of 0 - 10
Parameter 2 can accept a range of 20 - 40
Parameter 3 can accept a range of 6 - 66
myfunction(para1, para2, para3)
myfunction(min,min,min)
myfunction(min,min,mid)
myfunction(min,min,max)
myfunction(min,mid,min)
myfunction(min,mid,mid)
myfunction(min,mid,max)
etc...
so using our example above:
The first time it loops I need to run
myfunction(0, 20, 0)
next time it loops it needs to run
myfunction(0, 20, 36)
next time it loops it needs to run
myfunction(0, 20, 66)
etc...
For all possible combinations (in this case all 27).
However, if the number of parameters changes to accept 4, it needs to be able to accommodate that and so on. I've looked into doing it as a loop or recursively, but I thought as a loop would be easier to understand, but either would be really helpful.
I don't want to have to do this manually so any help will be much appreciated.
For an arbitrary number of parameters (not fixed to 3), you can use the following code. It makes use of comma-separated lists, which is a powerful tool to handle a variable number of parameters.
Let n be the number of parameters. Then the number of combinations is N = 3^n.
params = {linspace(0,10,3), linspace(20,40,3), linspace(6,66,3)};
%// cell array with arbitrary number of elements. Each cell contains a 3-vector
%// which defines min, mid, max of one parameter.
n = numel(params); %// number of parameters
N = 3^n; %// number of combinations
paramCombs = cell(1,n); %// initialization for output of ndgrid
[paramCombs{end:-1:1}] = ndgrid(params{end:-1:1}); %// generate all combinations
%// in desired order. Gives n matrices, each containing values of one parameter
paramCombs = cellfun(#(c) c(:), paramCombs, 'uni', 0); %// linearize matrices
%// into n column vectors, each with N rows.
paramCombs = [paramCombs{:}]; %// concat column vectors into N x n matrix
paramCombs = mat2cell(paramCombs,ones(N,1),ones(n,1)); %// convert to
%// N x n cell array. Each row contains a combination of parameter values
result = arrayfun(#(n) myFun(paramCombs{n,:}), 1:N, 'uni', 0); %// call myFun
%// with each combination of parameter values
The result variable is a 1 x N cell array, where each cell contains the result of calling myFun with a combination of the n parameters.
Example 1: myFun's output simply replicates the input (as in #thewaywewalk's answer). params is defined as given above, so there are 3 parameters:
>> result{1}
ans =
0 20 6
>> result{2}
ans =
0 20 36
>> result{3}
ans =
0 20 66
>> result{4}
ans =
0 30 6
>> result{5}
ans =
0 30 36
etc.
Example 2: case with 2 parameters: params = {linspace(0,2,3), linspace(0,10,3)}. Again, myFun simply replicates the input:
>> result{1}
ans =
0 0
>> result{2}
ans =
0 5
>> result{3}
ans =
0 10
>> result{4}
ans =
1 0
>> result{5}
ans =
1 5
etc.
The method can be further generalized to an arbitrary (and possibly different) number of values for each parameter, just replacing the line N = 3^n; by
N = prod(cellfun(#numel, params)); %// number of combinations
Example 3: there are 2 parameters; the first with 3 values, and the second with 2: params = {[1 2 3], [10 20]};:
>> result{1}
ans =
1 10
>> result{2}
ans =
1 20
>> result{3}
ans =
2 10
>> result{4}
ans =
2 20
>> result{5}
ans =
3 10
>> result{6}
ans =
3 20
Think about something like this:
function result = permfunction()
% I assume you every parameter-range is defined by 3 values: min, mid, max
% you can define every triple as follows:
para1 = linspace(0,10,3);
para2 = linspace(20,40,3);
para3 = linspace(6,66,3);
% all possible parameters
parameters = [para1(:),para2(:),para3(:)];
% possible combinations of parameters-indices
a = perms(1:3);
% transformed into a cell array with linear indices, to achieve this +3 and +6
% are added to the 2nd and 3rd row.
idx = mat2cell( [a(:,1) , a(:,2)+3 , a(:,3)+6] , ones(length(a),1) );
% all parameter combinations
combinations = cellfun(#(x) parameters(x),idx,'uni',0');
% apply to your function myfunction (custom)
result = cellfun(#myfunction, combinations,'uni',0' );
end
function y = myfunction( parametertriple )
%just pass the input to the output
y = parametertriple;
end
you finally get a cell array with the results of myfunction for all your combinations of parameters. In this case I just passed the parameters to the output:
>> celldisp(ans)
ans{1} =
10 30 6
ans{2} =
10 20 36
ans{3} =
5 40 6
ans{4} =
5 20 66
ans{5} =
0 30 66
ans{6} =
0 40 36
This is how I would solve it:
%dummy function
testfun=#(a,b,c)fprintf('call function for %d,%d,%d\n',a,b,c);
%functon name
testfunname='testfun';
%intended inputs
input={[0,5,10],[20,30,40],[6,36,66]};
%generate all inputs
eval(['[' sprintf('a{%d} ',1:numel(input)) ']=meshgrid(input{:});']);
%call function
eval(['arrayfun(' testfunname sprintf(',a{%d} ',1:numel(input)) ');']);
Using eval is a dirty solution, but I don't find an alternative which allows variable input size.
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} :)