Skip to content

Nexus: Add PseudoSet class to improve pseudopotential handling for users. - #6043

Merged
prckent merged 28 commits into
QMCPACK:developfrom
brockdyer03:oop-pseudo
Jul 31, 2026
Merged

Nexus: Add PseudoSet class to improve pseudopotential handling for users.#6043
prckent merged 28 commits into
QMCPACK:developfrom
brockdyer03:oop-pseudo

Conversation

@brockdyer03

@brockdyer03 brockdyer03 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Proposed changes

This PR adds a class called PseudoSet to Nexus that will eventually replace the existing ppset class.

PseudoSet offers a more flexible and intuitive API for users that offers several advantages over the current ppset. Some notable advantages are:

  • Ability to keep pseudopotentials in separate directories (no need to set pseudo_dir in settings).
  • Ability to automatically read a set of pseudopotentials for a single code in a directory with PseudoSet.from_dir().
  • Ability to automatically read a directory with pseudopotentials for multiple codes with PseudoSet.from_mixed_dir().
  • Ability to automatically parse Z-valences from files with PseudoSet.get_Zeffs().
  • Improved error messages, including, among other things, warnings for non-existent files and descriptive errors for duplicate pseudos for the same element.
  • Support for gradual deprecation of ppset with PseudoSet._register_legacy_ppset().

Example usage

I've included some examples here so you don't need to pore through the code to see how the functions work.

The examples here assume the following contents of pseudo_dir

/tmp/pseudo_dir 
├── C
│   └── POTCAR
├── C.BFD.gms
├── C.ccECP.upf
├── C.ccECP.xml
├── C.USPP.upf
├── H
│   └── POTCAR
├── H.BFD.gms
├── H.ccECP.upf
├── H.ccECP.xml
└── H.USPP.upf

PseudoSet.from_dir()

>>> psps = PseudoSet.from_dir(pseudo_dir=pseudo_dir, code="qmcpack")
>>> for lbl, psp in psps.pseudos.items():
...     print(f"{lbl}: {psp}")
H: /tmp/pseudo_dir/H.ccECP.xml
C: /tmp/pseudo_dir/C.ccECP.xml
>>> psps = PseudoSet.from_dir(pseudo_dir=pseudo_dir, code="vasp")
>>> for lbl, psp in psps.pseudos.items():
...     print(f"{lbl}: {psp}")
C: /home/brock/tmp/pseudo_dir/C/POTCAR
H: /home/brock/tmp/pseudo_dir/H/POTCAR
>>> psps = PseudoSet.from_dir(
...     pseudo_dir=pseudo_dir,
...     code="espresso",
...     pattern="ccECP"
... )
>>> for lbl, psp in psps.pseudos.items():
...     print(f"{lbl}: {psp}")
C: /home/brock/tmp/pseudo_dir/C.ccECP.upf
H: /home/brock/tmp/pseudo_dir/H.ccECP.upf

PseudoSet.from_mixed_dir()

>>> psps = PseudoSet.from_mixed_dir(
...     pseudo_dir=pseudo_dir,
...     patterns={"espresso": "USPP"},
... )
>>> for code, ps_set in psps.items():
...     print(f"{code} pseudos:")
...     for lbl, psp in ps_set.pseudos.items():
...         print(f"  {lbl}: {psp}")
espresso pseudos:
C: /path/to/pseudo_dir/C.USPP.upf
H: /path/to/pseudo_dir/H.USPP.upf
gamess pseudos:
H: /path/to/pseudo_dir/H.BFD.gms
C: /path/to/pseudo_dir/C.BFD.gms
vasp pseudos:
C: /path/to/pseudo_dir/C/POTCAR
H: /path/to/pseudo_dir/H/POTCAR
qmcpack pseudos:
H: /path/to/pseudo_dir/H.ccECP.xml
C: /path/to/pseudo_dir/C.ccECP.xml

What type(s) of changes does this code introduce?

  • New feature
  • Testing changes (e.g. new unit/integration/performance tests)
  • Documentation changes

Does this introduce a breaking change?

  • No

What systems has this change been tested on?

Laptop, Fedora Linux 43 (KDE Plasma Desktop Edition)
AMD Ryzen 7 PRO 7840U (8 cores, 16 logical processors)

