Average on contiguos segments of a vector - matlab

I'm sure this is a trivial question for a signals person. I need to find the function in Matlab that outputs averaging of contiguous segments of windowsize= l of a vector, e.g.
origSignal: [1 2 3 4 5 6 7 8 9];
windowSize = 3;
output = [2 5 8]; % i.e. [(1+2+3)/3 (4+5+6)/3 (7+8+9)/3]
EDIT: Neither one of the options presented in How can I (efficiently) compute a moving average of a vector? seems to work because I need that the window of size 3 slides, and doesnt include any of the previous elements... Maybe I'm missing it. Take a look at my example...
Thanks!

If the size of the original data is always a multiple of widowsize:
mean(reshape(origSignal,windowSize,[]));
Else, in one line:
mean(reshape(origSignal(1:end-mod(length(origSignal),windowSize)),windowSize,[]))
This is the same as before, but the signal is only taken to the end minus the extra values less than windowsize.

Related

Matlab Dimensions Swapped in Meshgrid

In something which made me spent several hours, I have found an inconsistency in how Matlab deals with dimensions. I somebody can explain to me OR indicate me how to report this to Matlab, please enlight me.
For size, ones,zeros,mean, std, and most every other old and common commands existing inside Matlab, the dimension arrangement is like the classical one and like the intended standard (as per the size of every dimension), the first dimension is along the column vector, the second dimension is along the row vector, and the following are the non graphical following indexes.
>x(:,:,1)=[1 2 3 4;5 6 7 8];
>x(:,:,2)=[9 10 11 12;13 14 15 16];
>m=mean(x,1)
m(:,:,1) = 3 4 5 6
m(:,:,2) = 11 12 13 14
m=mean(x,2)
m(:,:,1) =
2.5000
6.5000
m(:,:,2) =
10.5000
14.5000
m=mean(x,3)
m = 5 6 7 8
9 10 11 12
d=size(m)
d = 2 4 2
However, for graphical commands like stream3,streamline and others relying on the meshgrid output format, the dimensions 1 and 2 are swapped!: the first dimension is the row vector and the second dimension is the column vector, and the following (third) is the non graphical index.
> [x,y]=meshgrid(1:2,1:3)
x = 1 2
1 2
1 2
y = 1 1
2 2
3 3
Then, for stream3 to operate with classically arranged matrices, we should use permute(XXX,[2 1 3]) at every 3D argument:
xyz=stream3(permute(x,[2 1 3]),permute(y,[2 1 3]),permute(z,[2 1 3])...
,permute(u,[2 1 3]),permute(v,[2 1 3]),permute(w,[2 1 3])...
,xs,ys,zs);
If anybody can explain why this happens, and can indicate to me why this is not a bug, welcome.
This behavior is not a bug because it is clearly documented as the intended behavior: https://www.mathworks.com/help/matlab/ref/meshgrid.html. Specifically:
[X,Y,Z]= meshgrid(x,y,z) returns 3-D grid coordinates defined by the vectors x, y, and z. The grid represented by X, Y, and Z has size length(y)-by-length(x)-by-length(z).
Without speaking to the original authors, the exact motivation may be a bit obscure, but I suspect it has to do with the fact that the y-axis is generally associated with the rows of an image, while x is the columns.
Columns are either "j" or "x" in the documentation, rows are either "i" or "y".
Some functions deal with spatial coordinates. The documentation will refer to "x, y, z". These functions will thus take column values before row values as input arguments.
Some functions deal with array indices. The documentation will refer to "i, j" (or sometimes "i1, i2, i3, ..., in", or using specific names instead of "i" before the dimension number). These functions will thus take row values before column values as input arguments.
Yes, this can be confusing. But if you pay attention to the names of the variables in the documentation, you will quickly figure out the right order.
With meshgrid in particular, if the "x, y, ..." order of arguments is confusing, use ndgrid instead, which takes arguments in array indexing order.

Remove redundant points on plot

