Skip to content

Update for viewer monorepo#292

Open
MLovetroy wants to merge 99 commits into
masterfrom
update-for-viewer-monorepo
Open

Update for viewer monorepo#292
MLovetroy wants to merge 99 commits into
masterfrom
update-for-viewer-monorepo

Conversation

@MLovetroy

Copy link
Copy Markdown
Collaborator

Implemented utilities surrounding vasp.viewer and View functionality related to interface changes (mostly volume support)

  • Add Calculation.selections() to obtain loadable quantities (and method to check can be specified)

  • Add View.to_vasp_viewer_config() and refactor View.to_vasp_viewer()

  • Add support for adding up View instances (__add__)

  • Share additive logic between Graph and View

  • Add tests for all changes and features

  • Removed an unused submodule link to workshop that had no URL and prevented importing py4vasp on this branch as a dependency via uv; the link was likely added unintentionally?

- Implement DataAccess[T] and DataContext[T] in data_access.py
  - __call__ returns iterable of DataContext, supports (raw, ctx) tuple unpacking
  - from_data classmethod wraps raw data directly for testing/composition
  - Source resolution: parses selection, matches schema sources, strips token
- Add 25 tests covering all paths (passthrough, source resolution, errors)
- Update port-quantity SKILL.md to iteration pattern (for raw, _ in self._data():)
- Update docs/architecture/calculation.rst to iteration pattern
… results

- merge(generator) unwraps single results, combines multiple dicts, returns None for empty/all-None
- Add 9 tests covering all merge paths including primary DataAccess usage patterns
martin-schlipf and others added 24 commits May 29, 2026 10:07
…election from *args

- dispatch.py: add _method_accepts_selection() which inspects whether a
  handler method's first positional parameter is named 'selection'. Modify
  _dispatch() to automatically prepend remaining_selection to method args
  when the handler accepts it, removing the need for callers to pass
  selection in *args.

- New convention enforced by test_selection_convention.py:
  * Dispatcher has 'selection' param -> 3rd merge arg = selection
  * Dispatcher has no 'selection' param -> 3rd merge arg = None
  * 'selection' NEVER appears in *args (dispatch handles forwarding)

- Quantity dispatcher fixes (remove selection from *args, fix 3rd arg):
  band, bandgap, current_density, density, dielectric_function,
  _dispersion, dos, effective_coulomb, electronic_minimization, energy,
  exciton_density, local_moment, nics, pair_correlation, partial_density,
  phonon_band, phonon_dos, potential, projector

- density.py: rename DensityHandler.to_view/to_contour 'selection'
  parameter to 'component' to avoid accidental auto-forwarding (density
  uses self._selection_name for source routing, not the method parameter)

- test_dispatch.py: update tests for new auto-forwarding behavior,
  add _FakeHandler.read_with_selection, remove selection from *args
  in test helpers, mock schema_selections where needed
- @quantity decorator now auto-injects from_path(), from_file(), and
  _path property on all dispatcher classes via FileSource construction
- Remove manually-defined from_path/from_file/pathlib imports from all
  dispatcher classes to avoid duplication (~21 files cleaned up)
- Fix _dispatch() to distinguish handler selection params with defaults
  vs required: skip forwarding remaining_selection=None when default
  exists, always forward when selection is required
- Fix __str__ on all dispatchers to accept selection=None and forward
  to merge_strings (~25 files)
- Fix phonon_band.py: pass width as keyword arg to avoid positional
  collision with selection in _dispatch
- Refactor conftest.py check_factory_methods: derive quantity name from
  _quantity_name attr, detect methods without selection param, relax
  selection forwarding assertions
- Remove @pytest.mark.skip from all 38 test files; add skip_methods for
  kpoint (selections) and stoichiometry (to_mdtraj)
- Fix test_electronic_minimization: uncomment test_factory_methods

Result: 42/42 test_factory_methods pass, 2051 total tests pass
(6 pre-existing failures require optional mdtraj package)
…erties dict

