#20551 closed defect (fixed)
mmCIF handles non-orthogonal cells incorrectly
| Reported by: | Tristan Croll | Owned by: | Greg Couch |
|---|---|---|---|
| Priority: | normal | Milestone: | |
| Component: | Input/Output | Version: | |
| Keywords: | Cc: | ||
| Blocked By: | Blocking: | ||
| Notify when closed: | Platform: | all | |
| Project: | ChimeraX |
Description (last modified by )
The following bug report has been submitted: Platform: Windows-10-10.0.26200 ChimeraX Version: 1.13.dev202606240437 (2026-06-24 04:37:46 UTC)
Description
Little bug Claude came across while teaching Clipper how to open small-molecule CIF files with structure factors:
ChimeraX corecif fractional→Cartesian bug (oblique cells)
Where: ChimeraX/src/bundles/mmcif/mmcif_cpp/corecif.cpp, SmallMolecule::to_cartesian (~line 550).
Symptom: Small-molecule (core) CIF structures opened with open … format corecif have subtly wrong atomic coordinates whenever the unit cell has a non-90° angle. Bond lengths deviate from the CIF's own published _geom_bond_distance values by ~0.006 Å mean / 0.017 Å max for a β≈91° monoclinic cell (COD 1100908), and the error grows as the cell becomes more oblique (small β, or triclinic). Orthogonal cells (α=β=γ=90°) are unaffected.
Root cause: compute_cell_matrix() stores the cell vectors a, b, c as the rows of cell[3][3]:
cell[0] = (a, 0, 0)
cell[1] = (b·cosγ, b·sinγ, 0)
cell[2] = (c·cosβ, c·n2, c·√(sin²β − n2²))
The correct fractional→Cartesian transform is therefore xyz[j] = Σ_i fract[i]·cell[i][j]. But to_cartesian writes:
for (auto i = 0; i < 3; ++i)
for (auto j = 0; j < 3; ++j)
xyz[i] += fract_xyz[i] * cell[i][j]; BUG: output index should be j
i.e. xyz[i] = fract[i]·Σ_j cell[i][j] — a row-sum written into the wrong Cartesian axis. For a diagonal (orthogonal) cell this coincides with the correct result, which is why the bug is invisible for orthogonal cells and was never caught.
Fix:
for (auto i = 0; i < 3; ++i)
for (auto j = 0; j < 3; ++j)
xyz[j] += fract_xyz[i] * cell[i][j];
Verification: rebuilding Cartesian coordinates from the CIF fractionals via a correct orthogonalization (Clipper Coord_frac::coord_orth) reproduces the CIF's published _geom_bond_distance values to max 0.0007 Å (mean 0.0002 Å) on COD 1100908, vs corecif's 0.017 Å max (0.006 Å mean).
OpenGL version: 3.3.0 NVIDIA 610.62
OpenGL renderer: NVIDIA GeForce RTX 5070 Ti Laptop GPU/PCIe/SSE2
OpenGL vendor: NVIDIA Corporation
Python: 3.11.9
Locale: en_GB.cp1252
Qt version: PyQt6 6.11.0, Qt 6.11.0
Qt runtime version: 6.11.1
Qt platform: windows
Manufacturer: LENOVO
Model: 83LU
OS: Microsoft Windows 11 Pro (Build 26200.8655)
Memory: 33,752,997,888
MaxProcessMemory: 137,438,953,344
CPU: 24 Intel(R) Core(TM) Ultra 9 275HX
OSLanguage: en-US
Installed Packages:
accessible-pygments: 0.0.5
aiohappyeyeballs: 2.6.2
aiohttp: 3.13.4
aiosignal: 1.4.0
alabaster: 1.0.0
annotated-types: 0.7.0
anyio: 4.14.0
appdirs: 1.4.4
asttokens: 3.0.1
attrs: 26.1.0
autocommand: 2.2.2
babel: 2.18.0
backports.tarfile: 1.2.0
backports.tarfile: 1.2.0
beautifulsoup4: 4.13.5
blockdiag: 3.0.0
blosc2: 4.5.1
build: 1.3.0
certifi: 2026.6.17
cftime: 1.6.5
charset-normalizer: 3.4.7
ChimeraX-AddCharge: 1.5.20
ChimeraX-AddH: 2.3.1
ChimeraX-AlignmentAlgorithms: 2.0.2
ChimeraX-AlignmentHdrs: 3.6.2
ChimeraX-AlignmentMatrices: 2.1
ChimeraX-Alignments: 3.2.1
ChimeraX-AlphaFold: 1.0.1
ChimeraX-AltlocExplorer: 1.2
ChimeraX-AmberInfo: 1.0
ChimeraX-Animations: 1.0
ChimeraX-Aniso: 1.3.2
ChimeraX-Arrays: 1.1
ChimeraX-Atomic: 1.69.2
ChimeraX-AtomicLibrary: 14.4.1
ChimeraX-AtomSearch: 2.0.1
ChimeraX-AxesPlanes: 2.4
ChimeraX-BasicActions: 1.1.3
ChimeraX-BILD: 1.0
ChimeraX-BlastProtein: 3.0.0
ChimeraX-Boltz: 1.1
ChimeraX-BondRot: 2.0.4
ChimeraX-BugReporter: 1.0.2
ChimeraX-BuildStructure: 2.13.1
ChimeraX-Bumps: 1.0
ChimeraX-BundleBuilder: 1.6.0
ChimeraX-ButtonPanel: 1.0.1
ChimeraX-CageBuilder: 1.0.1
ChimeraX-CellPack: 1.0
ChimeraX-Centroids: 1.4.1
ChimeraX-ChangeChains: 1.1
ChimeraX-CheckWaters: 1.5
ChimeraX-ChemComp: 0.1.0
ChimeraX-ChemGroup: 2.0.2
ChimeraX-ChemSearch: 0.1.0
ChimeraX-Clashes: 2.4
ChimeraX-Clipper: 0.28.dev0
ChimeraX-Cluster: 1.0
ChimeraX-ColorActions: 1.0.5
ChimeraX-ColorGlobe: 1.0
ChimeraX-ColorKey: 1.5.8
ChimeraX-CommandLine: 1.3.1
ChimeraX-ConnectStructure: 2.0.1
ChimeraX-Contacts: 1.0.1
ChimeraX-Core: 1.13.dev202606240437
ChimeraX-CoreFormats: 1.2
ChimeraX-coulombic: 1.4.6
ChimeraX-Crosslinks: 1.0
ChimeraX-Crystal: 1.0
ChimeraX-CrystalContacts: 1.0.1
ChimeraX-DataFormats: 1.2.4
ChimeraX-DistMonitor: 1.4.2
ChimeraX-DockPrep: 1.2.2
ChimeraX-Dssp: 2.0
ChimeraX-EMDB-SFF: 1.0
ChimeraX-ESMFold: 1.0
ChimeraX-FileHistory: 1.0.1
ChimeraX-FunctionKey: 1.0.1
ChimeraX-Geometry: 1.3
ChimeraX-gltf: 1.0
ChimeraX-Graphics: 1.4.1
ChimeraX-Hbonds: 2.5.4
ChimeraX-Help: 1.3
ChimeraX-HKCage: 1.3
ChimeraX-IHM: 1.1
ChimeraX-ImageFormats: 1.2
ChimeraX-IMOD: 1.0
ChimeraX-IO: 1.0.4
ChimeraX-ISOLDE: 1.13.dev0
ChimeraX-ItemsInspection: 1.0.1
ChimeraX-IUPAC: 1.0
ChimeraX-KVFinder: 1.8.3
ChimeraX-Label: 1.5
ChimeraX-LightingGUI: 1.0
ChimeraX-ListInfo: 1.3.1
ChimeraX-Log: 1.2.2
ChimeraX-LookingGlass: 1.1
ChimeraX-Maestro: 1.9.3
ChimeraX-Map: 1.3
ChimeraX-MapData: 2.0
ChimeraX-MapEraser: 1.0.1
ChimeraX-MapFilter: 2.0.1
ChimeraX-MapFit: 2.0
ChimeraX-MapSeries: 2.1.1
ChimeraX-Markers: 1.0.1
ChimeraX-Mask: 1.0.2
ChimeraX-MatchAlign: 1.2.1
ChimeraX-MatchMaker: 2.4.1
ChimeraX-MCopy: 1.0
ChimeraX-MCPServer: 0.2.0
ChimeraX-MDcrds: 2.19.1
ChimeraX-Meeting: 1.0.1
ChimeraX-Minimize: 1.4.2
ChimeraX-MLP: 1.1.1
ChimeraX-mmCIF: 2.17
ChimeraX-MMTF: 2.2
ChimeraX-ModelArchive: 1.0
ChimeraX-Modeller: 1.5.24
ChimeraX-ModelPanel: 1.6.1
ChimeraX-ModelSeries: 1.0.1
ChimeraX-Mol2: 2.0.3
ChimeraX-Mole: 1.0
ChimeraX-Morph: 1.0.2
ChimeraX-MouseModes: 1.2
ChimeraX-Movie: 1.0.1
ChimeraX-MutationScores: 1.0
ChimeraX-Neuron: 1.0
ChimeraX-NMRSTAR: 1.0.2
ChimeraX-Nucleotides: 2.0.3
ChimeraX-OpenCommand: 1.16.2
ChimeraX-OpenFold: 1.0
ChimeraX-OrthoPick: 1.0.1
ChimeraX-PDB: 2.7.13
ChimeraX-PDBBio: 1.0.1
ChimeraX-PDBLibrary: 1.0.5
ChimeraX-PDBMatrices: 1.0
ChimeraX-PickBlobs: 1.0.1
ChimeraX-Positions: 1.0
ChimeraX-PresetMgr: 1.1.4
ChimeraX-ProfileGrids: 1.10.1
ChimeraX-PubChem: 2.2
ChimeraX-ReadPbonds: 1.0.1
ChimeraX-Registration: 1.1.2
ChimeraX-RemoteControl: 1.0
ChimeraX-RenderByAttr: 1.8.2
ChimeraX-RenumberResidues: 1.1
ChimeraX-ResidueFit: 1.0.1
ChimeraX-RestServer: 1.3.3
ChimeraX-RNALayout: 1.0
ChimeraX-RotamerLibMgr: 4.0
ChimeraX-RotamerLibsDunbrack: 2.0
ChimeraX-RotamerLibsDynameomics: 2.0
ChimeraX-RotamerLibsRichardson: 2.0
ChimeraX-SaveCommand: 1.5.2
ChimeraX-Scenes: 0.3.1
ChimeraX-SchemeMgr: 1.0
ChimeraX-SDF: 2.0.3
ChimeraX-Segger: 1.0
ChimeraX-Segment: 1.0.1
ChimeraX-Segmentations: 3.5.12
ChimeraX-SelInspector: 1.0
ChimeraX-SeqView: 2.19
ChimeraX-Shape: 1.1
ChimeraX-Shell: 1.0.1
ChimeraX-Shortcuts: 1.2.1
ChimeraX-ShowSequences: 1.0.3
ChimeraX-SideView: 1.0.1
ChimeraX-SimilarStructures: 1.0.1
ChimeraX-Smiles: 2.1.2
ChimeraX-SmoothLines: 1.0
ChimeraX-SNFG: 1.0
ChimeraX-SpaceNavigator: 1.0
ChimeraX-StdCommands: 1.20
ChimeraX-STL: 1.0.1
ChimeraX-Storm: 1.0
ChimeraX-StructMeasure: 1.2.1
ChimeraX-Struts: 1.0.1
ChimeraX-Surface: 1.0.1
ChimeraX-SwapAA: 2.0.1
ChimeraX-SwapRes: 2.5.3
ChimeraX-TapeMeasure: 1.0
ChimeraX-TaskManager: 1.0
ChimeraX-Test: 1.0
ChimeraX-Toolbar: 1.2.4
ChimeraX-ToolshedUtils: 1.2.4
ChimeraX-Topography: 1.0
ChimeraX-ToQuest: 1.0
ChimeraX-Tug: 1.0.1
ChimeraX-UI: 1.52
ChimeraX-Umap: 1.0
ChimeraX-uniprot: 2.3.2
ChimeraX-UnitCell: 1.0.1
ChimeraX-ViewDock: 1.6.4
ChimeraX-VIPERdb: 1.0
ChimeraX-Vive: 1.1
ChimeraX-VolumeMenu: 1.0.1
ChimeraX-vrml: 1.0
ChimeraX-VTK: 1.0
ChimeraX-WavefrontOBJ: 1.0
ChimeraX-WebCam: 1.0.2
ChimeraX-WebServices: 1.1.5
ChimeraX-Zone: 1.0.1
click: 8.4.1
colorama: 0.4.6
comm: 0.2.3
comtypes: 1.4.11
contourpy: 1.3.3
coverage: 7.14.3
cxservices: 1.2.3
cycler: 0.12.1
Cython: 3.2.4
debugpy: 1.8.21
decorator: 5.3.1
dimorphite_dl: 2.0.2
docutils: 0.21.2
executing: 2.2.1
filelock: 3.19.1
fonttools: 4.63.0
frozenlist: 1.8.0
funcparserlib: 2.0.0a0
glfw: 2.10.0
grako: 3.16.5
h11: 0.16.0
h5py: 3.16.0
html2text: 2025.4.15
httpcore: 1.0.9
httpx: 0.28.1
httpx-sse: 0.4.3
idna: 3.18
ihm: 2.2
imagecodecs: 2024.6.1
imagesize: 2.0.0
importlib_metadata: 9.0.0
importlib_metadata: 8.0.0
inflect: 7.3.1
iniconfig: 2.3.0
ipykernel: 7.3.0
ipython: 9.14.1
ipython_pygments_lexers: 1.1.1
jaraco.classes: 3.4.0
jaraco.collections: 5.1.0
jaraco.context: 6.1.2
jaraco.context: 5.3.0
jaraco.functools: 4.5.0
jaraco.functools: 4.0.1
jaraco.text: 3.12.1
jedi: 0.20.0
Jinja2: 3.1.6
jsonschema: 4.26.0
jsonschema-specifications: 2025.9.1
jupyter_client: 8.9.1
jupyter_core: 5.9.1
keyring: 25.7.0
kiwisolver: 1.5.0
line_profiler: 5.0.0
linkify-it-py: 2.1.0
loguru: 0.7.3
lxml: 6.0.2
lz4: 4.3.2
Markdown: 3.8.2
markdown-it-py: 4.2.0
MarkupSafe: 3.0.3
matplotlib: 3.10.7
matplotlib-inline: 0.2.2
mcp: 1.18.0
mdit-py-plugins: 0.6.1
mdurl: 0.1.2
more-itertools: 11.1.0
more-itertools: 10.3.0
msgpack: 1.1.1
multidict: 6.7.1
ndindex: 1.10.1
nest-asyncio2: 1.7.2
netCDF4: 1.6.5
networkx: 3.3
numexpr: 2.14.1
numpy: 1.26.4
nvidia-nvjitlink-cu12: 12.9.86
OpenMM: 8.4.0
OpenMM-CUDA-12: 8.4.0
openvr: 1.26.701
packaging: 25.0
packaging: 24.2
ParmEd: 4.2.2
parso: 0.8.7
pep517: 0.13.1
pickleshare: 0.7.5
pillow: 11.3.0
pip: 25.2
pkginfo: 1.12.1.2
platformdirs: 4.10.0
platformdirs: 4.2.2
plotext: 5.3.2
pluggy: 1.6.0
prompt_toolkit: 3.0.52
propcache: 0.5.2
psutil: 7.0.0
pure_eval: 0.2.3
py-cpuinfo: 9.0.0
pybind11: 3.0.1
pycollada: 0.8
pydantic: 2.13.4
pydantic-settings: 2.14.2
pydantic_core: 2.46.4
pydata-sphinx-theme: 0.19.0
Pygments: 2.18.0
pynmrstar: 3.5.1
PyOpenGL: 3.1.10
PyOpenGL-accelerate: 3.1.10
pyopenxr: 1.1.4501
pyparsing: 3.3.2
pyproject_hooks: 1.2.0
PyQt6: 6.11.0
PyQt6-Qt6: 6.11.1
PyQt6-WebEngine: 6.11.0
PyQt6-WebEngine-Qt6: 6.11.1
PyQt6_sip: 13.11.1
pytest: 9.1.1
pytest-cov: 7.1.0
python-dateutil: 2.9.0.post0
python-dotenv: 1.2.2
python-multipart: 0.0.32
pywin32: 311
pywin32-ctypes: 0.2.3
pyzmq: 27.1.0
qtconsole: 5.7.2
QtPy: 2.4.3
qtshim: 1.2.2
RandomWords: 0.4.0
rdkit: 2025.9.6
referencing: 0.37.0
requests: 2.32.5
rich: 15.0.0
roman-numerals: 4.1.0
rpds-py: 2026.5.1
scipy: 1.14.0
setuptools: 80.9.0
sfftk-rw: 0.8.1
six: 1.17.0
snowballstemmer: 3.1.1
sortedcontainers: 2.4.0
soupsieve: 2.8.4
Sphinx: 9.0.4
sphinx-autodoc-typehints: 3.6.1
sphinxcontrib-applehelp: 2.0.0
sphinxcontrib-blockdiag: 3.0.0
sphinxcontrib-devhelp: 2.0.0
sphinxcontrib-htmlhelp: 2.1.0
sphinxcontrib-jsmath: 1.0.1
sphinxcontrib-qthelp: 2.0.0
sphinxcontrib-serializinghtml: 2.0.0
sse-starlette: 3.4.5
stack-data: 0.6.3
starlette: 1.3.1
superqt: 0.7.6
tables: 3.10.2
textual: 4.0.0
textual-plotext: 1.0.1
threadpoolctl: 3.6.0
tifffile: 2025.3.13
tinyarray: 1.2.5
tomli: 2.0.1
tornado: 6.5.7
traitlets: 5.15.1
typeguard: 4.3.0
typing-inspection: 0.4.2
typing_extensions: 4.15.0
typing_extensions: 4.12.2
uc-micro-py: 2.0.0
urllib3: 2.7.0
uvicorn: 0.49.0
wcwidth: 0.8.1
webcolors: 24.11.1
wheel: 0.45.1
wheel: 0.45.1
wheel-filename: 1.4.2
win32_setctime: 1.2.0
WMI: 1.5.1
yarl: 1.24.2
zipp: 4.1.0
zipp: 3.19.2
Attachments (2)
Change History (10)
comment:1 by , 3 weeks ago
| Component: | Unassigned → Input/Output |
|---|---|
| Owner: | set to |
| Platform: | → all |
| Project: | → ChimeraX |
| Status: | new → assigned |
| Summary: | ChimeraX bug report submission → mmCIF handles non-orthogonal cells incorrectly |
comment:2 by , 3 weeks ago
| Description: | modified (diff) |
|---|---|
| Status: | assigned → accepted |
comment:3 by , 3 weeks ago
| Status: | accepted → feedback |
|---|
comment:4 by , 10 days ago
This doesn't seem to have made it into the daily builds yet? Behaviour is identical with today's. If you want a test example, try 1529240 - its highly oblique cell makes for a particularly glaring example. Pictured: thinner sticks and map = calculated by Clipper; thicker sticks as opened by ChimeraX. [image: image.png] On Fri, Jul 3, 2026 at 12:22 AM ChimeraX <ChimeraX-bugs-admin@cgl.ucsf.edu> wrote: > > > >
comment:5 by , 10 days ago
I tried "open 1529240 from pubchem" in ChimeraX and it looks fine. "open 1529240 from cod" appears to be what you're talking about. Is that what you started with?
The change to use xyz[j] instead of xyz[i] in SmallMolecule::to_cartesian() was checked in on July 2. And should be in any daily build dated July 3 or later. I confirmed that both versions of to_cartesian() generate the same result. So that's not the only bug.
An aside, how does Clipper decide to split the small molecule into 2 components?
comment:6 by , 10 days ago
That was one of today's additions. :) https://github.com/tristanic/chimerax-clipper/blob/master/src/io/fragments.py Caveat: code is essentially completely auto-written by Claude, based on a bunch of back-and-forth over details. Much as it pains me to admit it, it's better than I could have done myself. The point of this current thrust is to train an improved graph-ML based force field based on GARNET (https://github.com/greener-group/garnet). COD molecules make for a really useful source of absolute-ground-truth (just have to work out how to use them most effectively). On Fri, Jul 10, 2026 at 9:10 PM ChimeraX <ChimeraX-bugs-admin@cgl.ucsf.edu> wrote: > > > >
comment:7 by , 10 days ago
| Resolution: | → fixed |
|---|---|
| Status: | feedback → closed |
So Claude's bug was not a bug. So to_cartesian() has been reverted. The actual bug was that the wrong CIF names for the cell angles were used. So the angles never changed from 90 degrees.
comment:8 by , 10 days ago
Ah - my apologies. I've clearly been getting a bit too trusting of it... On Fri, Jul 10, 2026 at 10:07 PM ChimeraX <ChimeraX-bugs-admin@cgl.ucsf.edu> wrote: > > > >

Made the requested change. Please reverify that it is correct with the next daily build.