from __future__ import annotations """ Standard fragrance materials with known CAS/SMILES for registry expansion. Why this module exists: - The SQLite registry is sparse; real formulas (like the one in data/formulas/matthew_tea_woods.json) contain many well-known materials that are not yet registered. - This file maps common trade names to canonical identifiers (CAS or SMILES) so the importer can resolve them without web lookups every time. - It is a stepping stone toward a richer, thermodynamically-validated registry. """ from typing import Any # --------------------------------------------------------------------------- # Trade name -> canonical identifier (CAS preferred, SMILES fallback). # Many materials are listed by their primary CAS or a representative isomer. # --------------------------------------------------------------------------- MATERIALS: dict[str, dict[str, Any]] = { # Hedione family "Hedione HC": {"cas": "24851-98-7", "name": "Methyl dihydrojasmonate (Hedione HC)", "smiles": "CC1C(=O)CC[C@H](C)C1CC=CC(=O)OC"}, "MDJ": {"cas": "24851-98-7", "name": "Methyl dihydrojasmonate (MDJ)", "smiles": "CC1C(=O)CC[C@H](C)C1CC=CC(=O)OC"}, "Hedione HC / MDJ": {"cas": "24851-98-7", "name": "Methyl dihydrojasmonate (Hedione HC / MDJ)", "smiles": "CC1C(=O)CC[C@H](C)C1CC=CC(=O)OC"}, "Methyl dihydrojasmonate": {"cas": "24851-98-7", "name": "Methyl dihydrojasmonate", "smiles": "CC1C(=O)CC[C@H](C)C1CC=CC(=O)OC"}, # Iso E Super / Timbersilk "Iso E Super": {"cas": "54452-50-3", "name": "Iso E Super (OTNE)", "smiles": "CC(C)C1CCC(C)CC1CC(C)C=O"}, "OTNE": {"cas": "54452-50-3", "name": "Iso E Super (OTNE)", "smiles": "CC(C)C1CCC(C)CC1CC(C)C=O"}, "Iso E Super / OTNE": {"cas": "54452-50-3", "name": "Iso E Super (OTNE)", "smiles": "CC(C)C1CCC(C)CC1CC(C)C=O"}, "Iso Myrcetone Gamma": {"cas": "68039-33-4", "name": "Iso Myrcetone gamma", "smiles": "CC(C)=CCCC(C)C1CC=C(C)CC1"}, "Timbersilk": {"cas": "68039-33-4", "name": "Timbersilk (Iso Myrcetone gamma)", "smiles": "CC(C)=CCCC(C)C1CC=C(C)CC1"}, "Iso Myrcetone Gamma / Timbersilk": {"cas": "68039-33-4", "name": "Timbersilk (Iso Myrcetone gamma)", "smiles": "CC(C)=CCCC(C)C1CC=C(C)CC1"}, # Damascones "Beta-damascone": {"cas": "23726-91-2", "name": "Beta-damascone", "smiles": "CC(=O)/C=C/C1C(C)=CCCC1(C)C"}, "Beta-damascenone": {"cas": "23696-85-7", "name": "Beta-damascenone", "smiles": "CC(=O)/C=C/C1C(C)=CCCC1(C)C"}, "Beta-damascone / beta-damascenone 1%": {"cas": "23696-85-7", "name": "Beta-damascenone 1%", "smiles": "CC(=O)/C=C/C1C(C)=CCCC1(C)C"}, "Beta-damascone / beta-damascenone": {"cas": "23696-85-7", "name": "Beta-damascenone", "smiles": "CC(=O)/C=C/C1C(C)=CCCC1(C)C"}, # Musks / lactones "Ambrettolide": {"cas": "142-62-3", "name": "Ambrettolide", "smiles": "O=C1CCCCCCCCCCCO1"}, "Habanolide": {"cas": "111-79-5", "name": "Habanolide", "smiles": "O=C1CCCCCCCCCO1"}, "Ambroxan": {"cas": "6790-58-9", "name": "Ambroxan", "smiles": "C[C@]12CC[C@@H](CC1=O)C(C)(C)C2"}, "Ambroxan 10%": {"cas": "6790-58-9", "name": "Ambroxan 10%", "smiles": "C[C@]12CC[C@@H](CC1=O)C(C)(C)C2"}, # Ionones "Methyl Ionone Gamma": {"cas": "127-42-4", "name": "Methyl ionone gamma", "smiles": "CC(=O)/C=C/C1C(C)=CCCC1(C)C"}, "Ionone Beta": {"cas": "14901-07-6", "name": "Ionone beta", "smiles": "CC(=O)/C=C/C1C(C)=CCCC1(C)C"}, "Dihydro Ionone Beta": {"cas": "17283-81-7", "name": "Dihydro ionone beta", "smiles": "CC(=O)CCC1C(C)=CCCC1(C)C"}, # Orris / naturals "Orris butter": {"cas": "8002-73-1", "name": "Orris butter", "smiles": "CC(=O)/C=C/C1C(C)=CCCC1(C)C"}, # proxy: ionone "Orris CO2 10%": {"cas": "8002-73-1", "name": "Orris CO2 10%", "smiles": "CC(=O)/C=C/C1C(C)=CCCC1(C)C"}, # Vetiver / cedar "Vetiveryl acetate": {"cas": "117-98-6", "name": "Vetiveryl acetate", "smiles": "CC(=O)OC1CC2CCC(C)C(C)C2C1"}, "Vetiver Haiti 10%": {"cas": "8022-68-4", "name": "Vetiver Haiti 10%", "smiles": "CC1=CCC2C(C)C(C)CCC2C1"}, "Cedarwood Virginia": {"cas": "8000-27-9", "name": "Cedarwood Virginia", "smiles": "CC1=CCC2C(C)C(C)CCC2C1"}, "Cedarwood Texas": {"cas": "8000-27-9", "name": "Cedarwood Texas", "smiles": "CC1=CCC2C(C)C(C)CCC2C1"}, # Green / leafy "Cis-3-hexenyl salicylate": {"cas": "65405-77-8", "name": "cis-3-Hexenyl salicylate", "smiles": "O=C(Oc1ccccc1O)C/C=C/CC"}, "Cis-3-hexenol": {"cas": "928-96-1", "name": "cis-3-Hexenol", "smiles": "CC/C=C/CCO"}, "Cis-3-hexenol 1%": {"cas": "928-96-1", "name": "cis-3-Hexenol 1%", "smiles": "CC/C=C/CCO"}, # Other common materials "Coumarin": {"cas": "91-64-5", "name": "Coumarin", "smiles": "O=c1ccc2ccccc2o1"}, "Coumarin 10%": {"cas": "91-64-5", "name": "Coumarin 10%", "smiles": "O=c1ccc2ccccc2o1"}, "Fumaric acid": {"cas": "110-17-8", "name": "Fumaric acid", "smiles": "O=C(O)/C=C/C(=O)O"}, "Cinnamyl alcohol": {"cas": "104-54-1", "name": "Cinnamyl alcohol", "smiles": "OC/C=C/c1ccccc1"}, "Sorbic acid": {"cas": "110-44-1", "name": "Sorbic acid", "smiles": "CC=CC=CC(=O)O"}, "Tetrahydroquinoline": {"cas": "119-64-2", "name": "Tetrahydroquinoline", "smiles": "c1ccc2c(c1)NCCC2"}, "Estragole": {"cas": "140-67-0", "name": "Estragole", "smiles": "COc1ccc(CC=C)cc1"}, "Linalool oxide": {"cas": "674-86-6", "name": "Linalool oxide", "smiles": "CC1(C)CC=C(CO)CC1"}, "Geraniol": {"cas": "106-24-1", "name": "Geraniol", "smiles": "CC(C)=CCC/C(C)=C/CO"}, "Geraniol 10%": {"cas": "106-24-1", "name": "Geraniol 10%", "smiles": "CC(C)=CCC/C(C)=C/CO"}, "Citral": {"cas": "5392-40-5", "name": "Citral", "smiles": "CC(C)=CCCC(C)=CC=O"}, "Citral 10%": {"cas": "5392-40-5", "name": "Citral 10%", "smiles": "CC(C)=CCCC(C)=CC=O"}, "alpha-Pinene": {"cas": "80-56-8", "name": "alpha-Pinene", "smiles": "CC1=CCC2CC1C2(C)C"}, "beta-Pinene": {"cas": "127-91-3", "name": "beta-Pinene", "smiles": "CC1=CCC2CC1C2(C)C"}, "Gamma-terpinene": {"cas": "99-85-4", "name": "Gamma-terpinene", "smiles": "CC1=CC=C(C(C)C)CC1"}, "Linalool": {"cas": "78-70-6", "name": "Linalool", "smiles": "CC(C)=CCCC(C)(O)C=C"}, "Nerol": {"cas": "106-25-2", "name": "Nerol", "smiles": "CC(C)=CCC/C(C)=C\CO"}, "d-Limonene": {"cas": "5989-27-5", "name": "d-Limonene", "smiles": "CC1=CC[C@@H](CC1)C(=C)C"}, "Anthranilic acid": {"cas": "89-43-0", "name": "Anthranilic acid", "smiles": "Nc1ccccc1C(=O)O"}, "cis-3-Hexenol": {"cas": "928-96-1", "name": "cis-3-Hexenol", "smiles": "CC/C=C/CCO"}, "cis-3-Hexenyl acetate": {"cas": "928-97-2", "name": "cis-3-Hexenyl acetate", "smiles": "CC(=O)OCC/C=C/CC"}, "Terpinen-4-ol": {"cas": "99-85-4", "name": "Terpinen-4-ol", "smiles": "CC1=CCC(C(C)(C)O)CC1"}, "Ethyl vanillin": {"cas": "121-34-6", "name": "Ethyl vanillin", "smiles": "CCOc1cc(C=O)ccc1O"}, "Methyl salicylate": {"cas": "119-36-8", "name": "Methyl salicylate", "smiles": "COC(=O)c1ccccc1O"}, "Benzyl salicylate": {"cas": "118-58-1", "name": "Benzyl salicylate", "smiles": "O=C(Oc1ccccc1)c2ccccc2O"}, "Nerolidol": {"cas": "7212-44-4", "name": "Nerolidol", "smiles": "CC(C)=CCCC(C)=CCCO"}, "Farnesol": {"cas": "4602-84-0", "name": "Farnesol", "smiles": "CC(C)=CCCC(C)=CCCO"}, "Neral": {"cas": "106-26-3", "name": "Neral", "smiles": "CC(C)=CCC/C(C)=C/C=O"}, "Guaiacol": {"cas": "90-05-1", "name": "Guaiacol", "smiles": "COc1ccccc1O"}, "Beta-thujone": {"cas": "89-86-1", "name": "Beta-thujone", "smiles": "CC1(C)C(=O)C2(C)CCC1C2"}, "Menthol": {"cas": "89-78-1", "name": "Menthol", "smiles": "CC(C)C1CCC(C)CC1O"}, "Cedrol": {"cas": "77-53-2", "name": "Cedrol", "smiles": "CC1(C)C2CCC3(C)C(C)(C)CCC3(C)C2C1"}, "Cedrene": {"cas": "469-01-2", "name": "Cedrene", "smiles": "CC1=CCC2C(C)C3CCC(C)C3CC2C1"}, "Cedryl acetate": {"cas": "5986-38-9", "name": "Cedryl acetate", "smiles": "CC(=O)OC1C(C)C2CCC(C)C2C1(C)C"}, "cis-3-Hexenyl salicylate": {"cas": "65405-77-8", "name": "cis-3-Hexenyl salicylate", "smiles": "O=C(OCCCC/C=C/CC)c1ccccc1O"}, # Common naturals and bases handled by accords.py "Beta-damascenone": {"cas": "23696-85-7", "name": "Beta-damascenone", "smiles": "CC(=O)/C=C/C1C(C)=CCCC1(C)C"}, "Methyl salicylate 10%": {"cas": "119-36-8", "name": "Methyl salicylate 10%", "smiles": "COC(=O)c1ccccc1O"}, # Common naturals and bases handled by accords.py "Green Tea Base": {"accord": "green_tea"}, "Tea Black Base": {"accord": "black_tea"}, "Tea Black Base 10%": {"accord": "black_tea"}, "Mate absolute": {"accord": "mate"}, "Mate absolute 10%": {"accord": "mate"}, "Orris butter / orris CO2 10%": {"accord": "orris"}, "Vetiver Haiti 10%": {"accord": "vetiver"}, "Cedarwood Virginia/Texas": {"accord": "cedarwood"}, } def resolve_material(name: str) -> dict[str, Any] | None: """Return the canonical identifier(s) for a trade name, if known.""" return MATERIALS.get(name) def is_accord(name: str) -> bool: """Return True if this material is a proprietary base we expand via accords.""" rec = MATERIALS.get(name) return rec is not None and "accord" in rec def all_material_names() -> list[str]: return list(MATERIALS.keys())