Add mqdt into python#32
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces MQDT (multichannel quantum defect theory) support into the rydstate Python package, including new MQDT species parameterizations (Sr87/Sr88 and Yb171/Yb173/Yb174), an MQDT Rydberg-state representation, and an MQDT basis builder, along with accompanying tests and documentation updates.
Changes:
- Add MQDT species + model definitions (
FModel) and theSpeciesObjectMQDTAPI. - Implement MQDT state construction (
RydbergStateMQDT) and basis generation (BasisMQDT) using root-finding and nullspace utilities. - Update public exports and Sphinx API docs to include MQDT features.
Reviewed changes
Copilot reviewed 36 out of 37 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_mqdt_models.py | Adds consistency/unitarity checks across all discovered MQDT FModel implementations. |
| tests/test_basis_mqdt.py | Adds smoke tests for BasisMQDT creation, filtering, sorting, and normalization. |
| src/rydstate/utils/linalg.py | Introduces find_roots and calc_nullvector utilities used by MQDT computations. |
| src/rydstate/species/utils.py | Adds a RydbergRitzParameters type alias used by SQDT/MQDT parameterization. |
| src/rydstate/species/sqdt/species_object_sqdt.py | Aligns SQDT species with a new reference_ionization_energy_au API and updates defect typing. |
| src/rydstate/species/species_object.py | Adds abstract reference_ionization_energy_au contract for all species objects. |
| src/rydstate/species/mqdt/sr87.py | Adds Sr87 MQDT species thresholds/constants and associated MQDT FModel sets. |
| src/rydstate/species/mqdt/sr88.py | Adds Sr88 MQDT species thresholds/constants and associated MQDT FModel sets. |
| src/rydstate/species/mqdt/yb171.py | Adds Yb171 MQDT species thresholds/constants and extensive FModel sets. |
| src/rydstate/species/mqdt/yb173.py | Adds Yb173 MQDT species thresholds/constants and FModel sets. |
| src/rydstate/species/mqdt/yb174.py | Adds Yb174 MQDT species thresholds/constants and FModel sets. |
| src/rydstate/species/mqdt/species_object_mqdt.py | Implements SpeciesObjectMQDT including threshold lookup and MQDT model selection. |
| src/rydstate/species/mqdt/fmodel.py | Implements MQDT model math (frame transforms, K/M matrices, determinant roots). |
| src/rydstate/species/mqdt/init.py | Exposes MQDT species and model classes at the rydstate.species.mqdt package level. |
| src/rydstate/species/init.py | Re-exports MQDT classes/species in the main rydstate.species namespace. |
| src/rydstate/rydberg/rydberg_sqdt.py | Broadens SQDT state typing to SpeciesObject and adds SQDT-only guard for transition rates. |
| src/rydstate/rydberg/rydberg_mqdt.py | Adds RydbergStateMQDT and computation of MQDT states from FModel roots. |
| src/rydstate/rydberg/rydberg_dummy.py | Adds RydbergStateSQDTDummy to represent MQDT dummy/perturber channels. |
| src/rydstate/rydberg/init.py | Exports RydbergStateMQDT. |
| src/rydstate/basis/basis_mqdt.py | Adds BasisMQDT to enumerate channels/models and build MQDT state bases. |
| src/rydstate/basis/init.py | Exports BasisMQDT. |
| src/rydstate/angular/utils.py | Introduces Unknown=np.nan, is_unknown, is_dummy_ket, and related helper behavior for MQDT. |
| src/rydstate/angular/core_ket_base.py | Adds CoreKet/CoreKetDummy used to key ionization thresholds in MQDT species. |
| src/rydstate/angular/angular_state.py | Extends AngularState to allow dummy kets and handle Unknown values in expectation computations. |
| src/rydstate/angular/angular_ket_dummy.py | Adds AngularKetDummy to model unknown MQDT channels while safely contributing zero to matrix elements. |
| src/rydstate/angular/angular_ket.py | Adds handling for unknown quantum numbers (convert to dummy) and implements AngularKetFJ.get_core_ket(). |
| src/rydstate/init.py | Re-exports MQDT basis/state types at the top-level rydstate package. |
| pyproject.toml | Adds Ruff per-file ignores for generated/parameter-heavy MQDT species modules. |
| docs/conf.py | Tweaks RTD theme navigation options (depth/collapse). |
| docs/api_reference.rst | Restructures API reference into a toctree-based layout. |
| docs/api/species_sqdt.rst | Adds a dedicated SQDT API page. |
| docs/api/species_mqdt.rst | Adds a dedicated MQDT API page. |
| docs/api/rydberg_states.rst | Adds MQDT Rydberg state to the documented API. |
| docs/api/radial.rst | Adds a dedicated radial module API page. |
| docs/api/basis.rst | Adds MQDT basis to the documented API. |
| docs/api/angular.rst | Adds a dedicated angular module API page. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Vectorized bracket detection: sign changes between finite adjacent pairs | ||
| finite = np.isfinite(fs) | ||
| both_finite = finite[:-1] & finite[1:] | ||
| sign_change = np.sign(fs[:-1]) * np.sign(fs[1:]) < 0 | ||
| bracket_indices = np.where(both_finite & sign_change)[0] |
There was a problem hiding this comment.
find_roots can miss roots when func(x) evaluates to exactly 0 on a grid point (or very close), because bracket detection only looks for strict sign changes between adjacent points (np.sign(f[i]) * np.sign(f[i+1]) < 0). Consider explicitly handling near-zero samples (e.g., treat |f| < atol as a root and/or create brackets that include zeros) so MQDT root-finding is robust.
| l_r=l_r, j_r=float(j_r), f_c=float(f_c), f_tot=float(_f_tot), species=species | ||
| ) | ||
| self.models.extend(species.get_mqdt_models(channel)) | ||
| self.models = list(set(self.models)) # remove duplicates |
There was a problem hiding this comment.
self.models = list(set(self.models)) will not actually remove duplicates because FModel instances don’t define a value-based __eq__/__hash__ (so each instance hashes by identity). This can lead to repeated work and large self.models when the same model is discovered multiple times. Consider deduplicating by model class (e.g., type(model)) or by a stable key like (model.species_name, model.name) (and similarly caching FModelSQDT per channel).
| self.models = list(set(self.models)) # remove duplicates | |
| # Deduplicate models by a stable value-based key instead of object identity. | |
| unique_models: dict[tuple[str | None, str | None], FModel] = {} | |
| for model in self.models: | |
| key = (getattr(model, "species_name", None), getattr(model, "name", None)) | |
| if key not in unique_models: | |
| unique_models[key] = model | |
| self.models = list(unique_models.values()) |
4f9102f to
c3765c2
Compare
No description provided.