Skip to content

Nexus: PseudoSet user guide - #6165

Open
brockdyer03 wants to merge 4 commits into
QMCPACK:developfrom
brockdyer03:pseudoset-guide
Open

Nexus: PseudoSet user guide#6165
brockdyer03 wants to merge 4 commits into
QMCPACK:developfrom
brockdyer03:pseudoset-guide

Conversation

@brockdyer03

Copy link
Copy Markdown
Contributor

Proposed changes

This PR adds several examples to the Nexus user guide for using PseudoSet, and additionally adds a migration guide to switch from ppset to generate_pseudoset.

A quick set of changes were also made to pseudoset.py which do not affect existing functionality, but do make the output of various functions more consistent.

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

  • Documentation or build script changes

Does this introduce a breaking change?

  • No

What systems has this change been tested on?

Desktop, Fedora Linux 43 (KDE Plasma Desktop Edition)
AMD Ryzen 9 7900X (12 cores, 24 logical processors)

Python        3.14.5
uv            0.12.3
cif2cell      2.1.0
coverage      7.15.4
h5py          3.16.0
matplotlib    3.11.1
numpy         2.5.2
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'
    • Code added or changed in the PR has been clang-formatted
    • 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 self-assigned this Aug 26, 2026
@github-actions github-actions Bot added nexus documentation python Pull requests that update python code labels Aug 26, 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.

First: this is far too long for the feature it covers. +40 pages to the user manual is way too much (at least 800+ lines in the rst file). This should cover the most common (1-3?) use cases. Maybe 5 pages max.

Second: the UI is via generate_pseudoset alone as we have discussed at length previously. If you want to start alternative class-based docs at the end of the manual, that is your choice.

@brockdyer03

Copy link
Copy Markdown
Contributor Author

First: this is far too long for the feature it covers. +40 pages to the user manual is way too much (at least 800+ lines in the rst file). This should cover the most common (1-3?) use cases. Maybe 5 pages max.

I am not sure where you get this 40 page metric, the actual rendered docs are quite short and to the point. Yes, the rST files are long, but that is because I included examples for each case. Roughly half the lines in the file are just the printout from the Python code snippets, which I think is important for users to see. It also means that the code would be testable through doctest in the future.

Second: the UI is via generate_pseudoset alone as we have discussed at length previously. If you want to start alternative class-based docs at the end of the manual, that is your choice.

I think all routes should be explicitly accessible for users. I will make the function interface the default in the docs, but I think there is no reason to hide a class-based interface at the end of the documentation.

@jtkrogel

Copy link
Copy Markdown
Contributor

Yes, they will be accessible. The primary UI is input file like -- user's should not have to be exposed to detailed classes, calling many functions, etc.

If they want to dig deeper, that is fine -- but the main UI to Nexus, as established over its entire existence, is not going to change.

@brockdyer03
brockdyer03 requested a review from jtkrogel August 27, 2026 13:53

@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/pseudoset.py
:func:`ppset` has been replaced by :func:`generate_pseudoset` because
the labeling system that :func:`ppset` requires checks for the existence
of the label at runtime, whereas :func:`generate_pseudoset` returns an
object with a name, and if that name is misspelled then Python will not

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.

"object with a name as other generate functions do." Remove the rest.

Comment thread nexus/nexus/pseudoset.py
raise ValueError(msg) from None

return pseudos
sorted_pseudos = {k: v for k, v in sorted(pseudos.items(), key=lambda x: x[0])}

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.

Remind me what the keys are

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.

Code names

=================================

Nexus currently has several utilities for discovering, parsing, and copying pseudopotential files.
The latest and most complete method is through the :py:class:`~.PseudoSet` class and its associated builder :py:func:`~.generate_pseudoset`, and is recommended for most users.

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.

Don't discuss the class in the main user-facing documentation. What they need to know is how to use generate_pseudoset, not how it is implemented behind the scenes. Remember, many (most?) of our users do not know object-oriented programming, nor should they in order to understand the UI and use Nexus effectively.

Nexus currently has several utilities for discovering, parsing, and copying pseudopotential files.
The latest and most complete method is through the :py:class:`~.PseudoSet` class and its associated builder :py:func:`~.generate_pseudoset`, and is recommended for most users.

All objects returned by the methods described here can be passed into a generate function (e.g. :py:func:`~.generate_pwscf`), but require that you also pass the system to be simulated as a :py:class:`~.PhysicalSystem` object using the ``system`` keyword argument, which you can create with :py:func:`~.generate_physical_system`.

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.

Remove mention of "objects" and the PhysicalSystem class.


.. _pseudoset-usage:

Using :py:func:`~.generate_pseudoset` and :py:class:`~.PseudoSet`

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.

Don't reference the class


The following sections provide examples for how to use :py:class:`~.PseudoSet` for a variety of situations, primarily focused on the layout of a user's pseudopotential files.
You can switch between a class-based interface and an interface based on :py:func:`~.generate_pseudoset` by clicking on each code block below.
Each example has the output of the ``tree`` command in the pseudopotential directory to start.

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.

Example 1 should show the settings(pseudo_dir=...) + generate_pwscf(pseudos=[...],...) route. They need to know that the way they have traditionally specified pseudopotential locations still works.

This and other examples should be illustrated within a user script environment, consistent with the rest of the documentation in the manual. This is important because this is how they will use it -- and this is what they need to know.

#. Unlike the single-code example which used :py:meth:`~.PseudoSet.from_dir`, the multi-code example uses :py:meth:`~.PseudoSet.from_mixed_dir`, which can automatically filter pseudos for specific codes.
- The function :py:meth:`~.PseudoSet.from_dir` works well with directories containing pseudopotentials only for one code, e.g. if you have only a single set of ``.upf`` pseudopotentials. It can auto-detect the codes that *could* use those pseudopotentials (it can be more than one since, for example, both QE and RMG can also read UPF-formatted pseudopotentials)

Example 2 - Unstructured Directory

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.

"Example 4: Searching via inclusion pattern matching"

)


Multi-code workflows become more complex since we need to specify which files to include.

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.

This one is redundant with the "select by extension" example above. Remove one of them.


As with the single-code example, you can change out ``include`` to match different pseudopotential sets.

Example 3 - VASP Pseudopotentials

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.

"Example X: searching via exclusion pattern matching"


.. _legacy-ppset:

Migrating from :py:func:`~.ppset`

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.

OK, this is the stuff that needs to go at the top. generate_pseudoset is put forward as the replacement. The "replacement" form (this) needs to be given to them first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation nexus python Pull requests that update python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants