Refactor/ase first - #61
Merged
Merged
Conversation
…, use ASE Atoms with C++ descriptors
atoms_to_dict() now passes numpy arrays directly instead of converting to Python lists via .tolist(). pybind11 handles the conversion automatically. This eliminates ~27ms of overhead per descriptor call for a 4000-atom system. Before: atoms_to_dict = 27ms, steinhardt q6 FCC 4000 = 36ms After: atoms_to_dict = 0.01ms, steinhardt q6 FCC 4000 = 18ms All descriptors now match or beat the old v3.3.1 API performance.
…order to C++ Moved 4 pure Python descriptor methods to C++ (puremath.cpp): - chi_params: 22-25x faster (523ms → 23ms at 4000 atoms) - voronoi_vector: 24-25x faster (468ms → 19ms at 4000 atoms) - short_range_order: 9x faster (21ms → 2.3ms at 4000 atoms) - angular_criteria: 2.8x faster (52ms → 18ms at 4000 atoms) Also fixes a floating-point bug where cosines slightly below -1.0 (from FP rounding) were silently dropped by numpy histogram. Cosines are now properly clamped to [-1, 1].
- Replace 16 legacy notebooks with 13 focused tutorials - Notebooks cover full API: neighbors, Steinhardt, CNA, Voronoi, disorder, angular/chi, centrosymmetry, entropy, SRO, solid/liquid clustering, and trajectory module - Remove unused data files (Al.eam.fs, Mo.set, conf.bcc, etc.) - Remove scratch notebooks from repo root - All 13 notebooks execute cleanly; all 54 tests pass
- Create docs/api.md with autodoc for all 16 public functions + Trajectory - Enable sphinx.ext.autodoc, autosummary, napoleon in _config.yml - Fix _config.yml repository URL (was pointing to wrong repo) - Fix _toc.yml to reference 13 new notebooks (was pointing to 16 deleted ones) - Rewrite docs/intro.md: ASE-first description, quick start, feature list - Update docs/index.rst: clean badges, new toctree - Update docs/examples.md: correct notebook links and descriptions - Update docs/methods_landing.md: correct example links - Update docs/gettingstarted.md: Windows support, simplified install - Add Returns section to find_neighbors docstring (documents stored keys) - Improve Trajectory/Timeslice class docstrings with full numpydoc - Remove stale pyscal.rst, modules.rst, prologue/api.md
…-arch tests - Tests used relative paths (e.g. 'tests/files/...') which fail when cibuildwheel runs pytest from a temp directory. Fixed all 4 test files to resolve paths relative to __file__. - Removed deprecated macos-13 runner from deploy.yml matrix. - Added test-skip for x86_64 on macOS (arm64 runner can't run x86_64) and aarch64 on Linux (QEMU too slow for scipy/spglib).
manylinux2014 (CentOS 7) has old pip/SSL that fails to install dependencies like ase/numpy in cibuildwheel test containers. manylinux_2_28 (AlmaLinux 8) is the recommended image for new projects and has a modern toolchain.
Building C++ under QEMU emulation takes 30-60 min. ARM Linux users can install from the source distribution instead.
Implement W_l, W-hat_l (normalized), and neighbor-averaged variants (Lechner-Dellago) via Wigner 3j symbols using the Racah formula. C++ (sh.cpp): - factorial_int(), wigner3j(l, m1, m2, m3) via Racah formula - calculate_w_single(): per-atom W_l and W-hat_l - calculate_aw_single(): neighbor-averaged versions Python (descriptors.py): - wigner_w_parameter(atoms, l, averaged, normalized) Tests (12 new): FCC/BCC/HCP match Steinhardt 1983 Table I values: FCC W-hat_6 = -0.01316, BCC W-hat_6 = +0.01316, HCP = -0.01244 References: Steinhardt, Nelson & Ronchetti, Phys. Rev. B 28, 784 (1983) Lechner & Dellago, J. Chem. Phys. 129, 114707 (2008)
Expose pyscal3.minkowski_parameter(atoms, l, voroexp=1, averaged=False) which computes Voronoi face-area weighted Steinhardt parameters. The existing C++ infrastructure already supports weighted Y_lm sums via the neighborweight array — this function provides a clean API that automatically performs Voronoi neighbor finding with the requested face-area exponent and delegates to steinhardt_parameter. Validated against Mickel et al. (2013) Table I: FCC: q4=0.1909, q6=0.5745 (exact match) BCC: q4=0.2240, q6=0.5669 (14-neighbor Voronoi tessellation) HCP: q4=0.0972, q6=0.4848 Tests: 11 tests covering reference values, multi-l, averaged mode, voroexp variation, FCC/BCC discrimination, noise sensitivity. Example notebook: 15_minkowski_structure_metrics.ipynb Reference: Mickel, Kapfer, Schröder-Turk & Mecke, J. Chem. Phys. 138, 044501 (2013). doi:10.1063/1.4774084
This was referenced Feb 28, 2026
Implement identify_ackland_jones(atoms) which classifies each atom as FCC (1), HCP (2), BCC (3), ICO (4), or other (0) using a decision tree on the chi-parameter histogram. No new C++ code - classification is a vectorized numpy decision tree operating on the existing chi-parameter output. Tests: 10 tests, Example notebook: 16_ackland_jones_classification.ipynb Reference: Ackland and Jones, Phys. Rev. B 73, 054104 (2006)
Add four coordination descriptors as pure Python functions: - coordination_number(atoms): simple integer neighbor count - effective_coordination_number(atoms): distance-weighted ECoN (Hoppe 1979) using iterative self-consistent weighting exp(1 - (d/d_avg)^6) - generalized_coordination_number(atoms, cn_max): GCN accounting for neighbor coordination (Calle-Vallejo et al., Science 350, 185, 2015) - local_density(atoms): local atomic number density from mean neighbor distance All functions operate on pre-computed neighbor data (no new C++ code). Results stored in atoms.arrays with pyscal_ prefix. Tests: 13 tests. Notebook: 17_coordination_variants.ipynb
New descriptors: - angular_distribution_function(): histogram of all bond angles theta_jik formed by neighbor pairs around each atom - bond_length_distribution(): histogram of neighbor distances (like RDF but without shell-volume normalisation) Both are pure-Python wrappers (no C++ changes needed): - ADF reuses chi_params(angles=True) cosine computation - BLDF uses existing pyscal_neighbordist neighbor data Validated: FCC peaks at 60/90/120/180 deg; BCC at ~70.5/109.5 deg 13 tests, example notebook 18_angular_bond_distributions.ipynb
New deformation descriptors (require reference configuration): - atomic_strain(): Green-Lagrange strain tensor per atom - von_mises_strain(): scalar shear strain invariant - d2min(): Falk-Langer non-affine squared displacement - slip_vector(): average neighbor displacement difference Pure Python implementation (least-squares deformation gradient fit). 14 tests, example notebook 21_deformation_descriptors.ipynb
New Wigner-Seitz cell defect analysis: - wigner_seitz_analysis(): assign atoms to nearest reference lattice sites - identify_defect_atoms(): convenience wrapper with defect masks Features: - Vacancy detection (empty sites) - Interstitial detection (multiply-occupied sites) - Antisite tracking via per_type_occupancies - Affine mapping for thermal expansion - PBC via periodic image expansion Pure Python with scipy.spatial.cKDTree for O(N log N) performance. 17 tests, example notebook 22_wigner_seitz_defects.ipynb
Implements ACE descriptors following Drautz (2019), providing a unified framework that includes SOAP (nu=2) and bispectrum (nu=3) as special cases. Features: - A-basis (single-particle) coefficient computation - B-basis rotation-invariant descriptors for nu=1,2,3 - Chebyshev polynomial radial basis with cosine cutoff - Spherical harmonics angular basis via scipy - Configurable nmax, lmax, nu_max parameters - Optional normalization The descriptor count scales as: - nu=1: O(nmax) - radial density - nu=2: O(nmax² × lmax) - power spectrum - nu=3: O(nmax³ × lmax³) - triplet correlations (limited)
- Replace skipped rotation test with two working variants: 1. Cubic symmetry operation (90° z rotation, orthogonal cell) 2. Arbitrary 37° rotation using cluster-in-large-box technique - Both pass with machine-precision agreement (~1e-15) - Root cause of original failure: neighbor finder breaks on non-orthogonal cells (not an ACE math issue) - Add cross-validation script (_validate_ace.py) verifying A-basis, nu1, nu2 against independent reference implementation (12/12 tests pass)
fix(_bridge): get_box_params now checks cell matrix diagonality instead of vector orthogonality. A rotated-but-orthogonal cell has perpendicular vectors (dot product = 0) but non-zero off-diagonal elements, which requires the triclinic C++ code path. The old check misclassified these as orthorhombic, producing spurious ghost neighbors in padded systems. validation: add ACE cross-validation suites - _validate_ace.py: 12 tests against independent scipy reference - _validate_ace_lammps.py: 11 LAMMPS property-based tests - _validate_ace_pyace.py: 9 tests cross-validated against python-ace (dimer/trimer coupling, rotation invariance, convention factors, FCC symmetry, analytical identities, LAMMPS energy, pyscal3 self-consistency and rotation invariance)
Feat/wl parameters
# Conflicts: # src/pyscal3/descriptors.py Co-authored-by: srmnitc <12624457+srmnitc@users.noreply.github.com>
Feat/ace
…nkowski-ql # Conflicts: # src/pyscal3/__init__.py Co-authored-by: srmnitc <12624457+srmnitc@users.noreply.github.com>
feat: add Minkowski structure metrics (Voronoi-weighted q_l)
feat: add Ackland-Jones structure classifier
…oordination variants) Co-authored-by: srmnitc <12624457+srmnitc@users.noreply.github.com>
feat: add coordination number variants (CN, ECoN, GCN, local density)
Feat/adf
…d_jones alongside deformation descriptors) Co-authored-by: srmnitc <12624457+srmnitc@users.noreply.github.com>
Feat/deformation
…gner-seitz # Conflicts: # src/pyscal3/__init__.py # src/pyscal3/descriptors.py Co-authored-by: srmnitc <12624457+srmnitc@users.noreply.github.com>
Feat/wigner seitz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request modernizes and improves the documentation, packaging, and CI workflows for the
pyscal3project. The most significant changes include a complete overhaul of the GitHub Actions workflows for testing and deployment, a reorganization and update of the documentation structure and content, and improvements to packaging and distribution. These changes enhance maintainability, usability, and clarity for both users and developers.CI/CD Workflow Improvements
.github/workflows/deploy.ymlfile was refactored to build wheels for all major platforms (including Windows and new macOS runners), use the latest GitHub Actions andcibuildwheelversions, and switch to OIDC-based trusted publishing to PyPI, removing the need for API tokens. Publishing is now triggered only on GitHub Releases..github/workflows/testing.ymlworkflow now tests across more Python versions (3.10–3.13) and platforms, uses modern Python setup actions, and uploads coverage only for a specific matrix configuration. Concurrency controls were added to prevent overlapping runs.Documentation Restructuring and Updates
_toc.yml) was reorganized to streamline and clarify example topics, with new ordering and grouping, and an API reference was added.docs/index.rst) was rewritten to reflect the newpyscal3branding, update badges, and provide a concise library description.docs/examples.md) was rewritten for clarity, with updated descriptions and links to match the new example structure. [1] [2] [3]docs/api.md) was added, providing documentation for all public functions and classes using Sphinx autodoc directives.docs/gettingstarted.md) was updated to clarify Windows support and simplify conda instructions. [1] [2]_config.ymlwas updated to enable autodoc, autosummary, and Napoleon extensions for better API documentation.Packaging and Distribution
MANIFEST.infile was updated to include additional source and header files needed for distribution, including C++ sources and headers.Repository Metadata
_config.ymlwere updated to point to the correctpyscal3repository.