Utility scripts for 3D ED (electron diffraction) crystallography data management and analysis.
CLI tool to retrieve checkCIF alert explanations from the IUCr (International Union of Crystallography) validation page.
Fetches alert codes with their Type, Purpose, and SUMMATION information from https://journals.iucr.org/services/cif/datavalidation.html
-
Look up a single alert code:
python checkcif_alerts.py ABSMU01
-
Look up multiple alerts with detailed SUMMATION (fetches from individual detail pages):
python checkcif_alerts.py ABSMU01 PLAT020 --fetch-summation
-
Search for alerts related to a topic:
python checkcif_alerts.py --search "absorption"
-
List all available alert codes:
python checkcif_alerts.py --list-all
-
Case-insensitive lookup:
python checkcif_alerts.py absmu01
- --fetch-summation, -f: Fetch detailed SUMMATION from individual alert pages (slower but more complete)
- --list-all, -l: List all available alert codes
- --search, -s QUERY: Search for alerts matching query in code or purpose
- --verbose, -v: Verbose output
- --no-cache: Do not use cached data
- --refresh, -r: Force refresh from web
- --cache-info: Show cache file location
- The script caches alert data locally in
~/.cache/checkcif_alerts.jsonto speed up subsequent lookups - Use
--fetch-summationto retrieve the full SUMMATION text for each alert (requires fetching individual detail pages) - Alert codes are case-insensitive
- Uses only Python standard library (no external dependencies required)
Generate "stripped" CIF files containing only essential crystallographic data (symmetry, cell parameters, atomic coordinates). Removes all metadata, experimental details, and publication information.
CLI with explicit paths:
python cif_stripper.py input.cif output_stripped.cif
Minimal GUI picker (select input CIF and output folder):
python cif_stripper.py --gui
Quick convenience mode (opens file picker if no input path is given):
python cif_stripper.py
With options:
python cif_stripper.py input.cif output.cif --no-header
python cif_stripper.py input.cif --validate-only
python cif_stripper.py --list-fields
As a Python module:
from cif_stripper import StrippedCIFGenerator
generator = StrippedCIFGenerator()
generator.generate_stripped_cif_from_file("input.cif", "output.cif")- Fully standalone - uses only Python standard library
- GUI mode uses built-in
tkinter(no pip package required) - If output file is omitted, defaults to
<input_stem>_stripped.cifin the input CIF folder - In
--guimode, canceling output folder selection falls back to the input CIF folder - Optionally includes a custom header file
- Creates minimal CIFs suitable for structure visualization and analysis
Generate crystallographic tables from CIF files for inclusion in reports. Exports data to Excel format with proper formatting.
-
Generate table from a single CIF file:
python cif_to_table.py structure.cif
-
Generate table from merged dataset with individual collection data:
python cif_to_table.py m_971_973_974_978_980_981.cif --exp-root ./data
-
Include absolute structure determination data from Olex2 Enantiomers analysis:
python cif_to_table.py structure.cif --exp-root ./data --all-enantiomers
-
Specify custom output filename:
python cif_to_table.py structure.cif --output report_table.xlsx
-
Skip the merged collections table:
python cif_to_table.py merged.cif --no-merged-table
- --output, -o: Specify output Excel filename (default:
<cif_name>_table.xlsx) - --merged, -m: Force treat as merged dataset (auto-detected by default)
- --exp-root: Root directory containing
exp_#folders with.cif_odfiles (default: current directory) - --no-merged-table: Skip generating the merged collections table
- --all-enantiomers: Search ALL
exp_####folders for Enantiomers data, not just those in the CIF filename
For merged datasets (detected via "List of Runs" in CIF):
- Extracts experiment numbers from the CIF filename (e.g.,
m_3792_3793.cif→ experiments 3792, 3793) - Looks for corresponding
exp_###/exp_###.cif_odfiles for cell parameters - Generates a "Distinct Data Collections" table showing cell parameters for each collection
For chiral structures (Sohncke space groups):
- Automatically searches for
exp_###/struct/olex2_exp_###*/Enantiomers/log.txtfiles - Parses Olex2 Enantiomers analysis output and creates an "Absolute Structure" worksheet
- Summary table shows: Experiment name, Z-score (raw), ΔR1 (%), and source path
- Full analysis output included for reference
- Use
--all-enantiomersto search allexp_####folders (useful when more experiments were analyzed than shown in the CIF filename) - Script will remind you to use
--exp-rootif a chiral space group is detected but no exp-root is provided
- Crystal Data: Main crystallographic information
- Alternative Format: Alternative presentation of crystal data
- Atomic Coordinates: Fractional coordinates and isotropic displacement parameters
- Aniso Displacements: Anisotropic displacement parameters
- Bond Lengths: All bond distances
- Bond Angles: All bond angles
- Torsion Angles: All torsion angles
- Hydrogen Atoms: Hydrogen atom coordinates
- Hydrogen Bonds: Hydrogen bonding information
- Absolute Structure (optional): Enantiomer/absolute structure determination data (if available for chiral structures)
Generate crystallographic tables from CIF files for inclusion in reports. Exports data to Microsoft Word (.docx) with configurable table and typography styling.
-
Generate report from a single CIF file:
python cif_to_docx.py structure.cif
-
Generate report from merged dataset with individual collection data:
python cif_to_docx.py m_971_973_974_978_980_981.cif --exp-root ./data
-
Include absolute structure determination data from Olex2 Enantiomers analysis:
python cif_to_docx.py structure.cif --exp-root ./data --all-enantiomers
-
Specify custom output filename:
python cif_to_docx.py structure.cif --output report.docx
-
Basic style override examples:
python cif_to_docx.py structure.cif --table-style "Light Grid Accent 1" --font-name "Arial" --font-size 10.5
- Core data options mirror
cif_to_table.py:--merged,--exp-root,--no-merged-table,--all-enantiomers --output, -o: Output Word filename (default:<cif_name>_table.docx)--title: Document title--font-name,--font-size: Base body font controls--heading-size,--subheading-size: Heading font size controls--table-style: Word table style name--label-col-cm,--value-col-cm: Two-column table width controls
- Crystal Data
- Distinct Data Collections (optional, merged datasets)
- Alternative Format
- Atomic Coordinates
- Aniso Displacements
- Bond Lengths
- Bond Angles
- Torsion Angles
- Hydrogen Atoms
- Hydrogen Bonds
- Absolute Structure (optional, if available for chiral structures)
Batch-apply a solved SHELXL model (.res/.ins) to multiple target .ins files.
Designed for workflows where one dataset has already been solved/refined and you want to reuse that model as the starting point for several additional data collections (for example, collections processed in CrysAlisPRO).
- Reads the reference file and extracts everything between the final
UNITline andHKLF/END - For each target
.insfile:- keeps the target header up to and including
UNIT(preserving dataset-specific cell/header data) - keeps the target
HKLF/ENDtail (preserving reflection linkage and ending section) - replaces the middle section with the reference model/refinement block
- keeps the target header up to and including
-
In-place update all
.insfiles under a directory (creates.bakbackups):python shelxl_start_model_batch.py ref_model.res ./data --pattern "*.ins"
-
Preview only (no files changed):
python shelxl_start_model_batch.py ref_model.res ./data --dry-run
-
Write to new sibling files instead of editing originals:
python shelxl_start_model_batch.py ref_model.res ./data --suffix "_start"
-
Exclude some files/folders:
python shelxl_start_model_batch.py ref_model.res ./data --exclude "_start.ins" --exclude "/archive/*"
--pattern: Filename pattern used when scanning directories (default:*.ins)--exclude: Exclude by basename or full-path glob (repeatable)--suffix: Output suffix for non-destructive writes (e.g.,_start)--backup-ext: Backup extension for in-place writes (default:.bak)--dry-run: Show what would be changed without writing files
Calculate the number of unpaired electrons for elements in different oxidation states. Handles high-spin and low-spin configurations for transition metal complexes.
Run interactively:
python unpaired_electrons.py
The script will:
- Show examples for common ions (Fe²⁺, Fe³⁺, Cu²⁺)
- Enter interactive mode where you can query any element/oxidation state
- For d-block elements, specify high-spin, low-spin, or both configurations
- Uses only Python standard library
- Particularly useful for transition metals in crystallography
- Accounts for high-spin vs low-spin electronic configurations
Search recursively for experiment_results.xmlinfo files and replace the <__USER__>...</__USER__> tag content. Optionally also updates exp_*_sample.ini files in the [User] section.
PowerShell:
.\replace_user_tag.ps1Python:
python replace_user_tag.py
Both scripts will prompt for:
- Directory to search (defaults to current directory)
- Replacement user name
- Whether to also update INI files (default: no)
- Whether to create
.bakbackups (default: yes)
Python CLI args (non-interactive):
python replace_user_tag.py --dir "C:\path" --user "New User" --update-ini
- Python version uses only standard library
- Both versions create
.bakbackups by default - INI file updates are opt-in (must explicitly confirm)
- Updates
name="..."line in[User]section ofexp_*_sample.inifiles