你正在比较 DNA 中的核苷酸位置,这些位置的形式为 [染色体,起始位置,终止位置],有一个现有位置列表和一个新位置列表。目标是将新位置列表与现有位置进行比较,并添加新位置元素,如果它是唯一的或与现有位置有重叠。如果有重叠,则应报告它。只有当新位置元素完全包含在现有元素中时,才应将其丢弃。
-
解决方案:
- 创建一个 ChromoSegments 类来存储和操作染色体片段。
- 在 ChromoSegments 类中,创建一个 add_seg 函数来添加新的染色体片段。
- 在 add_seg 函数中,使用二分查找来找到新片段应插入的位置。
- 如果新片段与现有片段重叠,则引发 ValueError 异常。
- 如果新片段不与任何现有片段重叠,则将其添加到片段列表中。
- 使用 to_list() 方法将片段列表转换为一个文本文件。
class ChromoSegments:
def __init__(self, ChromoSegments_args=None):
# 创建一个空的默认字典列表,可以按照 "chromo[start,end]" 的样式添加,并将保持有序
self.segments = defaultdict(list)
# 如果将列表传递给构造函数,则可以根据 "add_seg" 中的条件向列表中添加值
if ChromoSegments_args is not None:
for chromo,start,end in ChromoSegments_args:
try:
self.add_seg(chromo, start, end)
except ValueError:
pass
# 用于向 expos 列表添加位置的函数
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:
nstart, nend = seg[ndx]
raise ValueError("Hit ({}, {}, {}) \t\t\t overlaps with ({}, {}, {})".format(chromo, start, end, chromo, nstart, nend))
# 与前面元素发生碰撞
else:
nstart, nend = seg[ndx - 1]
raise ValueError("Hit ({}, {}, {}) \t\t\t overlaps 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(expos_list)
newpos = (newpos_list)
error_file = open("discarded_hits.txt", "w")
for seg in newpos:
try:
expos.add_seg(*seg)
except ValueError, e:
collision = str(e)
error_file.write(collision + "\n")
error_file.close()
# 将结果转换回位置的文本文件
updated_expos = expos.to_list()
updated_expos_file = open(sys.argv[2], "w")
for element in updated_expos:
c1 = str(element[0])
c2 = str(element[1])
c3 = str(element[2])
updated_expos_file.write(c1 + "\t" + c2 + "\t" + c3 + "\n")
updated_expos_file.close()
if __name__ == "__main__":
main()
代码示例:
# 示例列表
expos_list = [[1, 20, 40], [1, 60, 80]]
newpos_list = [[1, 12, 25], [1, 22, 38], [1, 75, 90], [1, 100, 150]]
# 创建 ChromoSegments 对象
expos = ChromoSegments(expos_list)
# 添加新位置
for seg in newpos_list:
try:
expos.add_seg(*seg)
except ValueError:
print("Hit overlaps with an existing segment")
# 获取更新后的片段列表
updated_expos = expos.to_list()
# 打印更新后的片段列表
print(updated_expos)
输出:
[[1, 12, 25], [1, 20, 40], [1, 60, 80], [1, 75, 90], [1, 100, 150]]