In MATLAB R2020b I use the following code to check if time ranges overlap each other.
% start = start time of time range, array of matlab datenum's
% finish = end time of time range, array of matlab datenum's
overlap = bsxfun(@lt, start(:), finish(:).');
overlap = overlap & overlap.';
no_overlap = isdiag(double(overlap));
The result is a diagonal matrix in cases there is no overlap and a matrix filled with 1
(true) and 0
(false) if there is overlap.
Matrix example with no overlapping time ranges:
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
Matrix example with overlapping time ranges:
1 0 0 0 0
0 1 1 1 1
0 1 1 0 0
0 1 0 1 0
0 1 0 0 1
I tried to do the same thing in python to get overlapping time ranges, but I found only solutions that compare time range 1 with time range 2. But I need to compare all time ranges with each other such as time range 1 with for example time range 5.
I used the information of this post Determine Whether Two Date Ranges Overlap and came up with the following code, which is an adjusted code from Find Non-overlapping intervals among a given set of intervals:
# arr = list of start finsh in format [[start1,finish1],[start2,finish2],....]
# N = length of arr
def findTimeOverlap(arr, N):
# If there are no set of interval
if N < 1:
return
# To store the set of overlaps
P = []
# Sort the given interval according Starting time
arr.sort(key = lambda a:a[0])
# Iterate over all the interval
for i in range(1, N):
# Previous interval start
prevStart = arr[i - 1][0] # A
# Previous interval end
prevEnd = arr[i - 1][1] # B
# Current interval start
currStart = arr[i][0] # C
# Current interval end
currEnd = arr[i][1] # D
# If Previous Interval is less than current Interval then we store that answer
if max([prevStart,currStart]) < min([prevEnd,currEnd]):
P.append([prevStart, prevEnd, currStart, currEnd])
# intervals to dataframe
df = pd.DataFrame(P, columns=["start_A","finish_A","start_B","finish_B"])
if not df.empty:
df["start_A"] = pd.to_datetime(df["start_A"], unit='ns')
df["finish_A"] = pd.to_datetime(df["finish_A"], unit='ns')
df["start_B"] = pd.to_datetime(df["start_B"], unit='ns')
df["finish_B"] = pd.to_datetime(df["finish_B"], unit='ns')
return df
Only this give a comparison based on time range 1 with time range 2 and not all the time ranges compared against each other.
How can I cross-compare all my time ranges and obtain a logical matrix like in the MATLAB example?
Based on Adriaan's comment about Matlab, I was able to create a python solution.
def findTimeOverlap(start,finish):
S = np.transpose(np.zeros([len(start), len(finish)]) + start)
F = np.zeros([len(start), len(finish)]) + finish
T = S < F
T = (T == np.transpose(T)).astype(int)
Overlapping = np.count_nonzero(T - np.diag(np.diagonal(T))) != 0
return Overlapping, T
In the case of time ranges with overlapping ranges:
start = np.array([1,2,3,4,5])
finish = np.array([2,6,4,5,6])
Overlapping, T = findTimeOverlap(start,finish)
Overlapping = True
T = array([[1, 0, 0, 0, 0],
[0, 1, 1, 1, 1],
[0, 1, 1, 0, 0],
[0, 1, 0, 1, 0],
[0, 1, 0, 0, 1]])
In the case of time ranges with no overlapping ranges:
start = np.array([1,2,3,4,5])
finish = np.array([2,3,4,5,6])
Overlapping, T = findTimeOverlap(start,finish)
Overlapping = False
T = array([[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 0, 1]])