- _DatabaseData now has only two fields: metadata and properties
- properties keys use <quantity>_<selection> format, no leading underscore
- CalculationMetaData has path (directory), schema_version, file presence flags;
  removed hdf5_original_path, tags, infer_none_files
- _DBDataMixin no longer carries __schema_version__ per-instance field
- Calculation._to_database() takes no arguments
- _compute_database_data iterates _REGISTRY via _ensure_all_quantities_imported
- Added _to_database(selection=None) to 30 dispatcher classes
- Updated tests: new test_to_database_new.py (16 tests), dispatcher tests,
  and updated test_database.py to use new API
Group members like @quantity('self_energy', group='electron_phonon') were
storing _quantity_name = 'self_energy' (short name). Group.__getattr__
then passed this short name to the dispatcher constructor, causing
FileAccessError because the schema key is 'electron_phonon_self_energy'.

Fix: store _quantity_name = f'{group}_{name}' when a group is given, so the
full schema-compatible key is always used.

Add two tests:
- TestQuantityDecorator::test_stores_full_quantity_name_for_grouped_quantity
- TestGroup::test_attribute_access_passes_full_quantity_name_for_decorated_group
All handler to_database() methods now return the DB object directly instead
of {"quantity": DB_object}. Update tests to drop the ["key"] subscript and
update dispatcher tests to expect the DB object at result["default"] rather
than result["default"]["key"].
Introduces merge_to_database in dispatch.py, which wraps _dispatch and
remaps result keys from selection names to quantity-prefixed keys:
the default selection maps to just the quantity name, non-default
selections to quantity_selection. Leading underscores are stripped so
private quantities like _CONTCAR appear without the prefix.

All dispatcher _to_database methods are updated to use merge_to_database
instead of _dispatch, and _collect_to_database in __init__.py is
simplified to use the pre-built keys directly. Two placement bugs are
also fixed: the Dos and Energy _to_database methods were previously
unreachable dead code in the wrong scope.
…r for monorepo architecture and refactoring, as well as new features; adjust tests accordingly
…urrent branch

