From dbdca1f7c7da998c76658007b0ed7ef1d2d792d8 Mon Sep 17 00:00:00 2001 From: "Jose M. Pizarro" <112697669+JosePizarro3@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:28:39 +0200 Subject: [PATCH] Adapting new entry points structure (#88) * New src/nomad_simulations/schema_packages structure * Fix imports in src and tests modules * Fixed pyproject toml * Fixed pipeline * Deleted nomad.yaml * Fix and improve README * Deleted unused files * Added config parameters into the pydantic entry point model * Added python action for publishing in pypi on release --- .github/workflows/actions.yaml | 73 ------------ .github/workflows/actions.yml | 74 ++++++++++++ .github/workflows/mkdocs-deploy.yml | 26 ++--- .github/workflows/publish.yml | 105 ++++++------------ Dockerfile | 15 --- MANIFEST.in | 1 - README.md | 90 ++++++++------- nomad.yaml | 13 --- pyproject.toml | 94 ++++++++++++---- requirements_docs.txt | 4 + src/nomad_simulations/__init__.py | 20 ---- src/nomad_simulations/nomad_plugin.yaml | 4 - .../schema_packages/__init__.py | 61 ++++++++++ .../{ => schema_packages}/atoms_state.py | 47 ++++---- .../{ => schema_packages}/general.py | 40 +++++-- .../{ => schema_packages}/model_method.py | 71 ++++++------ .../{ => schema_packages}/model_system.py | 76 +++++++------ .../numerical_settings.py | 62 ++++++----- .../{ => schema_packages}/outputs.py | 35 +++--- .../physical_property.py | 35 +++--- .../properties/__init__.py | 14 +-- .../properties/band_gap.py | 21 ++-- .../properties/band_structure.py | 58 ++++++---- .../properties/energies.py | 19 +++- .../properties/fermi_surface.py | 15 ++- .../properties/hopping_matrix.py | 19 +++- .../properties/permittivity.py | 26 +++-- .../properties/spectral_profile.py | 77 +++++++------ .../{ => schema_packages}/utils/__init__.py | 6 +- .../{ => schema_packages}/utils/utils.py | 6 +- .../{ => schema_packages}/variables.py | 43 +++---- tests/conftest.py | 20 ++-- tests/test_atoms_state.py | 6 +- tests/test_band_gap.py | 6 +- tests/test_band_structure.py | 8 +- tests/test_energies.py | 2 +- tests/test_fermi_surface.py | 5 +- tests/test_general.py | 8 +- tests/test_hopping_matrix.py | 7 +- tests/test_model_method.py | 16 ++- tests/test_model_system.py | 8 +- tests/test_numerical_settings.py | 6 +- tests/test_outputs.py | 10 +- tests/test_permittivity.py | 12 +- tests/test_physical_properties.py | 8 +- tests/test_spectral_profile.py | 16 +-- tests/test_utils.py | 13 ++- tests/test_variables.py | 4 +- 48 files changed, 758 insertions(+), 647 deletions(-) delete mode 100644 .github/workflows/actions.yaml create mode 100644 .github/workflows/actions.yml delete mode 100644 Dockerfile delete mode 100644 MANIFEST.in delete mode 100644 nomad.yaml create mode 100644 requirements_docs.txt delete mode 100644 src/nomad_simulations/nomad_plugin.yaml create mode 100644 src/nomad_simulations/schema_packages/__init__.py rename src/nomad_simulations/{ => schema_packages}/atoms_state.py (94%) rename src/nomad_simulations/{ => schema_packages}/general.py (89%) rename src/nomad_simulations/{ => schema_packages}/model_method.py (95%) rename src/nomad_simulations/{ => schema_packages}/model_system.py (95%) rename src/nomad_simulations/{ => schema_packages}/numerical_settings.py (95%) rename src/nomad_simulations/{ => schema_packages}/outputs.py (93%) rename src/nomad_simulations/{ => schema_packages}/physical_property.py (94%) rename src/nomad_simulations/{ => schema_packages}/properties/__init__.py (82%) rename src/nomad_simulations/{ => schema_packages}/properties/band_gap.py (89%) rename src/nomad_simulations/{ => schema_packages}/properties/band_structure.py (85%) rename src/nomad_simulations/{ => schema_packages}/properties/energies.py (75%) rename src/nomad_simulations/{ => schema_packages}/properties/fermi_surface.py (76%) rename src/nomad_simulations/{ => schema_packages}/properties/hopping_matrix.py (82%) rename src/nomad_simulations/{ => schema_packages}/properties/permittivity.py (84%) rename src/nomad_simulations/{ => schema_packages}/properties/spectral_profile.py (90%) rename src/nomad_simulations/{ => schema_packages}/utils/__init__.py (100%) rename src/nomad_simulations/{ => schema_packages}/utils/utils.py (99%) rename src/nomad_simulations/{ => schema_packages}/variables.py (80%) diff --git a/.github/workflows/actions.yaml b/.github/workflows/actions.yaml deleted file mode 100644 index f43f9cc9..00000000 --- a/.github/workflows/actions.yaml +++ /dev/null @@ -1,73 +0,0 @@ -name: install-and-test -on: [push] - -# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs -# `contents` is for permission to the contents of the repository. -# `pull-requests` is for permission to pull request -permissions: - contents: write - checks: write - pull-requests: write - -jobs: - install-and-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up Python 3.9 - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - name: Install dependencies - run: | - pip install uv - uv pip install -e '.[dev]' --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple --system - uv pip install coveralls --system - - name: mypy - run: | - python -m mypy --ignore-missing-imports --follow-imports=silent --no-strict-optional src/nomad_simulations tests - - name: Build coverage file - run: | - pytest --junitxml=pytest.xml --cov-report=term-missing:skip-covered --cov=src tests | tee pytest-coverage.txt - - name: Pytest coverage comment - uses: MishaKav/pytest-coverage-comment@main - with: - pytest-coverage-path: pytest-coverage.txt - junitxml-path: pytest.xml - - name: Submit to coveralls - continue-on-error: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - coveralls --service=github - build-and-install: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up Python 3.9 - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - name: Build the package - run: | - pip install uv - uv pip install --upgrade pip --system - uv pip install build --system - python -m build --sdist - - name: Install the package - run: | - uv pip install dist/*.tar.gz --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple --system - ruff-linting: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: chartboost/ruff-action@v1 - with: - args: "check ." - ruff-formatting: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: chartboost/ruff-action@v1 - with: - args: "format . --check --verbose" diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml new file mode 100644 index 00000000..9d753ef4 --- /dev/null +++ b/.github/workflows/actions.yml @@ -0,0 +1,74 @@ +name: install-and-test +on: [push] + +# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs +# `contents` is for permission to the contents of the repository. +# `pull-requests` is for permission to pull request +permissions: + contents: write + checks: write + pull-requests: write + +jobs: + install-and-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.9 + uses: actions/setup-python@v5 + with: + python-version: 3.9 + - name: Install dependencies + run: | + pip install --upgrade pip + pip install uv + uv pip install -e '.[dev]' --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple --system + uv pip install coveralls --system + - name: mypy + run: | + python -m mypy --ignore-missing-imports --follow-imports=silent --no-strict-optional src/nomad_simulations/schema_packages tests + - name: Build coverage file + run: | + pytest --junitxml=pytest.xml --cov-report=term-missing:skip-covered --cov=src tests | tee pytest-coverage.txt + - name: Pytest coverage comment + uses: MishaKav/pytest-coverage-comment@main + with: + pytest-coverage-path: pytest-coverage.txt + junitxml-path: pytest.xml + - name: Submit to coveralls + continue-on-error: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + coveralls --service=github + build-and-install: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.9 + uses: actions/setup-python@v5 + with: + python-version: 3.9 + - name: Build the package + run: | + pip install uv + uv pip install --upgrade pip --system + uv pip install build --system + python -m build --sdist + - name: Install the package + run: | + uv pip install dist/*.tar.gz --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple --system + ruff-linting: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: chartboost/ruff-action@v1 + with: + args: "check ." + ruff-formatting: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: chartboost/ruff-action@v1 + with: + args: "format . --check --verbose" diff --git a/.github/workflows/mkdocs-deploy.yml b/.github/workflows/mkdocs-deploy.yml index f067db5a..c46ff230 100644 --- a/.github/workflows/mkdocs-deploy.yml +++ b/.github/workflows/mkdocs-deploy.yml @@ -1,9 +1,12 @@ -name: deploy-mkdocs +name: Deploy MkDocs Site on: push: branches: - - develop # Triggers deployment on push to the main branch + - main # Triggers deployment on push to the main branch + +permissions: + contents: write jobs: deploy: @@ -13,16 +16,9 @@ jobs: - name: Checkout Repository uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.x" - - - name: Install Dependencies - run: | - python -m pip install --upgrade pip - pip install mkdocs mkdocs-material==8.1.1 pymdown-extensions mkdocs-click - - - name: Build and Deploy - run: | - mkdocs gh-deploy --config-file ../nomad-simulations/mkdocs.yml --force --remote-branch gh-pages + - name: Deploy docs + uses: mhausenblas/mkdocs-deploy-gh-pages@master + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CONFIG_FILE: mkdocs.yml + REQUIREMENTS: requirements_docs.txt diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 40c8df55..d4e46753 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,84 +1,43 @@ -# Upload python package to pypi server and github release. -# Reference: https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/ +# This workflow will upload a Python Package using Twine when a release is created +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries -name: Upload Python Package +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Build and Publish Python Package on: release: types: [published] +permissions: + contents: read + jobs: - # publish-to-pypi: - # name: >- - # Publish distribution to PyPI - # runs-on: ubuntu-latest - # environment: - # name: pypi - # url: https://pypi.org/p/nomad-simulations - # permissions: - # id-token: write # IMPORTANT: mandatory for trusted publishing - # - # steps: - # - uses: actions/checkout@v4 - # - name: Set up Python - # uses: actions/setup-python@v4 - # with: - # python-version: "3.9" - # - name: Install pypa/build - # run: >- - # python3 -m - # pip install - # build - # --user - # - name: Build a binary wheel and a source tarball - # run: python3 -m build - # - name: Publish distribution to PyPI - # uses: pypa/gh-action-pypi-publish@release/v1 + deploy: - github-release: - name: >- - Sign the Python distribution with Sigstore - and upload them to GitHub Release runs-on: ubuntu-latest - permissions: - contents: write # IMPORTANT: mandatory for making GitHub Releases - id-token: write # IMPORTANT: mandatory for sigstore steps: - - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.9" - - name: Install pypa/build - run: >- - python3 -m - pip install - build - --user - - name: Build a binary wheel and a source tarball - run: python3 -m build - - name: Sign the dists with Sigstore - uses: sigstore/gh-action-sigstore-python@v1.2.3 - with: - inputs: >- - ./dist/*.tar.gz - ./dist/*.whl - - name: Create GitHub Release - env: - GITHUB_TOKEN: ${{ github.token }} - run: >- - gh release create - '${{ github.ref_name }}' - --repo '${{ github.repository }}' - --notes "" - - name: Upload artifact signatures to GitHub Release - env: - GITHUB_TOKEN: ${{ github.token }} - # Upload to GitHub Release using the `gh` CLI. - # `dist/` contains the built packages, and the - # sigstore-produced signatures and certificates. - run: >- - gh release upload - '${{ github.ref_name }}' dist/** - --repo '${{ github.repository }}' + - uses: actions/checkout@v3 + + - name: Set up Python 3.9 + uses: actions/setup-python@v3 + with: + python-version: '3.9' + + - name: Install dependencies + run: | + pip install --upgrade pip + pip install build + + - name: Build package + run: python -m build + + - name: Publish package to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 819e745f..00000000 --- a/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM gitlab-registry.mpcdf.mpg.de/nomad-lab/nomad-fair:latest - -RUN pip install build - -COPY \ - src/nomad_simulations \ - tests \ - README.md \ - LICENSE \ - pyproject.toml \ - . - -RUN python -m build --sdist - -RUN pip install dist/nomad-simulations-*.tar.gz diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 7281e592..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -recursive-include * nomad_plugin.yaml \ No newline at end of file diff --git a/README.md b/README.md index 89a94e82..747692cd 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,10 @@ ![](https://img.shields.io/pypi/v/nomad-simulations) --> -# NOMAD's Simulations Schema Plugin -This is a plugin for [NOMAD](https://nomad-lab.eu) which contains the base sections schema definitions for materials science simulations.. +# `nomad-simulations` schema plugin +This is a plugin for [NOMAD](https://nomad-lab.eu) which contains the base sections schema definitions for materials science simulations. - ## Getting started @@ -26,6 +25,11 @@ python3.9 -m venv .pyenv . .pyenv/bin/activate ``` +Make sure to have `pip` upgraded: +```sh +pip install --upgrade pip +``` + We recommend installing `uv` for fast pip installation of the packages: ```sh pip install uv @@ -34,7 +38,6 @@ pip install uv Install the `nomad-lab` package: ```sh -pip install --upgrade pip uv pip install '.[dev]' --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple ``` @@ -42,6 +45,12 @@ uv pip install '.[dev]' --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/ Until we have an official pypi NOMAD release with the plugins functionality. Make sure to include NOMAD's internal package registry (via `--index-url` in the above command). +The plugin is still under development. If you would like to contribute, install the package in editable mode (with the added `-e` flag) with the development dependencies: + +```sh +uv pip install -e '.[dev]' --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple +``` + ### Run the tests You can run local tests using the `pytest` package: @@ -55,8 +64,8 @@ where the `-s` and `-v` options toggle the output verbosity. Our CI/CD pipeline produces a more comprehensive test report using `coverage` and `coveralls` packages. We suggest you to generate your own coverage reports locally by doing: ```sh -pip install coverage coveralls -python -m pytest --cov=src tests +uv pip install pytest-cov +python -m pytest --cov=src tests ``` You can also run the script to generate a local file `coverage.txt` with the same information by doing: @@ -64,46 +73,10 @@ You can also run the script to generate a local file `coverage.txt` with the sam ./scripts/generate_coverage_txt.sh ``` -## Development - -The plugin is still under development. If you would like to contribute, install the package in editable mode (with the added `-e` flag) with the development dependencies: - -```sh -uv pip install -e .[dev] --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple -``` - ### Setting up plugin on your local installation Read the [NOMAD plugin documentation](https://nomad-lab.eu/prod/v1/staging/docs/howto/oasis/plugins_install.html) for all details on how to deploy the plugin on your NOMAD instance. -You need to modify the ```src/nomad_simulations/nomad_plugin.yaml``` to define the plugin adding the following content: - -```yaml -plugin_type: schema -name: schemas/nomad_simulations -description: | - This is a collection of NOMAD schemas for simulation data. -``` - -and define the ```nomad.yaml``` configuration file of your NOMAD instance in the root folder with the following content: - -```yaml -plugins: - include: - - schemas/nomad_simulations - options: - schemas/nomad_simulations: - python_package: nomad_simulations -``` - -You also need to add the package folder to the `PYTHONPATH` of the Python environment of your local NOMAD installation. This can be done by specifying the relative path to this repository. Either run the following command every time you start a new terminal for running the appworker, or add it to your virtual environment in `/.pyenv/bin/activate` file: - -```sh -export PYTHONPATH="$PYTHONPATH:/src" -``` - -If you are working in this repository, you just need to activate the environment to start working using the ```nomad_simulations``` package. - ### Run linting and auto-formatting ```sh @@ -146,6 +119,39 @@ where `${workspaceFolder}` refers to the NOMAD root. The settings configuration file `.vscode/settings.json` performs automatically applies the linting upon saving the file progress. +### Build the python package + +The `pyproject.toml` file contains everything that is necessary to turn the project +into a pip installable python package. Run the python build tool to create a package distribution: + +``` +uv pip install build +python -m build --sdist +``` + +You can install the package with pip: + +``` +uv pip install dist/nomad-simulations-0.1.0 +``` + +Read more about python packages, `pyproject.toml`, and how to upload packages to PyPI +on the [PyPI documentation](https://packaging.python.org/en/latest/tutorials/packaging-projects/). + +### Documentation on Github pages + +To deploy documentation on Github pages, make sure to [enable GitHub pages via the repo settings](https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#publishing-from-a-branch). + +To view the documentation locally, install the documentation related packages using: + +```sh +uv pip install -r requirements_docs.txt +``` + +Run the documentation server: +```sh +mkdocs serve +``` ## Main contributors | Name | E-mail | Topics | Github profiles | diff --git a/nomad.yaml b/nomad.yaml deleted file mode 100644 index 8be3d8d5..00000000 --- a/nomad.yaml +++ /dev/null @@ -1,13 +0,0 @@ -normalize: - normalizers: - include: - - MetainfoNormalizer -plugins: - # We only include our schema here. Without the explicit include, all plugins will be - # loaded. Many build in plugins require more dependencies. Install nomad-lab[parsing] - # to make all default plugins work. - include: - - 'schemas/nomad_simulations' - options: - schemas/nomad_simulations: - python_package: nomad_simulations \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 3a596817..5c644e84 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,23 +1,34 @@ [build-system] -requires = [ - "setuptools>=61.0.0", - "setuptools-scm>=8.0", -] +requires = ["setuptools>=61.0.0", "setuptools-scm>=8.0"] build-backend = "setuptools.build_meta" [project] -name = 'nomad-simulations' +classifiers = [ + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "License :: OSI Approved :: Apache Software License", +] +name = "nomad-simulations" +description = "A NOMAD plugin for FAIR schemas for simulation data." dynamic = ["version"] -description = 'A NOMAD plugin for FAIR schemas for simulation data.' readme = "README.md" +requires-python = ">=3.9" authors = [ { name = "Jose M. Pizarro", email = "jose.pizarro@physik.hu-berlin.de" }, { name = "Nathan Daelman", email = "ndaelman@physik.hu-berlin.de" }, { name = "Bernadette Mohr", email = "mohrbern@physik.hu-berlin.de" }, { name = "Joseph F. Rudzinski", email = "joseph.rudzinski@physik.hu-berlin.de" } ] -license = { text = "Apache-2.0" } -requires-python = ">=3.9" +maintainers = [ + { name = "Jose M. Pizarro", email = "jose.pizarro@physik.hu-berlin.de" }, + { name = "Joseph F. Rudzinski", email = "joseph.rudzinski@physik.hu-berlin.de" } +] +license = { file = "LICENSE" } dependencies = [ "nomad-lab>=1.2.2dev578", "matid>=2.0.0.dev2", @@ -30,23 +41,53 @@ dependencies = [ [project.optional-dependencies] dev = [ - 'mypy==1.0.1', - 'pytest', - 'pytest-timeout', - 'pytest-cov', - 'ruff', - "structlog==22.3.0", - "lxml_html_clean>=0.1.0", + "mypy==1.0.1", + "ruff", + "pytest", + "pytest-timeout", + "pytest-cov", + "structlog", + "lxml_html_clean>=0.1.0" ] [tool.ruff] -include = ["src/nomad_simulations/*.py", "tests/*.py"] -lint.select = [ +# Exclude a variety of commonly ignored directories. +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".git-rewrite", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "venv", +] + +# Same as Black. +line-length = 88 +indent-width = 4 + +[tool.ruff.lint] +select = [ "E", # pycodestyle "W", # pycodestyle "PL", # pylint ] -lint.ignore = [ + +ignore = [ "E501", # Line too long ({width} > {limit} characters) "E701", # Multiple statements on one line (colon) "E731", # Do not assign a lambda expression, use a def @@ -61,12 +102,13 @@ lint.ignore = [ "PLR1714", # consider-using-in "PLR5501", # else-if-used ] -lint.fixable = ["ALL"] -# Same as Black. -line-length = 88 -indent-width = 4 +fixable = ["ALL"] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" +# this is entirely optional, you can remove this if you wish to [tool.ruff.format] # use single quotes for strings. quote-style = "single" @@ -80,8 +122,12 @@ skip-magic-trailing-comma = false # Like Black, automatically detect the appropriate line ending. line-ending = "auto" +[tool.setuptools] +package-dir = { "" = "src" } + [tool.setuptools.packages.find] where = ["src"] -[tool.setuptools.package-data] -nomad_simulations = ["*/nomad_plugin.yaml"] +[project.entry-points.'nomad.plugin'] + +nomad_simulations_plugin = "nomad_simulations.schema_packages:nomad_simulations_plugin" diff --git a/requirements_docs.txt b/requirements_docs.txt new file mode 100644 index 00000000..bacf1ed5 --- /dev/null +++ b/requirements_docs.txt @@ -0,0 +1,4 @@ +mkdocs +mkdocs-material==8.1.1 +pymdown-extensions +mkdocs-click diff --git a/src/nomad_simulations/__init__.py b/src/nomad_simulations/__init__.py index 606c722c..e69de29b 100644 --- a/src/nomad_simulations/__init__.py +++ b/src/nomad_simulations/__init__.py @@ -1,20 +0,0 @@ -# -# Copyright The NOMAD Authors. -# -# This file is part of NOMAD. -# See https://nomad-lab.eu for further info. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -from .general import Program, Simulation diff --git a/src/nomad_simulations/nomad_plugin.yaml b/src/nomad_simulations/nomad_plugin.yaml deleted file mode 100644 index 07cb8346..00000000 --- a/src/nomad_simulations/nomad_plugin.yaml +++ /dev/null @@ -1,4 +0,0 @@ -plugin_type: schema -name: schemas/nomad_simulations -description: | - This is a collection of NOMAD schemas for simulation data. diff --git a/src/nomad_simulations/schema_packages/__init__.py b/src/nomad_simulations/schema_packages/__init__.py new file mode 100644 index 00000000..183fab03 --- /dev/null +++ b/src/nomad_simulations/schema_packages/__init__.py @@ -0,0 +1,61 @@ +# +# Copyright The NOMAD Authors. +# +# This file is part of NOMAD. See https://nomad-lab.eu for further info. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +from nomad.config.models.plugins import SchemaPackageEntryPoint +from pydantic import Field + + +class NOMADSimulationsEntryPoint(SchemaPackageEntryPoint): + dos_energy_tolerance: float = Field( + 8.01088e-21, + description='Tolerance of the DOS energies in Joules to match the reference of energies in the DOS normalize function.', + ) + dos_intensities_threshold: float = Field( + 1e-8, + description='Threshold value at which the DOS intensities are considered non-zero.', + ) + occupation_tolerance: float = Field( + 1e-3, + description='Tolerance for the occupation of a eigenstate to be non-occupied.', + ) + fermi_surface_tolerance: float = Field( + 1e-8, + description='Tolerance for energies to be close to the Fermi level and hence define the Fermi surface of a material.', + ) + symmetry_tolerance: float = Field( + 0.1, description='Tolerance for the symmetry analyzer used from MatID.' + ) + cluster_threshold: float = Field( + 2.5, + description='Threshold for the distance between atoms to be considered in the same cluster.', + ) + limit_system_type_classification: float = Field( + 64, + description='Limite of the number of atoms in the unit cell to be treated for the system type classification from MatID to work. This is done to avoid overhead of the package.', + ) + + def load(self): + from nomad_simulations.schema_packages.general import m_package + + return m_package + + +nomad_simulations_plugin = NOMADSimulationsEntryPoint( + name='NOMADSimulations', + description='A NOMAD plugin for FAIR schemas for simulation data.', +) diff --git a/src/nomad_simulations/atoms_state.py b/src/nomad_simulations/schema_packages/atoms_state.py similarity index 94% rename from src/nomad_simulations/atoms_state.py rename to src/nomad_simulations/schema_packages/atoms_state.py index 6b32f43e..c091fa35 100644 --- a/src/nomad_simulations/atoms_state.py +++ b/src/nomad_simulations/schema_packages/atoms_state.py @@ -16,19 +16,24 @@ # limitations under the License. # -import numpy as np +from typing import TYPE_CHECKING, Any, Dict, Optional, Union + import ase +import numpy as np import pint -from typing import Optional, Union, Dict, Any -from structlog.stdlib import BoundLogger -from nomad.units import ureg -from nomad.metainfo import Quantity, SubSection, MEnum, Section, Context from nomad.datamodel.data import ArchiveSection -from nomad.datamodel.metainfo.basesections import Entity from nomad.datamodel.metainfo.annotations import ELNAnnotation +from nomad.datamodel.metainfo.basesections import Entity +from nomad.metainfo import MEnum, Quantity, SubSection +from nomad.units import ureg + +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger -from nomad_simulations.utils import RussellSaundersState +from nomad_simulations.schema_packages.utils import RussellSaundersState class OrbitalsState(Entity): @@ -127,7 +132,7 @@ class OrbitalsState(Entity): """, ) - def __init__(self, m_def: Section = None, m_context: Context = None, **kwargs): + def __init__(self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs): super().__init__(m_def, m_context, **kwargs) self._orbitals = { -1: dict(zip(range(4), ('s', 'p', 'd', 'f'))), @@ -152,15 +157,15 @@ def __init__(self, m_def: Section = None, m_context: Context = None, **kwargs): self._orbitals_map: Dict[str, Any] = { 'l_symbols': self._orbitals[-1], 'ml_symbols': {i: self._orbitals[i] for i in range(4)}, - 'ms_symbols': dict((zip((-0.5, 0.5), ('down', 'up')))), + 'ms_symbols': dict(zip((-0.5, 0.5), ('down', 'up'))), 'l_numbers': {v: k for k, v in self._orbitals[-1].items()}, 'ml_numbers': { k: {v: k for k, v in self._orbitals[k].items()} for k in range(4) }, - 'ms_numbers': dict((zip(('down', 'up'), (-0.5, 0.5)))), + 'ms_numbers': dict(zip(('down', 'up'), (-0.5, 0.5))), } - def validate_quantum_numbers(self, logger: BoundLogger) -> bool: + def validate_quantum_numbers(self, logger: 'BoundLogger') -> bool: """ Validate the quantum numbers (`n`, `l`, `ml`, `ms`) by checking if they are physically sensible. @@ -193,7 +198,7 @@ def validate_quantum_numbers(self, logger: BoundLogger) -> bool: return True def resolve_number_and_symbol( - self, quantum_name: str, quantum_type: str, logger: BoundLogger + self, quantum_name: str, quantum_type: str, logger: 'BoundLogger' ) -> Optional[Union[str, int]]: """ Resolves the quantum number or symbol from the `self._orbitals_map` on the passed `quantum_type`. @@ -289,7 +294,7 @@ def resolve_degeneracy(self) -> Optional[int]: degeneracy += RussellSaundersState(J=jj, occ=1).degeneracy return degeneracy - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # General checks for physical quantum numbers and symbols @@ -344,7 +349,7 @@ class CoreHole(ArchiveSection): """, ) - def resolve_occupation(self, logger: BoundLogger) -> Optional[np.float64]: + def resolve_occupation(self, logger: 'BoundLogger') -> Optional[np.float64]: """ Resolves the occupation of the orbital state. The occupation is resolved from the degeneracy and the number of excited electrons. @@ -368,7 +373,7 @@ def resolve_occupation(self, logger: BoundLogger) -> Optional[np.float64]: return degeneracy - self.n_excited_electrons return None - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Check if n_excited_electrons is between 0 and 1 @@ -491,7 +496,7 @@ class HubbardInteractions(ArchiveSection): a_eln=ELNAnnotation(component='StringEditQuantity'), ) - def resolve_u_interactions(self, logger: BoundLogger) -> Optional[tuple]: + def resolve_u_interactions(self, logger: 'BoundLogger') -> Optional[tuple]: """ Resolves the Hubbard interactions (u_interaction, u_interorbital_interaction, j_hunds_coupling) from the Slater integrals (F0, F2, F4) in the units defined for the Quantity. @@ -519,7 +524,7 @@ def resolve_u_interactions(self, logger: BoundLogger) -> Optional[tuple]: ) return u_interaction, u_interorbital_interaction, j_hunds_coupling - def resolve_u_effective(self, logger: BoundLogger) -> Optional[pint.Quantity]: + def resolve_u_effective(self, logger: 'BoundLogger') -> Optional[pint.Quantity]: """ Resolves the effective U parameter (u_interaction - j_local_exchange_interaction). @@ -539,7 +544,7 @@ def resolve_u_effective(self, logger: BoundLogger) -> Optional[pint.Quantity]: self.j_local_exchange_interaction = 0.0 * ureg.eV return self.u_interaction - self.j_local_exchange_interaction - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Obtain (u, up, j_hunds_coupling) from slater_integrals @@ -609,7 +614,7 @@ class AtomsState(Entity): sub_section=HubbardInteractions.m_def, repeats=False ) - def resolve_chemical_symbol(self, logger: BoundLogger) -> Optional[str]: + def resolve_chemical_symbol(self, logger: 'BoundLogger') -> Optional[str]: """ Resolves the `chemical_symbol` from the `atomic_number`. @@ -628,7 +633,7 @@ def resolve_chemical_symbol(self, logger: BoundLogger) -> Optional[str]: ) return None - def resolve_atomic_number(self, logger: BoundLogger) -> Optional[int]: + def resolve_atomic_number(self, logger: 'BoundLogger') -> Optional[int]: """ Resolves the `atomic_number` from the `chemical_symbol`. @@ -647,7 +652,7 @@ def resolve_atomic_number(self, logger: BoundLogger) -> Optional[int]: ) return None - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Get chemical_symbol from atomic_number and viceversa diff --git a/src/nomad_simulations/general.py b/src/nomad_simulations/schema_packages/general.py similarity index 89% rename from src/nomad_simulations/general.py rename to src/nomad_simulations/schema_packages/general.py index 791addf3..3a27b044 100644 --- a/src/nomad_simulations/general.py +++ b/src/nomad_simulations/schema_packages/general.py @@ -16,18 +16,33 @@ # limitations under the License. # +from typing import TYPE_CHECKING, List + import numpy as np -from typing import List -from nomad.metainfo import SubSection, Quantity, Section, Datetime -from nomad.datamodel.metainfo.annotations import ELNAnnotation +from nomad.config import config from nomad.datamodel.data import EntryData -from nomad.datamodel.metainfo.basesections import Entity, Activity +from nomad.datamodel.metainfo.annotations import ELNAnnotation +from nomad.datamodel.metainfo.basesections import Activity, Entity +from nomad.metainfo import Datetime, Quantity, SchemaPackage, Section, SubSection + +if TYPE_CHECKING: + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger -from nomad_simulations.model_system import ModelSystem -from nomad_simulations.model_method import ModelMethod -from nomad_simulations.outputs import Outputs -from nomad_simulations.utils import is_not_representative, get_composition +from nomad_simulations.schema_packages.model_method import ModelMethod +from nomad_simulations.schema_packages.model_system import ModelSystem +from nomad_simulations.schema_packages.outputs import Outputs +from nomad_simulations.schema_packages.utils import ( + get_composition, + is_not_representative, +) + +configuration = config.get_plugin_entry_point( + 'nomad_simulations.schema_packages:nomad_simulations_plugin' +) + +m_package = SchemaPackage() class Program(Entity): @@ -80,7 +95,7 @@ class Program(Entity): a_eln=ELNAnnotation(component='StringEditQuantity'), ) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: pass @@ -144,7 +159,7 @@ class BaseSimulation(Activity): program = SubSection(sub_section=Program.m_def, repeats=False) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: pass @@ -248,7 +263,7 @@ def get_composition_recurs(system: ModelSystem, atom_labels: List[str]) -> None: ) get_composition_recurs(system=system_parent, atom_labels=atom_labels) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super(EntryData, self).normalize(archive, logger) # Finding which is the representative system of a calculation: typically, we will @@ -272,3 +287,6 @@ def normalize(self, archive, logger) -> None: if is_not_representative(model_system=system_parent, logger=logger): continue self.resolve_composition_formula(system_parent=system_parent) + + +m_package.__init_metainfo__() diff --git a/src/nomad_simulations/model_method.py b/src/nomad_simulations/schema_packages/model_method.py similarity index 95% rename from src/nomad_simulations/model_method.py rename to src/nomad_simulations/schema_packages/model_method.py index 68619892..7dfaf2f4 100644 --- a/src/nomad_simulations/model_method.py +++ b/src/nomad_simulations/schema_packages/model_method.py @@ -16,25 +16,24 @@ # limitations under the License. # -import numpy as np import re -from structlog.stdlib import BoundLogger -from typing import Optional, List +from typing import TYPE_CHECKING, List, Optional + +import numpy as np from nomad.datamodel.data import ArchiveSection from nomad.datamodel.metainfo.annotations import ELNAnnotation -from nomad.metainfo import ( - Quantity, - SubSection, - MEnum, - Section, - Context, -) +from nomad.metainfo import MEnum, Quantity, SubSection -from nomad_simulations.numerical_settings import NumericalSettings -from nomad_simulations.model_system import ModelSystem, AtomicCell -from nomad_simulations.atoms_state import OrbitalsState, CoreHole -from nomad_simulations.utils import is_not_representative +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger + +from nomad_simulations.schema_packages.atoms_state import CoreHole, OrbitalsState +from nomad_simulations.schema_packages.model_system import ModelSystem +from nomad_simulations.schema_packages.numerical_settings import NumericalSettings +from nomad_simulations.schema_packages.utils import is_not_representative class ModelMethod(ArchiveSection): @@ -76,7 +75,7 @@ class ModelMethod(ArchiveSection): numerical_settings = SubSection(sub_section=NumericalSettings.m_def, repeats=True) - def normalize(self, archive, logger): + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -109,7 +108,7 @@ class ModelMethodElectronic(ModelMethod): a_eln=ELNAnnotation(component='EnumEditQuantity'), ) - def normalize(self, archive, logger): + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -118,8 +117,6 @@ class XCFunctional(ArchiveSection): A base section used to define the parameters of an exchange or correlation functional. """ - m_def = Section(validate=False) - libxc_name = Quantity( type=str, description=""" @@ -163,7 +160,7 @@ def get_weight_name(self, weight: Optional[np.float64]) -> Optional[str]: weight_name = f'{str(weight)}*' return weight_name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Appending `weight` as a string to `libxc_name` @@ -261,7 +258,7 @@ class DFT(ModelMethodElectronic): a_eln=ELNAnnotation(component='EnumEditQuantity'), ) - def __init__(self, m_def: Section = None, m_context: Context = None, **kwargs): + def __init__(self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs): super().__init__(m_def, m_context, **kwargs) self._jacobs_ladder_map = { 'lda': 'LDA', @@ -367,7 +364,7 @@ def _scan_patterns(patterns: List[str], xc_name: str) -> bool: return 0.56 return None - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) libxc_names = self.resolve_libxc_names(self.xc_functionals) @@ -465,7 +462,7 @@ def resolve_type(self) -> Optional[str]: def resolve_orbital_references( self, model_systems: List[ModelSystem], - logger: BoundLogger, + logger: 'BoundLogger', model_index: int = -1, ) -> Optional[List[OrbitalsState]]: """ @@ -524,7 +521,7 @@ def resolve_orbital_references( orbitals_ref.append(orbital) return orbitals_ref - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Set `name` to "TB" @@ -593,7 +590,7 @@ class Wannier(TB): """, ) - def normalize(self, archive, logger): + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Resolve `localization_type` from `is_maximally_localized` @@ -660,7 +657,7 @@ class SlaterKosterBond(ArchiveSection): """, ) - def __init__(self, m_def: Section = None, m_context: Context = None, **kwargs): + def __init__(self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs): super().__init__(m_def, m_context, **kwargs) # TODO extend this to cover all bond names self._bond_name_map = { @@ -674,7 +671,7 @@ def resolve_bond_name_from_references( orbital_1: Optional[OrbitalsState], orbital_2: Optional[OrbitalsState], bravais_vector: Optional[tuple], - logger: BoundLogger, + logger: 'BoundLogger', ) -> Optional[str]: """ Resolves the `name` of the `SlaterKosterBond` from the references to the `OrbitalsState` sections. @@ -712,7 +709,7 @@ def resolve_bond_name_from_references( break return bond_name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Resolve the SK bond `name` from the `OrbitalsState` references and the `bravais_vector` @@ -736,7 +733,7 @@ class SlaterKoster(TB): overlaps = SubSection(sub_section=SlaterKosterBond.m_def, repeats=True) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -747,7 +744,7 @@ class xTB(TB): # ? Deprecate this - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -789,7 +786,7 @@ class Photon(ArchiveSection): """, ) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Add warning in case `multipole_type` and `momentum_transfer` are not consistent @@ -842,7 +839,7 @@ class ExcitedStateMethodology(ModelMethodElectronic): a_eln=ELNAnnotation(component='NumberEditQuantity'), ) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -861,7 +858,7 @@ class Screening(ExcitedStateMethodology): a_eln=ELNAnnotation(component='NumberEditQuantity'), ) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -941,7 +938,7 @@ class GW(ExcitedStateMethodology): a_eln=ELNAnnotation(component='ReferenceEditQuantity'), ) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -1000,7 +997,7 @@ class BSE(ExcitedStateMethodology): a_eln=ELNAnnotation(component='ReferenceEditQuantity'), ) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -1011,8 +1008,6 @@ class CoreHoleSpectra(ModelMethodElectronic): also contains reference to the specific methodological section (DFT, BSE) used to obtain the core-hole spectra. """ - m_def = Section(validate=False) - # # TODO add examples # solver = Quantity( # type=str, @@ -1075,7 +1070,7 @@ class CoreHoleSpectra(ModelMethodElectronic): # TODO add normalization to obtain `edge` - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -1187,5 +1182,5 @@ class DMFT(ModelMethodElectronic): """, ) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) diff --git a/src/nomad_simulations/model_system.py b/src/nomad_simulations/schema_packages/model_system.py similarity index 95% rename from src/nomad_simulations/model_system.py rename to src/nomad_simulations/schema_packages/model_system.py index a1551a29..8dc21cb5 100644 --- a/src/nomad_simulations/model_system.py +++ b/src/nomad_simulations/schema_packages/model_system.py @@ -17,37 +17,44 @@ # import re -import numpy as np +from typing import TYPE_CHECKING, Optional, Tuple + import ase -from typing import Tuple, Optional -from structlog.stdlib import BoundLogger +import numpy as np -from matid import SymmetryAnalyzer, Classifier # pylint: disable=import-error +from matid import Classifier, SymmetryAnalyzer # pylint: disable=import-error from matid.classification.classifications import ( - Class0D, Atom, + Class0D, Class1D, Class2D, + Class3D, Material2D, Surface, - Class3D, -) # pylint: disable=import-error - -from nomad import config -from nomad.units import ureg -from nomad.atomutils import ( - Formula, - get_normalized_wyckoff, - search_aflow_prototype, ) -from nomad.metainfo import Quantity, SubSection, SectionProxy, MEnum, Section, Context +from nomad.config import config +from nomad.atomutils import Formula, get_normalized_wyckoff, search_aflow_prototype from nomad.datamodel.data import ArchiveSection -from nomad.datamodel.metainfo.basesections import Entity, System from nomad.datamodel.metainfo.annotations import ELNAnnotation +from nomad.datamodel.metainfo.basesections import Entity, System +from nomad.metainfo import MEnum, Quantity, SectionProxy, SubSection +from nomad.units import ureg -from nomad_simulations.atoms_state import AtomsState -from nomad_simulations.utils import get_sibling_section, is_not_representative +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger + +from nomad_simulations.schema_packages.atoms_state import AtomsState +from nomad_simulations.schema_packages.utils import ( + get_sibling_section, + is_not_representative, +) + +configuration = config.get_plugin_entry_point( + 'nomad_simulations.schema_packages:nomad_simulations_plugin' +) class GeometricSpace(Entity): @@ -177,7 +184,7 @@ class GeometricSpace(Entity): """, ) - def get_geometric_space_for_atomic_cell(self, logger: BoundLogger) -> None: + def get_geometric_space_for_atomic_cell(self, logger: 'BoundLogger') -> None: """ Get the real space parameters for the atomic cell using ASE. @@ -194,7 +201,7 @@ def get_geometric_space_for_atomic_cell(self, logger: BoundLogger) -> None: ) self.volume = cell.volume * ureg.angstrom**3 - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: # Skip normalization for `Entity` try: self.get_geometric_space_for_atomic_cell(logger=logger) @@ -283,7 +290,7 @@ class Cell(GeometricSpace): """, ) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -321,12 +328,12 @@ class AtomicCell(Cell): """, ) - def __init__(self, m_def: Section = None, m_context: Context = None, **kwargs): + def __init__(self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs): super().__init__(m_def, m_context, **kwargs) # Set the name of the section self.name = self.m_def.name - def to_ase_atoms(self, logger: BoundLogger) -> Optional[ase.Atoms]: + def to_ase_atoms(self, logger: 'BoundLogger') -> Optional[ase.Atoms]: """ Generates an ASE Atoms object with the most basic information from the parsed `AtomicCell` section (labels, periodic_boundary_conditions, positions, and lattice_vectors). @@ -371,7 +378,7 @@ def to_ase_atoms(self, logger: BoundLogger) -> Optional[ase.Atoms]: return ase_atoms - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Set the name of the section @@ -488,7 +495,7 @@ class Symmetry(ArchiveSection): ) def resolve_analyzed_atomic_cell( - self, symmetry_analyzer: SymmetryAnalyzer, cell_type: str, logger: BoundLogger + self, symmetry_analyzer: SymmetryAnalyzer, cell_type: str, logger: 'BoundLogger' ) -> Optional[AtomicCell]: """ Resolves the `AtomicCell` section from the `SymmetryAnalyzer` object and the cell_type @@ -533,7 +540,7 @@ def resolve_analyzed_atomic_cell( return atomic_cell def resolve_bulk_symmetry( - self, original_atomic_cell: AtomicCell, logger: BoundLogger + self, original_atomic_cell: AtomicCell, logger: 'BoundLogger' ) -> Tuple[Optional[AtomicCell], Optional[AtomicCell]]: """ Resolves the symmetry of the material being simulated using MatID and the @@ -553,7 +560,7 @@ def resolve_bulk_symmetry( try: ase_atoms = original_atomic_cell.to_ase_atoms(logger=logger) symmetry_analyzer = SymmetryAnalyzer( - ase_atoms, symmetry_tol=config.normalize.symmetry_tolerance + ase_atoms, symmetry_tol=configuration.symmetry_tolerance ) except ValueError as e: logger.debug( @@ -633,7 +640,7 @@ def resolve_bulk_symmetry( return primitive_atomic_cell, conventional_atomic_cell - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) atomic_cell = get_sibling_section( @@ -722,7 +729,7 @@ def resolve_chemical_formulas(self, formula: Formula) -> None: self.hill = formula.format(fmt='hill') self.anonymous = formula.format(fmt='anonymous') - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) atomic_cell = get_sibling_section( @@ -937,7 +944,7 @@ class ModelSystem(System): model_system = SubSection(sub_section=SectionProxy('ModelSystem'), repeats=True) def resolve_system_type_and_dimensionality( - self, ase_atoms: ase.Atoms, logger: BoundLogger + self, ase_atoms: ase.Atoms, logger: 'BoundLogger' ) -> Tuple[str, int]: """ Resolves the `ModelSystem.type` and `ModelSystem.dimensionality` using `MatID` classification analyzer: @@ -952,14 +959,11 @@ def resolve_system_type_and_dimensionality( """ classification = None system_type, dimensionality = self.type, self.dimensionality - if ( - len(ase_atoms) - <= config.normalize.system_classification_with_clusters_threshold - ): + if len(ase_atoms) <= configuration.limit_system_type_classification: try: classifier = Classifier( radii='covalent', - cluster_threshold=config.normalize.cluster_threshold, + cluster_threshold=configuration.cluster_threshold, ) classification = classifier.classify(input_system=ase_atoms) except Exception as e: @@ -993,7 +997,7 @@ def resolve_system_type_and_dimensionality( return system_type, dimensionality - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # We don't need to normalize if the system is not representative diff --git a/src/nomad_simulations/numerical_settings.py b/src/nomad_simulations/schema_packages/numerical_settings.py similarity index 95% rename from src/nomad_simulations/numerical_settings.py rename to src/nomad_simulations/schema_packages/numerical_settings.py index 6157c9b4..480201c2 100644 --- a/src/nomad_simulations/numerical_settings.py +++ b/src/nomad_simulations/schema_packages/numerical_settings.py @@ -16,19 +16,25 @@ # limitations under the License. # +from itertools import accumulate, chain, tee +from typing import TYPE_CHECKING, List, Optional, Tuple, Union + import numpy as np import pint -from itertools import accumulate, tee, chain -from structlog.stdlib import BoundLogger -from typing import Optional, List, Tuple, Union -from ase.dft.kpoints import monkhorst_pack, get_monkhorst_pack_size_and_offset -from nomad.units import ureg +from ase.dft.kpoints import get_monkhorst_pack_size_and_offset, monkhorst_pack + from nomad.datamodel.data import ArchiveSection -from nomad.metainfo import Quantity, SubSection, MEnum, Section, Context, JSON +from nomad.metainfo import JSON, MEnum, Quantity, SubSection +from nomad.units import ureg + +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger -from nomad_simulations.model_system import ModelSystem -from nomad_simulations.utils import is_not_representative +from nomad_simulations.schema_packages.model_system import ModelSystem +from nomad_simulations.schema_packages.utils import is_not_representative class NumericalSettings(ArchiveSection): @@ -46,7 +52,7 @@ class NumericalSettings(ArchiveSection): """, ) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -156,7 +162,7 @@ class Mesh(ArchiveSection): """, ) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -168,7 +174,7 @@ class KSpaceFunctionalities: def validate_reciprocal_lattice_vectors( self, reciprocal_lattice_vectors: Optional[pint.Quantity], - logger: BoundLogger, + logger: 'BoundLogger', check_grid: Optional[bool] = False, grid: Optional[List[int]] = [], ) -> bool: @@ -206,7 +212,7 @@ def validate_reciprocal_lattice_vectors( def resolve_high_symmetry_points( self, model_systems: List[ModelSystem], - logger: BoundLogger, + logger: 'BoundLogger', eps: float = 3e-3, ) -> Optional[dict]: """ @@ -357,7 +363,7 @@ class KMesh(Mesh): # TODO add extraction of `high_symmetry_points` using BandStructureNormalizer idea (left for later when defining outputs.py) def resolve_points_and_offset( - self, logger: BoundLogger + self, logger: 'BoundLogger' ) -> Tuple[Optional[List[np.ndarray]], Optional[np.ndarray]]: """ Resolves the `points` and `offset` of the `KMesh` from the `grid` and the `center`. @@ -391,7 +397,7 @@ def resolve_points_and_offset( return points, offset def get_k_line_density( - self, reciprocal_lattice_vectors: Optional[pint.Quantity], logger: BoundLogger + self, reciprocal_lattice_vectors: Optional[pint.Quantity], logger: 'BoundLogger' ) -> Optional[np.float64]: """ Gets the k-line density of the `KMesh`. This quantity is used as a precision measure @@ -425,7 +431,7 @@ def resolve_k_line_density( self, model_systems: List[ModelSystem], reciprocal_lattice_vectors: pint.Quantity, - logger: BoundLogger, + logger: 'BoundLogger', ) -> Optional[pint.Quantity]: """ Resolves the `k_line_density` of the `KMesh` from the the list of `ModelSystem`. @@ -462,7 +468,7 @@ def resolve_k_line_density( return k_line_density return None - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # If `grid` is not defined, we do not normalize the KMesh @@ -541,7 +547,7 @@ def resolve_high_symmetry_path_values( self, model_systems: List[ModelSystem], reciprocal_lattice_vectors: pint.Quantity, - logger: BoundLogger, + logger: 'BoundLogger', ) -> Optional[List[float]]: """ Resolves the `high_symmetry_path_values` of the `KLinePath` from the `high_symmetry_path_names`. @@ -578,7 +584,7 @@ def resolve_high_symmetry_path_values( ] return high_symmetry_path_values - def validate_high_symmetry_path(self, logger: BoundLogger) -> bool: + def validate_high_symmetry_path(self, logger: 'BoundLogger') -> bool: """ Validate `high_symmetry_path_names` and `high_symmetry_path_values` by checking if they are defined and have the same length. @@ -609,7 +615,7 @@ def validate_high_symmetry_path(self, logger: BoundLogger) -> bool: def get_high_symmetry_path_norms( self, reciprocal_lattice_vectors: Optional[pint.Quantity], - logger: BoundLogger, + logger: 'BoundLogger', ) -> Optional[List[pint.Quantity]]: """ Get the high symmetry path points norms from the list of dictionaries of vectors in units of the `reciprocal_lattice_vectors`. @@ -662,7 +668,7 @@ def resolve_points( self, points_norm: Union[np.ndarray, List[float]], reciprocal_lattice_vectors: Optional[np.ndarray], - logger: BoundLogger, + logger: 'BoundLogger', ) -> None: """ Resolves the `points` of the `KLinePath` from the `points_norm` and the `reciprocal_lattice_vectors`. This is useful @@ -738,7 +744,7 @@ def linspace_segments( logger.info('Overwriting `KLinePath.points` with the resolved points.') self.points = new_points - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Resolves `high_symmetry_path_values` from `high_symmetry_path_names` @@ -785,13 +791,13 @@ class KSpace(NumericalSettings): k_line_path = SubSection(sub_section=KLinePath.m_def) - def __init__(self, m_def: Section = None, m_context: Context = None, **kwargs): + def __init__(self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs): super().__init__(m_def, m_context, **kwargs) # Set the name of the section self.name = self.m_def.name def resolve_reciprocal_lattice_vectors( - self, model_systems: List[ModelSystem], logger: BoundLogger + self, model_systems: List[ModelSystem], logger: 'BoundLogger' ) -> Optional[pint.Quantity]: """ Resolve the `reciprocal_lattice_vectors` of the `KSpace` from the representative `ModelSystem` section. @@ -823,7 +829,7 @@ def resolve_reciprocal_lattice_vectors( return 2 * np.pi * ase_atoms.get_reciprocal_cell() / ureg.angstrom return None - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Resolve `reciprocal_lattice_vectors` from the `ModelSystem` ASE object @@ -877,12 +883,12 @@ class SelfConsistency(NumericalSettings): """, ) - def __init__(self, m_def: Section = None, m_context: Context = None, **kwargs): + def __init__(self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs): super().__init__(m_def, m_context, **kwargs) # Set the name of the section self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -891,10 +897,10 @@ class BasisSet(NumericalSettings): # TODO work on this base section (@ndaelman-hu) - def __init__(self, m_def: Section = None, m_context: Context = None, **kwargs): + def __init__(self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs): super().__init__(m_def, m_context, **kwargs) # Set the name of the section self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) diff --git a/src/nomad_simulations/outputs.py b/src/nomad_simulations/schema_packages/outputs.py similarity index 93% rename from src/nomad_simulations/outputs.py rename to src/nomad_simulations/schema_packages/outputs.py index 388e6504..2578aba2 100644 --- a/src/nomad_simulations/outputs.py +++ b/src/nomad_simulations/schema_packages/outputs.py @@ -16,29 +16,32 @@ # limitations under the License. # -from structlog.stdlib import BoundLogger -from typing import Optional, List +from typing import TYPE_CHECKING, List, Optional from nomad.datamodel.data import ArchiveSection -from nomad.metainfo import Quantity, SubSection from nomad.datamodel.metainfo.annotations import ELNAnnotation +from nomad.metainfo import Quantity, SubSection -from nomad_simulations.model_system import ModelSystem -from nomad_simulations.physical_property import PhysicalProperty -from nomad_simulations.numerical_settings import SelfConsistency -from nomad_simulations.properties import ( - FermiLevel, +if TYPE_CHECKING: + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger + +from nomad_simulations.schema_packages.model_system import ModelSystem +from nomad_simulations.schema_packages.numerical_settings import SelfConsistency +from nomad_simulations.schema_packages.physical_property import PhysicalProperty +from nomad_simulations.schema_packages.properties import ( + AbsorptionSpectrum, ChemicalPotential, CrystalFieldSplitting, - HoppingMatrix, ElectronicBandGap, + ElectronicBandStructure, ElectronicDensityOfStates, ElectronicEigenvalues, + FermiLevel, FermiSurface, - ElectronicBandStructure, - AbsorptionSpectrum, - XASSpectrum, + HoppingMatrix, Permittivity, + XASSpectrum, ) @@ -139,7 +142,7 @@ def set_model_system_ref(self) -> Optional[ModelSystem]: return model_systems[-1] return None - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Set ref to the last ModelSystem if this is not set in the output @@ -171,7 +174,7 @@ def get_last_scf_steps_value( property_name: str, i_property: int, scf_parameters: Optional[SelfConsistency], - logger: BoundLogger, + logger: 'BoundLogger', ) -> Optional[list]: """ Get the last two SCF values' magnitudes of a physical property and appends then in a list. @@ -212,7 +215,7 @@ def resolve_is_scf_converged( property_name: str, i_property: int, physical_property: PhysicalProperty, - logger: BoundLogger, + logger: 'BoundLogger', ) -> bool: """ Resolves if the physical property is converged or not after a SCF process. This is only ran @@ -257,7 +260,7 @@ def resolve_is_scf_converged( ) return False - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Resolve the `is_scf_converged` flag for all SCF obtained properties diff --git a/src/nomad_simulations/physical_property.py b/src/nomad_simulations/schema_packages/physical_property.py similarity index 94% rename from src/nomad_simulations/physical_property.py rename to src/nomad_simulations/schema_packages/physical_property.py index 39c1d926..92841b97 100644 --- a/src/nomad_simulations/physical_property.py +++ b/src/nomad_simulations/schema_packages/physical_property.py @@ -16,30 +16,33 @@ # limitations under the License. # -import numpy as np -from typing import Any, Optional from functools import wraps +from typing import TYPE_CHECKING, Any, Optional + +import numpy as np from nomad import utils from nomad.datamodel.data import ArchiveSection +from nomad.datamodel.metainfo.basesections import Entity from nomad.metainfo import ( + URL, + MEnum, Quantity, - SubSection, - SectionProxy, Reference, - Section, - Context, - MEnum, - URL, + SectionProxy, + SubSection, ) -from nomad.metainfo.metainfo import DirectQuantity, Dimension, _placeholder_quantity -from nomad.datamodel.metainfo.basesections import Entity +from nomad.metainfo.metainfo import Dimension, DirectQuantity, _placeholder_quantity -from nomad_simulations.variables import Variables -from nomad_simulations.numerical_settings import SelfConsistency +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger +from nomad_simulations.schema_packages.numerical_settings import SelfConsistency +from nomad_simulations.schema_packages.variables import Variables -# We add `logger` for the `PhysicalProperty.variables_shape` method +# We add `logger` for the `validate_quantity_wrt_value` decorator logger = utils.get_logger(__name__) @@ -65,7 +68,7 @@ def wrapper(self, *args, **kwargs): # Checks if `value` exists and has the same shape as `quantity` value = getattr(self, 'value', None) if value is None: - logger.warning(f'The quantity `value` is not defined.') + logger.warning('The quantity `value` is not defined.') return False if value is not None and value.shape != quantity.shape: logger.warning( @@ -256,7 +259,7 @@ def _new_value(self) -> Quantity: ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) @@ -316,7 +319,7 @@ def _is_derived(self) -> bool: return True return False - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Resolve if the physical property `is_derived` or not from another physical property. diff --git a/src/nomad_simulations/properties/__init__.py b/src/nomad_simulations/schema_packages/properties/__init__.py similarity index 82% rename from src/nomad_simulations/properties/__init__.py rename to src/nomad_simulations/schema_packages/properties/__init__.py index 3c6194ed..78e5fe41 100644 --- a/src/nomad_simulations/properties/__init__.py +++ b/src/nomad_simulations/schema_packages/properties/__init__.py @@ -16,16 +16,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .energies import FermiLevel, ChemicalPotential from .band_gap import ElectronicBandGap +from .band_structure import ElectronicBandStructure, ElectronicEigenvalues +from .energies import ChemicalPotential, FermiLevel +from .fermi_surface import FermiSurface +from .hopping_matrix import CrystalFieldSplitting, HoppingMatrix +from .permittivity import Permittivity from .spectral_profile import ( - SpectralProfile, + AbsorptionSpectrum, DOSProfile, ElectronicDensityOfStates, - AbsorptionSpectrum, + SpectralProfile, XASSpectrum, ) -from .hopping_matrix import HoppingMatrix, CrystalFieldSplitting -from .permittivity import Permittivity -from .fermi_surface import FermiSurface -from .band_structure import ElectronicEigenvalues, ElectronicBandStructure diff --git a/src/nomad_simulations/properties/band_gap.py b/src/nomad_simulations/schema_packages/properties/band_gap.py similarity index 89% rename from src/nomad_simulations/properties/band_gap.py rename to src/nomad_simulations/schema_packages/properties/band_gap.py index 6245bc63..35b83d32 100644 --- a/src/nomad_simulations/properties/band_gap.py +++ b/src/nomad_simulations/schema_packages/properties/band_gap.py @@ -16,14 +16,19 @@ # limitations under the License. # +from typing import TYPE_CHECKING, Optional + import numpy as np -from structlog.stdlib import BoundLogger import pint -from typing import Optional -from nomad.metainfo import Quantity, MEnum, Section, Context +from nomad.metainfo import MEnum, Quantity + +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger -from nomad_simulations.physical_property import PhysicalProperty +from nomad_simulations.schema_packages.physical_property import PhysicalProperty class ElectronicBandGap(PhysicalProperty): @@ -77,13 +82,13 @@ class ElectronicBandGap(PhysicalProperty): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.name = self.m_def.name self.rank = [] - def validate_values(self, logger: BoundLogger) -> Optional[pint.Quantity]: + def validate_values(self, logger: 'BoundLogger') -> Optional[pint.Quantity]: """ Validate the electronic band gap `value` by checking if they are negative and sets them to None if they are. @@ -105,7 +110,7 @@ def validate_values(self, logger: BoundLogger) -> Optional[pint.Quantity]: value = value[0] return value * self.value.u - def resolve_type(self, logger: BoundLogger) -> Optional[str]: + def resolve_type(self, logger: 'BoundLogger') -> Optional[str]: """ Resolves the `type` of the electronic band gap based on the stored `momentum_transfer` values. @@ -139,7 +144,7 @@ def resolve_type(self, logger: BoundLogger) -> Optional[str]: else: return 'indirect' - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Checks if the `value` is negative and sets it to None if it is. diff --git a/src/nomad_simulations/properties/band_structure.py b/src/nomad_simulations/schema_packages/properties/band_structure.py similarity index 85% rename from src/nomad_simulations/properties/band_structure.py rename to src/nomad_simulations/schema_packages/properties/band_structure.py index 4e35ab49..5bb887ed 100644 --- a/src/nomad_simulations/properties/band_structure.py +++ b/src/nomad_simulations/schema_packages/properties/band_structure.py @@ -16,20 +16,31 @@ # limitations under the License. # +from typing import TYPE_CHECKING, Optional, Tuple, Union + import numpy as np -from structlog.stdlib import BoundLogger -from typing import Optional, Tuple, Union import pint -from nomad.metainfo import Quantity, Section, Context, SubSection +from nomad.config import config +from nomad.metainfo import Quantity, SubSection + +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger -from nomad_simulations.numerical_settings import KSpace -from nomad_simulations.physical_property import ( +from nomad_simulations.schema_packages.numerical_settings import KSpace +from nomad_simulations.schema_packages.physical_property import ( PhysicalProperty, validate_quantity_wrt_value, ) -from nomad_simulations.properties import ElectronicBandGap, FermiSurface -from nomad_simulations.utils import get_sibling_section +from nomad_simulations.schema_packages.properties.band_gap import ElectronicBandGap +from nomad_simulations.schema_packages.properties.fermi_surface import FermiSurface +from nomad_simulations.schema_packages.utils import get_sibling_section + +configuration = config.get_plugin_entry_point( + 'nomad_simulations.schema_packages:nomad_simulations_plugin' +) class BaseElectronicEigenvalues(PhysicalProperty): @@ -55,13 +66,13 @@ class BaseElectronicEigenvalues(PhysicalProperty): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) # ! `n_bands` need to be set up during initialization of the class self.rank = [int(kwargs.get('n_bands'))] - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -133,7 +144,7 @@ class ElectronicEigenvalues(BaseElectronicEigenvalues): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.name = self.m_def.name @@ -187,14 +198,18 @@ def resolve_homo_lumo_eigenvalues( sorted_value = sorted_value.magnitude # Binary search ot find the transition point between `occupation = 2` and `occupation = 0` - tolerance = 1e-3 # TODO add tolerance from config fields homo = self.highest_occupied lumo = self.lowest_unoccupied - mid = np.searchsorted(sorted_occupation <= tolerance, True) - 1 + mid = ( + np.searchsorted( + sorted_occupation <= configuration.occupation_tolerance, True + ) + - 1 + ) if mid >= 0 and mid < len(sorted_occupation) - 1: if sorted_occupation[mid] > 0 and ( - sorted_occupation[mid + 1] >= -tolerance - and sorted_occupation[mid + 1] <= tolerance + sorted_occupation[mid + 1] >= -configuration.occupation_tolerance + and sorted_occupation[mid + 1] <= configuration.occupation_tolerance ): homo = sorted_value[mid] * sorted_value_unit lumo = sorted_value[mid + 1] * sorted_value_unit @@ -221,7 +236,7 @@ def extract_band_gap(self) -> Optional[ElectronicBandGap]: return band_gap # TODO fix this method once `FermiSurface` property is implemented - def extract_fermi_surface(self, logger: BoundLogger) -> Optional[FermiSurface]: + def extract_fermi_surface(self, logger: 'BoundLogger') -> Optional[FermiSurface]: """ Extract the Fermi surface for metal systems and using the `FermiLevel.value`. @@ -248,10 +263,11 @@ def extract_fermi_surface(self, logger: BoundLogger) -> Optional[FermiSurface]: fermi_level_value = fermi_level.value.magnitude # Extract values close to the `fermi_level.value` - tolerance = 1e-8 # TODO change this for a config field fermi_indices = np.logical_and( - self.value.magnitude >= (fermi_level_value - tolerance), - self.value.magnitude <= (fermi_level_value + tolerance), + self.value.magnitude + >= (fermi_level_value - configuration.fermi_surface_tolerance), + self.value.magnitude + <= (fermi_level_value + configuration.fermi_surface_tolerance), ) fermi_values = self.value[fermi_indices] @@ -287,7 +303,7 @@ def resolve_reciprocal_cell(self) -> Optional[pint.Quantity]: return None return k_space - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Resolve `highest_occupied` and `lowest_unoccupied` eigenvalues @@ -318,10 +334,10 @@ class ElectronicBandStructure(ElectronicEigenvalues): iri = 'http://fairmat-nfdi.eu/taxonomy/ElectronicBandStructure' def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) diff --git a/src/nomad_simulations/properties/energies.py b/src/nomad_simulations/schema_packages/properties/energies.py similarity index 75% rename from src/nomad_simulations/properties/energies.py rename to src/nomad_simulations/schema_packages/properties/energies.py index 3283a1f8..732d47be 100644 --- a/src/nomad_simulations/properties/energies.py +++ b/src/nomad_simulations/schema_packages/properties/energies.py @@ -16,11 +16,18 @@ # limitations under the License. # +from typing import TYPE_CHECKING + import numpy as np -from nomad.metainfo import Quantity, Section, Context +from nomad.metainfo import Quantity + +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger -from nomad_simulations.physical_property import PhysicalProperty +from nomad_simulations.schema_packages.physical_property import PhysicalProperty class FermiLevel(PhysicalProperty): @@ -41,13 +48,13 @@ class FermiLevel(PhysicalProperty): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.rank = [] self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -69,11 +76,11 @@ class ChemicalPotential(PhysicalProperty): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.rank = [] self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) diff --git a/src/nomad_simulations/properties/fermi_surface.py b/src/nomad_simulations/schema_packages/properties/fermi_surface.py similarity index 76% rename from src/nomad_simulations/properties/fermi_surface.py rename to src/nomad_simulations/schema_packages/properties/fermi_surface.py index 5d8392b2..b4c8edc4 100644 --- a/src/nomad_simulations/properties/fermi_surface.py +++ b/src/nomad_simulations/schema_packages/properties/fermi_surface.py @@ -16,11 +16,18 @@ # limitations under the License. # +from typing import TYPE_CHECKING + import numpy as np -from nomad.metainfo import Quantity, Section, Context +from nomad.metainfo import Quantity + +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger -from nomad_simulations.physical_property import PhysicalProperty +from nomad_simulations.schema_packages.physical_property import PhysicalProperty # TODO This class is not implemented yet. @JosePizarro3 will work in another PR to implement it. @@ -41,12 +48,12 @@ class FermiSurface(PhysicalProperty): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) # ! `n_bands` need to be set up during initialization of the class self.rank = [int(kwargs.get('n_bands'))] self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) diff --git a/src/nomad_simulations/properties/hopping_matrix.py b/src/nomad_simulations/schema_packages/properties/hopping_matrix.py similarity index 82% rename from src/nomad_simulations/properties/hopping_matrix.py rename to src/nomad_simulations/schema_packages/properties/hopping_matrix.py index 57652eb0..cc2aae19 100644 --- a/src/nomad_simulations/properties/hopping_matrix.py +++ b/src/nomad_simulations/schema_packages/properties/hopping_matrix.py @@ -16,11 +16,18 @@ # limitations under the License. # +from typing import TYPE_CHECKING + import numpy as np -from nomad.metainfo import Quantity, Section, Context +from nomad.metainfo import Quantity + +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger -from nomad_simulations.physical_property import PhysicalProperty +from nomad_simulations.schema_packages.physical_property import PhysicalProperty class HoppingMatrix(PhysicalProperty): @@ -56,7 +63,7 @@ class HoppingMatrix(PhysicalProperty): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) # ! n_orbitals need to be set up during initialization of the class @@ -65,7 +72,7 @@ def __init__( # TODO add normalization to extract DOS, band structure, etc, properties from `HoppingMatrix` - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -93,12 +100,12 @@ class CrystalFieldSplitting(PhysicalProperty): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) # ! `n_orbitals` need to be set up during initialization of the class self.rank = [int(kwargs.get('n_orbitals'))] self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) diff --git a/src/nomad_simulations/properties/permittivity.py b/src/nomad_simulations/schema_packages/properties/permittivity.py similarity index 84% rename from src/nomad_simulations/properties/permittivity.py rename to src/nomad_simulations/schema_packages/properties/permittivity.py index f4e4511c..5776a0aa 100644 --- a/src/nomad_simulations/properties/permittivity.py +++ b/src/nomad_simulations/schema_packages/properties/permittivity.py @@ -16,17 +16,23 @@ # limitations under the License. # +from typing import TYPE_CHECKING, List, Optional + import numpy as np -from structlog.stdlib import BoundLogger -from typing import Optional, List -from nomad.metainfo import Quantity, Section, Context, MEnum +from nomad.metainfo import Quantity, MEnum -from nomad_simulations.physical_property import PhysicalProperty -from nomad_simulations.utils import get_variables -from nomad_simulations.variables import Frequency, KMesh -from nomad_simulations.properties.spectral_profile import AbsorptionSpectrum +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger +from nomad_simulations.schema_packages.physical_property import PhysicalProperty +from nomad_simulations.schema_packages.properties.spectral_profile import ( + AbsorptionSpectrum, +) +from nomad_simulations.schema_packages.utils import get_variables +from nomad_simulations.schema_packages.variables import Frequency, KMesh # TODO add `DielectricStrength` when we have examples and understand how to extract it from the `Permittivity` tensor. @@ -61,7 +67,7 @@ class Permittivity(PhysicalProperty): # ? `ionic` and `electronic` contributions are common in the literature. def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.rank = [3, 3] @@ -75,7 +81,7 @@ def resolve_type(self) -> str: return 'static' def extract_absorption_spectra( - self, logger: BoundLogger + self, logger: 'BoundLogger' ) -> Optional[List[AbsorptionSpectrum]]: """ Extract the absorption spectrum from the imaginary part of the permittivity tensor. @@ -106,7 +112,7 @@ def extract_absorption_spectra( spectra.append(absorption_spectrum) return spectra - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Resolve the `type` of permittivity diff --git a/src/nomad_simulations/properties/spectral_profile.py b/src/nomad_simulations/schema_packages/properties/spectral_profile.py similarity index 90% rename from src/nomad_simulations/properties/spectral_profile.py rename to src/nomad_simulations/schema_packages/properties/spectral_profile.py index 9b11d94e..2ea5c932 100644 --- a/src/nomad_simulations/properties/spectral_profile.py +++ b/src/nomad_simulations/schema_packages/properties/spectral_profile.py @@ -16,19 +16,28 @@ # limitations under the License. # +from typing import TYPE_CHECKING, Dict, List, Optional + import numpy as np -from structlog.stdlib import BoundLogger -from typing import Optional, List, Dict import pint -from nomad import config -from nomad.metainfo import Quantity, SubSection, Section, Context, MEnum +from nomad.config import config +from nomad.metainfo import MEnum, Quantity, SubSection + +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger -from nomad_simulations.utils import get_sibling_section, get_variables -from nomad_simulations.physical_property import PhysicalProperty -from nomad_simulations.variables import Energy2 as Energy -from nomad_simulations.atoms_state import AtomsState, OrbitalsState -from nomad_simulations.properties.band_gap import ElectronicBandGap +from nomad_simulations.schema_packages.atoms_state import AtomsState, OrbitalsState +from nomad_simulations.schema_packages.physical_property import PhysicalProperty +from nomad_simulations.schema_packages.properties.band_gap import ElectronicBandGap +from nomad_simulations.schema_packages.utils import get_sibling_section, get_variables +from nomad_simulations.schema_packages.variables import Energy2 as Energy + +configuration = config.get_plugin_entry_point( + 'nomad_simulations.schema_packages:nomad_simulations_plugin' +) class SpectralProfile(PhysicalProperty): @@ -44,7 +53,7 @@ class SpectralProfile(PhysicalProperty): ) # TODO check units and normalization_factor of DOS and Spectras and see whether they can be merged def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.rank = [] @@ -60,7 +69,7 @@ def is_valid_spectral_profile(self) -> bool: return False return True - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) if self.is_valid_spectral_profile() is False: @@ -85,11 +94,11 @@ class DOSProfile(SpectralProfile): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) - def resolve_pdos_name(self, logger: BoundLogger) -> Optional[str]: + def resolve_pdos_name(self, logger: 'BoundLogger') -> Optional[str]: """ Resolve the `name` of the projected `DOSProfile` from the `entity_ref` section. This is resolved as: - `'atom X'` with 'X' being the chemical symbol for `AtomsState` references. @@ -115,7 +124,7 @@ def resolve_pdos_name(self, logger: BoundLogger) -> Optional[str]: name = f'orbital {self.entity_ref.l_quantum_symbol}{self.entity_ref.ml_quantum_symbol} {self.entity_ref.m_parent.chemical_symbol}' return name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # We resolve @@ -181,7 +190,7 @@ class ElectronicDensityOfStates(DOSProfile): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.name = self.m_def.name @@ -190,7 +199,7 @@ def resolve_energies_origin( self, energies: pint.Quantity, fermi_level: Optional[pint.Quantity], - logger: BoundLogger, + logger: 'BoundLogger', ) -> Optional[pint.Quantity]: """ Resolve the origin of reference for the energies from the sibling `ElectronicEigenvalues` section and its @@ -229,10 +238,6 @@ def resolve_energies_origin( if lowest_unoccupied_energy is not None: self.m_cache['lowest_unoccupied_energy'] = lowest_unoccupied_energy - # Set thresholds for the energies and values - energy_threshold = config.normalize.band_structure_energy_tolerance - value_threshold = 1e-8 # The DOS value that is considered to be zero - # Check that the closest `energies` to the energy reference is not too far away. # If it is very far away, normalization may be very inaccurate and we do not report it. dos_values = self.value.magnitude @@ -241,7 +246,7 @@ def resolve_energies_origin( fermi_energy_closest = energies[fermi_idx] distance = np.abs(fermi_energy_closest - eref) single_peak_fermi = False - if distance.magnitude <= energy_threshold: + if distance.magnitude <= configuration.dos_energy_tolerance: # See if there are zero values close below the energy reference. idx = fermi_idx idx_descend = fermi_idx @@ -251,9 +256,9 @@ def resolve_energies_origin( energy_distance = np.abs(eref - energies[idx]) except IndexError: break - if energy_distance.magnitude > energy_threshold: + if energy_distance.magnitude > configuration.dos_energy_tolerance: break - if value <= value_threshold: + if value <= configuration.dos_intensities_threshold: idx_descend = idx break idx -= 1 @@ -267,9 +272,9 @@ def resolve_energies_origin( energy_distance = np.abs(eref - energies[idx]) except IndexError: break - if energy_distance.magnitude > energy_threshold: + if energy_distance.magnitude > configuration.dos_energy_tolerance: break - if value <= value_threshold: + if value <= configuration.dos_intensities_threshold: idx_ascend = idx break idx += 1 @@ -289,7 +294,7 @@ def resolve_energies_origin( value = dos_values[idx] except IndexError: break - if value > value_threshold: + if value > configuration.dos_intensities_threshold: idx = idx if idx == idx_descend else idx + 1 self.m_cache['highest_occupied_energy'] = energies[idx] break @@ -301,7 +306,7 @@ def resolve_energies_origin( value = dos_values[idx] except IndexError: break - if value > value_threshold: + if value > configuration.dos_intensities_threshold: idx = idx if idx == idx_ascend else idx - 1 self.m_cache['highest_occupied_energy'] = energies[idx] break @@ -313,7 +318,7 @@ def resolve_energies_origin( energies_origin = fermi_level return energies_origin - def resolve_normalization_factor(self, logger: BoundLogger) -> Optional[float]: + def resolve_normalization_factor(self, logger: 'BoundLogger') -> Optional[float]: """ Resolve the `normalization_factor` for the electronic DOS to get a cell-independent intensive DOS. @@ -382,7 +387,7 @@ def extract_band_gap(self) -> Optional[ElectronicBandGap]: return band_gap def extract_projected_dos( - self, type: str, logger: BoundLogger + self, type: str, logger: 'BoundLogger' ) -> List[Optional[DOSProfile]]: """ Extract the projected DOS from the `projected_dos` section and the specified `type`. @@ -414,7 +419,7 @@ def extract_projected_dos( return extracted_pdos def generate_from_projected_dos( - self, logger: BoundLogger + self, logger: 'BoundLogger' ) -> Optional[pint.Quantity]: """ Generate the total `value` of the electronic DOS from the `projected_dos` contributions. If the `projected_dos` @@ -476,7 +481,7 @@ def generate_from_projected_dos( value = np.sum(atom_values, axis=0) * atom_unit return value - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Initial check to see if `variables` contains the required `Energy` variable @@ -530,13 +535,13 @@ class AbsorptionSpectrum(SpectralProfile): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) # Set the name of the section self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -564,13 +569,13 @@ class XASSpectrum(AbsorptionSpectrum): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) # Set the name of the section self.name = self.m_def.name - def generate_from_contributions(self, logger: BoundLogger) -> None: + def generate_from_contributions(self, logger: 'BoundLogger') -> None: """ Generate the `value` of the XAS spectrum by concatenating the XANES and EXAFS contributions. It also concatenates the `Energy` grid points of the XANES and EXAFS parts. @@ -608,7 +613,7 @@ def generate_from_contributions(self, logger: BoundLogger) -> None: 'The XANES and EXAFS `value` have different shapes. Could not concatenate the values.' ) - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) if self.value is None: diff --git a/src/nomad_simulations/utils/__init__.py b/src/nomad_simulations/schema_packages/utils/__init__.py similarity index 100% rename from src/nomad_simulations/utils/__init__.py rename to src/nomad_simulations/schema_packages/utils/__init__.py index 47f68bf9..dc4e7ea4 100644 --- a/src/nomad_simulations/utils/__init__.py +++ b/src/nomad_simulations/schema_packages/utils/__init__.py @@ -17,9 +17,9 @@ # limitations under the License. from .utils import ( - get_sibling_section, RussellSaundersState, - is_not_representative, - get_variables, get_composition, + get_sibling_section, + get_variables, + is_not_representative, ) diff --git a/src/nomad_simulations/utils/utils.py b/src/nomad_simulations/schema_packages/utils/utils.py similarity index 99% rename from src/nomad_simulations/utils/utils.py rename to src/nomad_simulations/schema_packages/utils/utils.py index 5055c250..cbb0ce98 100644 --- a/src/nomad_simulations/utils/utils.py +++ b/src/nomad_simulations/schema_packages/utils/utils.py @@ -17,12 +17,12 @@ # limitations under the License. # -import numpy as np from math import factorial -from typing import Optional, List -from structlog.stdlib import BoundLogger +from typing import List, Optional +import numpy as np from nomad.datamodel.data import ArchiveSection +from structlog.stdlib import BoundLogger def get_sibling_section( diff --git a/src/nomad_simulations/variables.py b/src/nomad_simulations/schema_packages/variables.py similarity index 80% rename from src/nomad_simulations/variables.py rename to src/nomad_simulations/schema_packages/variables.py index 89f254f4..9736fd85 100644 --- a/src/nomad_simulations/variables.py +++ b/src/nomad_simulations/schema_packages/variables.py @@ -16,16 +16,21 @@ # limitations under the License. # +from typing import TYPE_CHECKING, Optional + import numpy as np -from typing import Optional -from structlog.stdlib import BoundLogger from nomad.datamodel.data import ArchiveSection -from nomad.metainfo import Quantity, Section, Context +from nomad.metainfo import Quantity -from nomad_simulations.numerical_settings import ( - KMesh as KMeshSettings, +if TYPE_CHECKING: + from nomad.metainfo import Section, Context + from nomad.datamodel.datamodel import EntryArchive + from structlog.stdlib import BoundLogger + +from nomad_simulations.schema_packages.numerical_settings import ( KLinePath as KLinePathSettings, + KMesh as KMeshSettings, ) @@ -60,7 +65,7 @@ class Variables(ArchiveSection): # ? Do we need to add `points_error`? - def get_n_points(self, logger: BoundLogger) -> Optional[int]: + def get_n_points(self, logger: 'BoundLogger') -> Optional[int]: """ Get the number of grid points from the `points` list. If `n_points` is previously defined and does not coincide with the length of `points`, a warning is issued and this function re-assigns `n_points` @@ -81,7 +86,7 @@ def get_n_points(self, logger: BoundLogger) -> Optional[int]: return len(self.points) return self.n_points - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) # Setting `n_points` if these are not defined @@ -101,12 +106,12 @@ class Temperature(Variables): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -124,12 +129,12 @@ class Energy2(Variables): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -148,12 +153,12 @@ class WignerSeitz(Variables): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -170,12 +175,12 @@ class Frequency(Variables): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -193,12 +198,12 @@ class KMesh(Variables): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) @@ -213,10 +218,10 @@ class KLinePath(Variables): ) def __init__( - self, m_def: Section = None, m_context: Context = None, **kwargs + self, m_def: 'Section' = None, m_context: 'Context' = None, **kwargs ) -> None: super().__init__(m_def, m_context, **kwargs) self.name = self.m_def.name - def normalize(self, archive, logger) -> None: + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: super().normalize(archive, logger) diff --git a/tests/conftest.py b/tests/conftest.py index 96ba526f..ec513a82 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -24,27 +24,27 @@ from nomad.units import ureg from nomad.datamodel import EntryArchive -from . import logger - -from nomad_simulations import Simulation -from nomad_simulations.model_system import ModelSystem, AtomicCell -from nomad_simulations.atoms_state import AtomsState, OrbitalsState -from nomad_simulations.model_method import ModelMethod -from nomad_simulations.numerical_settings import ( +from nomad_simulations.schema_packages.general import Simulation +from nomad_simulations.schema_packages.model_system import ModelSystem, AtomicCell +from nomad_simulations.schema_packages.atoms_state import AtomsState, OrbitalsState +from nomad_simulations.schema_packages.model_method import ModelMethod +from nomad_simulations.schema_packages.numerical_settings import ( SelfConsistency, KSpace, KMesh as KMeshSettings, KLinePath as KLinePathSettings, ) -from nomad_simulations.outputs import Outputs, SCFOutputs -from nomad_simulations.variables import Energy2 as Energy, KLinePath -from nomad_simulations.properties import ( +from nomad_simulations.schema_packages.outputs import Outputs, SCFOutputs +from nomad_simulations.schema_packages.variables import Energy2 as Energy, KLinePath +from nomad_simulations.schema_packages.properties import ( ElectronicBandGap, DOSProfile, ElectronicDensityOfStates, ElectronicEigenvalues, ) +from . import logger + if os.getenv('_PYTEST_RAISE', '0') != '0': @pytest.hookimpl(tryfirst=True) diff --git a/tests/test_atoms_state.py b/tests/test_atoms_state.py index d088c144..92fe9e70 100644 --- a/tests/test_atoms_state.py +++ b/tests/test_atoms_state.py @@ -23,15 +23,15 @@ from nomad.units import ureg from nomad.datamodel import EntryArchive -from . import logger - -from nomad_simulations.atoms_state import ( +from nomad_simulations.schema_packages.atoms_state import ( OrbitalsState, CoreHole, HubbardInteractions, AtomsState, ) +from . import logger + class TestOrbitalsState: """ diff --git a/tests/test_band_gap.py b/tests/test_band_gap.py index 062370c3..19840421 100644 --- a/tests/test_band_gap.py +++ b/tests/test_band_gap.py @@ -23,10 +23,10 @@ from nomad.units import ureg from nomad.datamodel import EntryArchive -from . import logger +from nomad_simulations.schema_packages.properties import ElectronicBandGap +from nomad_simulations.schema_packages.variables import Temperature -from nomad_simulations.properties import ElectronicBandGap -from nomad_simulations.variables import Temperature +from . import logger class TestElectronicBandGap: diff --git a/tests/test_band_structure.py b/tests/test_band_structure.py index c7b920ac..d7a546a4 100644 --- a/tests/test_band_structure.py +++ b/tests/test_band_structure.py @@ -18,15 +18,11 @@ import pytest import numpy as np -from typing import Optional, Tuple, Union, List -import pint +from typing import Optional, Tuple, List from nomad.datamodel import EntryArchive -from nomad_simulations.model_method import ModelMethod -from nomad_simulations.numerical_settings import KSpace, BasisSet -from nomad_simulations.outputs import Outputs -from nomad_simulations.properties import ElectronicEigenvalues +from nomad_simulations.schema_packages.properties import ElectronicEigenvalues from . import logger from .conftest import generate_electronic_eigenvalues, generate_simulation diff --git a/tests/test_energies.py b/tests/test_energies.py index f0f52e77..28d3a766 100644 --- a/tests/test_energies.py +++ b/tests/test_energies.py @@ -16,7 +16,7 @@ # limitations under the License. # -from nomad_simulations.properties import FermiLevel, ChemicalPotential +from nomad_simulations.schema_packages.properties import FermiLevel, ChemicalPotential class TestFermiLevel: diff --git a/tests/test_fermi_surface.py b/tests/test_fermi_surface.py index 59e1a41f..9b57dede 100644 --- a/tests/test_fermi_surface.py +++ b/tests/test_fermi_surface.py @@ -17,12 +17,9 @@ # import pytest -import numpy as np from typing import Optional -from nomad_simulations.properties import FermiSurface - -from . import logger +from nomad_simulations.schema_packages.properties import FermiSurface class TestFermiSurface: diff --git a/tests/test_general.py b/tests/test_general.py index 8d83b3c6..64d9d610 100644 --- a/tests/test_general.py +++ b/tests/test_general.py @@ -22,15 +22,15 @@ from nomad.datamodel import EntryArchive -from . import logger - -from nomad_simulations.general import Simulation -from nomad_simulations.model_system import ( +from nomad_simulations.schema_packages.general import Simulation +from nomad_simulations.schema_packages.model_system import ( ModelSystem, AtomicCell, AtomsState, ) +from . import logger + class TestSimulation: """ diff --git a/tests/test_hopping_matrix.py b/tests/test_hopping_matrix.py index f15f4b05..7cbef83b 100644 --- a/tests/test_hopping_matrix.py +++ b/tests/test_hopping_matrix.py @@ -19,9 +19,10 @@ import pytest from typing import Optional -from nomad_simulations.properties import HoppingMatrix, CrystalFieldSplitting - -from . import logger +from nomad_simulations.schema_packages.properties import ( + HoppingMatrix, + CrystalFieldSplitting, +) class TestHoppingMatrix: diff --git a/tests/test_model_method.py b/tests/test_model_method.py index 80071673..c7c4d18b 100644 --- a/tests/test_model_method.py +++ b/tests/test_model_method.py @@ -17,15 +17,19 @@ # import pytest -import numpy as np -from typing import List, Union, Optional, Tuple +from typing import List, Optional from nomad.datamodel import EntryArchive -from nomad_simulations.model_method import TB, Wannier, SlaterKoster, SlaterKosterBond -from nomad_simulations.atoms_state import OrbitalsState, AtomsState -from nomad_simulations import Simulation -from nomad_simulations.model_system import ModelSystem, AtomicCell +from nomad_simulations.schema_packages.general import Simulation +from nomad_simulations.schema_packages.model_method import ( + TB, + Wannier, + SlaterKoster, + SlaterKosterBond, +) +from nomad_simulations.schema_packages.atoms_state import OrbitalsState, AtomsState +from nomad_simulations.schema_packages.model_system import ModelSystem, AtomicCell from . import logger from .conftest import generate_simulation diff --git a/tests/test_model_system.py b/tests/test_model_system.py index c317daf7..5dd8a04e 100644 --- a/tests/test_model_system.py +++ b/tests/test_model_system.py @@ -22,11 +22,15 @@ from nomad.datamodel import EntryArchive +from nomad_simulations.schema_packages.model_system import ( + Symmetry, + ChemicalFormula, + ModelSystem, +) + from . import logger from .conftest import generate_atomic_cell -from nomad_simulations.model_system import Symmetry, ChemicalFormula, ModelSystem - class TestAtomicCell: """ diff --git a/tests/test_numerical_settings.py b/tests/test_numerical_settings.py index 242c0f08..ef5a362c 100644 --- a/tests/test_numerical_settings.py +++ b/tests/test_numerical_settings.py @@ -23,7 +23,11 @@ from nomad.units import ureg from nomad.datamodel import EntryArchive -from nomad_simulations.numerical_settings import KMesh, KLinePath, KSpaceFunctionalities +from nomad_simulations.schema_packages.numerical_settings import ( + KMesh, + KLinePath, + KSpaceFunctionalities, +) from . import logger from .conftest import generate_k_line_path, generate_k_space_simulation diff --git a/tests/test_outputs.py b/tests/test_outputs.py index 2bafc273..172e8f3d 100644 --- a/tests/test_outputs.py +++ b/tests/test_outputs.py @@ -21,14 +21,14 @@ from nomad.datamodel import EntryArchive +from nomad_simulations.schema_packages.model_system import ModelSystem +from nomad_simulations.schema_packages.numerical_settings import SelfConsistency +from nomad_simulations.schema_packages.outputs import Outputs, SCFOutputs +from nomad_simulations.schema_packages.properties import ElectronicBandGap + from . import logger from .conftest import generate_simulation, generate_scf_electronic_band_gap_template -from nomad_simulations.model_system import ModelSystem -from nomad_simulations.numerical_settings import SelfConsistency -from nomad_simulations.outputs import Outputs, SCFOutputs -from nomad_simulations.properties import ElectronicBandGap - class TestOutputs: """ diff --git a/tests/test_permittivity.py b/tests/test_permittivity.py index 8e85d10c..43b563e4 100644 --- a/tests/test_permittivity.py +++ b/tests/test_permittivity.py @@ -20,18 +20,10 @@ import numpy as np from typing import List, Optional -from nomad.units import ureg -from nomad.datamodel import EntryArchive +from nomad_simulations.schema_packages.properties import Permittivity +from nomad_simulations.schema_packages.variables import Variables, KMesh, Frequency from . import logger - -from nomad_simulations import Simulation -from nomad_simulations.model_system import ModelSystem, AtomicCell -from nomad_simulations.atoms_state import AtomsState -from nomad_simulations.outputs import Outputs -from nomad_simulations.properties import Permittivity -from nomad_simulations.variables import Variables, KMesh, Frequency - from .conftest import generate_k_space_simulation diff --git a/tests/test_physical_properties.py b/tests/test_physical_properties.py index d17650fe..e3ebd83b 100644 --- a/tests/test_physical_properties.py +++ b/tests/test_physical_properties.py @@ -24,14 +24,14 @@ from nomad.datamodel import EntryArchive from nomad.metainfo import Quantity -from . import logger - -from nomad_simulations.variables import Variables -from nomad_simulations.physical_property import ( +from nomad_simulations.schema_packages.variables import Variables +from nomad_simulations.schema_packages.physical_property import ( PhysicalProperty, validate_quantity_wrt_value, ) +from . import logger + class DummyPhysicalProperty(PhysicalProperty): value = Quantity( diff --git a/tests/test_spectral_profile.py b/tests/test_spectral_profile.py index 14a55034..6e898118 100644 --- a/tests/test_spectral_profile.py +++ b/tests/test_spectral_profile.py @@ -23,19 +23,19 @@ from nomad.units import ureg from nomad.datamodel import EntryArchive -from . import logger - -from nomad_simulations import Simulation -from nomad_simulations.model_system import ModelSystem, AtomicCell -from nomad_simulations.atoms_state import AtomsState -from nomad_simulations.outputs import Outputs -from nomad_simulations.properties import ( +from nomad_simulations.schema_packages.general import Simulation +from nomad_simulations.schema_packages.model_system import ModelSystem, AtomicCell +from nomad_simulations.schema_packages.atoms_state import AtomsState +from nomad_simulations.schema_packages.outputs import Outputs +from nomad_simulations.schema_packages.properties import ( SpectralProfile, ElectronicDensityOfStates, AbsorptionSpectrum, XASSpectrum, ) -from nomad_simulations.variables import Energy2 as Energy +from nomad_simulations.schema_packages.variables import Energy2 as Energy + +from . import logger class TestSpectralProfile: diff --git a/tests/test_utils.py b/tests/test_utils.py index 5a498952..80fddf5c 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -17,17 +17,18 @@ # import pytest -import numpy as np -from nomad.units import ureg - -from nomad_simulations.utils import ( +from nomad_simulations.schema_packages.utils import ( get_sibling_section, is_not_representative, get_variables, ) -from nomad_simulations.model_system import ModelSystem, AtomicCell, Symmetry -from nomad_simulations.variables import Temperature, Energy2 as Energy +from nomad_simulations.schema_packages.model_system import ( + ModelSystem, + AtomicCell, + Symmetry, +) +from nomad_simulations.schema_packages.variables import Temperature, Energy2 as Energy from . import logger diff --git a/tests/test_variables.py b/tests/test_variables.py index ab71b4a2..9f40be65 100644 --- a/tests/test_variables.py +++ b/tests/test_variables.py @@ -20,9 +20,9 @@ from nomad.datamodel import EntryArchive -from . import logger +from nomad_simulations.schema_packages.variables import Variables -from nomad_simulations.variables import Variables +from . import logger class TestVariables: