| """
|
| 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 = {
|
| "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 = {
|
| "28": "br28", "br-28": "br28", "29": "br29", "br-29": "br29",
|
| "chinigura": "chinigura", "polao (chinigura)": "chinigura",
|
| "miniket": "miniket", "mozammel-miniket": "miniket",
|
| }
|
|
|
| FUZZY = {
|
| "pyzam": "paijam", "paijam": "paijam",
|
| "utsob nazir": "nazir", "najirshail": "nazir", "katari nazir": "nazir",
|
| }
|
|
|
| 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
|
|
|
|
|
| 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"]
|
| 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}")
|
|
|
| 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.")
|
|
|