- the broken .gitlink seems to have accidentally added workshop as a git submodule, but the link is broken and is also broken on main (main does not have it as far as I can tell)
…]`; add `only_available` parameter to either constrain quantities/selections or not
… whether all demo quantities implement .read()
Base automatically changed from architecture-migration to master July 6, 2026 12:33
# Conflicts:
#	src/py4vasp/_calculation/_CONTCAR.py
#	src/py4vasp/_calculation/__init__.py
#	src/py4vasp/_calculation/_dispersion.py
#	src/py4vasp/_calculation/_stoichiometry.py
#	src/py4vasp/_calculation/band.py
#	src/py4vasp/_calculation/bandgap.py
#	src/py4vasp/_calculation/born_effective_charge.py
#	src/py4vasp/_calculation/cell.py
#	src/py4vasp/_calculation/current_density.py
#	src/py4vasp/_calculation/density.py
#	src/py4vasp/_calculation/dielectric_function.py
#	src/py4vasp/_calculation/dielectric_tensor.py
#	src/py4vasp/_calculation/dispatch.py
#	src/py4vasp/_calculation/dos.py
#	src/py4vasp/_calculation/effective_coulomb.py
#	src/py4vasp/_calculation/elastic_modulus.py
#	src/py4vasp/_calculation/electronic_minimization.py
#	src/py4vasp/_calculation/energy.py
#	src/py4vasp/_calculation/exciton_density.py
#	src/py4vasp/_calculation/exciton_eigenvector.py
#	src/py4vasp/_calculation/force.py
#	src/py4vasp/_calculation/kpoint.py
#	src/py4vasp/_calculation/local_moment.py
#	src/py4vasp/_calculation/nics.py
#	src/py4vasp/_calculation/pair_correlation.py
#	src/py4vasp/_calculation/phonon_band.py
#	src/py4vasp/_calculation/phonon_dos.py
#	src/py4vasp/_calculation/phonon_mode.py
#	src/py4vasp/_calculation/piezoelectric_tensor.py
#	src/py4vasp/_calculation/polarization.py
#	src/py4vasp/_calculation/potential.py
#	src/py4vasp/_calculation/projector.py
#	src/py4vasp/_calculation/run_info.py
#	src/py4vasp/_calculation/stress.py
#	src/py4vasp/_calculation/structure.py
#	src/py4vasp/_calculation/velocity.py
#	src/py4vasp/_calculation/workfunction.py
#	tests/calculation/conftest.py
#	tests/calculation/test_band.py
#	tests/calculation/test_calculation_registry.py
#	tests/calculation/test_contcar.py
#	tests/calculation/test_dispatch.py
#	tests/calculation/test_partial_density.py
#	tests/calculation/test_phonon_mode.py
#	tests/calculation/test_run_info.py
#	tests/calculation/test_selection_convention.py
#	tests/calculation/test_stoichiometry.py
#	tests/calculation/test_structure.py
)


class _TensorReduction(index.Reduction):

alpha_2d = (l_vacuum / (4.0 * np.pi)) * (eps_parallel - 1.0)
return alpha_2d
return None
Comment thread src/py4vasp/_calculation/elastic_modulus.py Fixed
Comment thread src/py4vasp/_calculation/_dispersion.py Fixed
Comment thread src/py4vasp/_calculation/band.py Fixed
Comment thread src/py4vasp/_calculation/band.py Fixed
Comment thread src/py4vasp/_calculation/band.py Fixed
Comment thread src/py4vasp/_calculation/bandgap.py Fixed
Comment thread src/py4vasp/_calculation/born_effective_charge.py Fixed
Comment thread src/py4vasp/_calculation/current_density.py Fixed
Remove unused imports flagged by the static-analysis bot:
- _dispatch from _dispersion, band, bandgap, born_effective_charge
- slice_steps from bandgap
- pathlib and Optional from band
- copy from current_density

Remove a redundant duplicate `vickers_hardness = elastic_tensor.get_hardness()`
in elastic_modulus._compute_elastic_properties: it was recomputed inside the
"fracture" suppress block after already being computed in the dedicated
"hardness" block.

The two remaining bot findings were false positives and left unchanged:
- nics._TensorReduction missing super().__init__(): the parent index.Reduction
  is an ABC whose __init__ is an empty abstractmethod, so there is no base setup.
- dielectric_tensor "unreachable" return None: it is reached when
  error.suppress_and_record swallows an exception in the with-block.
Comment on lines +9 to +16
from py4vasp._calculation.dispatch import (
DataSource,
_dispatch,
merge_default,
merge_strings,
merge_to_database,
quantity,
)
# Copyright © VASP Software GmbH,
# Licensed under the Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
import copy
import itertools
Comment on lines +7 to +15
from py4vasp._calculation.dispatch import (
DataSource,
_dispatch,
merge_default,
merge_graphs,
merge_strings,
merge_to_database,
quantity,
)
Comment on lines +9 to +16
from py4vasp._calculation.dispatch import (
DataSource,
_dispatch,
merge_default,
merge_strings,
merge_to_database,
quantity,
)
return "down" in name and "up" not in name and "total" not in name
# Copyright © VASP Software GmbH,
# Licensed under the Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
import pathlib
Comment on lines +10 to +17
from py4vasp._calculation.dispatch import (
DataSource,
_dispatch,
merge_default,
merge_strings,
merge_to_database,
quantity,
)
Comment on lines +11 to +19
from py4vasp._calculation.dispatch import (
DataSource,
_dispatch,
merge_default,
merge_graphs,
merge_strings,
merge_to_database,
quantity,
)
Comment on lines +10 to +17
from py4vasp._calculation.dispatch import (
DataSource,
_dispatch,
merge_default,
merge_strings,
merge_to_database,
quantity,
)
The `only_available=True` example claimed density had a loadable `tau` source,
but the demo data provides no loadable `tau` density, so the actual result is
`'density': ['default']`. Corrected the expected output to match, consistent
with the sibling `method="to_view", only_available=True` example that already
showed `['default']`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants