2022-01-13 23:27:39 +01:00
|
|
|
package obiseq
|
|
|
|
|
2022-10-05 09:41:59 +02:00
|
|
|
// ".ABCDEFGHIJKLMNOPQRSTUVWXYZ#![]"
|
2022-10-12 23:01:47 +02:00
|
|
|
var _revcmpDNA = []byte(".TVGHEFCDIJMLKNOPQYSAABWXRZ#!][")
|
2022-01-13 23:27:39 +01:00
|
|
|
|
|
|
|
// Reverse complements a DNA sequence.
|
|
|
|
// If the inplace parametter is true, that operation is done in place.
|
2022-02-21 19:00:23 +01:00
|
|
|
func (sequence *BioSequence) ReverseComplement(inplace bool) *BioSequence {
|
2022-01-13 23:27:39 +01:00
|
|
|
|
|
|
|
if !inplace {
|
|
|
|
sequence = sequence.Copy()
|
|
|
|
}
|
|
|
|
|
2022-02-21 19:00:23 +01:00
|
|
|
s := sequence.sequence
|
2022-01-13 23:27:39 +01:00
|
|
|
|
2022-11-17 11:09:58 +01:00
|
|
|
for i, j := sequence.Len()-1, 0; i >= j; i-- {
|
2022-01-13 23:27:39 +01:00
|
|
|
|
2022-10-12 23:01:47 +02:00
|
|
|
// ASCII code & 31 -> builds an index in witch (a|A) is 1
|
|
|
|
// ASCII code & 0x20 -> Foce lower case
|
|
|
|
|
|
|
|
s[j], s[i] = _revcmpDNA[s[i]&31]|(s[i]&0x20),
|
|
|
|
_revcmpDNA[s[j]&31]|(s[j]&0x20)
|
2022-01-13 23:27:39 +01:00
|
|
|
j++
|
|
|
|
}
|
|
|
|
|
2022-10-05 09:41:59 +02:00
|
|
|
if sequence.HasQualities() {
|
|
|
|
s := sequence.qualities
|
2022-11-17 11:09:58 +01:00
|
|
|
for i, j := sequence.Len()-1, 0; i >= j; i-- {
|
2022-10-05 09:41:59 +02:00
|
|
|
s[j], s[i] = s[i], s[j]
|
|
|
|
j++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-12 23:01:47 +02:00
|
|
|
return sequence._revcmpMutation()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (sequence *BioSequence) _revcmpMutation() *BioSequence {
|
|
|
|
|
|
|
|
rev := func(m string) string {
|
|
|
|
b := []byte(m)
|
|
|
|
|
|
|
|
// Echange and reverse complement symboles
|
|
|
|
b[1], b[9] = _revcmpDNA[b[9]&31]|(b[9]&0x20),
|
|
|
|
_revcmpDNA[b[1]&31]|(b[1]&0x20)
|
|
|
|
|
|
|
|
// Exchange sequencing scores
|
|
|
|
b[3], b[4], b[11], b[12] = b[11], b[12], b[3], b[4]
|
|
|
|
|
|
|
|
return string(b)
|
|
|
|
}
|
|
|
|
|
2022-11-17 11:09:58 +01:00
|
|
|
lseq := sequence.Len()
|
2022-10-12 23:01:47 +02:00
|
|
|
|
|
|
|
mut, ok := sequence.GetIntMap("pairing_mismatches")
|
|
|
|
if ok && len(mut) > 0 {
|
|
|
|
cmut := make(map[string]int, len(mut))
|
|
|
|
|
|
|
|
for m, p := range mut {
|
|
|
|
cmut[rev(m)] = lseq - p + 1
|
|
|
|
}
|
|
|
|
|
|
|
|
sequence.SetAttribute("pairing_mismatches", cmut)
|
|
|
|
}
|
|
|
|
|
2022-01-13 23:27:39 +01:00
|
|
|
return sequence
|
|
|
|
}
|
2023-01-22 22:39:13 +01:00
|
|
|
|
|
|
|
|
|
|
|
func ReverseComplementWorker(inplace bool) SeqWorker {
|
|
|
|
f := func(input *BioSequence) *BioSequence {
|
|
|
|
return input.ReverseComplement(inplace)
|
|
|
|
}
|
|
|
|
|
|
|
|
return f
|
|
|
|
}
|