diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 928e7bd..a27190f 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -12,5 +12,5 @@ chainfile = "0.2.1" directories = "5.0" [dependencies.pyo3] -version = "0.20.0" +version = "0.20.2" features = ["abi3-py38"] diff --git a/src/chainlifter/lifter.py b/src/chainlifter/lifter.py index c7a52aa..db4dffa 100644 --- a/src/chainlifter/lifter.py +++ b/src/chainlifter/lifter.py @@ -2,7 +2,7 @@ import logging from enum import Enum from pathlib import Path -from typing import Callable, List +from typing import Callable, List, Tuple from wags_tails import CustomData from wags_tails.utils.downloads import download_http, handle_gzip @@ -93,7 +93,7 @@ def _download_data(version: str, file: Path) -> None: def convert_coordinate( self, chrom: str, pos: int, strand: Strand = Strand.POSITIVE - ) -> List[List[str]]: + ) -> List[Tuple[str, int, Strand]]: """Perform liftover for given params The ``Strand`` enum provides constraints for legal strand values: @@ -113,9 +113,9 @@ def convert_coordinate( :return: list of coordinate matches (possibly empty) """ try: - result = self._chainlifter.lift(chrom, pos, strand) + results = self._chainlifter.lift(chrom, pos, strand) except _core.NoLiftoverError: - result = [] + results = [] except _core.ChainfileError: _logger.error( "Encountered internal error while converting coordinates - is the chainfile invalid? (%s, %s, %s)", @@ -123,5 +123,18 @@ def convert_coordinate( pos, strand, ) - result = [] - return result + results = [] + formatted_results: List[Tuple[str, int, Strand]] = [] + for result in results: + try: + pos = int(result[1]) + except ValueError: + _logger.error("Got invalid position value in %s", result) + continue + try: + strand = Strand(result[2]) + except ValueError: + _logger.error("Got invalid Strand value in %s", result) + continue + formatted_results.append((result[0], pos, strand)) + return formatted_results diff --git a/tests/test_liftover.py b/tests/test_liftover.py index fce8b8f..1e3dc8c 100644 --- a/tests/test_liftover.py +++ b/tests/test_liftover.py @@ -1,5 +1,5 @@ """Run liftover tests.""" -from chainlifter.lifter import ChainLifter, Genome +from chainlifter.lifter import ChainLifter, Genome, Strand def test_hg19_to_hg38(): @@ -8,19 +8,19 @@ def test_hg19_to_hg38(): result = ch.convert_coordinate("chr7", 140439611) assert len(result) == 1 - assert result[0] == ["chr7", "140739811", "+"] + assert result[0] == ("chr7", 140739811, Strand.POSITIVE) result = ch.convert_coordinate("chr7", 140439746) assert len(result) == 1 - assert result[0] == ["chr7", "140739946", "+"] + assert result[0] == ("chr7", 140739946, Strand.POSITIVE) result = ch.convert_coordinate("chr7", 140439703) assert len(result) == 1 - assert result[0] == ["chr7", "140739903", "+"] + assert result[0] == ("chr7", 140739903, Strand.POSITIVE) result = ch.convert_coordinate("chr7", 140453136) assert len(result) == 1 - assert result[0] == ["chr7", "140753336", "+"] + assert result[0] == ("chr7", 140753336, Strand.POSITIVE) # coordinate exceeds bounds result = ch.convert_coordinate("chr7", 14040053136) @@ -28,17 +28,17 @@ def test_hg19_to_hg38(): def test_hg38_to_hg19(): - """Test hg38 to hg19 lifter.""" + "Test hg38 to hg19 lifter." "" ch = ChainLifter(Genome.HG38, Genome.HG19) result = ch.convert_coordinate("chr7", 140739811) assert len(result) == 1 - assert result[0] == ["chr7", "140439611", "+"] + assert result[0] == ("chr7", 140439611, Strand.POSITIVE) result = ch.convert_coordinate("chr7", 140759820) assert len(result) == 1 - assert result[0] == ["chr7", "140459620", "+"] + assert result[0] == ("chr7", 140459620, Strand.POSITIVE) result = ch.convert_coordinate("chr7", 60878240) assert len(result) == 1 - assert result[0] == ["chr7", "61646115", "+"] + assert result[0] == ("chr7", 61646115, Strand.POSITIVE)