|
| 1 | +# Methods, Rules & Heuristics |
| 2 | + |
| 3 | +Every non-obvious rule, threshold, and trick Flavormancer uses — with its rationale and |
| 4 | +its ceiling. The discipline throughout: each output is tagged by **how** it's derived, |
| 5 | +and a rule is used only where it's *more honest* than a model. Companion to |
| 6 | +[`CAPABILITIES.md`](CAPABILITIES.md) (what it does) and [`SOURCES.md`](SOURCES.md) (the data). |
| 7 | + |
| 8 | +**Confidence tiers:** `computed` (exact from structure) · `trained` (ML on open data) · |
| 9 | +`rule` (deterministic structural rule) · `estimate` (published QSPR, known error) · |
| 10 | +`lookup` (loaded reference table) · `qualitative` (a class/flag, not a number). |
| 11 | + |
| 12 | +--- |
| 13 | + |
| 14 | +## Taste |
| 15 | +- **Sweet / bitter / umami** — `trained`. RandomForest on 2048-bit Morgan radius-2 fingerprints. |
| 16 | +- **Sweetness intensity** — `trained`, est. RandomForest regressor on **log₁₀(relative-to-sucrose)** |
| 17 | + sweetness (SweetenersDB). Shown as a multiplier (10^value). **Gate:** displayed only when |
| 18 | + sweet ≥ 0.5 **and logP < 2** — sweeteners are hydrophilic, so the logP cutoff suppresses |
| 19 | + lipophilic false-positives (the classifier wrongly calling limonene "sweet") while keeping |
| 20 | + real sweeteners (sugars, aspartame). Tagged "(est.)"; the value is the model's, not literature. |
| 21 | +- **Sour** — `rule`. SMARTS for acidic groups (carboxylic / sulfonic / phosphonic) matching |
| 22 | + **both protonated and deprotonated** forms (this lifted recall 0.57 → 0.93). Sourness is a |
| 23 | + solution/pH property, so a structural proxy is the honest move, not a per-molecule ML target. |
| 24 | +- **Salty** — `rule`. Fires only for a salt-forming cation (alkali metal Li/Na/K/Rb/Cs or |
| 25 | + ammonium) **+ a simple INORGANIC anion**. **Defers** when the anion carries carbon — so MSG |
| 26 | + (umami), Na-saccharin (sweet), Na-benzoate (preservative) are NOT called salty. Refuses the |
| 27 | + naive "has sodium → salty" mistake. |
| 28 | +- **Known-taste override** — `lookup`. A verified dataset label beats the rule/model and is |
| 29 | + marked "verified." |
| 30 | +- **taste_profile / multitaste** — trained heads ranked by probability; multitaste flag when ≥2 fire. |
| 31 | + |
| 32 | +## Applicability domain |
| 33 | +- **No-carbon → out of domain.** The trained taste/tox heads are fit on *organic* molecules; |
| 34 | + for carbon-free inputs (water, O₂, N₂, NaCl) their output is meaningless, so the UI suppresses |
| 35 | + them with a banner. Rules (sour/salty), structure, and computed properties stay valid. |
| 36 | + |
| 37 | +## Physicochemical |
| 38 | +- **logP / MW / TPSA / H-bond donors-acceptors / rings / heavy atoms** — `computed` (RDKit, exact). |
| 39 | +- **Water solubility, logS** — `estimate` (ESOL, Delaney 2004; ~0.7 log RMSE). |
| 40 | +- **Volatility tier** — `qualitative`. Heuristic from MW + H-bond donors + TPSA → top/middle/base note. |
| 41 | +- **Boiling point / vapor pressure** — `lookup`. Measured values from PubChem (public domain). |
| 42 | + **Structure-based BP (Joback) was evaluated and rejected** (33 °C mean / 89 °C max error across |
| 43 | + 12 flavor molecules). The BP parser **prefers atmospheric (~760 mmHg) readings**; when only |
| 44 | + reduced/elevated-pressure data exists it reports the value **with its pressure**, not a bare |
| 45 | + misleading number. |
| 46 | +- **pKa** — `qualitative`. Typical ranges for detected ionizable groups, not a per-molecule value. |
| 47 | + |
| 48 | +## Stability |
| 49 | +- **Oxidation / hydrolysis / photo watch-flags** — `rule`/`qualitative`. SMARTS for reactive |
| 50 | + motifs (e.g. phenol/aldehyde → oxidation). "Watch for," not a shelf-life prediction. |
| 51 | + |
| 52 | +## Chemesthesis (trigeminal — a dimension beyond taste) |
| 53 | +- **Cooling / pungent / astringent** — `rule`/`lookup`. SMARTS (isothiocyanate → pungent; |
| 54 | + ≥3 phenols → astringent) + InChIKey lookups (menthol → cooling/TRPM8; capsaicin & piperine → |
| 55 | + pungent/TRPV1). |
| 56 | + |
| 57 | +## Safety (all defensive, caution-only — never a clearance) |
| 58 | +- **Structural tox-alerts** — `rule`. A SMALL curated SMARTS set: aromatic nitro, N-nitroso, |
| 59 | + aromatic azo, epoxide. Deliberately limited to motifs **rare in the GRAS flavor palette** to |
| 60 | + avoid alert fatigue — we do NOT flag aldehydes or Michael acceptors (too many GRAS flavors |
| 61 | + carry them). Prompts for review; **not a comprehensive carcinogen detector** (e.g. furan isn't flagged). |
| 62 | +- **GRAS / food-use cross-check** — `lookup`. InChIKey-skeleton match against FDA "Substances |
| 63 | + Added to Food" (public domain). |
| 64 | +- **TTC / Cramer tier** — `qualitative`. Preliminary concern tier; Toxtree for the validated call. |
| 65 | +- **Tox21 assay flags** — `trained`, caution-only. 12 RandomForest heads (genotoxic-stress, AhR, |
| 66 | + mitochondrial, endocrine); flagged at probability ≥ 0.5; indicative in-vitro signals, never a |
| 67 | + determination. Suppressed for out-of-domain molecules. |
| 68 | +- **EU declarable-allergen labeling** — `lookup`. InChIKey match against a curated EU allergen subset. |
| 69 | + |
| 70 | +## Mixtures |
| 71 | +- **check_mixture** — `lookup`/`rule`. Detect molecular **roles** (benzoate, nitrite, secondary |
| 72 | + amine, urea, ascorbate, ethanol, asparagine, citrulline, reducing sugar, …) via SMARTS + |
| 73 | + InChIKey, then fire **documented** precursor→product hazards (benzene, nitrosamine, ethyl |
| 74 | + carbamate, acrylamide, furan, 3-MCPD, 4-MEI, biogenic amines) when the required roles co-occur, |
| 75 | + **gated on declared process** (high heat / refining / fermentation) → active vs conditional. |
| 76 | + A **curated documented-hazard screen, NOT a reaction predictor** — and precise: it distinguishes |
| 77 | + **nitrite** (forms nitrosamines) from **nitrate** (does not). |
| 78 | +- **Palette match** — `rule`. Jaccard similarity over the 5-basic-taste label sets: union the |
| 79 | + mixture's ingredient tastes, find single labeled molecules with the closest set. NOT blend |
| 80 | + perception — a blend ≠ the sum of its parts (suppression/synergy needs formulation data). |
| 81 | + |
| 82 | +## Search & resolution |
| 83 | +- **Substitution** — Tanimoto over Morgan fingerprints (self excluded), each neighbor with its known tastes. |
| 84 | +- **Names / structure** — PubChem name/CAS→SMILES resolution; common (Title) + IUPAC names (cached); |
| 85 | + RDKit 2D depiction (graceful without libXrender); typeahead over the curated flavor-volatile list. |
| 86 | + |
| 87 | +--- |
| 88 | + |
| 89 | +## The honest ceiling on "deeper flavor description" |
| 90 | +Taste tops out at the **5 basics + intensity + chemesthesis** on public data. The rich |
| 91 | +descriptors people mean by "flavor" — *vanilla, fruity, green, woody, minty, caramel…* — are |
| 92 | +**aroma**, not taste: a separate odor model that needs expert-labeled odor data (licensed or |
| 93 | +customer; deferred — see [`AROMA.md`](AROMA.md)). That model is the real route to deeper flavor |
| 94 | +language, and it's exactly the "comes with your data" piece. |
0 commit comments