Home > FMAToolbox > General > ConsolidateIntervals.m

ConsolidateIntervals

PURPOSE ^

ConsolidateIntervals - Consolidate intervals.

SYNOPSIS ^

function [consolidated,target] = ConsolidateIntervals(intervals,varargin)

DESCRIPTION ^

ConsolidateIntervals - Consolidate intervals.

 Consolidate overlapping intervals, e.g. replace [10,20] [15,25] with [10,25].

  USAGE

    [consolidated,target] = ConsolidateIntervals(intervals,<options>)

    intervals      list of intervals
    <options>      optional list of property-value pairs (see table below)

    =========================================================================
     Properties    Values
    -------------------------------------------------------------------------
     'strict'      intervals with common bounds are consolidated ('off')
                   or kept separate ('on') (default = 'off')
     'epsilon'     intervals with close enough bounds (distance lesser than
                   epsilon) are also consolidated (default = 0)
    =========================================================================

  OUTPUT

    consolidated   consolidated intervals
    target         for each original interval, the index of the consolidated
                   interval to which it belongs (empty intervals yield NaN)

  SEE

    See also SubtractIntervals, ExcludeIntervals, InIntervals, Restrict,
    FindInInterval, CountInIntervals, PlotIntervals.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [consolidated,target] = ConsolidateIntervals(intervals,varargin)
