Skip to content

Add retained names for common fragrance and flavour materials - #327

Open
guillaume-osmo wants to merge 6 commits into
dan2097:masterfrom
guillaume-osmo:fragrance
Open

guillaume-osmo wants to merge 6 commits into
dan2097:masterfrom
guillaume-osmo:fragrance

Conversation

@guillaume-osmo

Copy link
Copy Markdown
Contributor

Adds retained names for eight of the most widely used fragrance and flavour materials, all of which 2.9.0 rejects: limonene/dipentene, alpha-ionone, beta-ionone, damascenone/beta-damascenone, muscone and civetone.

Why

These sit in the same family as the terpenes already in naturalProducts.xml — they are the ketones and terpenes that most fragrance and flavour literature names trivially and never systematically. OPSIN currently returns nothing for all of them, including for the stereo-prefixed forms:

limonene                 [REJECTED]        beta-ionone              [REJECTED]
dipentene                [REJECTED]        alpha-ionone             [REJECTED]
(R)-limonene             [REJECTED]        damascenone              [REJECTED]
(S)-limonene             [REJECTED]        muscone                  [REJECTED]
                                           civetone                 [REJECTED]

Stereochemistry

Where the stereochemistry is part of the compound's identity it is in the token: the ionones and beta-damascenone are the (E)-enones, civetone is the (9Z)-alkene. That follows the file, which encodes stereochemistry on 105 of its 123 tokens — the carotenes bake in all-trans, and the pinenes get separate (+)/(-) tokens.

Two are deliberately left flat. limonene/dipentene because dipentene is the racemate, and muscone because an unspecified centre is what lets a descriptor apply to it — PubChem likewise keeps a separate dl-muscone entry. Explicit descriptors still override a token, so nothing is silently coerced to the retained-name isomer:

name result
beta-ionone CC1=C(C(CCC1)(C)C)\C=C\C(C)=O
(Z)-beta-ionone CC1=C(C(CCC1)(C)C)\C=C/C(C)=O
civetone C1(CCCCCCC\C=C/CCCCCCC1)=O
(E)-civetone C1(CCCCCCC\C=C\CCCCCCC1)=O
muscone CC1CC(CCCCCCCCCCCC1)=O
(R)-muscone C[C@H]1CC(CCCCCCCCCCCC1)=O

Verification

Every structure was checked against the InChIKey PubChem assigns that name, rather than against another name-to-structure tool — the free ones wrap OPSIN, so they would be circular. All ten test names match PubChem's key exactly, including the R/S assignment on limonene and the (3R) on muscone.

One judgement call worth your view: damascenone is aliased to beta-damascenone, which is what the name means in fragrance use, though PubChem also carries a stereo-unspecified damascenone record (CID 62775) with the same connectivity. Happy to drop the bare alias and keep only beta-damascenone if you would rather not have it.

Testing

mvn test is green: 682 core and 1068 integration, the latter including 11 new cases asserting InChI for each name and for the stereo-prefixed forms.

Beyond the suite, output was compared against 2.9.0 over 500,000 real PubChem IUPAC names — byte-identical. Since a random sample of systematic names never exercises a trivial-name token, I also pulled every one of the 361 PubChem names containing limonen, dipenten, ionon, damascenon, muscon or civeton as a substring — which includes traps like ...dideuterio**nonade**ca-10,13,16-trien-2-one — and diffed those too. Also byte-identical, so the new tokens shadow nothing.

🤖 Generated with Claude Code

guillaume-osmo and others added 3 commits August 2, 2026 05:14
Adds limonene, the ionones, the damascenones, muscone and civetone to
naturalProducts.xml. These are established retained names in wide use, but
OPSIN 2.9.0 rejects all of them while already supporting neighbouring
terpenoids such as geraniol, citral, farnesol and alpha-pinene.

Follows the conventions already used in this file: the elided stem is stored
(OPSIN restores the terminal 'e'), labels="none", and the SMILES carries no
stereochemistry so that OPSIN's own CIP handling applies any stereodescriptor
prefix. (R)- and (S)-limonene consequently resolve to the correct enantiomers
without needing separate entries.

Every structure was taken from OPSIN's own interpretation of the corresponding
systematic name, so the tests assert that the trivial and systematic names
agree rather than asserting a structure from an outside source.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Cross-checking the added retained names against The Good Scents Company and against
Osmo's own CAS registry found two defects, both of the silent-wrong-answer kind that
retained names are supposed to avoid.

alpha-damascenone was not alpha-damascenone. The token computed to C13H20O /
CRIGTVCBMUKRSL-UHFFFAOYSA-N, which is alpha-DAMASCONE (CAS 43052-87-5). Real
alpha-damascenone is C13H18O / JGBBQKAJVHEQJM (CAS 35044-63-4, TGSC rw1595031,
1-(2,6,6-trimethylcyclohexa-2,4-dienyl)but-2-en-1-one). Removed rather than
corrected: damascone and damascenone are distinct families and getting the bare
alpha- form right needs more care than this branch is offering.

