7
$\begingroup$

I have tried a bunch of apps such as Mercury, OpenLabel but they cannot convert CIF files to XYZ files in bulk. I am also thinking of doing it in Python but just want to know if there's an app for this. Thank you.

$\endgroup$
3
  • 3
    $\begingroup$ I have not worked with his program but may be Babel (openbabel.org) is fit for this porpouse. $\endgroup$
    – PAEP
    Commented Apr 26, 2023 at 20:11
  • 2
    $\begingroup$ While I personally would use OpenBabel obabel *.cif -O .xyz -m you could also do this with pymatgen or ASE $\endgroup$ Commented May 3, 2023 at 2:42
  • $\begingroup$ If my answer solved your question, could you please click on the tick mark next to it and mark it as the accepted answer. $\endgroup$ Commented May 18, 2023 at 18:30

2 Answers 2

5
$\begingroup$

ASE

You can use the ase python library to achieve this.

I tested the following code with 3 CIF files obtained from the Crystallographic Open Data: 1569089, 1000017, 1000003 and it produces their respective XYZ files.

Code

from ase.io import read, write

# Define the list of CIF files to convert
cif_files = ['1569089.cif', '1000017.cif', '1000003.cif']

for cif_file in cif_files:
    # Read the CIF file using ASE
    atoms = read(cif_file)

    # Define the output XYZ file name
    xyz_file = cif_file.replace('.cif', '.xyz')

    # Write the atoms to the output XYZ file using ASE
    write(xyz_file, atoms, format='xyz')
$\endgroup$
1
$\begingroup$

Non-molecular systems

For non-molecular structures, the procedure outlined by Vandan Revanur is entirely reasonable. As Geoff mentioned in the comments, you could also opt for OpenBabel instead which allows you to do the conversion in Python or directly on the command-line if you prefer.

On the command-line, it would be something like:

obabel 1569089.cif -O 1569089.xyz

Or to convert files in bulk, either:

for file in *.cif; do obabel "$file" -O "${file/.cif/.xyz}"; done

Or simply:

obabel *.cif -O .xyz -m

Note that by default ASE and OBabel handle the conversion differently. OBabel appears to extract the unit cell, while ASE extracts some form of the super-cell? You can probably tweak this by providing the right options to each, I'd recommend referring to the ASE/Obabel manual if you need to do this.

Molecular systems

For molecules, however, we need to do a bit more work. The cif file rarely contains the coordinates of only a single molecule; some atoms will likely be duplicated due to inhomogeneity in the crystal (multiple occupancies, crystal defects etc.) and solvent and/or counter-ions may be included.

Fortunately, the cod-tools package provides a number of great scripts for dealing with exactly these sorts of problems. After downloading the package (apt install cod-tools on debian-like systems), you can extract molecules from a cif file using the appropriately named cif_molecule command.

Using 1569774.cif as an example:

cif_molecule 1569774.cif --largest --one-datablock-output -i --continue-on-errors > 1569774_mol.cif

You can convert the resulting molecular cif file as normal:

obabel 1569774_mol.cif -O 1569774_mol.xyz

The resulting structure might still contain solvent molecules and/or counter ions. If you want to remove these too, specify the -r option to obabel:

obabel 1569774_mol.cif -O 1569774_mol.xyz -r

For bulk conversion, this would look like:

for file in *.cif; do cif_molecule "$file" --largest --one-datablock-output -i --continue-on-errors | obabel -i cif -O "${file/.cif/.xyz}" -r; done

Note that this extraction process will necessarily lose information. If you just want to visualise the crystal structure, or want to extract the molecule for some further processing (maybe as a starting point for quantum chemistry) this is totally fine. If you want to understand the crystal structure itself, best to leave the file in the cif format.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .