How do I interpolate between points without going beyond them? - matlab

I have data of variable lengths (reaching movements recorded in 2D) and want to create a function that will resample this data to a uniform length (500 samples).
However, I want matlab to only resample between the maximum and minimum values given, without adding any additional distance. For instance, if I resample the matrix [1:1:10], the resampled matrix should have a minimum value of 1 and a maximum value of 10.
So far I've tried the following:
x = [1:1:10];
interp(x, 500 / length(x));
This, however, gives values above my maximum specified value of 10.
Is there any way I can get matlab to resample/interpolate solely between two points, without extending beyond them?

If I understood you correctly, you need to:
x=(1:1:10);
n=500;
xi=interp1(1:length(x),x,linspace(min(x),max(x),n));

Related

How to quickly/easily merge and average data in matrix in MATLAB?

I have got a matrix of AirFuelRatio values at certain engine speeds and throttlepositions. (eg. the AFR is 14 at 2500rpm and 60% throttle)
The matrix is now 25x10, and the engine speed ranges from 1200-6000rpm with interval 200rpm, the throttle range from 0.1-1 with interval 0.1.
Say i have measured new values, eg. an AFR of 13.5 at 2138rpm and 74,3% throttle, how do i merge that in the matrix? The matrix closest values are 2000 or 2200rpm and 70 or 80% throttle. Also i don't want new data to replace the older data. How can i make the matrix take this value in and adjust its values to take the new value in account?
Simplified i have the following x-axis values(top row) and 1x4 matrix(below):
2 4 6 8
14 16 18 20
I just measured an AFR value of 15.5 at 3 rpm. If you interpolate the AFR matrix you would've gotten a 15, so this value is out of the ordinary.
I want the matrix to take this data and adjust the other variables to it, ie. average everything so that the more data i put in the more reliable and accurate the matrix becomes. So in the simplified case the matrix would become something like:
2 4 6 8
14.3 16.3 18.2 20.1
So it averages between old and new data. I've read the documentation about concatenation but i believe my problem can't be solved with that function.
EDIT: To clarify my question, the following visual clarification.
The 'matrix' keeps the same size of 5 points whil a new data point is added. It takes the new data in account and adjusts the matrix accordingly. This is what i'm trying to achieve. The more scatterd data i get, the more accurate the matrix becomes. (and yes the green dot in this case would be an outlier, but it explains my case)
Cheers
This is not a matter of simple merge/average. I don't think there's a quick method to do this unless you have simplifying assumptions. What you want is a statistical inference of the underlying trend. I suggest using Gaussian process regression to solve this problem. There's a great MATLAB toolbox by Rasmussen and Williams called GPML. http://www.gaussianprocess.org/gpml/
This sounds more like a data fitting task to me. What you are suggesting is that you have a set of measurements for which you wish to get the best linear fit. Instead of producing a table of data, what you need is a table of values, and then find the best fit to those values. So, for example, I could create a matrix, A, which has all of the recorded values. Let's start with:
A=[2,14;3,15.5;4,16;6,18;8,20];
I now need a matrix of points for the inputs to my fitting curve (which, in this instance, lets assume it is linear, so is the set of values 1 and x)
B=[ones(size(A,1),1), A(:,1)];
We can find the linear fit parameters (where it cuts the y-axis and the gradient) using:
B\A(:,2)
Or, if you want the points that the line goes through for the values of x:
B*(B\A(:,2))
This results in the points:
2,14.1897 3,15.1552 4,16.1207 6,18.0517 8,19.9828
which represents the best fit line through these points.
You can manually extend this to polynomial fitting if you want, or you can use the Matlab function polyfit. To manually extend the process you should use a revised B matrix. You can also produce only a specified set of points in the last line. The complete code would then be:
% Original measurements - could be read in from a file,
% but for this example we will set it to a matrix
% Note that not all tabulated values need to be present
A=[2,14; 3,15.5; 4,16; 5,17; 8,20];
% Now create the polynomial values of x corresponding to
% the data points. Choosing a second order polynomial...
B=[ones(size(A,1),1), A(:,1), A(:,1).^2];
% Find the polynomial coefficients for the best fit curve
coeffs=B\A(:,2);
% Now generate a table of values at specific points
% First define the x-values
tabinds = 2:2:8;
% Then generate the polynomial values of x
tabpolys=[ones(length(tabinds),1), tabinds', (tabinds').^2];
% Finally, multiply by the coefficients found
curve_table = [tabinds', tabpolys*coeffs];
% and display the results
disp(curve_table);

MATLAB: count number of peaks

I have a graph like this and I want to determine the number of peaks. Since it's a wave function the whole graph has many peaks that is why I was unsuccefull in finding the number of peaks using functions such as findpeaks for the graph below it returns a number of peaks around 3000 whereas I want to have the number 7.
My idea was to do a for or while loop that counts the number of instances where the average is higher than 0.5. So ultimately I want a function that iterates in segments over the graph returns the number of peaks and the range of y index values for which this peak occurs (I think the best way to do this would to save them to a zeros matrix).
link of file data: https://www.dropbox.com/s/vv8vqv28mqzfr9l/Example_data.mat?dl=0
Do you mean you are trying to count the 'on' parts of your data?
You're on the right track using findpeaks. If you scroll to the bottom of the documentation you'll see that you can actually tweak the routine in various ways, for example specifying the minimum distance between peaks, or the minimum difference between a point and its neighbour before it is considered a peak.
By defining the minimum distance between peaks, I detected the following 7 peaks. Code is included below. Alternatively you can play around with the other parameters you can pass into findpeaks.
The only other thing to note is that I took the absolute value of your data.
load('Example_data.mat')
indx = 1:numel(number11);
[pks, locs] = findpeaks(abs(number11), indx, 'MinPeakDistance', 0.25e4);
hold on
plot(number11)
plot(locs,pks, 'rx')
disp(numel(pks))

Why Kernel smoothing function, ksdensity, in MATLAB, results in values greater than one?

I have a set of samples, S, and I want to find its PDF. The problem is when I use ksdensity I get values greater than one!
[f,xi] = ksdensity(S)
In array f, most of the values are greater than one! Would you please tell me what the problem can be? Thanks for your help.
For example:
S=normrnd(0.3035, 0.0314,1,1000);
ksdensity(S)
ksdensity, as the name says, estimates a probability density function over a continuous variable. Probability densities can be larger than 1, they can actually have arbitrary values from zero upwards. The constraint on probabilities is that their sum over an exhaustive range of possibilities has to be 1. For probability densities, the constraint is that the integral over the whole range of values is 1.
A crude approximation of an integral of the pdf estimated by ksdensity can be obtained in Matlab like this:
sum(f) * min(diff(xi))
assuming that the values in xi are equally spaced. The value of this expression should be approximately 1.
If in your application you believe this approximation is not close enough to 1, you might want to specify the grid of estimation points (second parameter pts) such that the spacing is finer or the range is wider than the one automatically generated by ksdensity.

Why does MATLAB image processing Toolbox doesn't use equal bin size in imhist?

According to MATLAB's documentation the $p$-th bin contains the pixels between
$A\frac{(p-1.5)}{n-1}\leq x<A\frac{p-0.5}{n-1}$, where $x$ is the pixel intensity, and $n$ is the number of bins.
As far as I can understand this, $A$ is a scaling factor that is the maximal value of the data type used (e.g. if $A=1$ we consider an image with $x\in[0,1]$).
What I don't really understand, why we use the constants in the expression; for the first bin (assuming that MATLAB considers $p=1$ instead of $p=0$ as the first bin) we put values between $x\in[\frac{-0.5}{(n-1)}, \frac{0.5}{(n-1)}]$, but we have values between $x\in[0,1]$ so the effective width of the bin is only half of the "normal" bins (same goes to the last bin). Why don't MATLAB use $A\frac{p}{n-1}\leq x<A\frac{p+1}{n-1}$ for $p\in[0,n-1]$?
The answer was actually pretty easy and not MATLAB-related: if you divide your domain equidistantly (and choose these values as the representative value of the corresponding quantization level) and pick thresholds at the centroid of each of these intervals endpoints you get the thresholds that MATLAB uses.

Limit data values displayed in MATLAB histogram

I have a vector that I want to print a histogram of of data for. This data ranges from -100 to +100. The amount of data around the outer edges is insignificant and therefore I don't want to see it. I am most interested in showing data from -20 to +20.
1.) How can I limit that window to print on my histogram?
The amount of data I have at 0 outnumbers of the amount of data I have anywhere in the dataset by a minimum of 10:1. When I print the histogram, the layout of element frequency is lost because it is outnumbered by 0.
2.) Is there a way that I can scale the number of 0 values to be three times the number of -1 entries?
I am expecting an exponential drop of this dataset (in general) and therefore three times the frequency of -1 would easily allow me to see the frequency of the other data.
You can use something like
binCenters = -20:5:20;
[N,X] = hist(V,binCenters);
N = N./scalingVector;
bar(X(2:end-1),N(2:end-1));
Note that the code excludes the extremes of N and X from the bar plot, since they contain the number of values smaller than -20 and larger than 20. Also, by building scalingVector appropriately, you can scale N as you please.
You could also just toss out any values outside the [-20,20] range by using
subsetData=data(abs(data)<=20)
1) You can limit the histogram range you see on the plot by just setting the X axes limits:
xlim([-20 20])
Setting bins in hist command is good, but remember thatall the values outside the bins will fall into the most left and right bin. So you will need to set the axes limits anyway.
2) If there is a big difference between values in different bins, one way is to transform values on Y axes to log scale. Unfortunately just setting Y axes to log (set(gca,'YScale','log')) does not work for bar plot. Calculate the histogram with hist or histc (depending on whether you want to specify bins centers or edges) and log2 the values:
[y, xbin] = hist(data);
bar(xbin, log2(y) ,'hist')
Histogram has a few different methods of calling it. I strongly recommend you read the documentation on the function (doc hist)
What you are looking for is to put in a custom range in the histogram bin. It depends a bit on how many bins you want, but something like this will work.
Data=randn(1000,1)*20;
hist(Data,-20:20);
You could, if you want to, change the frequency of the binning as well. You could also change the axis so that you only focus on the range from -20 to 20, using a xaxis([-20 20]) command. You could also ignore the bin at 0, by using an yaxis and limiting the values to exclude the 0 bin. Without knowing what you want exactly, I can only give you suggestions.