Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 12 additions & 28 deletions lib/bx/align/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,34 +219,18 @@ def remove_all_gap_columns(self) -> None:
Remove any columns containing only gaps from alignment components,
text of components is modified IN PLACE.
"""
seqs: list[list[str] | None] = []
for c in self.components:
if c.empty or c.text is None:
seqs.append(None)
else:
seqs.append(list(c.text))
i = 0
text_size = self.text_size
while i < text_size:
all_gap = True
for seq in seqs:
if seq is None:
continue
if seq[i] != "-":
all_gap = False
if all_gap:
for seq in seqs:
if seq is None:
continue
del seq[i]
text_size -= 1
else:
i += 1
for component, seq in zip(self.components, seqs):
if seq is None:
continue
component.text = "".join(seq)
self.text_size = text_size
# A component can occur more than once; rebuild each object only once.
texts = list({id(c): (c, c.text) for c in self.components if not c.empty and c.text is not None}.values())
if any("-" not in text for _, text in texts):
return
# Decide which columns to retain before modifying any component. Deleting
# individual gaps from lists repeatedly shifts the remaining alignment.
keep = [i for i in range(self.text_size) if any(text[i] != "-" for _, text in texts)]
if len(keep) == self.text_size:
return
for component, text in texts:
component.text = "".join(text[i] for i in keep)
self.text_size = len(keep)

def __eq__(self, other: object) -> bool:
if other is None or not isinstance(other, type(self)):
Expand Down
14 changes: 13 additions & 1 deletion lib/bx/align/maf_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from io import StringIO

import pytest

from bx import align
from bx.align import maf

Expand Down Expand Up @@ -211,7 +213,9 @@ def test_column_iter():
assert c == expected[i]


def test_remove_all_gap_column():
@pytest.mark.parametrize("empty_index", [0, 1, 3])
@pytest.mark.parametrize("repeat_component", [False, True])
def test_remove_all_gap_column(empty_index, repeat_component):
complex_maf_gap = align.Alignment()
complex_maf_gap.score = "7009"
complex_maf_gap.components.append(
Expand All @@ -231,7 +235,15 @@ def test_remove_all_gap_column():
complex_maf_gap.components[-1].empty = True
complex_maf_gap.components[-1].synteny_empty = maf.MAF_INSERT_STATUS
complex_maf_gap.text_size = 11
empty = complex_maf_gap.components.pop()
complex_maf_gap.components.insert(empty_index, empty)
if repeat_component:
complex_maf_gap.add_component(next(c for c in complex_maf_gap.components if not c.empty))
complex_maf_gap.remove_all_gap_columns()
if repeat_component:
complex_maf_gap.components.pop()
# Return the empty row to its fixture position for the equality check.
complex_maf_gap.components.append(complex_maf_gap.components.pop(empty_index))
assert complex_maf_gap == complex_maf

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert complex_maf_gap == complex_maf
assert complex_maf_gap == complex_maf
assert complex_maf_gap.text_size == complex_maf.text_size



Expand Down
Loading