sdata 1.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. sdata/__init__.py +140 -0
  2. sdata/base.py +684 -0
  3. sdata/contrib/__init__.py +0 -0
  4. sdata/contrib/piexif/__init__.py +12 -0
  5. sdata/contrib/piexif/_common.py +94 -0
  6. sdata/contrib/piexif/_dump.py +346 -0
  7. sdata/contrib/piexif/_exceptions.py +2 -0
  8. sdata/contrib/piexif/_exif.py +638 -0
  9. sdata/contrib/piexif/_insert.py +60 -0
  10. sdata/contrib/piexif/_load.py +270 -0
  11. sdata/contrib/piexif/_remove.py +56 -0
  12. sdata/contrib/piexif/_transplant.py +45 -0
  13. sdata/contrib/piexif/_webp.py +240 -0
  14. sdata/contrib/piexif/helper.py +66 -0
  15. sdata/contrib/ranger/__init__.py +8 -0
  16. sdata/contrib/ranger/collections/__init__.py +0 -0
  17. sdata/contrib/ranger/collections/rangebucketmap.py +346 -0
  18. sdata/contrib/ranger/collections/rangemap.py +396 -0
  19. sdata/contrib/ranger/collections/rangeset.py +483 -0
  20. sdata/contrib/ranger/range/__init__.py +0 -0
  21. sdata/contrib/ranger/range/cut.py +285 -0
  22. sdata/contrib/ranger/range/range.py +644 -0
  23. sdata/contrib/sobol_seq.py +394 -0
  24. sdata/contrib/sortedcontainers/LICENSE +13 -0
  25. sdata/contrib/sortedcontainers/__init__.py +74 -0
  26. sdata/contrib/sortedcontainers/sorteddict.py +789 -0
  27. sdata/contrib/sortedcontainers/sortedlist.py +2646 -0
  28. sdata/contrib/sortedcontainers/sortedset.py +733 -0
  29. sdata/contrib/sqlitedict.py +598 -0
  30. sdata/contrib/timeflake/__init__.py +40 -0
  31. sdata/contrib/timeflake/flake.py +69 -0
  32. sdata/contrib/timeflake/utils.py +47 -0
  33. sdata/deprecated/__init__.py +10 -0
  34. sdata/deprecated/data.py +1503 -0
  35. sdata/did/__init__.py +129 -0
  36. sdata/did/_http.py +67 -0
  37. sdata/did/base58btc.py +49 -0
  38. sdata/did/did_github.py +152 -0
  39. sdata/did/did_peer4.py +155 -0
  40. sdata/did/did_web.py +222 -0
  41. sdata/did/diddoc.py +75 -0
  42. sdata/did/ed25519.py +225 -0
  43. sdata/did/eddsa.py +107 -0
  44. sdata/did/errors.py +40 -0
  45. sdata/did/issue_vc.py +193 -0
  46. sdata/did/jose.py +126 -0
  47. sdata/did/keys.py +104 -0
  48. sdata/did/utils_didkey.py +161 -0
  49. sdata/did/verify_vp.py +158 -0
  50. sdata/doe.py +101 -0
  51. sdata/dtypes.py +510 -0
  52. sdata/experiments/__init__.py +331 -0
  53. sdata/experiments/blob0.py +131 -0
  54. sdata/experiments/file.py +42 -0
  55. sdata/experiments/filegroup.py +144 -0
  56. sdata/experiments/image_old.py +313 -0
  57. sdata/experiments/ks2.py +15 -0
  58. sdata/experiments/lapshear.py +8 -0
  59. sdata/experiments/material.py +7 -0
  60. sdata/experiments/parameters_deprecated.py +394 -0
  61. sdata/experiments/workbook.py +226 -0
  62. sdata/format.py +125 -0
  63. sdata/imagemeta.py +533 -0
  64. sdata/interactive.py +118 -0
  65. sdata/iolib/__init__.py +51 -0
  66. sdata/iolib/hashtree.py +264 -0
  67. sdata/iolib/json1sqlitestore.py +554 -0
  68. sdata/iolib/jsonsqlitestore.py +704 -0
  69. sdata/iolib/pud.py +242 -0
  70. sdata/iolib/reader.py +262 -0
  71. sdata/iolib/writer.py +419 -0
  72. sdata/metadata.py +882 -0
  73. sdata/parameter.py +414 -0
  74. sdata/schema.py +273 -0
  75. sdata/sclass/__init__.py +111 -0
  76. sdata/sclass/bfo_classes.py +362 -0
  77. sdata/sclass/blob.py +362 -0
  78. sdata/sclass/content.py +87 -0
  79. sdata/sclass/dataframe.py +1251 -0
  80. sdata/sclass/dataframegroup.py +187 -0
  81. sdata/sclass/dependency_graph.py +85 -0
  82. sdata/sclass/filereference.py +124 -0
  83. sdata/sclass/image.py +218 -0
  84. sdata/sclass/lazy_namespace.py +155 -0
  85. sdata/sclass/process.py +383 -0
  86. sdata/sclass/process_graph.py +221 -0
  87. sdata/sclass/zipfile.py +135 -0
  88. sdata/semantic.py +346 -0
  89. sdata/suuid.py +136 -0
  90. sdata/timestamp.py +336 -0
  91. sdata/tools.py +14 -0
  92. sdata/units.py +602 -0
  93. sdata/vocab.py +149 -0
  94. sdata-1.5.0.dist-info/METADATA +264 -0
  95. sdata-1.5.0.dist-info/RECORD +98 -0
  96. sdata-1.5.0.dist-info/WHEEL +5 -0
  97. sdata-1.5.0.dist-info/licenses/LICENSE-MIT +21 -0
  98. sdata-1.5.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,483 @@
