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.
@@ -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())