Skip to content

Structures and resolution

AsciiChem’s model has two more front doors besides the ASCII syntax: structure interchange (SMILES, molfile) and resolution (identifiers → substance records). Both land in the same semantic model, so every formatter and the wire form work unchanged.

A molecular formula is not a structure — C_2H_6O is ethanol or dimethyl ether. The chemistry world carries connectivity as SMILES or connection tables (molfile/SDF), and so does AsciiChem:

AsciiChem.parse_smiles("CC(=O)OC1=CC=CC=C1C(=O)O") # aspirin
AsciiChem.parse_molfile(molfile_text) # V2000, coordinates preserved

Both produce ordinary Model::Molecules: bonds, ring closures, charges, isotopes, aromaticity. Render them (to_structural_svg), re-emit them (to_smiles — a deterministic writer; aspirin round-trips exactly), or serialise to the wire form.

From the CLI:

Terminal window
asciichem convert -i "CCO" --from smiles -t structural-svg
asciichem convert -f ethanol.mol --from molfile -t model-json

The supported subset is honest about its edges: chirality (@) and E/Z bond directions (/ \) raise actionable errors rather than silently dropping stereo.

Resolution turns identifiers into substance records with provenance (TODO.v2 07). The default source is PubChem (keyless, permissive); more sources are opt-in because sources carry license obligations.

substance = AsciiChem::Resolver.resolve(value: "50-78-2", convention: "cas")
substance.identifier_value("inchikey") # => "BSYNRYMUTXBXSQ-UHFFFAOYSA-N"
substance.structure.to_structural_svg # parsed from the source SMILES
substance.to_model_json # canonical substance record

Every result carries provenance — source, retrieved-at, attribution — because the citation track emits one bibitem per (substance, source). Results are cached in your user cache directory; --refresh bypasses it.

Terminal window
asciichem resolve --name aspirin --source pubchem
asciichem validate -i 'H_2O @cas("7732-18-5")' # offline

Identity can also be computed from the structure you drew — offline, through the IUPAC reference software (never a reimplementation). The engine is opt-in and external:

AsciiChem::Inchi.engine = AsciiChem::Inchi::BinaryEngine.new
AsciiChem::Inchi.identity_for(molecule).inchikey

With an engine configured, asciichem lint structurally cross-checks @inchi and @inchikey annotations against the drawn structure — catching transcription errors that format validation cannot. Python wraps the same library via RDKit (pip install 'asciichem[inchi]').

Wire form

The canonical JSON every implementation emits — /models.

Live renderer

Parse and draw structures in the browser — /playground.

Play