def test_liftover_bad_request():
    """Test variant liftover with non-valid request params"""

    # WHEN sending a liftover request with non-standard chromosome (M instead of MT)
    chromosome = "M"
    start = 7278
    end = 7278

    # THEN the service should not return mappings
    mappings = liftover("GRCh37", chromosome, start, end)
    assert mappings is None
def test_liftover_37_38():
    """Test variant liftover from GRCh37 to GRCh38"""

    # WHEN sending a liftover request with suitable coordinates in genome build 37
    chromosome = "X"
    start = 1000000
    end = 1000000

    # THEN the service should return valid mappings
    mappings = liftover("GRCh37", chromosome, start, end)

    # Each mapping should have the expected output format
    assert isinstance(mappings, list)
    assert isinstance(mappings[0], dict)
    for item in ["assembly", "seq_region_name", "start", "end"]:
        assert mappings[0]["mapped"][item]

    # And genome assembly should be GRCh38
    assert mappings[0]["mapped"]["assembly"] == "GRCh38"
def test_liftover_MT_variant():
    """Test liftover for a mitochondrial variant from GRCh37 to GRCh38"""

    # GIVEN a mitochondrial variant
    chromosome = "MT"
    start = 7278
    end = 7278

    # THEN the service should return valid mappings
    mappings = liftover("GRCh37", chromosome, start, end)

    # Each mapping should have the expected output format
    assert isinstance(mappings, list)
    assert isinstance(mappings[0], dict)
    for item in ["assembly", "seq_region_name", "start", "end"]:
        assert mappings[0]["mapped"][item]

    # And genome assembly should be GRCh38
    assert mappings[0]["mapped"]["assembly"] == "GRCh38"
def lift_variant(variant):
    """Perform a variant liftover using Ensebl REST API and return eventual variant in the other genome build

    Args:
        variant(dict): example:
            {'assembly': 'GRCh38', 'referenceName': '12', 'start': 14641142, 'end': 14641142, 'referenceBases': 'C', 'alternateBases': 'T'}

    Returns:
        lifted_variants(list of dict): example:
            [{'assembly': 'GRCh37', 'referenceName': '12', 'start': 14794076, 'end': 14794076, 'referenceBases': 'C', 'alternateBases': 'T'}]
    """
    lifted_vars = []
    mappings = liftover(
        variant.get("assembly"),
        variant.get("referenceName"),
        variant.get("start") + 1,  # coordinates are 0-based in MatchMaker
        variant.get("end") + 1 if variant.get("end") else variant.get("end"),
    )

    if mappings is None:
        return lifted_vars

    for res in mappings:
        # Create a variant which is the copy of the original variant
        lifted = deepcopy(variant)
        mapped = res["mapped"]
        # Modify coordinates of this variant according to mapping results
        lifted["assembly"] = mapped["assembly"]
        lifted["referenceName"] = mapped["seq_region_name"]
        lifted["start"] = mapped[
            "start"] - 1  # conver back to 0-based coordinates
        if variant.get("end") is None:
            continue
        lifted["end"] = mapped["end"] - 1

        lifted_vars.append(lifted)

    return lifted_vars