Python编写adaptor切除工具时序列大小写不敏感匹配问题求助
问题根源
- Python 原生字符串的
startswith()方法不支持正则标志位参数,re.I是正则模块的常量,传入startswith()会触发参数类型错误,这是修改后代码无法运行的直接原因。 - 原有逻辑只覆盖了adaptor全大写、全小写两种匹配场景,完全没有处理大小写混合的情况,所以遇到
TAta类的混合序列会匹配失败。 - 原有代码还存在两处逻辑隐患:
- 遍历
read.items()查找seq键的写法冗余,且输出逻辑会把read对象的所有键值都写入输出文件,如果存储了质量值、序列id等其他字段会导致输出异常 - 用
replace()删除开头adaptor的逻辑存在风险:如果序列中间也出现和adaptor一致的序列,极端场景下可能误删,直接按长度切片更安全。
- 遍历
修复方案
方案1:无需引入正则,统一大小写比对(性能更高,更推荐生物序列处理场景使用)
直接将序列开头的对应长度片段和adaptor统一转为大写/小写后比对,匹配成功直接切片切除即可,修改后代码如下:
elif operation == "adaptor-removal": adaptor = args.adaptor adaptor_len = len(adaptor) # 提前把adaptor转成大写,后续统一比对 adaptor_upper = adaptor.upper() reads = sequences(args.input, format) num_reads = len(reads) bases = "".join([read["seq"] for read in reads]) adaptors_found = 0 for read in reads: seq = read["seq"] # 只比对开头对应长度的片段,统一转大写 if len(seq) >= adaptor_len and seq[:adaptor_len].upper() == adaptor_upper: adaptors_found += 1 # 直接切片切除开头的adaptor seq = seq[adaptor_len:] # 只写入处理后的序列 args.output.write("%s\n" % seq) print_summary(operation) print("%s adaptors found" % adaptors_found)
方案2:使用正则实现大小写不敏感匹配
如果要使用正则的大小写不敏感能力,需要调用re模块的match方法(专门匹配字符串开头),写法如下:
首先要在代码开头导入正则模块:
import re
对应业务逻辑修改为:
elif operation == "adaptor-removal": adaptor = args.adaptor reads = sequences(args.input, format) num_reads = len(reads) bases = "".join([read["seq"] for read in reads]) adaptors_found = 0 adaptor_pattern = re.compile(re.escape(adaptor), re.IGNORECASE) for read in reads: seq = read["seq"] match_res = adaptor_pattern.match(seq) if match_res: adaptors_found += 1 # 从匹配结束的位置开始截取序列 seq = seq[match_res.end():] args.output.write("%s\n" % seq) print_summary(operation) print("%s adaptors found" % adaptors_found)
注意这里加了
re.escape()处理adaptor序列,避免adaptor里出现正则特殊字符时匹配异常,如果你确认adaptor只有ATCG四种字符可以省略。
内容的提问来源于stack exchange,提问作者ryn roderic
相关产品推荐
相关产品推荐

