How to interpolate a matrix in MATLAB? - matlab

I have the following data with me. The first row and the first column (highlighted) are two parameters for which the rest of the elements have been generated. I am hoping to convert this matrix into a 50 by 50 matrix, interpolating the data between the rows and column.
I have tried interpolating the second column in the following manner,
x=[100 300 500 700];
y=[-20 -184 -315.2 -412];
z = linspace(x(1),x(4),50);
yi=interp1(x,y,z,'cubic');
But, my problem is, I am not able to figure out how to interpolate with respect to the row simultaneously and get the entire matrix.
Any help/suggestion would be most welcome.
The data is given below;
30 60 90
100 -20 -45 -80.5
300 -184 -215 -225.4
500 -315.2 -254 -339
700 -412 -419 -488

Your data is a function of two variables (f(x,y)) so you'll need to use interp2 rather than interp1.
% Populate the data that you already have
rows = [100, 300, 500 700];
cols = [30, 60, 90];
data = [-20 -45 -80.5
-184 -215 -225.4
-315.2 -254 -339
-412 -419 -488];
% Interpolate this at 100 points in each direction
[newcols, newrows] = meshgrid(linspace(cols(1), cols(end)), ...
linspace(rows(1), rows(end)));
% Perform the bicubic interpolation
newdata = interp2(cols, rows, data, newcols, newrows, 'bicubic')

Related

finding indices of min or max calculated in a range of an array or matrix in matlab

