我把它分开了一点;试试看from collections import defaultdict
from bisect import bisect_left
class ChromoSegments:
def __init__(self, cs=None):
# A list of [(start, end), (start, end), ...] per chromosome;
# each list is kept sorted in ascending order
self.segments = defaultdict(list)
# Add segments from parameter list
if cs is not None:
for chromo,start,end in cs:
try:
self.add_seg(chromo, start, end)
except ValueError:
pass
def add_seg(self, chromo, start, end):
seg = self.segments[chromo]
val = (start, end)
ndx = bisect_left(seg, val)
if (ndx == 0 or seg[ndx - 1][1] < start):
if (ndx == len(seg) or end < seg[ndx][0]):
seg.insert(ndx, val)
else:
# collision with following element
nstart, nend = seg[ndx]
raise ValueError('Discard ({}, {}, {}): collision with ({}, {}, {})'.format(chromo, start, end, chromo, nstart, nend))
else:
# collision with preceding element
nstart, nend = seg[ndx - 1]
raise ValueError('Discard ({}, {}, {}): collision with ({}, {}, {})'.format(chromo, start, end, chromo, nstart, nend))
def to_list(self):
keys = sorted(self.segments.keys())
return [(k, s, e) for k in keys for s,e in self.segments[k]]
def main():
expos = ChromoSegments([[1, 10, 30], [1, 50, 80], [1, 100, 200]])
pos = [[1, 12, 25], [1, 90, 98], [1, 130, 180], [2, 25, 50]]
target_chromo = 1
for seg in pos:
if seg[0] != target_chromo:
print('Different chromosome')
else:
try:
expos.add_seg(*seg)
print('New')
except ValueError, e:
print(e.message)
print('\nResult: {}'.format(expos.to_list()))
if __name__ == "__main__":
main()
产生
^{pr2}$
注意,我编写这个类是为了正确处理多个染色体;“不同染色体”警告必须在main()中单独处理。在
编辑:
如果您想处理多个染色体,main()可以简化如下:def main():
expos = ChromoSegments([[1, 10, 30], [1, 50, 80], [1, 100, 200]])
pos = [[1, 12, 25], [1, 90, 98], [1, 130, 180], [2, 25, 50]]
for seg in pos:
try:
expos.add_seg(*seg)
print('New')
except ValueError, e:
print(e.message)
print('\nResult: {}'.format(expos.to_list()))
输出变成Discard (1, 12, 25): collision with (1, 10, 30)
New
Discard (1, 130, 180): collision with (1, 100, 200)
New
Result: [(1, 10, 30), (1, 50, 80), (1, 90, 98), (1, 100, 200), (2, 25, 50)]