diff --git a/.cruft.json b/.cruft.json new file mode 100644 index 0000000..68e4237 --- /dev/null +++ b/.cruft.json @@ -0,0 +1,26 @@ +{ + "template": "https://github.com/FAIRmat-NFDI/cookiecutter-nomad-plugin", + "commit": "dbf41935075d9057d69478db6eb9e7901bb44992", + "checkout": null, + "context": { + "cookiecutter": { + "full_name": "Alvin Noe Ladines", + "email": "ladinesa@physik.hu-berlin.de", + "github_username": "ladinesa", + "plugin_name": "nomad-simulation-workflow", + "module_name": "nomad_simulation_workflow", + "short_description": "Schema definition and normalizer for NOMAD simulation workflow", + "version": "0.1.0", + "license": "Apache Software License 2.0", + "include_schema_package": true, + "include_normalizer": true, + "include_parser": false, + "include_app": false, + "_copy_without_render": [ + "*.html" + ], + "_template": "https://github.com/FAIRmat-NFDI/cookiecutter-nomad-plugin" + } + }, + "directory": null +} diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml new file mode 100644 index 0000000..544ec7a --- /dev/null +++ b/.github/workflows/actions.yml @@ -0,0 +1,56 @@ +name: install-and-test-workflow +on: [push] +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 '.[dev]' --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple + pip install coverage coveralls + - name: Test with pytest + run: | + python -m coverage run -m pytest -sv + - 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 --upgrade pip + pip install build + python -m build --sdist + - name: Install the package + run: | + pip install dist/*.tar.gz --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple + ruff-linting: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: chartboost/ruff-action@v1 + with: + args: "check ." + # to enable auto-formatting check, uncomment the following lines below + # ruff-formatting: + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v4 + # - uses: chartboost/ruff-action@v1 + # with: + # args: "format . --check" diff --git a/.github/workflows/cruft-update.yml b/.github/workflows/cruft-update.yml new file mode 100644 index 0000000..ace73a7 --- /dev/null +++ b/.github/workflows/cruft-update.yml @@ -0,0 +1,75 @@ +# /.github/workflows/cruft-update.yml +name: Update repository with Cruft +permissions: + contents: write + pull-requests: write +on: + schedule: + - cron: "0 14 * * 1" # Every Monday at 2pm (UTC time) + workflow_dispatch: +jobs: + update: + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + include: + - add-paths: . + body: Use this to merge the changes to this repository. + branch: cruft/update + commit-message: "chore: accept new Cruft update" + title: New updates detected with Cruft + - add-paths: .cruft.json + body: Use this to reject the changes in this repository. + branch: cruft/reject + commit-message: "chore: reject new Cruft update" + title: Reject new updates detected with Cruft + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Install Cruft + run: pip3 install cruft + + - name: Check if update is available + continue-on-error: false + id: check + run: | + CHANGES=0 + if [ -f .cruft.json ]; then + if ! cruft check; then + CHANGES=1 + fi + else + echo "No .cruft.json file" + fi + + echo "has_changes=$CHANGES" >> "$GITHUB_OUTPUT" + + - name: Run update if available + if: steps.check.outputs.has_changes == '1' + run: | + git config --global user.email "you@example.com" + git config --global user.name "GitHub" + + cruft update --skip-apply-ask --refresh-private-variables + git restore --staged . + + - name: Create pull request + if: steps.check.outputs.has_changes == '1' + uses: peter-evans/create-pull-request@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + add-paths: ${{ matrix.add-paths }} + commit-message: ${{ matrix.commit-message }} + branch: ${{ matrix.branch }} + delete-branch: true + branch-suffix: timestamp + title: ${{ matrix.title }} + body: | + This is an autogenerated PR. ${{ matrix.body }} + + [Cruft](https://cruft.github.io/cruft/) has detected updates from the Cookiecutter repository. diff --git a/.github/workflows/mkdocs-deploy.yml b/.github/workflows/mkdocs-deploy.yml new file mode 100644 index 0000000..c46ff23 --- /dev/null +++ b/.github/workflows/mkdocs-deploy.yml @@ -0,0 +1,24 @@ +name: Deploy MkDocs Site + +on: + push: + branches: + - main # Triggers deployment on push to the main branch + +permissions: + contents: write + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + + - 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/.gitignore b/.gitignore new file mode 100644 index 0000000..b1619d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,130 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.pyenv + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0c8648f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,21 @@ +{ + "editor.rulers": [ + 90 + ], + "editor.renderWhitespace": "all", + "editor.tabSize": 4, + "files.trimTrailingWhitespace": true, + "[python]": { + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll": "explicit", + "source.organizeImports": "explicit" + }, + "editor.defaultFormatter": "charliermarsh.ruff" + }, + "python.testing.pytestArgs": [ + "tests" + ], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true +} diff --git a/LICENSE b/LICENSE index 261eeb9..427417b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,4 @@ + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -178,7 +179,7 @@ APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" + boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -186,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright [yyyy] [name of copyright owner] + Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..b5ccc2d --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +recursive-include * nomad_plugin.yaml diff --git a/README.md b/README.md index fcf513e..cd279e7 100644 --- a/README.md +++ b/README.md @@ -1,84 +1,93 @@ -# nomad-plugin-template -A template repository for creating a repository with a NOMAD plugin package. +# nomad-nomad-simulation-workflow +Schema definition and normalizer for NOMAD simulation workflow -## Getting started +---- -1. Click on the `Use this template` button and create a new plugin repository. The form will ask you to fill out the name for the new plugin repository. +This `nomad`_ plugin was generated with `Cookiecutter`_ along with `@nomad`_'s `cookiecutter-nomad-plugin`_ template. -2. In the newly created repository, start a new Github Codespace and generate the plugin structure. -Run the following command to create a new NOMAD plugin project using cookiecutter-nomad-plugin: +### Install + +You should create a virtual environment. You will need the `nomad-lab` package (and `pytest`). +We recommend using Python 3.9. ```sh -cruft create https://github.com/FAIRmat-NFDI/cookiecutter-nomad-plugin +python3 -m venv .pyenv +source .pyenv/bin/activate +pip install --upgrade pip +pip install -e '.[dev]' --index-url https://gitlab.mpcdf.mpg.de/api/v4/projects/2187/packages/pypi/simple ``` -Cookiecutter prompts you for information regarding your plugin: - -```no-highlight -full_name [John Doe]: Citizen Kane -email [john.doe@physik.hu-berlin.de]: citizen@kane.de -github_username [foo]: kane -plugin_name [foobar]: awesome-tools -module_name [awesome_tools]: awesome_tools -short_description [NOMAD example template]: An awesome plugin for NOMAD -version [0.1.0]: -Select license: -1 - MIT -2 - BSD-3 -3 - GNU GPL v3.0+ -Choose from 1, 2, 3 [1]: 2 -include_schema_package [y/n] (y): y -include_normalizer [y/n] (y): n -include_parser [y/n] (y): y -include_app [y/n] (y): n - -INFO:post_gen_project:Initializing python for package - src -.. -INFO:post_gen_project:Remove temporary folder: licenses -INFO:post_gen_project:Remove temporary folder: macros -INFO:post_gen_project:Remove temporary folder: py_sources +**Note!** +Until we have an official pypi NOMAD release with the plugins functionality. Make +sure to include NOMAD's internal package registry (e.g. via `--index-url`). + +### Testing + +You can run automated tests with `pytest`: + +```sh +pytest -svx tests ``` +### Run linting + +```sh +ruff check . +``` +### Run auto-formatting +This is entirely optional. To add this as a check in github actions pipeline, uncomment the `ruff-formatting` step in `./github/workflows/actions.yaml`. -There you go - you just created a minimal NOMAD plugin: - -> [!NOTE] -> In the above prompt, we pressed `y` for schema_package and parser, this creates a python package with two plugin entry points: one for parser and one for schema_package. - -```no-highlight -nomad-awesome-tools/ -├── LICENSE -├── README.rst -├── pyproject.toml -├── move_template_files.sh -├── src -│ └── nomad_awesome_tools -│ ├── __init__.py -| ├── schema_packages -│ | ├── __init__.py -│ | └── plugin.py -| └── parsers -│ ├── __init__.py -│ └── plugin.py -| -├── tests -│ ├── conftest.py -│ └── test_awesome.py -└── MANIFEST.in +```sh +ruff format . ``` +### Developing a NOMAD plugin + +Follow the [guide](https://nomad-lab.eu/prod/v1/staging/docs/howto/plugins/plugins.html) on how to develop NOMAD plugins. + +### Build the python package -> [!NOTE] -> The project `nomad-awesome-tools` is created in a new directory, we have included a helper script to move all the files to the parent level of the repository. +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: + +``` +pip install build +python -m build --sdist +``` +You can install the package with pip: + +``` +pip install dist/nomad-nomad-simulation-workflow-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 -sh CHANGE_TO_PLUGIN_NAME/move_template_files.sh +pip install -r requirements_docs.txt ``` -> [!IMPORTANT] -> The `CHANGE_TO_PLUGIN_NAME` should be substituted by the name of the plugin you've created. In the above case it'll be `sh nomad-awesome-tools/move_template_files.sh`. +Run the documentation server: +```sh +mkdocs serve +``` + +### Template update + +We use cruft to update the project based on template changes. A `cruft-update.yml` is included in Github workflows to automatically check for updates and create pull requests to apply updates. Follow the [instructions](https://github.blog/changelog/2022-05-03-github-actions-prevent-github-actions-from-creating-and-approving-pull-requests/) on how to enable Github Actions to create pull requests. + +To run the check for updates locally, follow the instructions on [`cruft` website](https://cruft.github.io/cruft/#updating-a-project). + +### License +Distributed under the terms of the `Apache Software License 2.0`_ license, "nomad-nomad-simulation-workflow" is free and open source software diff --git a/docs/assets/.gitignore b/docs/assets/.gitignore new file mode 100644 index 0000000..3881e38 --- /dev/null +++ b/docs/assets/.gitignore @@ -0,0 +1 @@ +nomad-oasis*.zip \ No newline at end of file diff --git a/docs/assets/favicon.png b/docs/assets/favicon.png new file mode 100644 index 0000000..f84c78f Binary files /dev/null and b/docs/assets/favicon.png differ diff --git a/docs/assets/nomad-plugin-logo.png b/docs/assets/nomad-plugin-logo.png new file mode 100644 index 0000000..149856c Binary files /dev/null and b/docs/assets/nomad-plugin-logo.png differ diff --git a/docs/explanation/explanation.md b/docs/explanation/explanation.md new file mode 100644 index 0000000..a2035f6 --- /dev/null +++ b/docs/explanation/explanation.md @@ -0,0 +1,4 @@ +# Explanation + +!!! note "Attention" + TODO diff --git a/docs/how_to/contribute_to_the_documentation.md b/docs/how_to/contribute_to_the_documentation.md new file mode 100644 index 0000000..173dce1 --- /dev/null +++ b/docs/how_to/contribute_to_the_documentation.md @@ -0,0 +1,4 @@ +# Contribute to the documentation + +!!! note "Attention" + TODO diff --git a/docs/how_to/contribute_to_this_plugin.md b/docs/how_to/contribute_to_this_plugin.md new file mode 100644 index 0000000..48d405a --- /dev/null +++ b/docs/how_to/contribute_to_this_plugin.md @@ -0,0 +1,5 @@ +# Contribute to This Plugin + +!!! note "Attention" + TODO + diff --git a/docs/how_to/install_this_plugin.md b/docs/how_to/install_this_plugin.md new file mode 100644 index 0000000..2b45e0f --- /dev/null +++ b/docs/how_to/install_this_plugin.md @@ -0,0 +1,4 @@ +# Install This Plugin + +!!! note "Attention" + TODO diff --git a/docs/how_to/use_this_plugin.md b/docs/how_to/use_this_plugin.md new file mode 100644 index 0000000..ad93966 --- /dev/null +++ b/docs/how_to/use_this_plugin.md @@ -0,0 +1,10 @@ +# How to Use This Plugin + +This plugin can be used in a NOMAD Oasis installation. + +## Add This Plugin to Your NOMAD installation + +Read the [NOMAD plugin documentation](https://nomad-lab.eu/prod/v1/staging/docs/plugins/plugins.html#add-a-plugin-to-your-nomad) for all details on how to deploy the plugin on your NOMAD instance. + +!!! note "Attention" + TODO diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..225769b --- /dev/null +++ b/docs/index.md @@ -0,0 +1,48 @@ +# Welcome to the `nomad-nomad-simulation-workflow` documentation + +Schema definition and normalizer for NOMAD simulation workflow + +## Introduction + +!!! note "Attention" + TODO + +<div markdown="block" class="home-grid"> +<div markdown="block"> + +### Tutorial + +TODO + +- [Tutorial](tutorial/tutorial.md) + +</div> +<div markdown="block"> + +### How-to guides + +How-to guides provide step-by-step instructions for a wide range of tasks, with the overarching topics: + +- [Install this plugin](how_to/install_this_plugin.md) +- [Use this plugin](how_to/use_this_plugin.md) +- [Contribute to this plugin](how_to/contribute_to_this_plugin.md) +- [Contribute to the documentation](how_to/contribute_to_the_documentation.md) + +</div> + +<div markdown="block"> + +### Explanation + +The explanation [section](explanation/explanation.md) provides background knowledge on this plugin. + +</div> +<div markdown="block"> + +### Reference + +The reference [section](reference/references.md) includes all CLI commands and arguments, all configuration options, +the possible schema annotations and their arguments, and a glossary of used terms. + +</div> +</div> diff --git a/docs/reference/references.md b/docs/reference/references.md new file mode 100644 index 0000000..c199e70 --- /dev/null +++ b/docs/reference/references.md @@ -0,0 +1,4 @@ +# References + +!!! note "Attention" + TODO diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 0000000..321e087 --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,69 @@ + +.md-header__button.md-logo :where(img,svg) { + width: 100%; + height: 30px; +} + +.md-header, .md-header__inner { + background-color: #fff; + color: #2A4CDF; +} + +.md-header[data-md-state=shadow] { + box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%); + transition: box-shadow 200ms linear; +} + +.md-header__inner { + height: 80px; +} + +.md-header__topic { + font-size: 24px; +} + +.md-footer { + background-color: #2A4CDF; +} + +.md-search__form:hover { + background-color: rgba(0,0,0,.13); +} + +.md-typeset h1 { + color: black; + font-weight: 700; +} + +.youtube { + position: relative; + width: 100%; + height: 0; + padding-bottom: 56.25%; +} + +.youtube iframe { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.home-grid { + display: grid; + grid-template-columns: 1fr 1fr; + grid-column-gap: 24px; + row-gap: 24px; +} + +.home-grid div { + border-radius: 4px; + padding: 24px; + background-color: #f3e9d9; +} + +.home-grid h3 { + margin-top: 0; + font-weight: 700; +} \ No newline at end of file diff --git a/docs/theme/partials/header.html b/docs/theme/partials/header.html new file mode 100644 index 0000000..5b091f3 --- /dev/null +++ b/docs/theme/partials/header.html @@ -0,0 +1,86 @@ +{#- + This file was automatically generated - do not edit +-#} +{% set class = "md-header" %} +{% if "navigation.tabs.sticky" in features %} + {% set class = class ~ " md-header--lifted" %} +{% endif %} +<header class="{{ class }}" data-md-component="header"> + <nav class="md-header__inner md-grid" aria-label="{{ lang.t('header.title') }}"> + <a href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}" title="{{ config.site_name | e }}" class="md-header__button md-logo" aria-label="{{ config.site_name }}" data-md-component="logo"> + {% include "partials/logo.html" %} + </a> + <label class="md-header__button md-icon" for="__drawer"> + {% include ".icons/material/menu" ~ ".svg" %} + </label> + <div class="md-header__title" data-md-component="header-title"> + <div class="md-header__ellipsis"> + <div class="md-header__topic"> + <span class="md-ellipsis"> + {{ config.site_name }} + </span> + </div> + <div class="md-header__topic" data-md-component="header-topic"> + <span class="md-ellipsis"> + {% if page and page.meta and page.meta.title %} + {{ page.meta.title }} + {% else %} + {{ page.title }} + {% endif %} + </span> + </div> + </div> + </div> + {% if not config.theme.palette is mapping %} + <form class="md-header__option" data-md-component="palette"> + {% for option in config.theme.palette %} + {% set primary = option.primary | replace(" ", "-") | lower %} + {% set accent = option.accent | replace(" ", "-") | lower %} + <input class="md-option" data-md-color-media="{{ option.media }}" data-md-color-scheme="{{ option.scheme }}" data-md-color-primary="{{ primary }}" data-md-color-accent="{{ accent }}" {% if option.toggle %} aria-label="{{ option.toggle.name }}" {% else %} aria-hidden="true" {% endif %} type="radio" name="__palette" id="__palette_{{ loop.index }}"> + {% if option.toggle %} + <label class="md-header__button md-icon" title="{{ option.toggle.name }}" for="__palette_{{ loop.index0 or loop.length }}" hidden> + {% include ".icons/" ~ option.toggle.icon ~ ".svg" %} + </label> + {% endif %} + {% endfor %} + </form> + {% endif %} + {% if config.extra.alternate %} + <div class="md-header__option"> + <div class="md-select"> + {% set icon = config.theme.icon.alternate or "material/translate" %} + <button class="md-header__button md-icon" aria-label="{{ lang.t('select.language.title') }}"> + {% include ".icons/" ~ icon ~ ".svg" %} + </button> + <div class="md-select__inner"> + <ul class="md-select__list"> + {% for alt in config.extra.alternate %} + <li class="md-select__item"> + <a href="{{ alt.link | url }}" hreflang="{{ alt.lang }}" class="md-select__link"> + {{ alt.name }} + </a> + </li> + {% endfor %} + </ul> + </div> + </div> + </div> + {% endif %} + {% if "search" in config["plugins"] %} + <label class="md-header__button md-icon" for="__search"> + {% include ".icons/material/magnify.svg" %} + </label> + {% include "partials/search.html" %} + {% endif %} + {% if config.repo_url %} + <div class="md-header__source"> + {% include "partials/source.html" %} + </div> + {% endif %} + </nav> + {% if "navigation.tabs.sticky" in features %} + {% if "navigation.tabs" in features %} + {% include "partials/tabs.html" %} + {% endif %} + {% endif %} +</header> \ No newline at end of file diff --git a/docs/tutorial/tutorial.md b/docs/tutorial/tutorial.md new file mode 100644 index 0000000..a24d72a --- /dev/null +++ b/docs/tutorial/tutorial.md @@ -0,0 +1,4 @@ +# Tutorial + +!!! note "Attention" + TODO diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..85020f0 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,57 @@ +site_name: nomad-nomad-simulation-workflow +site_description: Schema definition and normalizer for NOMAD simulation workflow +site_author: Alvin Noe Ladines + +repo_url: https://github.com/ladinesa/nomad-nomad-simulation-workflow + +nav: + - Home: index.md + - Tutorial: tutorial/tutorial.md + - How-to guides: + - Install this Plugin: how_to/install_this_plugin.md + - Use this Plugin: how_to/use_this_plugin.md + - Contribute to this plugin: how_to/contribute_to_this_plugin.md + - Contribute to the documentation: how_to/contribute_to_the_documentation.md + - Explanation: explanation/explanation.md + - Reference: reference/references.md +plugins: + - search +theme: + name: material + palette: + primary: "#2A4CDF" + accent: "#008A67" + font: + text: "Titillium Web" + logo: assets/nomad-plugin-logo.png + favicon: assets/favicon.png + features: + - navigation.instant + custom_dir: docs/theme +markdown_extensions: + - attr_list + - md_in_html + - admonition + - pymdownx.details + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences + - toc: + permalink: True + - pymdownx.arithmatex: + generic: true + - attr_list + - mkdocs-click + - pymdownx.extra +extra: + generator: false + homepage: https://nomad-lab.eu +use_directory_urls: false +extra_css: + - stylesheets/extra.css +extra_javascript: + - javascript.js + - https://polyfill.io/v3/polyfill.min.js?features=es6 + - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js diff --git a/move_template_files.sh b/move_template_files.sh new file mode 100644 index 0000000..41d6aae --- /dev/null +++ b/move_template_files.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +rsync -avh nomad-nomad-simulation-workflow/ . +rm -rfv nomad-nomad-simulation-workflow diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..34fbd5a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,114 @@ +[build-system] +requires = ["setuptools>=61.0.0", "setuptools-scm>=8.0"] +build-backend = "setuptools.build_meta" + +[project] +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-nomad-simulation-workflow" +description = "Schema definition and normalizer for NOMAD simulation workflow" +version = "0.1.0" +readme = "README.rst" +requires-python = ">=3.9" +authors = [ + { name = "Alvin Noe Ladines", email = "ladinesa@physik.hu-berlin.de" }, +] +maintainers = [ + { name = "Alvin Noe Ladines", email = "ladinesa@physik.hu-berlin.de" }, +] +license = { file = "LICENSE" } +dependencies = ["nomad-lab>=1.2.2dev578"] + +[project.urls] +Repository = "https://github.com/ladinesa/nomad-nomad-simulation-workflow" + +[project.optional-dependencies] +dev = ["ruff", "pytest", "structlog"] + +[tool.ruff] +# 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 = [ + # pycodestyle + "E", + # Pyflakes + "F", + # pyupgrade + "UP", + # isort + "I", + # pylint + "PL", +] + +ignore = [ + "F403", # 'from module import *' used; unable to detect undefined names +] + +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" + +# indent with spaces, rather than tabs. +indent-style = "space" + +# Like Black, respect magic trailing commas. +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"] + +[project.entry-points.'nomad.plugin'] + +mypackage = "nomad_nomad_simulation_workflow.schema_packages:mypackage" +mynormalizer = "nomad_nomad_simulation_workflow.normalizers:mynormalizer" + diff --git a/requirements_docs.txt b/requirements_docs.txt new file mode 100644 index 0000000..bacf1ed --- /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_nomad_simulation_workflow/__init__.py b/src/nomad_nomad_simulation_workflow/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/nomad_nomad_simulation_workflow/normalizers/__init__.py b/src/nomad_nomad_simulation_workflow/normalizers/__init__.py new file mode 100644 index 0000000..4286579 --- /dev/null +++ b/src/nomad_nomad_simulation_workflow/normalizers/__init__.py @@ -0,0 +1,17 @@ +from nomad.config.models.plugins import NormalizerEntryPoint +from pydantic import Field + + +class MyNormalizerEntryPoint(NormalizerEntryPoint): + parameter: int = Field(0, description='Custom configuration parameter') + + def load(self): + from nomad_nomad_simulation_workflow.normalizers.mynormalizer import MyNormalizer + + return MyNormalizer(**self.dict()) + + +mynormalizer = MyNormalizerEntryPoint( + name='MyNormalizer', + description='Normalizer defined using the new plugin mechanism.', +) diff --git a/src/nomad_nomad_simulation_workflow/normalizers/mynormalizer.py b/src/nomad_nomad_simulation_workflow/normalizers/mynormalizer.py new file mode 100644 index 0000000..fce0ce6 --- /dev/null +++ b/src/nomad_nomad_simulation_workflow/normalizers/mynormalizer.py @@ -0,0 +1,26 @@ +from typing import ( + TYPE_CHECKING, +) + +if TYPE_CHECKING: + from nomad.datamodel.datamodel import ( + EntryArchive, + ) + from structlog.stdlib import ( + BoundLogger, + ) + +from nomad.config import config +from nomad.normalizing import Normalizer + +configuration = config.get_plugin_entry_point( + 'nomad_nomad_simulation_workflow.normalizers:mynormalizer' +) + + +class MyNormalizer(Normalizer): + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: + super().normalize(archive, logger) + logger.info('MyNormalizer.normalize', parameter=configuration.parameter) + if archive.results and archive.results.material: + archive.results.material.elements = ['C', 'O'] diff --git a/src/nomad_nomad_simulation_workflow/schema_packages/__init__.py b/src/nomad_nomad_simulation_workflow/schema_packages/__init__.py new file mode 100644 index 0000000..16e8ee1 --- /dev/null +++ b/src/nomad_nomad_simulation_workflow/schema_packages/__init__.py @@ -0,0 +1,17 @@ +from nomad.config.models.plugins import SchemaPackageEntryPoint +from pydantic import Field + + +class MySchemaPackageEntryPoint(SchemaPackageEntryPoint): + parameter: int = Field(0, description='Custom configuration parameter') + + def load(self): + from nomad_nomad_simulation_workflow.schema_packages.mypackage import m_package + + return m_package + + +mypackage = MySchemaPackageEntryPoint( + name='MyPackage', + description='Schema package defined using the new plugin mechanism.', +) diff --git a/src/nomad_nomad_simulation_workflow/schema_packages/mypackage.py b/src/nomad_nomad_simulation_workflow/schema_packages/mypackage.py new file mode 100644 index 0000000..a5ecd7e --- /dev/null +++ b/src/nomad_nomad_simulation_workflow/schema_packages/mypackage.py @@ -0,0 +1,38 @@ +from typing import ( + TYPE_CHECKING, +) + +if TYPE_CHECKING: + from nomad.datamodel.datamodel import ( + EntryArchive, + ) + from structlog.stdlib import ( + BoundLogger, + ) + +from nomad.config import config +from nomad.datamodel.data import Schema +from nomad.datamodel.metainfo.annotations import ELNAnnotation, ELNComponentEnum +from nomad.metainfo import Quantity, SchemaPackage + +configuration = config.get_plugin_entry_point( + 'nomad_nomad_simulation_workflow.schema_packages:mypackage' +) + +m_package = SchemaPackage() + + +class MySchema(Schema): + name = Quantity( + type=str, a_eln=ELNAnnotation(component=ELNComponentEnum.StringEditQuantity) + ) + message = Quantity(type=str) + + def normalize(self, archive: 'EntryArchive', logger: 'BoundLogger') -> None: + super().normalize(archive, logger) + + logger.info('MySchema.normalize', parameter=configuration.parameter) + self.message = f'Hello {self.name}!' + + +m_package.__init_metainfo__() diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/data/.gitkeep b/tests/data/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/data/test.archive.yaml b/tests/data/test.archive.yaml new file mode 100644 index 0000000..2158710 --- /dev/null +++ b/tests/data/test.archive.yaml @@ -0,0 +1,3 @@ +data: + m_def: nomad_nomad_simulation_workflow.schema_packages.mypackage.MySchema + name: Markus diff --git a/tests/normalizers/test_normalizer.py b/tests/normalizers/test_normalizer.py new file mode 100644 index 0000000..4e1b058 --- /dev/null +++ b/tests/normalizers/test_normalizer.py @@ -0,0 +1,12 @@ +from nomad.client import normalize_all +from nomad.datamodel import EntryArchive, EntryMetadata +from nomad.datamodel.metainfo.workflow import Workflow + + +def test_normalizer(): + entry_archive = EntryArchive( + metadata=EntryMetadata(), workflow2=Workflow(name='test') + ) + normalize_all(entry_archive) + + assert entry_archive.workflow2.name == 'test' diff --git a/tests/schema_packages/test_schema.py b/tests/schema_packages/test_schema.py new file mode 100644 index 0000000..76210db --- /dev/null +++ b/tests/schema_packages/test_schema.py @@ -0,0 +1,11 @@ +import os.path + +from nomad.client import normalize_all, parse + + +def test_schema(): + test_file = os.path.join('tests', 'data', 'test.archive.yaml') + entry_archive = parse(test_file)[0] + normalize_all(entry_archive) + + assert entry_archive.data.message == 'Hello Markus!'