Skip to main content

SWORDlib is a Python library based on SWORD - Symmetry and Wyckoff-sequence of Ordered and Disordered crystals.

Project description

SWORDlib

SWORDlib provides tools for generating SWORD labels from ordered and disordered crystal structures. A SWORD label combines symmetry, standardized Wyckoff sequence information, and site-occupancy disorder information into a compact representation that can be used for structure grouping, disorder curation, and order-disorder family matching.

This package is the installable Python package form of SWORD:

Installation

pip install SWORDlib

Core SWORD Labelling

import sword

Use get_sword_label when you only need the compact label.

from sword import get_sword_label

label = get_sword_label("path/to/structure.cif")
print(label)

The input can be a CIF string, a CIF path, or a pymatgen.core.Structure.

Use get_sword_info when you also need the parsed entry and diagnostic metadata.

from sword import get_sword_info

entry, info = get_sword_info(
    cif_text,
    parser_occ_tolerance=1.05,
    occ_tolerance=1.0,
    site_tolerance=1e-4,
    vac_tolerance=1e-2,
    frac_tolerance=1e-4,
)

print(info["disorder_label"])
print(info["is_disorder"])
print(info["degree_of_mixing"])

The main labelling parameters are:

  • symprec: symmetry tolerance used during structure standardization. See pymatgen/spglib documentation for detailed behavior.
  • angle_tolerance: angular tolerance, in degrees, used during symmetry standardization. See pymatgen documentation for details.
  • site_tolerance: distance tolerance for deciding whether two sites should be treated as the same disorder site.
  • occ_tolerance: SWORD's post-parsing occupancy tolerance for each grouped orbit/site. Occupancy sums above this value are reported as occupancy-orbit errors.
  • vac_tolerance: minimum missing occupancy needed to record a VAC component in the disorder label. For example, an occupancy sum of 0.995 does not produce VAC when vac_tolerance=1e-2.
  • frac_tolerance: rounding tolerance used in fractional-coordinate and disorder-label operations. Values like 1e-4 or 1e-5 are recommended.
  • conventional_struct: whether to use pymatgen's conventionalized structure during the SWORD parsing path.
  • refine_struct: whether to let pymatgen refine the structure before labelling. This can change labels and should be used deliberately.

Two occupancy-related parameters are intentionally separate. parser_occ_tolerance: occupancy tolerance passed to pymatgen's CIF parser. Acts before SWORD, while the CIF is being read. occ_tolerance: SWORD's post-parsing occupancy tolerance for each grouped orbit/site. Occupancy sums above this value are reported as occupancy-orbit errors. For ICSD curation, a common choice is parser_occ_tolerance=1.05 and occ_tolerance=1.0.

ICSD Curation Pipeline

run_icsd_dedup_pipeline provides a high-level workflow for ICSD dataframes containing a CIF text column and a stable entry ID column.

import pandas as pd
from sword import run_icsd_dedup_pipeline

df = pd.read_pickle("ICSD2025_summary.pkl")

result = run_icsd_dedup_pipeline(
    df,
    cif_col="cif",
    id_col="CollectionCode",
    mode="from_collection_code",
    prescreen_params={
        "parser_occ_tolerance": 1.05,
        "excluded_elements": ("He", "Ne", "Ar", "Kr", "Es"),
        "exclude_hydrogen": True,
    },
    sword_params={
        "parser_occ_tolerance": 1.05,
        "occ_tolerance": 1.0,
        "site_tolerance": 1e-4,
        "vac_tolerance": 1e-2,
        "frac_tolerance": 1e-4,
    },
    family_info=False,
    dom_distance_tol=0.03,
    output_dir="sword_icsd_results",
)

The result object contains:

  • result.prescreen_rejected: entries removed before labelling, with reject reasons.
  • result.label_results: the labelled dataframe with SWORD labels and compact diagnostics.
  • result.anomalies: detailed warning/error tables.
  • result.label_groups: grouped SWORD-label summary table.
  • result.refined: curated and deduplicated entries.

