| from importlib.util import module_from_spec, spec_from_file_location |
| from pathlib import Path |
|
|
| from pino.registry import AromaRegistry |
|
|
|
|
| PATH = Path(__file__).parents[1] / "scripts" / "build_genre_challenge_v2.py" |
| SPEC = spec_from_file_location("build_genre_challenge_v2", PATH) |
| MODULE = module_from_spec(SPEC) |
| assert SPEC.loader |
| SPEC.loader.exec_module(MODULE) |
|
|
|
|
| def record(genre, components): |
| return {"genre": genre, "formula": components} |
|
|
|
|
| def component(cas, smiles=None, weight=0.5): |
| if smiles is None: |
| smiles = {"a": "CC", "b": "CCC", "c": "CCCC", "d": "CCCCC", "e": "CCCCCC", "f": "CCCCCCC", "g": "CCCCCCCC"}.get(cas, "CCO") |
| return {"cas": cas, "smiles": smiles, "weight_fraction": weight} |
|
|
|
|
| def test_characterize_excludes_solvent_and_requires_valid_single_fragment_smiles(): |
| row = record("fougere", [component("64-17-5", weight=0.2), component("a"), component("b")]) |
| result = MODULE.characterize(row, 7) |
| assert result["active_count"] == 2 |
| assert result["structurally_valid"] is True |
| assert result["source_index"] == 7 |
|
|
| invalid = MODULE.characterize(record("fougere", [component("a", "not-smiles"), component("b")]), 8) |
| assert invalid["structurally_valid"] is False |
|
|
|
|
| def test_composition_match_enforces_size_concentration_and_identity_calipers(): |
| base = MODULE.characterize(record("fougere", [component("a"), component("b")]), 0) |
| matched = MODULE.characterize(record("floral_woody", [component("c"), component("d")]), 1) |
| overlap = MODULE.characterize(record("floral_woody", [component("a"), component("d")]), 2) |
| singleton = MODULE.characterize(record("floral_woody", [component("c", weight=1.0)]), 3) |
| assert MODULE.composition_match(base, matched) |
| assert not MODULE.composition_match(base, overlap) |
| assert not MODULE.composition_match(base, singleton) |
|
|
|
|
| def test_census_keeps_wildcard_out_of_primary_pool(): |
| rows = [ |
| record("fougere", [component("a"), component("b")]), |
| record("floral_woody", [component("c"), component("d")]), |
| record("wildcard", [component("e"), component("f")]), |
| record("wildcard", [component("g", weight=1.0)]), |
| ] |
| result = MODULE.census(rows) |
| assert result["per_substantive_genre"]["fougere"]["composition_matchable"] == 1 |
| assert result["wildcard_open_set_pool"] == { |
| "multi_component_structurally_valid": 1, |
| "singleton_sanity_check": 1, |
| } |
|
|
|
|
| def test_characterize_resolves_cas_smiles_keys_expands_naturals_and_aggregates(tmp_path): |
| registry = AromaRegistry(tmp_path / "registry.db") |
| registry.add({"cas": "5989-27-5", "name": "limonene", "smiles": "CC1=CCC(CC1)C(=C)C"}) |
| registry.add({"cas": "123-35-3", "name": "myrcene", "smiles": "CC(=CCCC(=C)C=C)C"}) |
| row = record("citrus_cologne", [ |
| component("NATURAL:8008-57-9", smiles="", weight=0.5), |
| component("SMILES:CCO", smiles="", weight=0.25), |
| component("5989-27-5", smiles="", weight=0.25), |
| ]) |
| result = MODULE.characterize(row, 0, registry) |
| registry.close() |
| assert result["structurally_valid"] is True |
| assert result["active_count"] == 3 |
| assert result["unresolved_identifiers"] == [] |
| assert len(result["ingredients"]) == 3 |
|
|
|
|
| def test_characterize_reports_unresolved_identifier(tmp_path): |
| with AromaRegistry(tmp_path / "registry.db") as registry: |
| result = MODULE.characterize(record("fougere", [component("unknown", smiles="")]), 0, registry) |
| assert result["structurally_valid"] is False |
| assert result["unresolved_identifiers"] == ["unknown"] |
|
|
|
|
| def test_duplicate_collapse_is_order_independent_and_conservative(): |
| rows = [] |
| for index, weights in enumerate(((.5, .5), (.51, .49), (.8, .2))): |
| result = MODULE.characterize(record("fougere", [ |
| component("a", weight=weights[0]), component("b", weight=weights[1])]), index) |
| result["resolved_components"], _ = MODULE.resolved_active_components(record("fougere", [ |
| component("b", weight=weights[1]), component("a", weight=weights[0])])) |
| rows.append(result) |
| kept, audit = MODULE.collapse_duplicates(rows) |
| assert [row["source_index"] for row in kept] == [0, 2] |
| assert audit["collapsed_records"] == 1 |
|
|
|
|
| def test_natural_weight_share_uses_pre_expansion_formula_weight(): |
| row = record("citrus_cologne", [ |
| component("NATURAL:8008-57-9", smiles="", weight=.25), |
| component("SMILES:CCO", smiles="", weight=.75), |
| ]) |
| assert MODULE.natural_weight_share(row) == .25 |
|
|