Q:

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?

A:

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)