I trying to plot a function which has millions of points. Therefore it is not possible to plot the function as it would crash my computer. However, the entire plot consists of "elbows" in that more than 1 variable cannot change at a time.
Consider the following matrix
a = [1 2 3 4 4 4 4];
b = [1 1 1 1 2 3 4];
These points make the following figure when using plot(a,b)
However, upon closer inspection, I can reduce my plot vectors down to
a = [1 4 4];
b = [1 1 4];
and get the same plot.
My question is: what is a vectorized way to automatically remove every redundant point. I could easily loop through and search for points to remove but this would be expensive. I have tried using combinations of diff and cumsum to do this to no avail. I only have straight lines and right angles in the plot so I do not have to worry about anything of the form ax+b
You can use a diff(diff(a))~=0, or equivalently diff(a, 2)~=0, to get a perhaps cleaner looking solution. This will work whether you plug a or b into the diff function.
mat = [true, diff(a, 2)~=0, true];
a(mat)
ans =
1 4 4
b(mat)
ans =
1 1 4
Guess I'll answer my own question in case anyone else needs this. Basically what I'm doing is doing the first diff on each matrix to see if the values are changing between each element. The second diff looks for a change. Because we're looking for elbows, we end up switching from true on the x-axis to true on the y-axis. This is the point we're looking for. Then we add on the ends. From there we only keep the true elements for our original matrix.
mat = [true diff(logical(diff(a))-logical(diff(b))) true];
a(mat)
[1 4 4]
b(mat)
[1 1 4]
I'm open to alternative suggestions as this is very hacky.

How to determine the dimensions of a subplot in Matlab?

So I am writing a function that plots matrix data from n different cells. If n is 10, it should display 10 equally spaced plots on a single figure. If n is 7, it should try to space them out as equally as possible (so 3x2 or 2x3 plots with a plot by itself).
I am able to get these graphs drawn using subplot() and plot() but I'm having a hard time finding out how to initialise the dimensions for the subplot.
The number of subplots will be changing after each run so I can't initialise it to specific dimensions.
Can anyone point me in the right direction?
I am afraid problems like this tend to be messy. This normally problems like this need to be solved for different cases.
if (mod(n,2) && n<8)
% Do something
elseif (!mod(n,2) && n < 11)
% Do something else
elseif ...
....
end
The conditions are choosen a bit arbitarily since the specifications in the OP seemed a bit arbitary too. You probably understand the point and can set your own conditions.
There are two reasons why I recommend this approach.
1) This makes the code simpler to write. You do not have to come up with some complicated solution which may break in after some time.
2) By adding cases you can protect yourself against a rampant number of plots. In case the number of plots gets too large you do typically not want to have all plots in the same figure. It is also possible to wrap this into a function and apply this to X plots at a time in a loop. Typically you would want each iteration to be a separate figure.
It is not very easy to elaborate more on this since you have not yet specified how many cases you expect or what will happen to the last plot in case of odd numbers. Still this may give a good hint.
Good luck!
Another simple solution would be using round and ceil on the square root:
for n=1:20
[n, round(sqrt(n))*ceil(sqrt(n)), round(sqrt(n)), ceil(sqrt(n))]
end
output:
%(n, total_plots, x, y)
1 1 1 1
2 2 1 2
3 4 2 2
4 4 2 2
5 6 2 3
6 6 2 3
7 9 3 3
8 9 3 3
9 9 3 3
10 12 3 4
Usage example:
n = 7
subplot(round(sqrt(n)), ceil(sqrt(n)), plot_nr_x) % switch first 2 params to have either a slightly longer or slightly wider subplot
I ran into a very similar problem today and I was having a lot of trouble to define the size of the subplot that would fit everything. My reasoning is mostly a hack but it can help. If you have to represent at most n figures, you can thing as a square grid of sqrt(n) * sqrt(n). To make things better we add a safety row, so the final matrix would be (sqrt(n) + 1) * sqrt(n). I hope this helps solving your problem.
In my code have 2 nested loops:
within a loop that opens a figure for each kk element and is meant to plot a particular graph from the x position within the array.
for kk=1:length(some_file_list)
% Load data
% do some math
% get data as a cell array with things we care about in data(3,)
array_size = size(data(3,:),2);
for x=1:size(data(3,:),2);
% do more math and get things ready to plot matrix_A scaled by range_A
figure(kk); % open figure
grid_rows = round((sqrt(array_size)+1));
grid_cols = round(sqrt(array_size));
% plot
subplot(grid_rows, grid_cols, x);
imagesc(matrix_A,range_A); %plot in position
colormap(gray);
end
end

