How to interpolate this? - matlab

I have a problem with interpolating.
the plot of the points is
here.
If we zoom in , the plot looks something like this
this.
I do not know how to use the Matlab interp1 function to interpolate this.
Explanation:
This is a space time diagram, i.e. the x axis is the space and the y-axis is the time.
Hence, the structure of the vectors x and y is as follows:
The vector y is defined as
y=(1,1,2,2,3,3,4,4,...,2500,2500)
and the x-vector contains (pairwise) the positions, i.e.
x(i) and x(i+1) are the different positions at time y(i)=y(i+1).
I think the problem maybe is that at different times, we have the same points as can be seen in the zoomed in picture above.
How many time-steps the x-values remain the same differs, sometimes they remain the same for 3 time-steps, sometimes even for 4 time-steps, sometimes only for 2 time-steps.

You can use acccumarray to perform some operation on the values in Y that correspond to each unique value of X.
Using some example data:
x = [1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7, 7, 8, 8, 8];
y = 1:length(x);
We get something like the following:
Now use accumarray to perform some calculation on each cluster:
clusteravg = accumarray(x', y, [], #mean);
clustermax = accumarray(x', y, [], #max);
clustermin = accumarray(x', y, [], #min);
The first input to accumarray is an array of subscripts, the second input is an array of values that correspond to those subscripts. accumarray collects all of the elements of the second input that share the same subscript (first input) and performs the specified calculation on them. Here I've calculated the average, max, and min for each cluster of values:
Yay

Related

Matlab Plotting Two Matrixes and Marking some X-Coordinates On it Based off another vector

Say I have two vectors I want to plot on matlab, and I have this vector that I want to use to mark a small "X" on the plot where this X-value occurs on one of the vectors, how do I do that?
To clarify, say I have a vector of a = [1, 2, 3, 4, 5] another of b = [1, 2, 3, 4, 5, 6] and an identifier vector of a = [1, 4] how do I plot these and show an X on a/b on the plot on x=1 and x =4?
Actually, to find the points that you want, you can use the ismember function as show below.
a=1:5;
c=[1 4];
hold on
plot(a(~ismember(a,c)),'ro') %values of a that DO NOT match the extra entry
plot(a(ismember(a,c)),'rx') %values of a that match the extra entry
I'm not 100% clear if it is this what you want. You can give some comments and I (or someone else) can give you a better answer.

Median of arbitrary datapoint around index - MATLAB

I've been using the findpeaks function with great success to detect peaks in my signal. My next step is to clean these identified peaks, for which I have the indices.
My goal is to calculate the median of Y data points before and Y data points after a given index and replace whatever values (noise) there are with these new values (the calculated median).
Something like this:
% points before, peak, points after
% ↓ ↓ ↓
x = [1, 2, 3, 1, 34, 3, 2, 1, 3]
Calculate the median of the 4 data points preceding and following my peak the peak of 34...
Median of [1,2,3,1,3,2,1,3] is 2.
Replace my peak with this new value:
% Replaced peak with surrounding median
% ↓
x1 = [1, 2, 3, 1, 2, 3, 2, 1, 3]
Any suggestion on how to implement this?
Find the peaks and replace them with the results of medfilt1()
[~,idx]=findpeaks(x);
if ~isempty(idx)
m = medfilt1(x,9);
x(idx) = m(idx);
end
I think it is most efficient to process each peak individually. I'll demonstrate in a step-by-step manner in the following.
Take the neighborhood of each peak
x(idx_max-N:idx_max+N)
with N the number of elements to the left and right of the peak, respectively. The median of the neighborhood around each peak can be computed by using MATLAB's median() function:
median(x(idx_max-N:idx_max+N))
Now, you can replace either only the element at the peak position with the median of the neighborhood:
x(idx_max) = median(x(idx_max-N:idx_max+N))
or easily replace all elements of the neighborhood with the median value:
x(idx_max-N:idx_max+N) = median(x(idx_max-N:idx_max+N))
(Note that scalar expansion is used in the last example to assign a scalar value to multiple elements of an array.)

How can you set the XData of a Matlab line graph plot with a 2D array?

I'm having some issues dynamically changing the data that is displayed on a plot. The data set is stored in a 2D array of varying dimensions, during the running of the program, only the width of the matrix will change - all elements always have the same length. The intention here is to have each row of the matrix represented by a line on the line plot.
An example:
data = [1, 2, 3; 3, 4, 5; 4, 5, 6];
p = plot(data);
drawnow;
new_data = [7, 8, 9; 1, 2, 3; 4, 5, 6];
set(p, 'XData', new_data);
drawnow;
This method works well for updating plots when the data is better formatted, however I cannot seem to find a way to organise the data in a useful format that will allow this to plot.
To set multiple properties (as p is an array of handles to line objects), the property name as well as the properties to set need to be cell arrays, see e.g. this documentation page under "Set Line Style to Different Value for Multiple Lines" for an example.
In your example case, this would work:
set(p, {'XData'}, mat2cell(new_data, ones(1,3), 3));
See also mat2cell, in this case I use it to reshape new_data to a 3x1 cell array each containing a 1x3 row from new_data.

Matlab 3D plot plotting weird lines?

I have 3 arrays X, Y, Z that look something like this:
x = [1, 1, 1, 2, 2, 2, 3, 3, 3]
y = [1, 2, 3, 1, 2, 3, 1, 2, 3]
z = [1, 2, 3, 2, 4, 6, 3, 6, 9]
Then I am plotting these points with plot3(x,y,z).
However the result is something unexpected.. It's basically meant to appear like a log-graph, it does this but it also has extra lines. I have no idea how it's happening, maybe someone here can enlighten me!
Here is an example of my graph (obviously I've plotted my values for X, Y, Z and the arrays above are just an example of what they look like):
As you can see, the bottom curved lines are the log-graph lines which I am happy to be seeing, but the one that appears above it confuse me. I tried displaying the X Y Z values that match the following pattern: X is between 110 and 120 and Y = 0.05. This should theoretically give me TWO matches for each X. ie. Between X = [110, 120], I should get 20 matches since the graph shows two lines hitting at the point Y = 0.05 for each X.
To make it more clear what values of X are being graphed, it's basically increments of 0.1 so between X = 120 and X = 119, it is plotting 119.0, 119.1, ... , 120.0. In any case, only two points of X, Z hit Y = 0.05 between 119-120.
As I was saying, I checked for the values of X, Z that matched Y = 0.05 and it only returns ONE result per X. That is, for X = [110, 120], only 10 matches returned. These values were values on the bottom lines (ie. the log-graph lines) and NOT the top line. So effectively, these lines are not meant to exist. They are definitely hitting Y = 0.05 and are between X = [110, 120] so they should be appearing as a match..
So there you have it. Not really sure what's going on!
If someone could help, that'd be great.
EDIT - More Info.
Even manually putting the X, Y values to the function which returns Z never reaches the values on the upper line.
Thanks.
The example for x, y and z actually illustrates your problem quite well.
You are not plotting individual curves (one for each log-plot) but rather one continuous curve. Hence your extra lines are in fact connecting one end of a log curve to the beginning of the next.
You have to break up your plot command.
Edit
In the end it will require knowledge of your dataset, but for the x, y, z you provided above, this will work to produce three independent curves instead of one:
x = [1, 1, 1, 2, 2, 2, 3, 3, 3];
y = [1, 2, 3, 1, 2, 3, 1, 2, 3];
z = [1, 2, 3, 2, 4, 6, 3, 6, 9];
DATASET_SIZE = 3;
hold on;
for i=1:size(x,2)/DATASET_SIZE
plot3(x((i-1)*DATASET_SIZE+1:i*DATASET_SIZE),y((i-1)*DATASET_SIZE+1:i*DATASET_SIZE),z((i-1)*DATASET_SIZE+1:i*DATASET_SIZE));
plot3(x(i*DATASET_SIZE+1:2*DATASET_SIZE),y(i*DATASET_SIZE+1:2*DATASET_SIZE),z(i*DATASET_SIZE+1:2*DATASET_SIZE));
plot3(x(2*DATASET_SIZE+1:3*DATASET_SIZE),y(2*DATASET_SIZE+1:3*DATASET_SIZE),z(2*DATASET_SIZE+1:3*DATASET_SIZE));
view(3)
end
Edit 2
An easy way of finding out if this "problem" occured, is using the Data Cursor in the MATLAB plot window. Place it anywhere on your graph and use the up or down arrow keys to move around. If you can move along the entire length of the plot, it is a continuous line. Furthermore, you should see the Cursor jump from the "end" of one curve to the "start" of the next.
I had the same problem using surface(x,y,z) and addressed the issue by changing the renderer. MATLAB has 3 different renderers for plotting data and by default the openGL renderer plots as you have shown. You can view hwich renderer your figure uses with GET(gcf). You can change renderer as I have done using: set(gcf,'Renderer','painters')
The 3rd renderer I believe is zbuffer and may work as well.

Repeating sequences in a single matlab plot

Say I have 2 vectors:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9];
b = [1, 3, 5, 7, 9, 7, 5, 3, 1];
I want to plot these vectors against each other, a being X, and b being Y.
However, while I want the plotted point to be in the correct location, I want the actual values shown on the X axis to be a function of the values in a, where the result of the function is repeated over a given period AND I want these values to be sequential along the axis.
For example, say the function for the value to show on the X axis is mod(a - 1, 3) + 1. I would like for the X axis to read something like 1, 2, 3, 1, 2, 3, 1, 2, 3 as in
I have a feeling that some combination of subplot and axes may be required, but I'm not seeing anything obvious in the documentation.
You can set this via the axes properties xtick and xticklabel.
set(gca, 'xtick', a, 'xticklabel', mod(a,3)+1);
This won't give you the ticks you've described, but mod(a-1,3)+1 will. I'm not sure if you wanted the function you gave or the picture you showed, though.
Try setting the XtickLabels, like so,
>> set(gca,'XTickLabel',{'1','2','3'})