1
+ from bisect import bisect_left
2
+ from collections import deque
3
+ from sdata.contrib.ranger.range.range import Range
4
+
5
+
6
+ class RangeSet(object):
7
+ """ Class used to represent a set of non-overlapping ranges of the
8
+ same type. If a range is added that is connected to another range
9
+ already in the set, those ranges are merged. Otherwise, it is added as
10
+ a new range in the set
11
+ """
12
+
13
+ def __init__(self, ranges=None):
14
+ """ Instantiates the RangeSet
15
+
16
+ Parameters
17
+ ----------
18
+ ranges : List of Range objects
19
+ Ranges to add to the Set
20
+ """
21
+ ## Holds lower and upper cut points of ranges
22
+ self.lower_cuts = []
23
+ self.upper_cuts = []
24
+ ## Holds the range objects in the set
25
+ self.ranges = []
26
+ if ranges is not None:
27
+ for aRange in ranges:
28
+ self.add(aRange)
29
+
30
+ def __repr__(self):
31
+ if len(self) < 6:
32
+ return "RangeSet(%s)" % ", ".join(map(str, self.ranges))
33
+ else:
34
+ return "RangeSet(%s, ..., %s)" % (", ".join(map(str, self.ranges[:2])),
35
+ ", ".join(map(str, self.ranges[-2:])))
36
+
37
+ def __len__(self):
38
+ return len(self.ranges)
39
+
40
+ def __iter__(self):
41
+ return iter(self.ranges)
42
+
43
+ def __eq__(self, other):
44
+ if not isinstance(other, RangeSet):
45
+ return False
46
+ elif len(self) != len(other):
47
+ return False
48
+ else:
49
+ for r1, r2 in zip(self.ranges, other.ranges):
50
+ if r1 != r2: return False
51
+ return True
52
+
53
+ def __ne__(self, other):
54
+ return not self.__eq__(other)
55
+
56
+ def add(self, a_range):
57
+ """ Adds a range to the range set. If this range is not connected
58
+ to any current ranges, it will place the new range on its own. If
59
+ there is a connection, any connected ranges will be merged into a single
60
+ range
61
+
62
+ Parameters
63
+ ----------
64
+ a_range : A Range object
65
+ The Range to add to the RangeSet
66
+
67
+ Raises
68
+ ------
69
+ ValueError
70
+ If adding range of type not compatible with previously
71
+ added ranges
72
+ TypeError:
73
+ If not adding a Range
74
+ """
75
+ if not isinstance(a_range, Range):
76
+ raise TypeError("a_range is not a Range")
77
+ elif a_range.is_empty():
78
+ # Skip if this is an empty range
79
+ return
80
+ # Check for compatibility of types if necessary
81
+ if len(self) > 0:
82
+ if not (issubclass(a_range.lower_cut.the_type,
83
+ self.ranges[0].lower_cut.the_type) or \
84
+ issubclass(self.ranges[0].lower_cut.the_type,
85
+ a_range.lower_cut.the_type)):
86
+ raise ValueError("Range not compatible with previously added ranges")
87
+ # Get the insertion point (where the lower bound should go), should
88
+ # this range be added on its own
89
+ lower_ind = bisect_left(self.lower_cuts, a_range.lower_cut)
90
+ if len(self) == 0:
91
+ # Add on its own if there is nothing in the list
92
+ self.ranges.append(a_range)
93
+ self.lower_cuts.append(a_range.lower_cut)
94
+ self.upper_cuts.append(a_range.upper_cut)
95
+ elif len(self) == lower_ind:
96
+ if not a_range.is_connected(self.ranges[max(lower_ind - 1, 0)]):
97
+ # Add on its own if not connected to previous and last
98
+ self.ranges.insert(lower_ind, a_range)
99
+ self.lower_cuts.insert(lower_ind, a_range.lower_cut)
100
+ self.upper_cuts.insert(lower_ind, a_range.upper_cut)
101
+ else:
102
+ # If connected with the range below, replace with new range
103
+ new_lower_cut = min(a_range.lower_cut,
104
+ self.lower_cuts[max(lower_ind - 1, 0)])
105
+ new_upper_cut = max(a_range.upper_cut,
106
+ self.upper_cuts[max(lower_ind - 1, 0)])
107
+ new_range = Range(new_lower_cut, new_upper_cut)
108
+ self.ranges[-1] = new_range
109
+ self.lower_cuts[-1] = new_lower_cut
110
+ self.upper_cuts[-1] = new_upper_cut
111
+ elif not any((a_range.is_connected(self.ranges[max(lower_ind - 1, 0)]),
112
+ a_range.is_connected(self.ranges[lower_ind]))):
113
+ # Add on its own if not connected
114
+ self.ranges.insert(lower_ind, a_range)
115
+ self.lower_cuts.insert(lower_ind, a_range.lower_cut)
116
+ self.upper_cuts.insert(lower_ind, a_range.upper_cut)
117
+ elif a_range.is_connected(self.ranges[max(lower_ind - 1, 0)]):
118
+ # If connected with range below
119
+ new_lower_cut = min(self.lower_cuts[max(lower_ind - 1, 0)],
120
+ a_range.lower_cut)
121
+ new_upper_cut = max(a_range.upper_cut,
122
+ self.upper_cuts[max(lower_ind - 1, 0)])
123
+ remove_count = 1
124
+ if len(self) == (lower_ind):
125
+ # If hitting the last range, take the maximum uppercut
126
+ new_upper_cut = max(new_upper_cut, self.upper_cuts[max(lower_ind - 1, 0)])
127
+ else:
128
+ # If not hitting the last range, go find the upper cut
129
+ for i in range(max(1, lower_ind), len(self)):
130
+ if a_range.is_connected(self.ranges[i]):
131
+ new_upper_cut = max(new_upper_cut, self.upper_cuts[i])
132
+ remove_count += 1
133
+ else:
134
+ break
135
+ # Make the new range
136
+ new_range = Range(new_lower_cut, new_upper_cut)
137
+ # Get rid of all overlapping ranges
138
+ for i in range(remove_count):
139
+ self.ranges.pop(max(lower_ind - 1, 0))
140
+ self.lower_cuts.pop(max(lower_ind - 1, 0))
141
+ self.upper_cuts.pop(max(lower_ind - 1, 0))
142
+ # Add the new range
143
+ self.ranges.insert(max(lower_ind - 1, 0), new_range)
144
+ self.lower_cuts.insert(max(lower_ind - 1, 0), new_range.lower_cut)
145
+ self.upper_cuts.insert(max(lower_ind - 1, 0), new_range.upper_cut)
146
+ elif a_range.is_connected(self.ranges[lower_ind]):
147
+ # If connected with the range above
148
+ new_lower_cut = min(a_range.lower_cut, self.lower_cuts[lower_ind])
149
+ new_upper_cut = max(a_range.upper_cut, self.upper_cuts[lower_ind])
150
+ remove_count = 0
151
+ if len(self) == (lower_ind + 1):
152
+ # If hitting the last range, you're done
153
+ remove_count += 1
154
+ else:
155
+ # Go find the upper cut
156
+ for i in range(lower_ind, len(self)):
157
+ if a_range.is_connected(self.ranges[i]):
158
+ new_upper_cut = max(new_upper_cut, self.upper_cuts[i])
159
+ remove_count += 1
160
+ else:
161
+ break
162
+ # Make the new range
163
+ new_range = Range(new_lower_cut, new_upper_cut)
164
+ # Remove the overlapping ranges
165
+ for i in range(remove_count):
166
+ self.ranges.pop(lower_ind)
167
+ self.lower_cuts.pop(lower_ind)
168
+ self.upper_cuts.pop(lower_ind)
169
+ # Add the new range
170
+ self.ranges.insert(lower_ind, new_range)
171
+ self.lower_cuts.insert(lower_ind, new_range.lower_cut)
172
+ self.upper_cuts.insert(lower_ind, new_range.upper_cut)
173
+
174
+ def contains(self, val):
175
+ """ Returns true if any of the ranges fully enclose the given
176
+ value, which can be a single value or a Range object
177
+
178
+ Parameters
179
+ ----------
180
+ val : A single value or a Range object
181
+
182
+ Raises
183
+ ------
184
+ ValueError
185
+ If the value type not compatible with the ranges
186
+
187
+ Returns
188
+ -------
189
+ true if any of the ranges fully enclose the given value
190
+ """
191
+ if len(self) == 0: return False
192
+ # Get the index+1 of the highest lower cut <= to the value or its
193
+ # lower cutpoint and check if the value contained
194
+ if isinstance(val, Range):
195
+ lower_ind = max(bisect_left(self.lower_cuts, val.lower_cut), 0)
196
+ if lower_ind >= len(self.lower_cuts):
197
+ return self.ranges[lower_ind - 1].encloses(val)
198
+ elif val.lower_cut != self.lower_cuts[lower_ind]:
199
+ return self.ranges[lower_ind - 1].encloses(val)
200
+ else:
201
+ return self.ranges[lower_ind].encloses(val)
202
+ else:
203
+ lower_ind = max(bisect_left(self.lower_cuts, val) - 1, 0)
204
+ return self.ranges[lower_ind].contains(val)
205
+
206
+ def difference(self, otherSet):
207
+ """ Creates a new RangeSet in which all elements in another RangeSet
208
+ are taken out of this RangeSet
209
+
210
+ Parameters
211
+ ----------
212
+ otherSet : RangeSet object
213
+ The RangeSet used for this difference
214
+
215
+ Raises
216
+ ------
217
+ TypeError
218
+ If the object passed in is not a RangeSet
219
+ ValueError
220
+ If the value type of the ranges in the other set not compatible
221
+ with the range's values
222
+
223
+ Returns
224
+ -------
225
+ RangeSet consisting of the difference of the two sets
226
+ """
227
+ if not isinstance(otherSet, RangeSet):
228
+ raise TypeError("other_set is not a RangeSet")
229
+ new_set = RangeSet()
230
+ for add_range in self.ranges:
231
+ if otherSet.overlaps(add_range):
232
+ # Determine where overlap occurs
233
+ other_lower_ind = max(bisect_left(otherSet.lower_cuts,
234
+ add_range.lower_cut) - 1, 0)
235
+ other_upper_ind = bisect_left(otherSet.lower_cuts,
236
+ add_range.upper_cut)
237
+ new_lower_cut = add_range.lower_cut
238
+ new_upper_cut = add_range.upper_cut
239
+ add = True
240
+ for i in range(other_lower_ind, other_upper_ind):
241
+ try:
242
+ # Get the intersection of the ranges
243
+ intersect = add_range.intersection(otherSet.ranges[i])
244
+ if not intersect.is_empty():
245
+ if add_range == intersect:
246
+ add = False
247
+ break
248
+ elif add_range.lower_cut == intersect.lower_cut:
249
+ # If equal on the left cutpoint, subtract out left
250
+ # part
251
+ new_lower_cut = intersect.upper_cut
252
+ add_range = Range(new_lower_cut, new_upper_cut)
253
+ elif add_range.upper_cut == intersect.upper_cut:
254
+ # If equal on right cutpoint, subtract out right
255
+ # part
256
+ new_upper_cut = intersect.lower_cut
257
+ add_range = Range(add_range.lower_cut, new_upper_cut)
258
+ else:
259
+ # If in the middle, split into two parts and
260
+ # add the lower one immediately
261
+ new_set.add(Range(new_lower_cut,
262
+ intersect.lower_cut))
263
+ new_lower_cut = intersect.upper_cut
264
+ new_upper_cut = add_range.upper_cut
265
+ add_range = Range(new_lower_cut, new_upper_cut)
266
+ except ValueError:
267
+ continue
268
+ if add:
269
+ new_set.add(Range(new_lower_cut, new_upper_cut))
270
+ else:
271
+ new_set.add(add_range)
272
+ return new_set
273
+
274
+ def intersection(self, other_set):
275
+ """ Creates a new RangeSet that is the intersection of this and
276
+ another RangeSet
277
+
278
+ Parameters
279
+ ----------
280
+ other_set : RangeSet object
281
+ The RangeSet used for this intersection
282
+
283
+ Raises
284
+ ------
285
+ TypeError
286
+ If the object passed in is not a RangeSet
287
+ ValueError
288
+ If the value type of the ranges in the other set not compatible
289
+ with the range's values
290
+
291
+ Returns
292
+ -------
293
+ RangeSet consisting of the intersection of the two sets
294
+ """
295
+ if not isinstance(other_set, RangeSet):
296
+ raise TypeError("other_set is not a RangeSet")
297
+ new_set = RangeSet()
298
+ for addRange in self.ranges:
299
+ if other_set.overlaps(addRange):
300
+ # Determine where overlap occurs
301
+ other_lower_ind = max(bisect_left(other_set.lower_cuts,
302
+ addRange.lower_cut) - 1, 0)
303
+ other_upper_ind = bisect_left(other_set.lower_cuts,
304
+ addRange.upper_cut)
305
+ for i in range(other_lower_ind, other_upper_ind):
306
+ # Get the intersection of the ranges
307
+ try:
308
+ intersect = addRange.intersection(other_set.ranges[i])
309
+ # Add intersection if there is any overlap
310
+ if not intersect.is_empty():
311
+ new_set.add(intersect)
312
+ except ValueError:
313
+ continue
314
+ return new_set
315
+
316
+ def overlaps(self, val):
317
+ """ Returns true if any of the ranges at least partially overlap
318
+ the given value, which can be a single value or a Range object
319
+
320
+ Parameters
321
+ ----------
322
+ val : A single value or a Range object
323
+
324
+ Raises:
325
+ -------
326
+ ValueError
327
+ If the value type not compatible with the ranges
328
+
329
+ Returns
330
+ -------
331
+ true if any of the ranges fully enclose the given value
332
+ """
333
+ if len(self) == 0: return False
334
+ # Get the index+1 of the highest lower cut <= to the value or its
335
+ # lower cutpoint and check if the value overlaps
336
+ if isinstance(val, Range):
337
+ lower_ind = bisect_left(self.lower_cuts, val.lower_cut) - 1
338
+ upper_ind = bisect_left(self.lower_cuts, val.upper_cut)
339
+ for i in range(lower_ind, upper_ind):
340
+ if val.is_connected(self.ranges[i]):
341
+ if not self.ranges[i].intersection(val).is_empty():
342
+ return True
343
+ return False
344
+ else:
345
+ lower_ind = bisect_left(self.lower_cuts, val) - 1
346
+ return self.ranges[lower_ind].contains(val)
347
+
348
+ def remove(self, a_range):
349
+ """ Removes a range from the range set.
350
+
351
+ Parameters
352
+ ----------
353
+ a_range : A Range object
354
+ The Range to remove from the RangeSet
355
+
356
+ Raises
357
+ ------
358
+ ValueError
359
+ If removing range of type not compatible with previously
360
+ added ranges
361
+ TypeError
362
+ If not a Range
363
+ """
364
+ if not isinstance(a_range, Range):
365
+ raise TypeError("a_range is not a Range")
366
+ elif a_range.is_empty():
367
+ # Skip if this is an empty range
368
+ return
369
+ # Check for compatibility of types if necessary
370
+ if len(self) > 0:
371
+ if not (issubclass(a_range.lower_cut.the_type,
372
+ self.ranges[0].lower_cut.the_type) or issubclass(self.ranges[0].lower_cut.the_type,
373
+ a_range.lower_cut.the_type)):
374
+ raise ValueError("Range not compatible with previously added ranges")
375
+ # Check if the range actually overlaps with this set
376
+ if not self.overlaps(a_range):
377
+ return
378
+ else:
379
+ # There's some overlap, so deal with that
380
+ # Determine where overlap occurs
381
+ ovlap_lower_ind = max(bisect_left(self.lower_cuts, a_range.lower_cut) - 1, 0)
382
+ ovlap_upper_ind = bisect_left(self.lower_cuts, a_range.upper_cut)
383
+ # Create queue of indices marked for removal
384
+ remove_ranges = deque()
385
+ # Create queue of ranges to add
386
+ add_ranges = deque()
387
+ for i in range(ovlap_lower_ind, ovlap_upper_ind):
388
+ try:
389
+ # Get intersection of the ranges
390
+ intersect = a_range.intersection(self.ranges[i])
391
+ if not intersect.is_empty():
392
+ if intersect == self.ranges[i]:
393
+ # Mark range for removal
394
+ remove_ranges.append(i)
395
+ elif self.lower_cuts[i] == intersect.lower_cut:
396
+ # If equal on the left cutpoint, subtract out left
397
+ # part
398
+ self.lower_cuts[i] = intersect.upper_cut
399
+ self.ranges[i] = Range(intersect.upper_cut, self.upper_cuts[i])
400
+ elif self.upper_cuts[i] == intersect.upper_cut:
401
+ # If equal on right cutpoint, subtract out right
402
+ # part
403
+ self.upper_cuts[i] = intersect.lower_cut
404
+ self.ranges[i] = Range(self.lower_cuts[i], intersect.lower_cut)
405
+ else:
406
+ # If in the middle, split into two parts, putting both into
407
+ # add queue and placing the old range index into the removal
408
+ # queue
409
+ add_ranges.append(Range(self.lower_cuts[i], intersect.lower_cut))
410
+ add_ranges.append(Range(intersect.upper_cut, self.upper_cuts[i]))
411
+ remove_ranges.append(i)
412
+ except ValueError:
413
+ # Continue if no overlap with this range
414
+ continue
415
+ # Remove any ranges that are marked for removal
416
+ while len(remove_ranges) > 0:
417
+ remove_ind = remove_ranges.pop()
418
+ self.ranges.pop(remove_ind)
419
+ self.lower_cuts.pop(remove_ind)
420
+ self.upper_cuts.pop(remove_ind)
421
+ # Add any ranges that need to be added
422
+ while len(add_ranges) > 0:
423
+ self.add(add_ranges.pop())
424
+
425
+ def union(self, other_set):
426
+ """ Creates a new RangeSet that is the union of this set and
427
+ another RangeSet object
428
+
429
+ Parameters
430
+ ----------
431
+ other_set : RangeSet object
432
+ The RangeSet used for the union
433
+
434
+ Raises
435
+ ------
436
+ TypeError
437
+ If the object passed in is not a RangeSet
438
+ ValueError
439
+ If the value type of the set not compatible with the ranges
440
+
441
+ Returns
442
+ -------
443
+ RangeSet consisting of union of two sets
444
+ """
445
+ if not isinstance(other_set, RangeSet):
446
+ raise TypeError("other_set is not a RangeSet")
447
+ return RangeSet(set(self.ranges + other_set.ranges))
448
+
449
+ def which_overlaps(self, val):
450
+ """ Returns which of the Ranges overlap with a single value or
451
+ Range object
452
+
453
+ Parameters
454
+ ----------
455
+ val : A single value or a Range object
456
+
457
+ Raises:
458
+ -------
459
+ ValueError
460
+ If the value type not compatible with the ranges
461
+
462
+ Returns
463
+ -------
464
+ set of ranges overlapping with the value
465
+ """
466
+ if len(self) == 0: return False
467
+ # Get the index+1 of the highest lower cut <= to the value or its
468
+ # lower cutpoint and check if the value overlaps. If it does, add
469
+ # to set
470
+ overlap_set = set()
471
+ if isinstance(val, Range):
472
+ lower_ind = bisect_left(self.lower_cuts, val.lower_cut) - 1
473
+ upper_ind = bisect_left(self.lower_cuts, val.upper_cut)
474
+ for i in range(lower_ind, upper_ind):
475
+ if val.is_connected(self.ranges[i]):
476
+ if not self.ranges[i].intersection(val).is_empty():
477
+ overlap_set.add(self.ranges[i])
478
+ return overlap_set
479
+ else:
480
+ lower_ind = bisect_left(self.lower_cuts, val) - 1
481
+ if self.ranges[lower_ind].contains(val):
482
+ overlap_set.add(self.ranges[lower_ind])
483
+ return overlap_set
File without changes