If I have a matrix
A=rand(50,4);
and a matrix of range values like
range=[1 10 15 30 45 50];
and i want to calculate minimum value and its index in all A columns over the range matrix. for example
for i=1 :numel(range)-1
[value index]= find(min(A(range(i):range(i+1),[],1)
if i>1
index=index+ range(i)+1; % indx# was calculated onlyin a
% range of array and not for
%whole array.Updated here
end
B_ind(i,:)=index;
B_val(i,:)=value;
end
How can I get indices of min(A) for range(i:i+1) without using a loop approach?
Simply put, matrix 'B' should be like
B(1,column 1:4)=index of min(A (1:10)) in every column
B(2,column 1:4)=index of min(A (11:15)) in every column
B(3,column 1:4)=index of min(A (16:30)) in every column
and so on...
My question is how to do it without a 'for loop'?
One possibility would be:
% generate example data set
A=rand(50,4);
range=[1 10 15 30 45 50];
% generate indexes of interest
tmp_idx= arrayfun(#colon,range(1:end-1),range(2:end),'un',0);
% calculate the min function over the indexes
[min_value,min_idx]=cellfun(#(x) min(A(x,:)), tmp_idx, 'UniformOutput', false);
% get matrix B (with the offset of ranges)
B=cell2mat(min_idx')+(range(1:end-1)+1)';
B(1,:)=B(1,:)-2;

How can I detect the minimum and maximum values every 50 rows

I'm trying to detect peak values in MATLAB. I'm trying to use the findpeaks function. The problem is that my data consists of 4200 rows and I just want to detect the minimum and maximum point in every 50 rows.After I'll use this code for real time accelerometer data.
This is my code:
[peaks,peaklocations] = findpeaks( filteredX, 'minpeakdistance', 50 );
plot( x, filteredX, x( peaklocations ), peaks, 'or' )
So you want to first reshape your vector into 50 sample rows and then compute the peaks for each row.
A = randn(4200,1);
B = reshape (A,[50,size(A,1)/50]); %//which gives B the structure of 50*84 Matrix
pks=zeros(50,size(A,1)/50); %//pre-define and set to zero/NaN for stability
pklocations = zeros(50,size(A,1)/50); %//pre-define and set to zero/NaN for stability
for i = 1: size(A,1)/50
[pks(1:size(findpeaks(B(:,i)),1),i),pklocations(1:size(findpeaks(B(:,i)),1),i)] = findpeaks(B(:,i)); %//this gives you your peak, you can alter the parameters of the findpeaks function.
end
This generates 2 matrices, pklocations and pks for each of your segments. The downside ofc is that since you do not know how many peaks you will get for each segment and your matrix must have the same length of each column, so I padded it with zero, you can pad it with NaN if you want.
EDIT, since the OP is looking for only 1 maximum and 1 minimum for each 50 samples, this can easily be satisfied by the min/max function in MATLAB.
A = randn(4200,1);
B = reshape (A,[50,size(A,1)/50]); %//which gives B the structure of 50*84 Matrix
[pks,pklocations] = max(B);
[trghs,trghlocations] = min(B);
I guess alternatively, you could do a max(pks), but it is simply making it complicated.

Sensor time distributions from arrays and cell arrays

I have a cell array and a numeric array in matlab which are inherently linked. The numeric array (A) contains a series of times from several data sources e.g. the time of each measurement. The array is n sensors (columns) by n measurements (rows). The array is filled with -1 by default since 0 is a valid time.
A = [ [ 100 110 -1 -1 ] ; ...
[ -1 200 180 -1 ] ; ...
[ -1 200 210 240 ] ; ...
[ 400 -1 -1 450 ] ];
The cell contains the sensors, in chronological order, for each row of the numeric array. Each cell elements contains a vector showing the sensors in the order they made the measurements.
C = { [1 2] [3 2] [2 3 4] [1 4]};
I want to see the distribution of times relative to each sensor e.g. what is the distribution of times from sensor 2/3/4 (when they are present), relative to sensor?
For example...
Sensor 1 is involved in the first and fourth measurements and the other detectors were +10 (100 -> 110) and +50 (400 -> 450). In this case I'm looking to return an array such as [10 50].
Sensor 2 is involved in the first three events, one of which is a three-way event. In this case it sensor2 isn't always the first to trigger, so some values will be negative. In this case I'm looking to return [-10 -20 +10 +40)]
Using the same logic sensor3 should return [20 -10 30] and sensor4 [-40 -30 -50].
I'm sure there should be an easy way to do this but I can't get my head round it. Of course the example I've given is a very simple one.... normally I'm dealing with tens of sensors and 100,000's measurements so looping over each and every col / row will take a long time... and often draw little results if only two (or so) of the sensors trigger in each measurement. For this reason I was hoping to use the elements in the cell array to access only the correct elements in the numeric array.
Any thoughts?
If I have understood the problem well enough for solving, it seems you don't need to worry about C for the output. Here's the code -
num_sensors = size(A,2)%// No. of sensors
A = A'; %//' The tracking goes row-wise, so transpose the input array
A(A==-1)=nan; %//set minus 1's to NaNs as excluding elements
out = cell(num_sensors,1); %// storage for ouput
for k1 = 1:num_sensors
%// Per sensor subtractions
per_sensor_subt = bsxfun(#minus,A,A(k1,:));
%// Set all elements of its own row to NaNs to exclude own subtractions
per_sensor_subt(k1,:)=nan;
%// Get all the non-nans that correspond to the valid output
out{k1} = per_sensor_subt(~isnan(per_sensor_subt));
end
Output -
>> celldisp(out)
out{1} =
10
50
out{2} =
-10
-20
10
40
out{3} =
20
-10
30
out{4} =
-40
-30
-50
As you have confirmed that the order of the output for each cell isn't important, you can employ a simplified approach that could be faster -
num_sensors = size(A,2)%// No. of sensors
A(A==-1)=nan; %//set minus 1's to NaNs as excluding elements
out = cell(num_sensors,1); %// storage for ouput
for k1 = 1:num_sensors
%// Per sensor subtractions
per_sensor_subt = bsxfun(#minus,A,A(:,k1));
%// Set all elements of its own row to NaNs to exclude own subtractions
per_sensor_subt(:,k1)=nan;
%// Get all the non-nans that correspond to the valid output
out{k1} = per_sensor_subt(~isnan(per_sensor_subt));
end
Fully vectorized solution if memory permits -
[m,n] = size(A)%// No. of sensors and measurements
A(A==-1)=nan; %//set minus 1's to NaNs as excluding elements
%// Per sensor subtractions
per_sensor_subt = bsxfun(#minus,A,permute(A,[1 3 2]))
%// Set all elements of its own row to NaNs to exclude own subtractions
own_idx = bsxfun(#plus,bsxfun(#plus,[1:m]',[0:n-1]*numel(A)),[0:n-1]*m);%//'
per_sensor_subt(own_idx)=nan;
%// Linear and row-col-dim3 indices of valid subtractions
idx = find(~isnan(per_sensor_subt))
[x,y,z] = ind2sub(size(per_sensor_subt),idx)
%// Get per sensor output
out = arrayfun(#(n) per_sensor_subt(idx(z==n)),1:n,'un',0)
If you would like to calculate C, use this approach -
%// Sort A row-wise
[sortedA,sorted_idx] = sort(A,2)
%// Set all invalid indices to zeros, so that later on we can use `nonzeros`
%// to extract out the valid indices
valid_sorted_idx = sorted_idx.*(sortedA~=-1)
%// Convert to a cell array
valid_sorted_idx_cell = mat2cell(valid_sorted_idx,ones(1,size(A,1)),size(A,2))
%// Extract the valid ones(nonzero indices) for the final output, C
C = cellfun(#(x) nonzeros(x), valid_sorted_idx_cell,'un',0)

Matlab: spatial average in a 4d matrix (time, case, x, y)

Here is my dataset:
pressure(time, case, x, y)
>> size(pressure)
ans =
100 1 289 570
How to get a spatial nanmean pressure for x from 30 to 60 and y from 40 to 70 in each time step?
For example: a nanmean value for that particular region for each timestep from time 1 to time 100.
I tried this, "spatial_mean_pressure = nanmean(pressure(:,:,30:60,40:70))" It averaged the pressure in the timeserie. This is not the result I want.
>> size(spatial_mean_pressure)
ans =
1 1 31 31
I like to get the results like this:
>> size(spatial_mean_pressure)
ans =
100 1 1 1
You are trying to get a mean for an entire block of matrix. Therefore, you should apply nanmean twice and not once. Also, apply it along a particular dimension to get the desired result. I think this is what you want.
x=randi(10,[100 1 10 25]);
First take the mean along the third dimension.
mean_x_3=nanmean(x,3);
You would get an answer of size = [100 1 1 25]. Then take the mean along 4th dimension.
mean_x_4=nanmean(mean_x_3,4);
This should give you the desired answer. You can write this in one line as,
mean_x = nanmean(nanmean(x,3),4);

How to ignore NaNs in MATLAB?

I'm looking for a way to ignore specific entries in matrices for subsequent linear regression in MATLAB
I have two matricies: y =
9.3335 7.8105 5.8969 3.5928
23.1580 19.6043 15.3085 8.2010
40.1067 35.2643 28.9378 16.6753
56.4697 51.8224 44.5587 29.3674
70.7238 66.5842 58.8909 42.7623
83.0253 78.4561 71.1924 53.8532
and x =
300 300 300 300
400 400 400 400
500 500 500 500
600 600 600 600
700 700 700 700
800 800 800 800
I need to do linear regression on the points where y is between 20 and 80, so I need a way to fully automate the process. I tried making the outlying y values [and their corresponding x values] NaNs, but during linear regression, matlab included the NaNs in the calculations so I got NaN outputs. Can anyone suggest a good way to ignore those entries or to ignore NaNs completely calculations? (NOTE: the columns in y will often have different combinations of values, so I can't eliminate the whole row).
If the NaNs occur in the same locations in both the X and Y matrices, you can use a function call like the following, your_function( X(~isnan(X)), Y(~isnan(X)) ). If the NaNs don't occur in the same locations, you will have to first find the valid indices by something like, `X(~isnan(X)| isnan(Y))'
Since you perform your regression on each column separately, you can simply form an index into rows with the valid y-values:
nCols = size(x,2);
results = zeros(2,nCols);
validY = y>20 & y<80; %# a logical array the size of y with valid entries
nValid = sum(validY,1);
for c = 1:nCols
% results is [slope;intercept] in each column
results(:,c) = [x(validY(:,c),c),ones(nValid(c),1)]\y(validY(:,c),c);
end