diff --git a/modules/seq/base/pymod/export_sequence.cc b/modules/seq/base/pymod/export_sequence.cc index 6db4d304e88f968afd3d51ef1f63f79c940dd1a6..df18efd0db8a778a6779d2082a674732a214eb59 100644 --- a/modules/seq/base/pymod/export_sequence.cc +++ b/modules/seq/base/pymod/export_sequence.cc @@ -57,11 +57,17 @@ T do_slice(const T& t, slice& sl) { int start=0, end=t.GetCount(); try { start=extract<int>(sl.start()); + if (start<0) { + start=t.GetCount()+start; + } } catch(error_already_set) { PyErr_Clear(); } try { end=extract<int>(sl.stop()); + if (end<0) { + end=t.GetCount()+end; + } } catch(error_already_set) { PyErr_Clear(); } @@ -78,16 +84,43 @@ SequenceList do_slice_b(SequenceList& t, slice sl) return do_slice<SequenceList>(t, sl); } +String slice_seq(const ConstSequenceHandle& sh, slice& sl) { + int start=0, end=sh.GetLength(); + try { + start=extract<int>(sl.start()); + if (start<0) { + start=sh.GetLength()+start; + } + } catch(error_already_set) { + PyErr_Clear(); + } + try { + end=extract<int>(sl.stop()); + if (end<0) { + end=sh.GetLength()+end; + } + } catch(error_already_set) { + PyErr_Clear(); + } + String s=sh.GetString(); + return s.substr(start, end-start); +} AlignedRegion slice_aln(const AlignmentHandle& aln, slice sl) { int start=0, end=aln.GetLength(); try { start=extract<int>(sl.start()); + if (start<0) { + start=aln.GetLength()+start; + } } catch(error_already_set) { PyErr_Clear(); } try { end=extract<int>(sl.stop()); + if (end<0) { + end=aln.GetLength()+end; + } } catch(error_already_set) { PyErr_Clear(); } @@ -212,6 +245,7 @@ void const_seq_handle_def(O& bp_class) .def("GetOneLetterCode", &C::GetOneLetterCode) .def("__iter__", iterator<C>()) .def("__getitem__", &C::GetOneLetterCode) + .def("__getitem__", slice_seq) .def("GetOffset", &C::GetOffset) .def("Copy", &C::Copy) .def("IsValid", &C::IsValid) diff --git a/modules/seq/base/tests/test_seq.py b/modules/seq/base/tests/test_seq.py index 9ae40d5fc98cba9e64d15efe67dabd0978fc718b..7cc73a5cedb9cad4044948f840693b63bc72b16b 100644 --- a/modules/seq/base/tests/test_seq.py +++ b/modules/seq/base/tests/test_seq.py @@ -19,6 +19,55 @@ class TestSeq(unittest.TestCase): def setUp(self): self.ent=fixture() + + def testSeqSlice(self): + seq_string='abcdefg' + s=seq.CreateSequence('A', seq_string) + self.assertEqual(s[1:5], seq_string[1:5]) + self.assertEqual(s[:-1], seq_string[:-1]) + self.assertEqual(s[-3:-2], seq_string[-3:-2]) + self.assertEqual(s[-3:], seq_string[-3:]) + self.assertEqual(s[3:4], seq_string[3:4]) + + def testSeqListSlice(self): + a=seq.CreateSequence('A','aaaa') + b=seq.CreateSequence('B','bbbb') + c=seq.CreateSequence('C','cccc') + d=seq.CreateSequence('D','dddd') + sl=seq.CreateSequenceList(a, b, c, d) + sliced=sl[1:] + self.assertEqual(len(sliced), 3) + self.assertEqual(str(sliced[0]), str(b)) + self.assertEqual(str(sliced[1]), str(c)) + self.assertEqual(str(sliced[2]), str(d)) + sliced=sl[:-1] + self.assertEqual(len(sliced), 3) + self.assertEqual(str(sliced[0]), str(a)) + self.assertEqual(str(sliced[1]), str(b)) + self.assertEqual(str(sliced[2]), str(c)) + sliced=sl[-1:] + self.assertEqual(len(sliced), 1) + self.assertEqual(str(sliced[0]), str(d)) + + def testAlnSlice(self): + a=seq.CreateSequence('A','abcd') + b=seq.CreateSequence('B','efgh') + c=seq.CreateSequence('C','ijkl') + d=seq.CreateSequence('D','mnop') + aln=seq.CreateAlignment(a, b, c, d) + sliced=aln[1:] + self.assertEqual(len(sliced), 3) + self.assertEqual(str(sliced[0]), 'bfjn') + self.assertEqual(str(sliced[1]), 'cgko') + self.assertEqual(str(sliced[2]), 'dhlp') + sliced=aln[:-1] + self.assertEqual(len(sliced), 3) + self.assertEqual(str(sliced[0]), 'aeim') + self.assertEqual(str(sliced[1]), 'bfjn') + self.assertEqual(str(sliced[2]), 'cgko') + sliced=aln[-1:] + self.assertEqual(len(sliced), 1) + self.assertEqual(str(sliced[0]), 'dhlp') def testViewsFromSequences_01(self): seq_a=seq.CreateSequence("A", "ABCD-FGH")