torchcell.datamodels.compound_identity.resolved_compound

resolved_compound(name: str, *, pubchem_cid: int | None = None, smiles: str | None = None, inchi: str | None = None, roles: list[str] | None = None, known_proprietary: bool = False, derive_from_smiles: bool = False, derive_from_inchi: bool = False) → Compound[source]

Build a Compound fill-or-gap through the resolver (the loader entrypoint).

name is the loader’s SOURCE LABEL: whatever the paper’s column or table calls the compound. The returned Compound.name is the table’s CANONICAL name when a row matches, so two papers spelling one compound differently produce one node; the label itself is already recorded as that row’s synonym. With no row, the label is kept as-is.

Structure fields merge ADDITIVELY: a caller-supplied field (hoepfner’s smiles, wildenhain’s pubchem_cid) always wins; the resolver only fills what is still None. With derive_from_smiles=True an unmatched label whose SMILES parses gets an RDKit-derived InChIKey, but a curated row always outranks that route. With derive_from_inchi=True an unmatched label whose released inchi reads back gets the hash of that string instead (inchikey_from_inchi()); the two derived routes are exclusive, so asking for both raises rather than chaining one behind the other.

When no InChIKey can be filled, a typed ProvenanceGap is attached on inchikey: not_reported_by_primary when the absence is terminal (a vendor code, an undefined preparation, a homolog mixture with no single key), else deferred_pending_source_review (the growable worklist). The gap is asserted ONLY on the None field, honoring the ProvenanceGapMixin invariant.