result.prescreen_rejected["reject_reason"] records why a row did not enter the labelling stage. Possible reasons include:

  • parse_error: the CIF block could not be read by pymatgen.
  • hydrogen: the CIF site labels contain H, D, or T when exclude_hydrogen=True.
  • non_element: the CIF site labels contain unsupported/non-element symbols or elements listed in excluded_elements.
  • coordinate_error: fractional coordinates are missing or malformed.
  • wyckoff_error: Wyckoff symbols are missing or malformed.
  • multiplicity_error: site multiplicities are missing or malformed.
  • occupancy_error: a raw site occupancy is missing, non-positive, or larger than parser_occ_tolerance.

result.label_results["processing_issue"] records semicolon-separated warning or error flags generated during labelling. None means no issue was recorded. The detailed rows are stored in result.anomalies and, when output_dir is provided, saved under anomalies/:

  • label_errors: hard failures during structure parsing or SWORD label generation. The compact flag: structure_parse_failed or label_generation_failed.
  • wyck_float_warn: Wyckoff coordinate expansion gives more positions than the declared multiplicity, usually indicating floating-point or refinement issues in the CIF. The compact flag: wyckoff_float_warning.
  • occ_err_sites: grouped orbit/site occupancy exceeds occ_tolerance. The compact flag: occupancy_orbit_error.
  • equivalent_but_distinct_sites: sites are symmetry-equivalent but have distinct representative coordinates, often because the CIF coordinates are not exactly on the expected special position. The compact flag: equivalent_sites_warning.
  • same_valence_sites: same-element/same-valence co-occupancy was detected and merged for labelling. The compact flag is same_valence_site_warning.
  • intersect_orb_errors: the positional-disorder check failed. The compact flag is positional_check_failed. Positional disorder itself is recorded in is_positional_disorder.

By default, the refined table removes hard parse/label errors, positional disorder, occupancy-orbit errors, Wyckoff floating-point warnings, and equivalent-site warnings. Same-valence warnings are recorded but not removed by default.

Set family_info=True to append a SWORD_family_dic column to result.label_results. This is slower and usually not needed for a first ICSD curation pass.

result = run_icsd_dedup_pipeline(
    df,
    family_info=True,
    family_params={
        "parser_occ_tolerance": 10.0,
        "fill_vacancy": False,
    },
)

family_params must be a dictionary accepted by SWORDFamilyMatcher. Use fill_vacancy=False for most large reference-table precomputations such as ICSD/COD. Set fill_vacancy=True mainly for query-side ordered structure datasets/databases that may contain vacancy ordering or missing-site defects, e.g. Materials Project, LeMat-Bulk, where filling possible vacancies can help expose candidate disorder parents.

Generic Database Labelling

For non-ICSD databases, use label_dataframe. The dataframe only needs a CIF text column and a stable ID column.

from sword import label_dataframe

labelled, anomalies = label_dataframe(
    df,
    cif_col="cif",
    id_col="material_id",
    sword_params={
        "parser_occ_tolerance": 1.05,
        "occ_tolerance": 1.0,
        "site_tolerance": 1e-4,
        "vac_tolerance": 1e-2,
        "frac_tolerance": 1e-4,
    },
    family_info=False,
)

print(labelled[["material_id", "SWORD_label", "is_disorder"]])

This interface is appropriate for MP, LeMat, or user-built structure tables when each row can provide a CIF string.

Set family_info=True if you also want family dictionaries:

labelled, anomalies = label_dataframe(
    df,
    cif_col="cif",
    id_col="material_id",
    family_info=True,
    family_params={
        "symprec_child": 1e-2,
        "symprec_search": 1.0,
        "parser_occ_tolerance": 10.0,
        "fill_vacancy": False,   #turn on to True if this dataset may contain vacancy ordering and you want to find disordered parent structure of this vacancy-type ordered structure
    },
)

print(labelled[["material_id", "SWORD_label", "SWORD_family_dic"]])

Order-Disorder Family Matching

SWORDFamilyMatcher can generate a SWORD family dictionary for an ordered query structure and search for possible disordered parent labels.

from sword import SWORDFamilyMatcher

