""" analyze_rice_overlap.py — resolve the P2 rice go/no-go gate ON PAPER (no images). The rice cross-source benchmark hinges on whether varieties overlap across sources of different acquisition style — especially whether the only genuinely IN-THE-WILD set (D5 BDRice) shares varieties with the studio/microscope sets. Overlap is a NAME-mapping question, so we can answer it now from the variety lists in outputs/recon_rice.md, before downloading anything. Variety lists verified by the rice-data scout (outputs/recon_rice.md, 2026-06-22). Edit CONFIDENT / FUZZY as the manual mapping table (rice analog of spice class normalization). This file IS the seed of outputs/rice_class_map. python analyze_rice_overlap.py """ from itertools import combinations ACQ = { # acquisition style per source (the axis ARC-V tests) "D2_aruzz": "studio", "D4_riceseed": "studio", "D5_bdrice": "WILD", "D6_prbd": "microscope", "D1_koklu": "studio(TR)", } VARIETIES = { "D1_koklu": ["Arborio", "Basmati", "Ipsala", "Jasmine", "Karacadag"], "D2_aruzz": ["Subol Lota", "Bashmoti (Deshi)", "Ganjiya", "Shampakatari", "Sugandhi Katarivog", "BR-28", "BR-29", "Paijam", "Bashful", "Lal Aush", "BR-Jirashail", "Gutisharna", "Birui", "Najirshail", "Pahari Birui", "Polao (Katari)", "Polao (Chinigura)", "Amon", "Shorna-5", "Lal Binni"], "D4_riceseed": ["25", "28", "29", "89", "100", "Chinigura", "Kata Irri", "Kata Irri Vog"], "D5_bdrice": ["Haski", "Nabil", "Mozumder", "Utsob Nazir", "Mizan", "Atash", "Pyzam", "Mozammel-Miniket"], "D6_prbd": ["Aush", "Beroi", "BR-28", "BR-29", "Ghee Bhog", "Katari Nazir", "Katari Siddho", "Swarna", "Miniket", "Chinigura"], } # CONFIDENT: documented same cultivar (datasheets / standard BD nomenclature). CONFIDENT = { "28": "br28", "br-28": "br28", "29": "br29", "br-29": "br29", "chinigura": "chinigura", "polao (chinigura)": "chinigura", "miniket": "miniket", "mozammel-miniket": "miniket", # brand 'X-Miniket' = Miniket grade } # FUZZY: plausible same cultivar pending datasheet/photo check (spelling/brand variants). FUZZY = { "pyzam": "paijam", "paijam": "paijam", # Pyzam/Pajam/Paijam spelling variants "utsob nazir": "nazir", "najirshail": "nazir", "katari nazir": "nazir", } # D5 (wild) brand names with UNKNOWN underlying cultivar — these gate extra overlap. UNRESOLVED_D5 = ["Haski", "Nabil", "Mozumder", "Mizan", "Atash"] def norm(raw, fuzzy): k = raw.strip().lower() if k in CONFIDENT: return CONFIDENT[k] if fuzzy and k in FUZZY: return FUZZY[k] return k # unmapped -> stays distinct def canon(src, fuzzy): return {norm(v, fuzzy) for v in VARIETIES[src]} def report(fuzzy): tag = "CONFIDENT+FUZZY" if fuzzy else "CONFIDENT-only" print(f"\n{'='*66}\n OVERLAP [{tag}]\n{'='*66}") bd = ["D2_aruzz", "D4_riceseed", "D6_prbd"] # the studio+microscope BD core core = set.intersection(*[canon(s, fuzzy) for s in bd]) print(f" studio+microscope core ∩(D2,D4,D6) = {sorted(core)} (n={len(core)})") studio_micro_union = set().union(*[canon(s, fuzzy) for s in bd]) d5 = canon("D5_bdrice", fuzzy) wild_overlap = d5 & studio_micro_union print(f" WILD (D5) ∩ (D2∪D4∪D6) = {sorted(wild_overlap)} (n={len(wild_overlap)}) <-- the headline gate") for tok in sorted(wild_overlap): where = [s for s in bd if tok in canon(s, fuzzy)] d5raw = [v for v in VARIETIES["D5_bdrice"] if norm(v, fuzzy) == tok] print(f" {tok:10s}: D5{d5raw} ↔ {where}") # specifically D5 vs each studio set (the true studio-vs-wild contrast) for s in ("D2_aruzz", "D4_riceseed"): ov = d5 & canon(s, fuzzy) print(f" WILD (D5) ∩ {s} [{ACQ[s]}] = {sorted(ov)} (n={len(ov)})") if __name__ == "__main__": print("Rice cross-source variety-overlap analysis (names only; no images)") print("acquisition styles:", ACQ) for fuzzy in (False, True): report(fuzzy) print(f"\n{'='*66}") print("GATE: extra D5(wild) overlap is hidden behind these unmapped brand names") print(f" -> resolve via the BDRice datasheet/paper, NOT pixels: {UNRESOLVED_D5}") print("If >=2 of these map to BR-28/BR-29/Chinigura, the studio-vs-wild") print("headline (>=3 shared, wild vs studio) is fully viable.")