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 aVACcomponent in the disorder label. For example, an occupancy sum of 0.995 does not produceVACwhenvac_tolerance=1e-2.frac_tolerance: rounding tolerance used in fractional-coordinate and disorder-label operations. Values like1e-4or1e-5are 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 whenexclude_hydrogen=True.non_element: the CIF site labels contain unsupported/non-element symbols or elements listed inexcluded_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 thanparser_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_failedorlabel_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 exceedsocc_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 issame_valence_site_warning.intersect_orb_errors: the positional-disorder check failed. The compact flag ispositional_check_failed. Positional disorder itself is recorded inis_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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c909a5a5e75ea6d058955dae55c49cb3b49052c3afeec8a16c3df54dff37bcb
|
|
| MD5 |
9e2c6dcdbbf9176f0f34494c1daddeed
|
|
| BLAKE2b-256 |
fe6d93fed64f4be0386a61525e79928a21176b6ab156c986dcd55487d5a10508
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40ff74916bd42a2bb69118d2d943615d5370b34dfc244d4d2cb2d8fc82ff5b5c
|
|
| MD5 |
3db0136c3a3c89cf4e7c35a99b0209c5
|
|
| BLAKE2b-256 |
c3c3540186b135b3d86c500b66a51b0a62d2b6ab33ebdad3cd006686cd8261e7
|