MatLAB help: shuffling a predefined vector without consecutively repeating numbers (with equal occurrences of all values)

I'm having troubles with randomly shuffling a vector without repeating numbers (ex. 1 1 is not acceptable but 1 2 is acceptable), given that each value is repeated equally.
More specifically, I would like to repeat the matrix [1:4] ten times (40 elements in total) so that 1, 2, 3 and 4 would all repeat 10 times without being consecutive.
If there is any clarification needed please let me know, I hope this question was clear.
This is what I have so far:
cond_order = repmat([1:4],10,1); %make matrix
cond_order = cond_order(:); %make sequence
I know randperm is quite relevant but I'm not sure how to use it with the one condition of non-repeating numbers.
EDIT: Thank you for all the responses.
I realize I was quite unclear. These are the examples I would like to reject [1 1 2 2 4 4 4...].
So it doesn't matter if [1 2 3 4] occurs in that order as long as individual values are not repeated. (so both [1 2 3 4 1 2 3 4...] and [4 3 1 2...] are acceptable)
Preferably I am looking for a shuffled vector meeting the criteria that
it is random
there are no consecutively repeating values (ex. 1 1 4 4)
all four values appear equal amount of times
Kind of working with the rejection sampling idea, just repeating with randperm until a sequence permutation is found that has no repeated values.
cond_order = repmat(1:4,10,1); %//make matrix
N = numel(cond_order); %//number of elements
sequence_found = false;
while ~sequence_found
candidate = cond_order(randperm(N));
if all(diff(candidate) ~= 0) %// check if no repeated values
sequence_found = true;
end
end
result = candidate;
The solution from mikkola got it methodically right, but I think there is a more efficient way:
He chose to sample based on equal quantities and check for the difference. I chose to do it the other way round and ended up with a solution requiering much less iterations.
n=4;
k=10;
d=42; %// random number to fail first check
while(~all(sum(bsxfun(#eq,d,(1:n).'),2)==k)) %' //Check all numbers to appear k times.
d=mod(cumsum([randi(n,1,1),randi(n-1,1,(n*k)-1)]),n)+1; %generate new random sample, enforcing a difference of at least 1.
end
A subtle but important distinction: does the author need an equal probability of picking any feasible sequence?
A number of people have mentioned answers of the form, "Let's use randperm and then rearrange the sequence so that it's feasible." That may not work. What will make this problem quite hard is if the author needs an equal chance of choosing any feasible sequence. Let me give an example to show the problem.
Imagine the set of numbers [1 2 2 3 4]. First lets enumerate the set of feasible sequences:
6 sequences beginning with 1: [1 2 3 2 4], [1 2 3 4 2], [1 2 4 2 3], [1 2 4 3 2], [1 3 2 4 2], [1 4 2 3 2].
Then there are 6 sequences beginning with [2 1]: [2 1 2 3 4], [2 1 2 4 3], [2 1 3 2 4], [2 1 3 4 2], [2 1 4 2 3], [2 1 4 3 2]. By symmetry, there are 18 sequences beginning with 2 (i.e. 6 of [2 1], 6 of [2 3], 6 of [2 4]).
By symmetry there are 6 sequences beginning with 3 and another 6 starting with 4.
Hence there are 6 * 3 + 18 = 36 possible sequences.
Sampling uniformly from feasible sequences, the probability the first number is 2 is 18/36 = 50 percent! BUT if you just went with a random permutation, the probability the first digit is 2 would be 40 percent! (i.e. 2/5 numbers in set are 2)
If equal probability of any feasible sequence is required, you want 50 percent of a 2 as the first number, but naive use of randperm and then rejiggering numbers at 2:end to make sequence feasible would give you a 40 percent probability of the first digit being two.
Note that rejection sampling would get the probabilities right as every feasible sequence would have an equal probability of being accepted. (Of course rejection sampling becomes very slow as probability of being accepted goes towards 0.)
Following some of the discussion on here, I think that there is a trade-off between performance and the theoretical requirements of the application.
If a completely uniform draw from the set of all valid permutations is required, then pure rejection sampling method will probably be required. The problem with this of course is that as the size of the problem is increased, the rejection rate will become very high. To demonstrate this, if we consider the base example in the question being n multiples of [1 2 3 4] then we can see the number of samples rejected for each valid draw as follows (note the log y axis):
My alternative method is to randomly sort the array, and then if duplicates are detected then the remaining elements will again be randomly sorted:
cond_order = repmat(1:4,10,1); %make matrix
cond_order = reshape(cond_order, numel(cond_order), 1);
cond_order = cond_order(randperm(numel(cond_order)));
i = 2;
while i < numel(cond_order)
if cond_order(i) ~= cond_order(i - 1)
i = i + 1;
else
tmp = cond_order(i:end);
cond_order(i:end) = tmp(randperm(numel(tmp)));
end
end
cond_order
Note that there is no guarantee that this will converge, but in the case where is becomes clear that it will not converge, we can just start again and it will still be better that re-computing the whole sequence.
This definitely meets the second two requirements of the question:
B) there are no consecutive values
C) all 4 values appear equal amount of times
The question is whether it meets the first 'Random' requirement.
If we take the simplest version of the problem, with the input of [1 2 3 4 1 2 3 4] then there are 864 valid permutations (empirically determined!). If we run both methods over 100,000 runs, then we would expect a Gaussian distribution around 115.7 draws per permutation.
As expected, the pure rejection sampling method gives this:
However, my algorithm does not:
There is clearly a bias towards certain samples.
In the end, it depends on the requirements. Both methods sample over the whole distribution so both fill the core requirements of the problem. I have not included performance comparisons, but for anything other than the simplest of cases, I am confident that my algorithm would be much faster. However, the distribution of the draws is not perfectly uniform. Whether it is good enough is dependent on the application and the size of the actual problem.

Questions about matlab median filter commands

This is a question about Matlab/Octave.
I am seeing some results of the medfilt1(1D Median filter command in matlab) computation by which I am confused.
EDIT:Sorry forgot to mention:I am using Octave for Windows 3.2.4. This is where i see this behavior.
Please see the questions below, and point if I am missing something.
1] I have a 1D data array b=[ 3 5 -8 6 0];
out=medfilt1(b,3);
I expected the output to be [3 3 5 0 0] but it is showing the output as [4 3 5 0 3]
How come? What is wrong here?
FYI-Help says it pads the data at boundaries by 0(zero).
2] How does medfilt2(2D median filter command in matlab) work.
Help says "Each output pixel contains the median value in the m-by-n neighborhood around the corresponding pixel in the input image".
For m=3,n=3, So does it calculate a 3x3 matrix MAT for each of input pixels placed at its center and do median(median(MAT)) to compute its median value in the m-by-n neighbourhood?
Any pointers will help.
thank you. -AD
I was not able to replicate your error with Matlab 7.11.0, but from the information in your question it seems like your version of medfilt1 does not differentiate between an odd or even n.
When finding the median in a vector of even length, one usually take the mean of the two median values,
median([1 3 4 5]) = (3+4)/2 = 3.5
This seems to be what happens in your case. Instead of treating n as odd, and setting the value to be 3, n is treated as even and your first out value is calculated to be
median([0 3 5]) = (3+5)/2 = 4
and so on.. EDIT: This only seems to happen in the endpoints, which suggest that the padding with zeros is not properly working in your Octave code.
For your second question, you are almost right, it calculates a 3x3 matrix in each center, but it does not do median(median(MAT)), but median(MAT(:)). There is a difference!
A = [1 2 3
14 5 33
11 7 13];
median(median(A)) = 11
median(A(:)) = 7