Spaces:
Running
Running
| """Tests for sequence-visible expression risk (audit #24). | |
| Two things are actually being defended here: that no yield is ever predicted, | |
| and that the rare-codon threshold is derived from the tables rather than | |
| chosen β the second is what makes the first honest rather than merely cautious. | |
| """ | |
| import pytest | |
| from dee.core import expression as E | |
| ADAPTED = "ATG" + "AAACTGGCGCGTGAAGATCTGAAAGCGGTTCTGGAAAAC" * 3 + "TAA" | |
| RARE_HEAVY = "ATG" + "AAACTGGCGAGAAGGATAGATCTGAAAGCGGTTCTGGAAAAC" * 3 + "TAA" | |
| # ββ the honesty contract βββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def test_no_expression_level_is_ever_predicted(): | |
| r = E.assess(ADAPTED, "e_coli") | |
| assert r["ok"] | |
| assert "does NOT predict an expression level" in r["no_yield"] | |
| for key in ("yield", "expression_level", "mg_per_l", "predicted_yield", | |
| "expression_score"): | |
| assert key not in r | |
| def test_the_result_names_what_it_does_not_cover(): | |
| """An assessment that looks complete is worse than one that lists its own | |
| blind spots β the user assumes the unchecked thing was checked.""" | |
| n = E.assess(ADAPTED, "e_coli")["not_covered"] | |
| assert "Shine-Dalgarno" in n | |
| assert "#38" in n and "#39" in n | |
| assert "assess_solubility" in n | |
| # ββ the threshold is derived, and the derivation is checkable ββββββββββββ | |
| def test_the_rare_cutoff_selects_the_codons_rosetta_strains_supply(): | |
| """w < 0.15 against the E. coli table selects AGA, AGG, ATA, CTA β exactly | |
| the set argU/ileY/leuW exist to supply. That is the evidence the cutoff is | |
| measuring something real rather than being a round number.""" | |
| selected = set(E.assess(ADAPTED, "e_coli")["rare_codons_in_this_host"]) | |
| assert {"AGA", "AGG", "ATA", "CTA"} <= selected | |
| def test_the_same_cutoff_finds_nothing_rare_in_human_and_says_so(): | |
| """Mammalian codon usage is much flatter. Manufacturing a warning to look | |
| thorough would be worse than the empty result.""" | |
| r = E.assess(ADAPTED, "human") | |
| assert r["rare_codons_in_this_host"] == [] | |
| assert r["rare_codon_count"] == 0 | |
| assert "nothing" in r["method"] | |
| def test_the_method_line_lists_the_selected_codons(): | |
| m = E.assess(ADAPTED, "e_coli")["method"] | |
| assert "Sharp & Li" in m | |
| assert str(E.RARE_BELOW) in m | |
| assert "AGA" in m | |
| # ββ rare codons and the runs that matter βββββββββββββββββββββββββββββββββ | |
| def test_an_adapted_sequence_is_clean(): | |
| r = E.assess(ADAPTED, "e_coli") | |
| assert r["rare_codon_count"] == 0 | |
| assert r["flags"] == [] | |
| assert r["codon_adaptation_index"] > 0.9 | |
| def test_rare_codons_lower_the_adaptation_index(): | |
| assert (E.assess(RARE_HEAVY, "e_coli")["codon_adaptation_index"] | |
| < E.assess(ADAPTED, "e_coli")["codon_adaptation_index"]) | |
| def test_consecutive_rare_codons_are_reported_as_a_run(): | |
| """The finding that changes what someone does. A scattered rare codon is | |
| absorbed; three in a row depletes the local charged-tRNA pool.""" | |
| r = E.assess(RARE_HEAVY, "e_coli") | |
| assert r["rare_codon_runs"] | |
| run = r["rare_codon_runs"][0] | |
| assert run["length"] >= E.RUN_LENGTH | |
| assert run["codons"] == ["AGA", "AGG", "ATA"] | |
| flag = [f for f in r["flags"] if "consecutive rare" in f["factor"]][0] | |
| assert "recoding just this run" in flag["why"] | |
| def test_scattered_rare_codons_do_not_form_a_run(): | |
| dna = "ATG" + ("AGA" + "CTGGCGAAAGATCTGGAA") * 6 + "TAA" | |
| r = E.assess(dna, "e_coli") | |
| assert r["rare_codon_count"] >= 6 | |
| assert r["rare_codon_runs"] == [] | |
| def test_the_five_prime_ramp_is_reported_separately(): | |
| """A rare codon at codon 5 costs more than the same codon at codon 400.""" | |
| r = E.assess(RARE_HEAVY, "e_coli") | |
| assert r["rare_in_ramp"] | |
| assert all(x["codon_number"] <= E.RAMP_CODONS for x in r["rare_in_ramp"]) | |
| def test_cai_excludes_single_codon_families(): | |
| """Met and Trp have no synonym to choose between. Including them only | |
| drags every score toward 1 and makes a bad sequence look adapted.""" | |
| only_mw = "ATG" + "ATGTGG" * 20 + "TAA" | |
| r = E.assess(only_mw, "e_coli") | |
| assert r["codon_adaptation_index"] is None or r["codon_adaptation_index"] > 0 | |
| def test_cai_does_not_underflow_on_a_long_cds(): | |
| """The direct product of hundreds of fractions underflows to 0.0 and | |
| silently reports a perfectly adapted gene as unadapted.""" | |
| long_cds = "ATG" + "AAACTGGCGCGTGAAGATCTGAAAGCGGTTCTGGAAAAC" * 60 + "TAA" | |
| cai = E.assess(long_cds, "e_coli")["codon_adaptation_index"] | |
| assert cai is not None and cai > 0.5 | |
| # ββ reading frame ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def test_an_internal_stop_is_flagged_as_a_truncated_product(): | |
| dna = "ATG" + "AAACTGGCG" * 4 + "TAA" + "AAACTGGCG" * 6 + "TAA" | |
| r = E.assess(dna, "e_coli") | |
| assert r["internal_stops"] | |
| flag = [f for f in r["flags"] if "internal stop" in f["factor"]][0] | |
| assert "truncated" in flag["why"] | |
| def test_a_missing_terminal_stop_is_flagged(): | |
| r = E.assess(ADAPTED[:-3], "e_coli") | |
| assert r["has_terminal_stop"] is False | |
| assert any("no terminal stop" in f["factor"] for f in r["flags"]) | |
| def test_an_out_of_frame_length_is_flagged_not_silently_truncated(): | |
| r = E.assess(ADAPTED + "AT", "e_coli") | |
| assert r["in_frame"] is False | |
| assert any("whole number of codons" in f["factor"] for f in r["flags"]) | |
| # ββ hosts ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def test_an_unknown_host_declines_instead_of_using_another_table(): | |
| """Scoring a plant construct against the E. coli table would produce | |
| confident nonsense. The refusal must read as missing data, not as the | |
| organism being unsupported.""" | |
| r = E.assess(ADAPTED, "plant") | |
| assert r["ok"] is False and r["kind"] == "no_codon_table" | |
| assert "missing data file, not an unsupported organism" in r["next"] | |
| def test_a_missing_host_is_refused_because_expression_is_host_specific(): | |
| assert E.assess(ADAPTED, "")["ok"] is False | |
| def test_every_known_host_alias_works(): | |
| for host in ("e_coli", "ecoli", "yeast", "s_cerevisiae", "human", "h_sapiens"): | |
| assert E.assess(ADAPTED, host)["ok"], host | |
| def test_the_same_sequence_scores_differently_per_host(): | |
| """The point of asking for a host. E. coli-optimised DNA is not | |
| human-optimised.""" | |
| a = E.assess(ADAPTED, "e_coli")["codon_adaptation_index"] | |
| b = E.assess(ADAPTED, "human")["codon_adaptation_index"] | |
| assert a != b | |
| def test_too_short_is_refused(): | |
| assert E.assess("ATGAAACTG", "e_coli")["kind"] == "too_short" | |
| # ββ the agent tool βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def test_the_tool_runs_and_needs_a_host(): | |
| from dee.core import agent_tools as t | |
| fn = t._TOOLS["assess_expression"]["fn"] | |
| assert fn({"dna": ADAPTED, "host": "e_coli"})["ok"] | |
| assert fn({"host": "e_coli"})["ok"] is False | |
| def test_the_tool_explains_that_protein_input_cannot_answer_this(): | |
| from dee.core import agent_tools as t | |
| err = t._TOOLS["assess_expression"]["fn"]({"host": "e_coli"})["error"] | |
| assert "reverse-translate" in err | |
| def test_the_spec_forbids_substituting_another_hosts_table(): | |
| from dee.core import agent_tools as t | |
| desc = next(s for s in t.TOOL_SPECS | |
| if s["function"]["name"] == "assess_expression")["function"]["description"] | |
| assert "never substitute another host's table" in desc | |
| assert "no_yield" in desc | |
| # No enum on host β a hardcoded organism list is the hardest gate to see. | |
| props = next(s for s in t.TOOL_SPECS | |
| if s["function"]["name"] == "assess_expression")["function"]["parameters"]["properties"] | |
| assert "enum" not in props["host"] | |