0002 
0003 %ConsolidateIntervals - Consolidate intervals.
0004 %
0005 % Consolidate overlapping intervals, e.g. replace [10,20] [15,25] with [10,25].
0006 %
0007 %  USAGE
0008 %
0009 %    [consolidated,target] = ConsolidateIntervals(intervals,<options>)
0010 %
0011 %    intervals      list of intervals
0012 %    <options>      optional list of property-value pairs (see table below)
0013 %
0014 %    =========================================================================
0015 %     Properties    Values
0016 %    -------------------------------------------------------------------------
0017 %     'strict'      intervals with common bounds are consolidated ('off')
0018 %                   or kept separate ('on') (default = 'off')
0019 %     'epsilon'     intervals with close enough bounds (distance lesser than
0020 %                   epsilon) are also consolidated (default = 0)
0021 %    =========================================================================
0022 %
0023 %  OUTPUT
0024 %
0025 %    consolidated   consolidated intervals
0026 %    target         for each original interval, the index of the consolidated
0027 %                   interval to which it belongs (empty intervals yield NaN)
0028 %
0029 %  SEE
0030 %
0031 %    See also SubtractIntervals, ExcludeIntervals, InIntervals, Restrict,
0032 %    FindInInterval, CountInIntervals, PlotIntervals.
0033 
0034 
0035 % Copyright (C) 2004-2011 by Michaƫl Zugaro
0036 %
0037 % This program is free software; you can redistribute it and/or modify
0038 % it under the terms of the GNU General Public License as published by
0039 % the Free Software Foundation; either version 3 of the License, or
0040 % (at your option) any later version.
0041 
0042 % Default values
0043 strict = 'off';
0044 epsilon = 0;
0045 
0046 if nargin < 1,
0047   error('Incorrect number of parameters (type ''help <a href="matlab:help ConsolidateIntervals">ConsolidateIntervals</a>'' for details).');
0048 end
0049 
0050 if mod(length(varargin),2) ~= 0,
0051   error('Incorrect number of parameters (type ''help <a href="matlab:help ConsolidateIntervals">ConsolidateIntervals</a>'' for details).');
0052 end
0053 
0054 % Parse options
0055 for i = 1:2:length(varargin),
0056     if ~ischar(varargin{i}),
0057         error(['Parameter ' num2str(i+firstIndex) ' is not a property (type ''help <a href="matlab:help ConsolidateIntervals">ConsolidateIntervals</a>'' for details).']);
0058     end
0059     switch(lower(varargin{i})),
0060         case 'strict',
0061             strict = lower(varargin{i+1});
0062             if ~isastring(strict,'on','off'),
0063                 error('Incorrect value for property ''strict'' (type ''help <a href="matlab:help ConsolidateIntervals">ConsolidateIntervals</a>'' for details).');
0064             end
0065         case 'epsilon',
0066             epsilon = varargin{i+1};
0067             if ~isdscalar(epsilon,'>0'),
0068                 error('Incorrect value for property ''epsilon'' (type ''help <a href="matlab:help ConsolidateIntervals">ConsolidateIntervals</a>'' for details).');
0069             end
0070         otherwise,
0071             error(['Unknown property ''' num2str(varargin{i}) ''' (type ''help <a href="matlab:help ConsolidateIntervals">ConsolidateIntervals</a>'' for details).']);
0072     end
0073 end
0074 
0075 original = intervals;
0076 
0077 % Mark already consolidated intervals to avoid retesting them
0078 done = logical(zeros(size(intervals(:,1))));
0079 
0080 if strcmp(strict,'on'),
0081     for i = 1:size(intervals,1),
0082         if done(i), continue; end
0083         % Lower (L) and upper (U) interval bounds
0084         L = intervals(:,1);
0085         U = intervals(:,2);
0086         % Current interval is I = [l u], but we replace it with [l-e u+e] to take parameter 'epsilon' into account
0087         l = L(i)-epsilon;u = U(i)+epsilon;
0088         % Find all intervals that overlap with I:
0089         % 1) one of their bounds is strictly inside I
0090         % (their upper bound is greater than l, and their lower bound is lower than u)
0091         intersect = (U > l & L < u);
0092         % 2) they contain I
0093         if u == l,
0094              % Special case: I is a singleton
0095              intersect = intersect | (L < l & U > u);
0096         else
0097             intersect = intersect | (L <= l & U >= u);
0098         end
0099         % Determine smallest enclosing interval
0100         m = min(L(intersect));
0101         M = max(U(intersect));
0102         % Consolidate
0103         intervals(intersect,:) = repmat([m M],sum(intersect),1);
0104         done(intersect) = 1;
0105     end
0106 else
0107     % (same as above, but replacing e.g. < with <=)
0108     for i = 1:size(intervals,1),
0109         if done(i), continue; end
0110         % Lower (L) and upper (U) interval bounds
0111         L = intervals(:,1);
0112         U = intervals(:,2);
0113         % Current interval is I = [l u], but we replace it with [l-e u+e] to take parameter 'epsilon' into account
0114         l = L(i)-epsilon;u = U(i)+epsilon;
0115         % Find all intervals that overlap with I:
0116         % 1) one of their bounds is inside I
0117         % (their upper bound is greater than or equal to l, and their lower bound is lower than or equal to u)
0118         intersect = (U >= l & L <= u);
0119         m = min(L(intersect));
0120         M = max(U(intersect));
0121         % Consolidate
0122         intervals(intersect,:) = repmat([m M],sum(intersect),1);
0123         done(intersect) = 1;
0124     end
0125 end
0126 
0127 % Sort intervals in ascending order (and store reordering information so we can reuse it later)
0128 [intervals,order] = sortrows(intervals,1);
0129 
0130 % Assign each consolidated interval an ID (in ascending order)
0131 transitions = [1;find(diff(intervals(:,1))~=0)+1;length(intervals(:,1))];
0132 for i = 1:length(transitions)-1,
0133     target(transitions(i):transitions(i+1)) = repmat(i,transitions(i+1)-transitions(i)+1,1);
0134 end
0135 
0136 %  Reorder consolidated interval IDs
0137 target(order) = target;
0138 target = target';
0139 
0140 consolidated = unique(intervals,'rows');
0141 
0142 % Remove empty intervals from output...
0143 empty = diff(consolidated,1,2) < 0;
0144 consolidated(empty,:) = [];
0145 % ... and update target IDs
0146 empty = diff(original,1,2) < 0;
0147 [t,i] = sortrows([target empty]);
0148 target(i) = t(:,1)-cumsum(t(:,2));
0149 
0150 % Empty intervals belong to none
0151 target(empty) = NaN;

Generated on Fri 16-Mar-2018 13:00:20 by m2html © 2005