Spaces:
No application file
No application file
#!/usr/bin/env python | |
# Copyright 2004 by Michael Hoffman. All rights reserved. | |
# This file is part of the Biopython distribution and governed by your | |
# choice of the "Biopython License Agreement" or the "BSD 3-Clause License". | |
# Please see the LICENSE file that should have been included as part of this | |
# package. | |
"""Run and process output from the Wise2 package tool psw. | |
Bio.Wise contains modules for running and processing the output of | |
some of the models in the Wise2 package by Ewan Birney available from: | |
ftp://ftp.ebi.ac.uk/pub/software/unix/wise2/ | |
http://www.ebi.ac.uk/Wise2/ | |
Bio.Wise.psw is for protein Smith-Waterman alignments | |
Bio.Wise.dnal is for Smith-Waterman DNA alignments | |
""" | |
import os | |
import re | |
import sys | |
from Bio import Wise | |
_CMDLINE_PSW = ["psw", "-l", "-F"] | |
_OPTION_GAP_START = "-g" | |
_OPTION_GAP_EXTENSION = "-e" | |
_OPTION_SCORES = "-m" | |
class AlignmentColumnFullException(Exception): | |
"""Manage exception in the alignment output.""" | |
pass | |
class Alignment(list): | |
"""Define a container for all alignment Columns, output from running psw.""" | |
def append(self, column_unit): | |
"""Add an alignment Column to Alignment.""" | |
try: | |
self[-1].append(column_unit) | |
except AlignmentColumnFullException: | |
list.append(self, AlignmentColumn(column_unit)) | |
except IndexError: | |
list.append(self, AlignmentColumn(column_unit)) | |
class AlignmentColumn(list): | |
"""Define a container for the units that made the Column.""" | |
def _set_kind(self, column_unit): | |
if self.kind == "SEQUENCE": | |
self.kind = column_unit.kind | |
def __init__(self, column_unit): | |
"""Initialize the class.""" | |
assert column_unit.unit == 0 | |
self.kind = column_unit.kind | |
list.__init__(self, [column_unit.column, None]) | |
def __repr__(self): | |
"""Represent the AlignmentColumn object as a string for debugging.""" | |
return f"{self.kind}({self[0]!r}, {self[1]!r})" | |
def append(self, column_unit): | |
"""Add a unit to the Column.""" | |
if self[1] is not None: | |
raise AlignmentColumnFullException | |
assert column_unit.unit == 1 | |
self._set_kind(column_unit) | |
self[1] = column_unit.column | |
class ColumnUnit: | |
"""Define a container for the details of each sequence alignment.""" | |
def __init__(self, unit, column, kind): | |
"""Initialize the class.""" | |
self.unit = unit | |
self.column = column | |
self.kind = kind | |
def __repr__(self): | |
"""Represent the ColumnUnit object as a string for debugging.""" | |
return "ColumnUnit(unit=%r, column=%r, kind=%r)" % ( | |
self.unit, | |
self.column, | |
self.kind, | |
) | |
_re_unit = re.compile(r"^Unit +([01])- \[ *(-?\d+)- *(-?\d+)\] \[(\w+)\]$") | |
def parse_line(line): | |
"""Parse a line from psw. | |
>>> print(parse_line("Column 0:")) | |
None | |
>>> parse_line("Unit 0- [ -1- 0] [SEQUENCE]") | |
ColumnUnit(unit=0, column=0, kind='SEQUENCE') | |
>>> parse_line("Unit 1- [ 85- 86] [SEQUENCE]") | |
ColumnUnit(unit=1, column=86, kind='SEQUENCE') | |
""" | |
match = _re_unit.match(line.rstrip()) | |
if not match: | |
return | |
return ColumnUnit(int(match.group(1)), int(match.group(3)), match.group(4)) | |
def parse(iterable): | |
"""Parse a file. | |
format | |
Column 0: | |
Unit 0- [ -1- 0] [SEQUENCE] | |
Unit 1- [ 85- 86] [SEQUENCE] | |
means that seq1[0] == seq2[86] (0-based) | |
""" | |
alignment = Alignment() | |
for line in iterable: | |
try: | |
if os.environ["WISE_PY_DEBUG"]: | |
print(line) | |
except KeyError: | |
pass | |
column_unit = parse_line(line) | |
if column_unit: | |
alignment.append(column_unit) | |
return alignment | |
def align(pair, scores=None, gap_start=None, gap_extension=None, *args, **keywds): | |
"""Align a pair of DNA files using Wise2 psw.""" | |
cmdline = _CMDLINE_PSW[:] | |
if scores: | |
cmdline.extend((_OPTION_SCORES, scores)) | |
if gap_start: | |
cmdline.extend((_OPTION_GAP_START, str(gap_start))) | |
if gap_extension: | |
cmdline.extend((_OPTION_GAP_EXTENSION, str(gap_extension))) | |
temp_file = Wise.align(cmdline, pair, *args, **keywds) | |
return parse(temp_file) | |
def main(): | |
"""Command line implementation.""" | |
print(align(sys.argv[1:3])) | |
def _test(*args, **keywds): | |
import doctest | |
doctest.testmod(sys.modules[__name__], *args, **keywds) | |
if __name__ == "__main__": | |
if __debug__: | |
_test() | |
"""Initialize the class.""" | |
main() | |