Repository: cogent3/cogent3
Pull request #2088 (2024-11-01 04:47:02)

DEV: SeqDataView.map sliced by slice_record
Addressing comment on https://github.com/cogent3/cogent3/pull/2079#discussion_r1825401297

## Summary by Sourcery

Enhance the SeqDataView class by slicing the IndelMap in the 'map' property using slice_record, and update the parent_seq_coords method to use the parent's IndelMap for accurate index retrieval. Additionally, remove the xfail marker from a test, indicating a resolved issue.

Enhancements:
- Modify the 'map' property in SeqDataView to return a sliced IndelMap based on slice_record.

Tests:
- Remove the xfail marker from the test_coevo_annotated test, indicating the issue with inconsistent length between alignment and map has been resolved.


Patch:
diff --git a/src/cogent3/core/new_alignment.py b/src/cogent3/core/new_alignment.py
index 4e5a59bb6..291a2ea4e 100644
--- a/src/cogent3/core/new_alignment.py
+++ b/src/cogent3/core/new_alignment.py
@@ -3255,6 +3255,15 @@ class AlignedDataView(new_sequence.SeqViewABC):
 
     @property
     def map(self) -> IndelMap:
+        imap = self._parent_map()
+        start, stop, step = (
+            self.slice_record.start,
+            self.slice_record.stop,
+            self.slice_record.step,
+        )
+        return imap[start:stop:step]
+
+    def _parent_map(self) -> IndelMap:
         gap_pos_gap_length = self.parent.get_gaps(self.seqid)
         if gap_pos_gap_length.size > 0:
             gap_pos = numpy.array(gap_pos_gap_length[:, 0], dtype=int)
@@ -3264,9 +3273,6 @@ class AlignedDataView(new_sequence.SeqViewABC):
                 numpy.array([], dtype=int),
                 numpy.array([], dtype=int),
             )
-
-        # refactor: design
-        # should the returned map be sliced with the slice_record?
         return IndelMap(
             gap_pos=gap_pos,
             cum_gap_lengths=cum_gap_lengths,
@@ -3364,8 +3370,11 @@ class AlignedDataView(new_sequence.SeqViewABC):
 
     def parent_seq_coords(self) -> tuple[str, int, int, int]:
         """returns seqid, start, stop, strand on the parent sequence"""
-        start = self.map.get_seq_index(self.slice_record.parent_start)
-        stop = self.map.get_seq_index(self.slice_record.parent_stop)
+        # we want the coordinates on the parent, which means we need to use the
+        # parent's IndelMap for findings the correct indices.
+        parent_map = self._parent_map()
+        start = parent_map.get_seq_index(self.slice_record.parent_start)
+        stop = parent_map.get_seq_index(self.slice_record.parent_stop)
         strand = -1 if self.slice_record.step < 0 else 1
 
         return self.seqid, start, stop, strand


Test patch:
diff --git a/tests/test_draw/test_new_draw_integration.py b/tests/test_draw/test_new_draw_integration.py
index 829e7fc97..8b5980ed3 100644
--- a/tests/test_draw/test_new_draw_integration.py
+++ b/tests/test_draw/test_new_draw_integration.py
@@ -244,9 +244,6 @@ def test_coevo_drawables(load_alignment):
     check_drawable_styles(aln.coevolution, styles, show_progress=False)
 
 
-@pytest.mark.xfail(
-    reason="todo: for sliced alignment, inconsistent length between length of alignment and length of the map"
-)
 def test_coevo_annotated(load_alignment):
     """coevolution on alignment with annotated seqs should add to heatmap plot"""
     aln = load_alignment(True, False)