Skip to content
Automated refinement of single crystal diffraction data using SHELXTL
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Python library for automated single crystal refinement with Shelx

Authors: E. Antono and J. Ling at Citrine Informatics

Please contact: erin (at) citrine (dot) io with any questions.

This package is intended to be used with the SHELX code suite: Sheldrick, George M. "A short history of SHELX." Acta Crystallographica Section A: Foundations of Crystallography 64.1 (2008): 112-122.

The purpose of this package is to automate many of the steps in single crystal refinement. It automatically detects split occupancy, deficiency, wrong element assignments, and anisotropy.


Clone this git repo:

git clone

Then, use:

pip install -r requirements.txt
python install

to install python dependencies and the crystal structure refinement package. We recommend that this step is done in a python virtual environment (

Other Dependencies:


The optimization package can be run using a command line interface and configuration file. Run crystal_refinement -h to see the help menu for the command line interface.

To run an example optimization on the ins file in the example folder, change the path_to_xl and path_to_xs values in the minimal.yml file to correspond to the path of the SHELX executables on your machine. Then run:

crystal_refinement -c minimal.yml -d examples/ -i input -o test

The results of the optimization will be output to the examples/optimizer_results directory. 0.res is the highest scoring result file, optimization_graph.pdf is the optimization graph generated by graphviz, and report.txt will contain metadata on the optimization process.

See config.yml for further documentation of the configuration file parameters.

The optimization package can also be used directly in python by creating an instance of the Optimizer object and using the run() method.

How it works

The optimizer tries the following steps in order:

  1. Identify crystal sites (try adding or removing Q peaks)
  2. Switch elements at each crystal site
  3. Try site mixing at each site
  4. Try partial occupancy at each site
  5. Try extinguishing
  6. Try anisotropy

At each step, the optimization takes into account both the fit R1 value as well as the bond lengths. The ideal bond lengths can be determined by 3 different methods:

  1. User input via the bond_length argument to the Optimizer class
  2. A machine learning model for bond length hosted at To use this model, the user must have a free account on the public Citrination site.
  3. Atomic radii of the elements

The optimizer will follow multiple paths to see which path yields the best final fit. For example, if two different elements both yield similar R1 values at a given crystal site, the optimizer will try both options to see which give the best final fit. This results in a branching tree structure.

You can’t perform that action at this time.