@@ -65,7 +65,7 @@ from cpython cimport array as c_array
6565from cpython.bytearray cimport PyByteArray_FromStringAndSize, PyByteArray_GET_SIZE
6666from cpython.bytes cimport PyBytes_FromStringAndSize
6767from cpython.unicode cimport PyUnicode_DATA, PyUnicode_1BYTE_DATA, PyUnicode_1BYTE_KIND, \
68- PyUnicode_GET_LENGTH, PyUnicode_KIND, PyUnicode_WRITE
68+ PyUnicode_GET_LENGTH, PyUnicode_KIND, PyUnicode_New, PyUnicode_WRITE
6969from libc.string cimport memset, strchr
7070from libc.stdint cimport INT8_MIN, INT16_MIN, INT32_MIN, \
7171 INT8_MAX, INT16_MAX, INT32_MAX, \
@@ -632,29 +632,31 @@ cdef inline int32_t getQueryEnd(bam1_t *src) except -1:
632632 return end_offset
633633
634634
635- cdef inline bytes getSequenceInRange(bam1_t * src,
636- uint32_t start,
637- uint32_t end):
635+ cdef inline str getSequenceInRange(const bam1_t * src, uint32_t start, uint32_t end):
638636 """ return python string of the sequence in a bam1_t object.
639637 """
638+ seq = PyUnicode_New(end - start, 127 )
639+ cdef char * dest = < char * > PyUnicode_1BYTE_DATA(seq)
640+ cdef unsigned int di = 0
640641
641- cdef uint8_t * p
642- cdef uint32_t k
643- cdef char * s
642+ cdef const uint8_t * p = bam_get_seq(src)
643+ cdef unsigned int i = start // 2
644644
645- if not src.core.l_qseq:
646- return None
645+ if start & 1 :
646+ dest[di] = seq_nt16_str[p[i] & 0x0f ]
647+ i += 1
648+ di += 1
647649
648- seq = PyBytes_FromStringAndSize(NULL , end - start)
649- s = < char * > seq
650- p = pysam_bam_get_seq(src)
650+ for _ in range (i, end // 2 ):
651+ dest[di] = seq_nt16_str[p[i] >> 4 ]
652+ dest[di+ 1 ] = seq_nt16_str[p[i] & 0x0f ]
653+ i += 1
654+ di += 2
651655
652- for k from start <= k < end:
653- # equivalent to seq_nt16_str[bam1_seqi(s, i)] (see bam.c)
654- # note: do not use string literal as it will be a python string
655- s[k- start] = seq_nt16_str[p[k// 2 ] >> 4 * (1 - k% 2 ) & 0xf ]
656+ if end & 1 :
657+ dest[di] = seq_nt16_str[p[i] >> 4 ]
656658
657- return charptr_to_bytes( seq)
659+ return seq
658660
659661
660662# ####################################################################
@@ -1530,8 +1532,7 @@ cdef class AlignedSegment:
15301532 self .cache.query_sequence = None
15311533 return None
15321534
1533- self .cache.query_sequence = force_str(getSequenceInRange(
1534- src, 0 , src.core.l_qseq))
1535+ self .cache.query_sequence = getSequenceInRange(src, 0 , src.core.l_qseq)
15351536 return self .cache.query_sequence
15361537
15371538 def __set__ (self , seq ):
@@ -1898,7 +1899,7 @@ cdef class AlignedSegment:
18981899 start = getQueryStart(src)
18991900 end = getQueryEnd(src)
19001901
1901- self .cache.query_alignment_sequence = force_str( getSequenceInRange(src, start, end) )
1902+ self .cache.query_alignment_sequence = getSequenceInRange(src, start, end)
19021903 return self .cache.query_alignment_sequence
19031904
19041905 property query_alignment_qualities :
0 commit comments