Documentation
Getting started
There are two ways to use CIFlat: the hosted web app, which needs no installation, or the Python program, from the command line or from your own code. Both run the same conversion and the same checks.
The web app
- Open the hosted app on Hugging Face.
- Drop one or more structure files onto Structure files. A CIF is the main input;
.mmcif,.mol,.sdfand.smifiles are accepted too. - Leave the options at their defaults, or change them (see below), and start the conversion.
- Look at the previews and their status, then download the files: CDXML, MOL (V3000) and a PNG preview for each fragment.
A structure takes about a minute on the free CPU tier. Polynuclear or heavily disordered structures take longer.
| Option | Choices (default first) | Effect |
|---|---|---|
| Document style | acs, acs-wide, classic, default | Bond length and label size of the drawing. acs follows the ACS Document 1996 proportions (14.4 pt bonds, 10 pt labels). acs-wide gives crowded metal clusters more room. |
| Formal charges | all, no-metals, none | Which charges are drawn. no-metals leaves the metal centres bare for you to annotate. |
| Delocalised ambidentate groups | bridging, none, all | Draws carboxylate, carbonate, nitro, sulfonate, thiocyanate and azide groups with equal bonds and no charge: only those spanning more than one metal or chelating (bridging), every one, or none. |
| Metal–ligand bonds | plain lines, coordination arrows | Plain lines are the ACS convention. Arrows point from donor to metal. |
| Largest fragment only | off, on | Drops solvent and counter-ions. By default every fragment is drawn. |
| Polymers and wheels | automatic, whole assembly, 1–3 repeat units | How much of a polymer or a large wheel to draw. Automatic draws one bracketed repeat unit of a chain. |
| Drawings per structure | several to compare, one | Several searches run side by side; the best is kept and the others are shown as alternatives. |
| Layout time budget | 45 s (15–180 s) | Time for the layout search per fragment. Above 60 s, several searches run in parallel and the best drawing is kept. |
| Element colours | none | Colours the labels of chosen elements. Bonds stay black and the layout is unchanged. |
After a run with several drawings, the app may ask Which drawing do you prefer? Answering is optional; see Privacy for what an answer records.
Installing the program
CIFlat is written in Python and needs no GPU and no database. The source code is not yet public ([source code location to be announced]). Once you have it, create a virtual environment and install the pinned dependencies:
uv venv .venv
uv pip install --python .venv/bin/python -r requirements.txt
requirements.txt pins the tested stack: RDKit, NumPy, SciPy, Pillow, NetworkX and Indigo, at exact versions. Drawings are reproducible within the same pinned environment, options and input. An optional compiled layout core written in Rust makes the layout search about 1.98 times faster. It is switched on with CIFLAT_CORE=native and falls back to Python, without error, when it is not installed.
The command line
The program runs as a Python module. Convert one file:
python -m ciflat convert NAME.cif -o outputs
The output files are named after the input and written to outputs/. The command prints the status of each fragment, the result of every whole-structure check that did not pass, and any warnings. Add -v to list every check and every file written.
| Exit code | Status |
|---|---|
| 0 | ready |
| 1 | needs_review |
| 2 | invalid, or the conversion failed |
To look at the structural analysis without writing anything (formula, charge, coordination numbers, bridges, and every metal–donor contact with its distance and classification):
python -m ciflat analyse NAME.cif
Useful options
--mode fast|normal|slow- Effort of the layout search.
normal(the default) gives each fragment a 45 s budget.slowruns several searches with different seeds in parallel and keeps the best drawing.--time-budget Ssets the budget directly, and--seed Nchooses the seed. --style acs|acs-wide|classic|default- Drawing proportions, as on the web form.
--charges all|no-metals|noneand--delocalise none|bridging|all- Display conventions for charges and ambidentate groups. They do not change the chemistry written to MOL and SMILES.
--dative-bonds- Draws metal–ligand bonds as coordination arrows instead of plain lines.
--semi-coordinate auto|all|essential- Which long (semi-coordinate) contacts appear in the picture.
autoleaves out only the dashed contacts that would make an otherwise planar drawing non-planar. They are listed in the report and kept in a separate_all_contacts.cdxmldrawing. --condense auto|always|never- Abbreviations such as NO2, OMe or Ph, chosen before layout. In a fragment with four or more metals,
autoalso writes terminal alkoxides and longer alkyl groups as labels. A group is never abbreviated when an atom inside it is bonded to a metal. --excerpt N- Draws N consecutive repeat units of a polymer or wheel.
0never cuts. --largest-only,--keep-hydrogens- Keep only the largest fragment, or draw hydrogen atoms explicitly.
--alternatives- Also writes expanded, all-contact and dative drawings where they apply.
--colour Cu=blue --colour N=red- Colours element labels. The layout is unchanged.
--charge N- Sets the total charge of the species. The default,
auto, keeps ordinary metal oxidation states without forcing a total.
Bond-perception tolerances are not cosmetic
--covalent-tolerance, --metal-tolerance and --semi-tolerance change which contacts count as bonds, and so change the chemistry. The defaults are the values described in How it works.
Run python -m ciflat convert --help for the full list.
Batch mode
Convert every file in one or more directories, several at a time:
python -m ciflat batch structures/ -o outputs -j 2
-j sets the number of worker processes (at most 8; the default is 2). --subdirs puts each structure's files in a folder of its own. Batch mode writes outputs/manifest.json, which records each input's status, the files written, the warnings and the verification. Its exit code is the worst status among the inputs.
The Python API
Load a file, then convert a molecule:
from ciflat.io.sources import load
from ciflat.pipeline import convert
source = load("NAME.cif")
result = convert(source.molecules[0], "outputs", "NAME")
print(result.status) # "ready", "needs_review" or "invalid"
print(result.summary()) # formula, charge, metal centres, drawing quality
print(result.files) # paths of the files written
load returns a source whose molecules are the fragments of the structure: the complex, counter-ions and solvent. To convert a whole input with the same whole-structure checks as the command line and the web app, use convert_source:
from ciflat.pipeline import ConversionOptions, convert_source
results, overall = convert_source(source, "outputs", "NAME", ConversionOptions())
for r in results:
print(r.status, r.summary())
print(overall.as_dict()["summary"])
Outputs
For each fragment drawn (NAME is the stem; a structure with several fragments gets NAME_1, NAME_2, …):
| File | Contents |
|---|---|
NAME.cdxml | The editable drawing, the primary output. Open it directly in ChemDraw to keep CIFlat's layout. A cleanup there, or an import from SMILES, computes a different layout. |
NAME_V3000.mol, NAME_V2000.mol | The full chemistry, with abbreviations expanded and every contact kept. V3000 writes a π-bonded ring as one multicentre bond. The V2000 file is written when the structure is small enough for that format. |
NAME.smi | SMILES of the same chemistry. |
NAME.svg, NAME_preview.png | Previews of the drawing. |
NAME_coordination.csv | Every metal–donor contact, with its distance, its classification, and whether it is drawn. |
NAME_report.json | The report (below). |
NAME_all_contacts.cdxml | Written when contacts were left out of the main drawing: the same drawing with them put back. |
With --alternatives, the program also writes NAME_expanded.cdxml (no abbreviations), NAME_dative.cdxml and NAME_dative_V3000.mol where they apply.
The report
Every conversion writes a report so that a result can be checked rather than trusted. NAME_report.json holds:
- the formula, the formal charge, and the atoms and bonds as drawn;
- the provenance of the structure and every choice made for disordered and partly occupied sites, with site labels and occupancies;
- the formula check against the deposited sum formula, with any difference attributed to named sites;
- the perception: bond orders, charges, oxidation states, and anything left unresolved;
- the coordination of each metal, and any contacts left out of the picture;
- the layout quality, measured by the validator;
- the verification of the written files, check by check, and every warning.
A result marked needs_review therefore says what to look at. See Checks and statuses.