Declines#
When Orthonym cannot name a molecule, it says so, and what it says is not a name. The plain call returns the empty string and logs the reason, a limit code and a label, as one warning on the orthonym logger. The command line prints an empty name, and the reason on the error stream:
$ orthonym "O=[U](=O)=O"
O=[U](=O)=O UNSUPPORTED_ELEMENT: inorganic compound (not supported)
The first line is the (empty) name on the normal output, the second the reason on the error stream. --on-failure label (on_failure="label" in Python) prints and returns the label in place of a name, such as inorganic compound (not supported), as earlier versions did; --on-failure raise (on_failure="raise") stops with an error. The provenance row marks the row abstain with a reason code in limit_code:
$ orthonym "O=[U](=O)=O" --provenance | python -m json.tool
OPSIN validity gate suppressed unparseable name: 'unknown'
{
"name": "inorganic compound (not supported)",
"tier": "abstain",
"is_pin": false,
"source": "abstain",
"opsin": "n/a",
"gates_passed": [],
"gate_outcome": "suppressed",
"formula": "O3U",
"limit_code": "UNSUPPORTED_ELEMENT",
"stereo_unexpressed": false,
"suffix_free_prefix_name": false,
"prefix_order_fallback": false,
"verified": "unverified",
"spelling_failures": [],
"producer": null
}
The first line is a log message on the error stream: the engine withdrew a candidate that OPSIN could not read. The JSON row is on the normal output. producer is null: no name ships, so no code is named (Which code built the name).
The reason codes#
|
Label ( |
When |
|---|---|---|
|
|
an element outside the ones the rules cover, or a compound of a metal that is not admitted to the naming mechanisms and that no general producer names (Metal compounds) |
|
|
the structure has a |
|
|
an unnamed structure with more than 125 heavy atoms: a label given after the attempt, since the engine sets no size limit and attempts every input |
|
|
a single heavy atom |
|
|
a ring system the engine recognises but cannot name correctly yet (with |
|
|
an organic structure no candidate name passed the checks for |
|
|
the default tier built and checked a name, but not a verified PIN and not one of its exceptions; |
The codes are the stable part: the keys of orthonym.errors.LIMIT_CATALOG. The texts of the labels can change, so match a code, never a label.
Most organic declines carry the general UNNAMEABLE (no candidate name passed the checks) or, at the default tier, NO_VERIFIED_PIN (a checked name exists, but not the PIN).
Betaine shows the second case. Its strict-path name contains a part the engine records as not the preferred form, so the default tier declines, and a wider tier returns the name labelled systematic_verified:
$ orthonym "C[N+](C)(C)CC(=O)[O-]" --provenance
{"name": "unknown organic compound", "tier": "abstain", "is_pin": false, "source": "abstain", "opsin": "n/a", "gates_passed": [], "gate_outcome": "suppressed", "formula": "C5H11NO2", "limit_code": "NO_VERIFIED_PIN", "stereo_unexpressed": false, "suffix_free_prefix_name": false, "prefix_order_fallback": false, "verified": "unverified", "spelling_failures": [], "producer": null}
$ orthonym "C[N+](C)(C)CC(=O)[O-]" --emit-tier valid
(trimethylazaniumyl)acetate
The default-tier row has "producer": null although the engine built a name, because nothing ships. With --provenance the valid row names the code that built it.
Natural-product names are a second case. Where a molecule’s preferred name is a bridged fused name that the engine does not build yet, its natural-product name (diamorphine, (9R,13S,14S)-3-methoxy-17-methylmorphinan) is not the PIN. The default tier declines it with NO_VERIFIED_PIN, and a wider tier returns it labelled systematic_verified. --trivial also returns the trivial ones, such as diamorphine, at the default tier.
At a tier other than pin, the provenance row has no label for the name (null), and --on-failure label prints (no name — CODE) for it:
$ orthonym --emit-tier best-effort "O=[U](=O)=O" --on-failure label
(no name — UNSUPPORTED_ELEMENT)
In code#
A molecule that gets no name gets the empty string, and the reason is logged:
>>> from orthonym import name_compound
>>> name_compound("O=[U](=O)=O")
''
>>> name_compound("O=[U](=O)=O", on_failure="label")
'inorganic compound (not supported)'
orthonym.errors.is_failure_name is true for the empty string and for a label, and false for a name:
>>> from orthonym.errors import is_failure_name
>>> is_failure_name(name_compound("O=[U](=O)=O"))
True
>>> is_failure_name(name_compound("CCO"))
False
orthonym.classify_limit returns the reason without raising, and on_failure="raise" (or raise_on_limit=True) turns a decline into an OrthonymLimitError (Python). For a molecule the default tier declines with NO_VERIFIED_PIN, classify_limit returns that code and on_failure="raise" raises OrthonymLimitError with it.
A decline is never silent: a molecule that gets no name gets a logged reason (the limit code and a label), and --provenance gives a reason code. --batch leaves the name column of that line empty, prints the reason on the error stream, and counts such lines with --verbose.