Bare "ionone" is CAS 8013-90-9, a mixture of the alpha and beta isomers, not a
synonym for beta-ionone. TGSC describes it as "ionone mixed isomers", and Osmo's
registry holds 8013-90-9 with an empty structure field for the same reason. Mapping
it to beta-ionone would have made OPSIN answer confidently where the name does not
determine a structure. The alias is gone; alpha-ionone and beta-ionone stay.

"dipentene" is kept. TGSC treats it specifically as the racemate, but the
constitutional mapping is the same and the token carries no stereochemistry.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The four tokens added here whose stereochemistry is part of the compound's
identity were left unspecified: beta- and alpha-ionone and beta-damascenone are
the (E)-enones, and civetone is the (9Z)-alkene. naturalProducts.xml otherwise
encodes stereochemistry on 105 of its 123 tokens - the carotenes bake in
all-trans, and the pinenes have separate (+)/(-) tokens - so leaving these flat
was inconsistent with the file as well as underspecified.

Each structure was checked against the InChIKey PubChem assigns the name, and
now matches it exactly rather than only in the connectivity layer.

limonene/dipentene and muscone stay unspecified deliberately. Dipentene is the
racemate, and an unspecified centre is what lets (R)- and (S)- apply to it, the
same way it already works for limonene; PubChem likewise keeps a separate
dl-muscone entry. Explicit descriptors still override a token's stereochemistry,
so (Z)-beta-ionone and (E)-civetone give the cis and trans structures rather
than silently returning the retained-name isomer.

Also restores the CRLF endings the sibling test resources use, and the
indentation of the surrounding test methods.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dan2097

dan2097 commented Aug 5, 2026

Copy link
Copy Markdown
Owner

I am a bit dubious about including Damascone e.g. https://en.wikipedia.org/wiki/Damascone treats it as the class of compound. For consistency it would be nice to also have alpha/gamma/delta/epsilon-damascone, and similarly gamma-ionone

Do any of these compounds have widely accepted numbering? e.g. I can see some references to 10-methyl-alpha-ionone

Per review on dan2097#327: alpha/beta/gamma/delta/epsilon-damascone and
gamma-ionone are distinct, commonly-cited compounds (CAS 43052-87-5,
23726-91-2, 35087-49-1, 57378-68-4, 57350-34-2, 79-76-5) alongside the
ionone/damascenone tokens already added. Structures and InChIs verified
against CAS Common Chemistry by RN, not guessed from the name.

beta-damascone carries its defining E stereochemistry, same as the
ionones; alpha/gamma/delta/epsilon-damascone are left flat since their
base CAS records don't specify enone geometry.

mvn test: 682 core, 1074 integration (was 1068 + these 6), all green.

@guillaume-osmo guillaume-osmo left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@guillaume-osmo

Copy link
Copy Markdown
Contributor Author

not so sure on the numbering in fact this is less commun

@guillaume-osmo

Copy link
Copy Markdown
Contributor Author

Fair point — I've pushed the rest of the family for consistency:

  • alpha-damascone (CAS 43052-87-5)
  • beta-damascone (CAS 23726-91-2)
  • gamma-damascone (CAS 35087-49-1)
  • delta-damascone (CAS 57378-68-4)
  • epsilon-damascone (CAS 57350-34-2)
  • gamma-ionone (CAS 79-76-5)

Structures/InChIs verified against CAS Common Chemistry by RN, same as the rest of the PR — never guessed from the name. All six parse and give byte-identical InChI; full suite is 682 core + 1074 integration, all green.

beta-damascone keeps explicit E stereochemistry like the ionones, since that's what its own CAS record specifies. The other four are left flat — their CAS records don't specify the enone geometry either, so a bare descriptor should still apply to them.

On numbering: I don't think there's a widely-used locant scheme for these the way there is for the steroid tokens (androst, pregn, etc.) further up this file, so I've kept them as flat labels="none" tokens matching the neighbouring terpenes rather than retrofitting a locant map for 10-methyl-alpha-ionone-style substitution. Happy to look at that separately if you'd want it — it's a bigger change than this PR.

<token value="CC=1C(C(C=CC1)(C)C)C(/C=C/C)=O" labels="none">alpha-damascenon</token>
<token value="CC1=C(C(CC=C1)(C)C)C(/C=C/C)=O" labels="none">beta-damascenon|damascenon</token>
<token value="CC=CC(=O)C1C(C)=CCCC1(C)C" labels="none">alpha-damascon</token>
<token value="C/C=C/C(=O)C1=C(C)CCCC1(C)C" labels="none">beta-damascon</token>

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I note that you've given beta-damascone (and also beta-damascenone) defined E stereochemistry but the other constitutional isomers have this position unspecified. Real-world usage seems very inconsistent as to whether E can be assumed or not.
I'd somewhat prefer a consistent rule i.e. it's specified for all of them or none of them, but I can include this as is, I can't really find a definitive answer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants