midas-hkls 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- midas_hkls-0.1.0/PKG-INFO +90 -0
- midas_hkls-0.1.0/README.md +74 -0
- midas_hkls-0.1.0/midas_hkls/__init__.py +27 -0
- midas_hkls-0.1.0/midas_hkls/cli.py +102 -0
- midas_hkls-0.1.0/midas_hkls/data/space_groups.json +4772 -0
- midas_hkls-0.1.0/midas_hkls/hall.py +319 -0
- midas_hkls-0.1.0/midas_hkls/hkl_gen.py +124 -0
- midas_hkls-0.1.0/midas_hkls/lattice.py +97 -0
- midas_hkls-0.1.0/midas_hkls/space_group.py +203 -0
- midas_hkls-0.1.0/midas_hkls/symops.py +168 -0
- midas_hkls-0.1.0/midas_hkls/tables.py +96 -0
- midas_hkls-0.1.0/midas_hkls.egg-info/PKG-INFO +90 -0
- midas_hkls-0.1.0/midas_hkls.egg-info/SOURCES.txt +20 -0
- midas_hkls-0.1.0/midas_hkls.egg-info/dependency_links.txt +1 -0
- midas_hkls-0.1.0/midas_hkls.egg-info/entry_points.txt +2 -0
- midas_hkls-0.1.0/midas_hkls.egg-info/requires.txt +8 -0
- midas_hkls-0.1.0/midas_hkls.egg-info/top_level.txt +1 -0
- midas_hkls-0.1.0/pyproject.toml +43 -0
- midas_hkls-0.1.0/setup.cfg +4 -0
- midas_hkls-0.1.0/tests/test_c_parity.py +105 -0
- midas_hkls-0.1.0/tests/test_cli.py +43 -0
- midas_hkls-0.1.0/tests/test_unit.py +124 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: midas-hkls
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Pure-Python crystallography & HKL list generator. sginfo-equivalent: 230 space groups via Hall-symbol parser.
|
|
5
|
+
Author: MIDAS contributors
|
|
6
|
+
License: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/marinerhemant/MIDAS
|
|
8
|
+
Requires-Python: >=3.9
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: numpy>=1.22
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
13
|
+
Requires-Dist: pandas>=1.5; extra == "dev"
|
|
14
|
+
Provides-Extra: cif
|
|
15
|
+
Requires-Dist: pycifrw>=4.4; extra == "cif"
|
|
16
|
+
|
|
17
|
+
# midas-hkls
|
|
18
|
+
|
|
19
|
+
Pure-Python crystallography & HKL list generator. **sginfo-equivalent**: all 230
|
|
20
|
+
space groups via Hall-symbol parsing, no C dependencies at runtime.
|
|
21
|
+
|
|
22
|
+
## What it provides
|
|
23
|
+
|
|
24
|
+
- `SpaceGroup` — load by number, Hermann-Mauguin symbol, or Hall symbol; expose
|
|
25
|
+
symmetry operations, systematic absences, equivalent reflections, multiplicities,
|
|
26
|
+
Laue class, centering.
|
|
27
|
+
- `Lattice` — direct/reciprocal metric tensors, d-spacings, Bragg 2θ, with
|
|
28
|
+
per-crystal-system convenience constructors.
|
|
29
|
+
- `generate_hkls()` — enumerate Laue-unique allowed reflections within a
|
|
30
|
+
d-spacing or 2θ cutoff, sorted by d-descending, with multiplicities.
|
|
31
|
+
- CLI: `midas-hkls gen|info|list` (drop-in for `GetHKLList`).
|
|
32
|
+
|
|
33
|
+
## Quick start
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from midas_hkls import SpaceGroup, Lattice, generate_hkls
|
|
37
|
+
|
|
38
|
+
sg = SpaceGroup.from_number(225) # CeO₂ / Cu / Au / NaCl (Fm-3m)
|
|
39
|
+
lat = Lattice.for_system("cubic", a=5.411) # Å
|
|
40
|
+
refs = generate_hkls(sg, lat, wavelength_A=0.173, two_theta_max_deg=15.0)
|
|
41
|
+
|
|
42
|
+
for r in refs:
|
|
43
|
+
print(r.ring_nr, (r.h, r.k, r.l), r.d_spacing, r.two_theta_deg, r.multiplicity)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## CLI
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
midas-hkls gen --sg 225 --lat 5.411 5.411 5.411 90 90 90 --wavelength 0.173 \
|
|
50
|
+
--two-theta-max 15.0 -o ceo2.csv
|
|
51
|
+
midas-hkls info --sg "Fm-3m" --ops
|
|
52
|
+
midas-hkls list
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Parity with sginfo C library
|
|
56
|
+
|
|
57
|
+
`midas-hkls` is parity-tested byte-for-byte against MIDAS's `GetHKLList` (sginfo):
|
|
58
|
+
|
|
59
|
+
- Ring count, ring d-spacing, ring 2θ, ring multiplicity match exactly across
|
|
60
|
+
CeO₂, LaB₆, Si, α-Fe, α-Ti, calcite, Pnma, P21/c.
|
|
61
|
+
- All 230 space groups parse without error and have correct Friedel-corrected
|
|
62
|
+
Laue-class group orders.
|
|
63
|
+
|
|
64
|
+
Run `pytest` to exercise the parity matrix.
|
|
65
|
+
|
|
66
|
+
## Conventions
|
|
67
|
+
|
|
68
|
+
- Lattice constants in Å; angles in degrees.
|
|
69
|
+
- Wavelengths in Å.
|
|
70
|
+
- Symmetry operations stored as integer Seitz matrices over translation base
|
|
71
|
+
STBF=12 (so 1/2 → 6, 1/3 → 4, 1/4 → 3, etc.) — exact-arithmetic absence
|
|
72
|
+
detection, no float fuzz.
|
|
73
|
+
- Equivalent HKLs include Friedel pairs (centric structure factor under X-ray
|
|
74
|
+
Laue symmetry).
|
|
75
|
+
|
|
76
|
+
## Roadmap (post v0.1.0)
|
|
77
|
+
|
|
78
|
+
- CIF reader (`io/cif.py`).
|
|
79
|
+
- Atomic form factors (Cromer-Mann) and structure factors.
|
|
80
|
+
- Anomalous scattering (Henke / Cromer tables).
|
|
81
|
+
- Wyckoff positions tables (currently only general position is exposed).
|
|
82
|
+
- Origin-choice and alternate-setting transformations beyond what sginfo's
|
|
83
|
+
`extension` field provides.
|
|
84
|
+
|
|
85
|
+
## Origin
|
|
86
|
+
|
|
87
|
+
The 530-entry Hall-symbol table is extracted verbatim from sginfo
|
|
88
|
+
(© 1994-96 Ralf W. Grosse-Kunstleve, public domain) so that midas-hkls and
|
|
89
|
+
MIDAS's existing C tools resolve the same standard setting for every space
|
|
90
|
+
group.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# midas-hkls
|
|
2
|
+
|
|
3
|
+
Pure-Python crystallography & HKL list generator. **sginfo-equivalent**: all 230
|
|
4
|
+
space groups via Hall-symbol parsing, no C dependencies at runtime.
|
|
5
|
+
|
|
6
|
+
## What it provides
|
|
7
|
+
|
|
8
|
+
- `SpaceGroup` — load by number, Hermann-Mauguin symbol, or Hall symbol; expose
|
|
9
|
+
symmetry operations, systematic absences, equivalent reflections, multiplicities,
|
|
10
|
+
Laue class, centering.
|
|
11
|
+
- `Lattice` — direct/reciprocal metric tensors, d-spacings, Bragg 2θ, with
|
|
12
|
+
per-crystal-system convenience constructors.
|
|
13
|
+
- `generate_hkls()` — enumerate Laue-unique allowed reflections within a
|
|
14
|
+
d-spacing or 2θ cutoff, sorted by d-descending, with multiplicities.
|
|
15
|
+
- CLI: `midas-hkls gen|info|list` (drop-in for `GetHKLList`).
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from midas_hkls import SpaceGroup, Lattice, generate_hkls
|
|
21
|
+
|
|
22
|
+
sg = SpaceGroup.from_number(225) # CeO₂ / Cu / Au / NaCl (Fm-3m)
|
|
23
|
+
lat = Lattice.for_system("cubic", a=5.411) # Å
|
|
24
|
+
refs = generate_hkls(sg, lat, wavelength_A=0.173, two_theta_max_deg=15.0)
|
|
25
|
+
|
|
26
|
+
for r in refs:
|
|
27
|
+
print(r.ring_nr, (r.h, r.k, r.l), r.d_spacing, r.two_theta_deg, r.multiplicity)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## CLI
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
midas-hkls gen --sg 225 --lat 5.411 5.411 5.411 90 90 90 --wavelength 0.173 \
|
|
34
|
+
--two-theta-max 15.0 -o ceo2.csv
|
|
35
|
+
midas-hkls info --sg "Fm-3m" --ops
|
|
36
|
+
midas-hkls list
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Parity with sginfo C library
|
|
40
|
+
|
|
41
|
+
`midas-hkls` is parity-tested byte-for-byte against MIDAS's `GetHKLList` (sginfo):
|
|
42
|
+
|
|
43
|
+
- Ring count, ring d-spacing, ring 2θ, ring multiplicity match exactly across
|
|
44
|
+
CeO₂, LaB₆, Si, α-Fe, α-Ti, calcite, Pnma, P21/c.
|
|
45
|
+
- All 230 space groups parse without error and have correct Friedel-corrected
|
|
46
|
+
Laue-class group orders.
|
|
47
|
+
|
|
48
|
+
Run `pytest` to exercise the parity matrix.
|
|
49
|
+
|
|
50
|
+
## Conventions
|
|
51
|
+
|
|
52
|
+
- Lattice constants in Å; angles in degrees.
|
|
53
|
+
- Wavelengths in Å.
|
|
54
|
+
- Symmetry operations stored as integer Seitz matrices over translation base
|
|
55
|
+
STBF=12 (so 1/2 → 6, 1/3 → 4, 1/4 → 3, etc.) — exact-arithmetic absence
|
|
56
|
+
detection, no float fuzz.
|
|
57
|
+
- Equivalent HKLs include Friedel pairs (centric structure factor under X-ray
|
|
58
|
+
Laue symmetry).
|
|
59
|
+
|
|
60
|
+
## Roadmap (post v0.1.0)
|
|
61
|
+
|
|
62
|
+
- CIF reader (`io/cif.py`).
|
|
63
|
+
- Atomic form factors (Cromer-Mann) and structure factors.
|
|
64
|
+
- Anomalous scattering (Henke / Cromer tables).
|
|
65
|
+
- Wyckoff positions tables (currently only general position is exposed).
|
|
66
|
+
- Origin-choice and alternate-setting transformations beyond what sginfo's
|
|
67
|
+
`extension` field provides.
|
|
68
|
+
|
|
69
|
+
## Origin
|
|
70
|
+
|
|
71
|
+
The 530-entry Hall-symbol table is extracted verbatim from sginfo
|
|
72
|
+
(© 1994-96 Ralf W. Grosse-Kunstleve, public domain) so that midas-hkls and
|
|
73
|
+
MIDAS's existing C tools resolve the same standard setting for every space
|
|
74
|
+
group.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""midas-hkls — pure-Python crystallography & HKL list generator.
|
|
2
|
+
|
|
3
|
+
sginfo-equivalent (Ralf W. Grosse-Kunstleve, 1994-96) via Hall-symbol parsing.
|
|
4
|
+
Public API:
|
|
5
|
+
|
|
6
|
+
from midas_hkls import SpaceGroup, Lattice, generate_hkls, Reflection
|
|
7
|
+
|
|
8
|
+
sg = SpaceGroup.from_number(225) # CeO2 / NaCl / Cu / Au
|
|
9
|
+
lat = Lattice.for_system("cubic", a=5.411)
|
|
10
|
+
refs = generate_hkls(sg, lat, wavelength_A=0.173, two_theta_max_deg=20.0)
|
|
11
|
+
"""
|
|
12
|
+
from .hkl_gen import Reflection, generate_hkls, reflections_to_dataframe
|
|
13
|
+
from .lattice import Lattice
|
|
14
|
+
from .space_group import SpaceGroup, list_space_groups
|
|
15
|
+
from .symops import SymOp
|
|
16
|
+
|
|
17
|
+
__version__ = "0.1.0"
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"Lattice",
|
|
21
|
+
"Reflection",
|
|
22
|
+
"SpaceGroup",
|
|
23
|
+
"SymOp",
|
|
24
|
+
"generate_hkls",
|
|
25
|
+
"list_space_groups",
|
|
26
|
+
"reflections_to_dataframe",
|
|
27
|
+
]
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""Command-line interface — drop-in replacement for GetHKLList."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import csv
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Sequence
|
|
9
|
+
|
|
10
|
+
from .hkl_gen import generate_hkls
|
|
11
|
+
from .lattice import Lattice
|
|
12
|
+
from .space_group import SpaceGroup, list_space_groups
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _build_parser() -> argparse.ArgumentParser:
|
|
16
|
+
p = argparse.ArgumentParser(prog="midas-hkls", description="Generate HKL list (sginfo replacement)")
|
|
17
|
+
sub = p.add_subparsers(dest="cmd", required=True)
|
|
18
|
+
|
|
19
|
+
g = sub.add_parser("gen", help="Generate an HKL list")
|
|
20
|
+
g.add_argument("--sg", required=True, help="Space group: number, HM symbol, or Hall symbol")
|
|
21
|
+
g.add_argument("--lat", nargs=6, type=float, metavar=("a", "b", "c", "alpha", "beta", "gamma"),
|
|
22
|
+
required=True, help="Lattice constants (Å, Å, Å, deg, deg, deg)")
|
|
23
|
+
g.add_argument("--wavelength", type=float, required=True, help="X-ray wavelength (Å)")
|
|
24
|
+
g.add_argument("--two-theta-max", type=float, default=None, help="Maximum 2θ in degrees")
|
|
25
|
+
g.add_argument("--d-min", type=float, default=None, help="Minimum d-spacing in Å")
|
|
26
|
+
g.add_argument("--output", "-o", type=Path, default=None, help="CSV output path (default: stdout)")
|
|
27
|
+
g.add_argument("--ext", default="", help="Setting extension (sginfo extension code)")
|
|
28
|
+
|
|
29
|
+
sub.add_parser("list", help="List all 230 space groups in the canonical table")
|
|
30
|
+
|
|
31
|
+
info = sub.add_parser("info", help="Print space group info (operations, centering, Laue)")
|
|
32
|
+
info.add_argument("--sg", required=True, help="Space group: number, HM, or Hall")
|
|
33
|
+
info.add_argument("--ops", action="store_true", help="Print all symmetry operations")
|
|
34
|
+
|
|
35
|
+
return p
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _resolve_space_group(spec: str, ext: str = "") -> SpaceGroup:
|
|
39
|
+
spec = spec.strip()
|
|
40
|
+
if spec.isdigit():
|
|
41
|
+
return SpaceGroup.from_number(int(spec), extension=ext)
|
|
42
|
+
if " " in spec or spec.startswith("-"):
|
|
43
|
+
return SpaceGroup.from_hall(spec)
|
|
44
|
+
try:
|
|
45
|
+
return SpaceGroup.from_hm(spec)
|
|
46
|
+
except ValueError:
|
|
47
|
+
return SpaceGroup.from_hall(spec)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _emit_csv(refs, fp) -> None:
|
|
51
|
+
w = csv.writer(fp)
|
|
52
|
+
w.writerow(["ring_nr", "h", "k", "l", "d_spacing", "two_theta_deg", "multiplicity"])
|
|
53
|
+
for r in refs:
|
|
54
|
+
w.writerow([r.ring_nr, r.h, r.k, r.l, f"{r.d_spacing:.8g}",
|
|
55
|
+
f"{r.two_theta_deg:.8g}", r.multiplicity])
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def main(argv: Sequence[str] | None = None) -> int:
|
|
59
|
+
args = _build_parser().parse_args(argv)
|
|
60
|
+
|
|
61
|
+
if args.cmd == "list":
|
|
62
|
+
for num, hall, hm in list_space_groups():
|
|
63
|
+
print(f"{num:>3} {hall:<28} {hm}")
|
|
64
|
+
return 0
|
|
65
|
+
|
|
66
|
+
if args.cmd == "info":
|
|
67
|
+
sg = _resolve_space_group(args.sg)
|
|
68
|
+
print(f"Number : {sg.number}")
|
|
69
|
+
print(f"Hall symbol : {sg.hall_symbol!r}")
|
|
70
|
+
print(f"HM symbol : {sg.hm_symbol!r}")
|
|
71
|
+
print(f"Crystal sys : {sg.crystal_system}")
|
|
72
|
+
print(f"Laue class : {sg.laue_class}")
|
|
73
|
+
print(f"Centering : {sg.centering}")
|
|
74
|
+
print(f"Order : {sg.order}")
|
|
75
|
+
print(f"Centric : {sg.is_centrosymmetric()}")
|
|
76
|
+
if args.ops:
|
|
77
|
+
for i, op in enumerate(sg.operations):
|
|
78
|
+
print(f" {i + 1:3d}: {op.to_xyz()}")
|
|
79
|
+
return 0
|
|
80
|
+
|
|
81
|
+
if args.cmd == "gen":
|
|
82
|
+
sg = _resolve_space_group(args.sg, ext=args.ext)
|
|
83
|
+
lat = Lattice(*args.lat)
|
|
84
|
+
refs = generate_hkls(
|
|
85
|
+
sg, lat,
|
|
86
|
+
wavelength_A=args.wavelength,
|
|
87
|
+
d_min=args.d_min,
|
|
88
|
+
two_theta_max_deg=args.two_theta_max,
|
|
89
|
+
)
|
|
90
|
+
if args.output is None:
|
|
91
|
+
_emit_csv(refs, sys.stdout)
|
|
92
|
+
else:
|
|
93
|
+
with args.output.open("w", newline="") as fp:
|
|
94
|
+
_emit_csv(refs, fp)
|
|
95
|
+
print(f"Wrote {len(refs)} reflections to {args.output}", file=sys.stderr)
|
|
96
|
+
return 0
|
|
97
|
+
|
|
98
|
+
return 1
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
if __name__ == "__main__":
|
|
102
|
+
sys.exit(main())
|