matcher = SWORDFamilyMatcher(
    symprec_child=1e-2,
    symprec_search=1.0,
    parser_occ_tolerance=10.0,
    fill_vacancy=False,
)

family = matcher.get_sword_dic("path/to/ordered_query.cif")

print(family["child_label"])
print(family["parent_labels"])

For repeated searches, precompute a family dictionary column for the reference table. This can be slow for large datasets, so it is usually done once and saved. For large reference tables, keep fill_vacancy=False unless you explicitly want the reference-side vacancy-filling expansion.

from sword import SWORDFamilyMatcher

matcher = SWORDFamilyMatcher(fill_vacancy=False)

reference_df["SWORD_family_dic"] = reference_df["cif"].apply(
    matcher.get_sword_dic
)

Then compare a query against the reference table:

matches = matcher.fit_many(query_structure, reference_df)

print(matches["matched_disordered_ids"])
print(matches["matched_disordered_labels"])

By default, fit_many reads reference_df["SWORD_family_dic"]. If the query is a dataframe row with SWORD_family_dic and SWORD_family_dic_vac, both query columns are used and matches["matched_source_by_id"] records which query column produced each match.

fill_vacancy=True can be useful when ordered structures may represent vacancy ordering variants. In practice, this is most useful for query structures that are ordered but may be vacancy-ordered or vacancy-deficient variants. For large ICSD-style reference precomputation, fill_vacancy=False is usually a better default because it is faster and avoids generating extra vacancy-filled candidates for every entry.

Notes

SWORD labels are intended for symmetry- and Wyckoff-aware grouping of materials structures. They are especially useful for comparing ordered and disordered entries under a common structural representation, but they do not replace manual crystallographic judgment for ambiguous or low-quality CIF records.

Citation

If you use SWORDlib, please cite our papers:

@article{huang2026sword,
  title   = {SWORD: Symmetry and Wyckoff-sequence of Ordered and Disordered crystals},
  author  = {Huang, Yuyao and Nong, Wei and Yamazaki, Shuya and Petersen, Martin Hoffmann and Wang, Jianghai and Zhu, Ruiming and Hippalgaonkar, Kedar},
  journal = {arXiv preprint arXiv:2604.17994},
  year    = {2026},
  url     = {https://arxiv.org/abs/2604.17994},
  doi     = {10.48550/arXiv.2604.17994}
}

For family-matching functions, please cite:

@article{yamazaki2026orderdisorder,
  title   = {Navigating Order-(Dis)Order Family Trees via Group-Subgroup Transitions},
  author  = {Yamazaki, Shuya and Huang, Yuyao and Petersen, Martin Hoffmann and Nong, Wei and Hippalgaonkar, Kedar},
  journal = {arXiv preprint arXiv:2604.21386},
  year    = {2026},
  url     = {https://arxiv.org/abs/2604.21386},
  doi     = {10.48550/arXiv.2604.21386}
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

swordlib-0.1.0.tar.gz (55.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

swordlib-0.1.0-py3-none-any.whl (58.1 kB view details)

Uploaded Python 3

File details

Details for the file swordlib-0.1.0.tar.gz.

File metadata

  • Download URL: swordlib-0.1.0.tar.gz
  • Upload date:
  • Size: 55.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.17

File hashes

Hashes for swordlib-0.1.0.tar.gz
Algorithm Hash digest
SHA256 0c909a5a5e75ea6d058955dae55c49cb3b49052c3afeec8a16c3df54dff37bcb
MD5 9e2c6dcdbbf9176f0f34494c1daddeed
BLAKE2b-256 fe6d93fed64f4be0386a61525e79928a21176b6ab156c986dcd55487d5a10508

See more details on using hashes here.

File details

Details for the file swordlib-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: swordlib-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 58.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.17

File hashes

Hashes for swordlib-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 40ff74916bd42a2bb69118d2d943615d5370b34dfc244d4d2cb2d8fc82ff5b5c
MD5 3db0136c3a3c89cf4e7c35a99b0209c5
BLAKE2b-256 c3c3540186b135b3d86c500b66a51b0a62d2b6ab33ebdad3cd006686cd8261e7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page