Python        3.14.5
uv            0.11.26
cif2cell      2.1.0
coverage      7.15.0
h5py          3.16.0
matplotlib    3.11.0
numpy         2.5.1
pycifrw       4.4.6
pydot         4.0.1
pytest        9.1.1
pytest-cov    7.1.0
pytest-order  1.5.0
scipy         1.18.0
seekpath      2.2.1
spglib        2.7.0
sphinx        9.1.0

Checklist

    • I have read the pull request guidance and develop docs
    • This PR is up to date with the current state of 'develop'
    • This PR adds tests to cover any new code, or to catch a bug that is being fixed
    • Documentation has been added (if appropriate)

@brockdyer03
brockdyer03 requested a review from jtkrogel July 14, 2026 01:47
@brockdyer03 brockdyer03 self-assigned this Jul 14, 2026
@brockdyer03 brockdyer03 added enhancement nexus python Pull requests that update python code labels Jul 14, 2026

@jtkrogel jtkrogel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hold on this. Discussion needed when time permits later.

@brockdyer03
brockdyer03 requested a review from jtkrogel July 24, 2026 13:20

@jtkrogel jtkrogel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comments

Comment thread nexus/nexus/pseudopotential.py Outdated
Comment thread nexus/nexus/pseudopotential.py
Comment thread nexus/nexus/pseudopotential.py Outdated
Comment thread nexus/nexus/pseudopotential.py
Comment thread nexus/nexus/pseudopotential.py Outdated
Comment thread nexus/nexus/pseudopotential.py
Comment thread nexus/nexus/pseudopotential.py Outdated
cls.legacy_pseudos[label][code] = PseudoSet(pseudos=pseudos, code=code)
#end def _register_legacy_ppset

def __repr__(self) -> str:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obviated by DevBase inheritance. Remove.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DevBase repr does not follow Python standards.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally, offline agreement was that the DevBase __repr__ and __str__ could be overridden if someone wanted to.

@jtkrogel jtkrogel Jul 30, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major classes inherit from DevBase in Nexus - this is fully intended to provide a consistent set of properties and behavior across the codebase. You already agreed to this with the streamlined DevBase update. Deviating repr behavior is only really warranted in "leaf" data types that approach simple/flat types rather than nested collections as in this case.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm leaving __str__ intact, but keeping __repr__ as a form of prettyprint. Most people don't even interact with the repr function since print() defaults to an object's __str__ method.

@jtkrogel jtkrogel Jul 30, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a start. The complete interface is there to allow people to navigate nested Nexus objects the same way one peruses a file system tree. Both functions are needed for this. Please make efforts to resist this urge down the line as it undermines the intentional construction at the foundation of the codebase.

Comment thread nexus/nexus/pseudopotential.py Outdated
Comment thread nexus/nexus/tests/test_pseudopotential.py
@brockdyer03

Copy link
Copy Markdown
Contributor Author

I want to note for the record that though this PR seems to add >2000 lines of code, if you remove tests and docstrings the actual PseudoSet class is only ~400 lines.

jtkrogel
jtkrogel previously approved these changes Jul 30, 2026

@jtkrogel jtkrogel left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we go

@prckent

prckent commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

@brockdyer03 Please fix the conflict when you have a moment

@prckent

prckent commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Test this please

@prckent prckent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q. Is there a plan to add documentation of these capabilities?

I suggest to create an issue reminding us that this is needed. These user friendly features will only exist for users when e.g. they are in the docs with a small copyable example.

@brockdyer03

Copy link
Copy Markdown
Contributor Author

Q. Is there a plan to add documentation of these capabilities?

I suggest to create an issue reminding us that this is needed. These user friendly features will only exist for users when e.g. they are in the docs with a small copyable example.

For starters, there are examples written into the docstrings of the code that demonstrate usage. But also, I do plan on writing extensive examples into an rST for users to see with copyable examples and common use cases.

@prckent prckent left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough, getting #5978 in will help. This will make all the docstrings visible.

@prckent
prckent enabled auto-merge July 31, 2026 15:34
@prckent
prckent merged commit 7e81317 into QMCPACK:develop Jul 31, 2026
50 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement nexus python Pull requests that update python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants