aakash0017's picture
Upload folder using huggingface_hub
b7731cd
# Copyright 2022 by Michiel de Hoon. 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.
"""Bio.Align support for alignment files in the bigPsl format.
A bigPsl file is a bigBed file with a BED12+13 format consisting of the 12
predefined BED fields and 13 custom fields defined in the autoSql file
bigPsl.as. This module uses the Bio.Align.bigbed module to parse the file,
but stores the data in a PSL-consistent manner as defined in bigPsl.as. As the
bigPsl format is a special case of the bigBed format, bigPsl files are binary
and are indexed as bigBed files.
See http://genome.ucsc.edu/goldenPath/help/bigPsl.html for more information.
You are expected to use this module via the Bio.Align functions.
"""
import numpy
from Bio.Align import Alignment
from Bio.Align import bigbed
from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
from Bio.SeqFeature import SeqFeature, Location
class AlignmentIterator(bigbed.AlignmentIterator):
"""Alignment iterator for bigPsl files.
The pairwise alignments stored in the bigPsl file are loaded and returned
incrementally. Additional alignment information is stored as attributes
of each alignment.
"""
fmt = "bigPsl"
def _analyze_fields(self, fields, fieldCount, definedFieldCount):
names = (
"chrom",
"chromStart",
"chromEnd",
"name", # 0
"score", # 1
"strand", # 2
"thickStart", # 3
"thickEnd", # 4
"reserved", # 5
"blockCount", # 6
"blockSizes", # 7
"chromStarts", # 8
"oChromStart", # 9
"oChromEnd", # 10
"oStrand", # 11
"oChromSize", # 12
"oChromStarts", # 13
"oSequence", # 14
"oCDS", # 15
"chromSize", # 16
"match", # 17
"misMatch", # 18
"repMatch", # 19
"nCount", # 20
"seqType", # 21
)
for i, name in enumerate(names):
if name != fields[i].name:
raise ValueError(
"Expected field name '%s'; found '%s'" % (name, fields[i].name)
)
def _create_alignment(self, chunk):
chromId, tStart, tEnd, rest = chunk
words = rest.decode().split("\t")
if len(words) != 22:
raise ValueError(
"Unexpected number of fields (%d, expected 22)" % len(words)
)
target_record = self.targets[chromId]
tSize = int(words[16])
if len(target_record) != tSize:
raise ValueError(
"Unexpected chromosome size %d (expected %d)"
% (tSize, len(target_record))
)
strand = words[2]
qName = words[0]
qSize = int(words[12])
blockCount = int(words[6])
blockSizes = [int(blockSize) for blockSize in words[7].rstrip(",").split(",")]
tStarts = [int(start) for start in words[8].rstrip(",").split(",")]
qStarts = [int(start) for start in words[13].rstrip(",").split(",")]
if len(blockSizes) != blockCount:
raise ValueError(
"Inconsistent number of blocks (%d found, expected %d)"
% (len(blockSizes), blockCount)
)
if len(qStarts) != blockCount:
raise ValueError(
"Inconsistent number of query start positions (%d found, expected %d)"
% (len(qStarts), blockCount)
)
if len(tStarts) != blockCount:
raise ValueError(
"Inconsistent number of target start positions (%d found, expected %d)"
% (len(qStarts), blockCount)
)
qStarts = numpy.array(qStarts)
tStarts = numpy.array(tStarts)
tBlockSizes = numpy.array(blockSizes)
query_sequence = words[14]
if query_sequence == "":
query_sequence = Seq(None, length=qSize)
else:
query_sequence = Seq(query_sequence)
if len(query_sequence) != qSize:
raise ValueError(
"Inconsistent query sequence length (%d, expected %d)"
% (len(query_sequence), qSize)
)
query_record = SeqRecord(query_sequence, id=qName)
cds = words[15]
if cds and cds != "n/a":
location = Location.fromstring(cds)
feature = SeqFeature(location, type="CDS")
query_record.features.append(feature)
seqType = words[21]
if seqType == "0":
qBlockSizes = tBlockSizes
elif seqType == "1":
query_record.annotations["molecule_type"] = "DNA"
qBlockSizes = tBlockSizes
elif seqType == "2":
query_record.annotations["molecule_type"] = "protein"
qBlockSizes = tBlockSizes // 3
else:
raise ValueError("Unexpected sequence type '%s'" % seqType)
tStarts += tStart
qStrand = words[11]
if qStrand == "-" and strand == "-":
tStart, tEnd = tEnd, tStart
qStarts = qSize - qStarts - qBlockSizes
tStarts = tSize - tStarts - tBlockSizes
qStarts = qStarts[::-1]
tStarts = tStarts[::-1]
qBlockSizes = qBlockSizes[::-1]
tBlockSizes = tBlockSizes[::-1]
qPosition = qStarts[0]
tPosition = tStarts[0]
coordinates = [[tPosition, qPosition]]
for tB, qB, tS, qS in zip(tBlockSizes, qBlockSizes, tStarts, qStarts):
if tS != tPosition:
coordinates.append([tS, qPosition])
tPosition = tS
if qS != qPosition:
coordinates.append([tPosition, qS])
qPosition = qS
tPosition += tB
qPosition += qB
coordinates.append([tPosition, qPosition])
coordinates = numpy.array(coordinates).transpose()
qStart = int(words[9])
qEnd = int(words[10])
if strand == "-":
if qStrand == "-":
coordinates[0, :] = tSize - coordinates[0, :]
else:
qStart, qEnd = qEnd, qStart
coordinates[1, :] = qSize - coordinates[1, :]
if tStart != coordinates[0, 0]:
raise ValueError(
"Inconsistent tStart found (%d, expected %d)"
% (tStart, coordinates[0, 0])
)
if tEnd != coordinates[0, -1]:
raise ValueError(
"Inconsistent tEnd found (%d, expected %d)" % (tEnd, coordinates[0, -1])
)
if qStart != coordinates[1, 0]:
raise ValueError(
"Inconsistent qStart found (%d, expected %d)"
% (qStart, coordinates[1, 0])
)
if qEnd != coordinates[1, -1]:
raise ValueError(
"Inconsistent qEnd found (%d, expected %d)" % (qEnd, coordinates[1, -1])
)
records = [target_record, query_record]
alignment = Alignment(records, coordinates)
alignment.annotations = {}
score = words[1]
try:
score = float(score)
except ValueError:
pass
else:
if score.is_integer():
score = int(score)
alignment.score = score
alignment.thickStart = int(words[3])
alignment.thickEnd = int(words[4])
alignment.itemRgb = words[5]
alignment.matches = int(words[17])
alignment.misMatches = int(words[18])
alignment.repMatches = int(words[19])
alignment.nCount = int(words[20])
return alignment