diff --git a/.cruft.json b/.cruft.json
new file mode 100644
index 0000000..7eccb65
--- /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": "Lauri Himanen",
+ "email": "lauri.himanen@physik.hu-berlin.de",
+ "github_username": "lauri-codes",
+ "plugin_name": "bayesian-optimization",
+ "module_name": "bayesian_optimization",
+ "short_description": "NOMAD plugin for driving experiments/simulations using bayesian optimization",
+ "version": "0.1.0",
+ "license": "Apache Software License 2.0",
+ "include_schema_package": true,
+ "include_normalizer": false,
+ "include_parser": false,
+ "include_app": true,
+ "_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..b8ded12 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-bayesian-optimization
+NOMAD plugin for driving experiments/simulations using bayesian optimization
-## 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-bayesian-optimization-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-bayesian-optimization" 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..7a3814a
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,48 @@
+# Welcome to the `nomad-bayesian-optimization` documentation
+
+NOMAD plugin for driving experiments/simulations using bayesian optimization
+
+## Introduction
+
+!!! note "Attention"
+ TODO
+
+
+
+
+### Tutorial
+
+TODO
+
+- [Tutorial](tutorial/tutorial.md)
+
+
+
+
+### 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)
+
+
+
+
+
+### Explanation
+
+The explanation [section](explanation/explanation.md) provides background knowledge on this plugin.
+
+
+
+
+### 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.
+
+
+
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 %}
+
+
+ {% if "navigation.tabs.sticky" in features %}
+ {% if "navigation.tabs" in features %}
+ {% include "partials/tabs.html" %}
+ {% endif %}
+ {% endif %}
+
\ 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..979ad69
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,57 @@
+site_name: nomad-bayesian-optimization
+site_description: NOMAD plugin for driving experiments/simulations using bayesian optimization
+site_author: Lauri Himanen
+
+repo_url: https://github.com/lauri-codes/nomad-bayesian-optimization
+
+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..bd3bd0d
--- /dev/null
+++ b/move_template_files.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+rsync -avh nomad-bayesian-optimization/ .
+rm -rfv nomad-bayesian-optimization
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..5ed2803
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,116 @@
+[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-bayesian-optimization"
+description = "NOMAD plugin for driving experiments/simulations using bayesian optimization"
+version = "0.1.0"
+readme = "README.rst"
+requires-python = ">=3.9"
+authors = [
+ { name = "Lauri Himanen", email = "lauri.himanen@physik.hu-berlin.de" },
+]
+maintainers = [
+ { name = "Lauri Himanen", email = "lauri.himanen@physik.hu-berlin.de" },
+]
+license = { file = "LICENSE" }
+dependencies = [
+ "nomad-lab>=1.2.2dev578",
+ "baybe",
+ "structlog",
+]
+
+[project.urls]
+Repository = "https://github.com/lauri-codes/nomad-bayesian-optimization"
+
+[project.optional-dependencies]
+dev = ["ruff", "pytest"]
+
+[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']
+experiments = "nomad_bayesian_optimization.schema_packages:experiments"
+bayesian_optimization = "nomad_bayesian_optimization.schema_packages:bayesian_optimization"
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_bayesian_optimization/__init__.py b/src/nomad_bayesian_optimization/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/nomad_bayesian_optimization/apps/__init__.py b/src/nomad_bayesian_optimization/apps/__init__.py
new file mode 100644
index 0000000..cfbc588
--- /dev/null
+++ b/src/nomad_bayesian_optimization/apps/__init__.py
@@ -0,0 +1,24 @@
+from nomad.config.models.plugins import AppEntryPoint
+from nomad.config.models.ui import App, Column, Columns, FilterMenu, FilterMenus
+
+
+myapp = AppEntryPoint(
+ name='MyApp',
+ description='App defined using the new plugin mechanism.',
+ app=App(
+ label='MyApp',
+ path='myapp',
+ category='simulation',
+ columns=Columns(
+ selected=['entry_id'],
+ options={
+ 'entry_id': Column(),
+ },
+ ),
+ filter_menus=FilterMenus(
+ options={
+ 'material': FilterMenu(label='Material'),
+ }
+ ),
+ ),
+)
diff --git a/src/nomad_bayesian_optimization/example_uploads/__init__.py b/src/nomad_bayesian_optimization/example_uploads/__init__.py
new file mode 100644
index 0000000..a05ef8e
--- /dev/null
+++ b/src/nomad_bayesian_optimization/example_uploads/__init__.py
@@ -0,0 +1,24 @@
+from nomad.config.models.plugins import AppEntryPoint
+from nomad.config.models.ui import App, Column, Columns, FilterMenu, FilterMenus
+
+
+myexampleupload = AppEntryPoint(
+ name='MyApp',
+ description='App defined using the new plugin mechanism.',
+ app=App(
+ label='MyApp',
+ path='myapp',
+ category='simulation',
+ columns=Columns(
+ selected=['entry_id'],
+ options={
+ 'entry_id': Column(),
+ },
+ ),
+ filter_menus=FilterMenus(
+ options={
+ 'material': FilterMenu(label='Material'),
+ }
+ ),
+ ),
+)
diff --git a/src/nomad_bayesian_optimization/example_uploads/getting_started/archive.json b/src/nomad_bayesian_optimization/example_uploads/getting_started/archive.json
new file mode 100644
index 0000000..e89bd35
--- /dev/null
+++ b/src/nomad_bayesian_optimization/example_uploads/getting_started/archive.json
@@ -0,0 +1,942 @@
+{
+ "data": {
+ "m_def": "nomad_bayesian_optimization.schema_packages.bayesian_optimization.BayesianOptimization",
+ "optimization": "gASVvwMAAAAAAACMEXBhbmRhcy5jb3JlLmZyYW1llIwJRGF0YUZyYW1llJOUKYGUfZQojARfbWdylIwecGFuZGFzLmNvcmUuaW50ZXJuYWxzLm1hbmFnZXJzlIwMQmxvY2tNYW5hZ2VylJOUKIwWcGFuZGFzLl9saWJzLmludGVybmFsc5SMD191bnBpY2tsZV9ibG9ja5STlIwVbnVtcHkuY29yZS5tdWx0aWFycmF5lIwMX3JlY29uc3RydWN0lJOUjAVudW1weZSMB25kYXJyYXmUk5RLAIWUQwFilIeUUpQoSwFLAUsBhpRoD4wFZHR5cGWUk5SMAk84lImIh5RSlChLA4wBfJROTk5K/////0r/////Sz90lGKJXZSMB1NpbGljb26UYXSUYowIYnVpbHRpbnOUjAVzbGljZZSTlEsASwFLAYeUUpRLAoeUUpRoC2gOaBFLAIWUaBOHlFKUKEsBSwNLAYaUaBiMAmY4lImIh5RSlChLA4wBPJROTk5K/////0r/////SwB0lGKJQxgL2B0UJzZ/QFfdIlBVafc/4aCIaXfX/D+UdJRiaCNLAUsESwGHlFKUSwKHlFKUaAtoDmgRSwCFlGgTh5RSlChLAUsBSwGGlGgYjAJpOJSJiIeUUpQoSwNoL05OTkr/////Sv////9LAHSUYolDCAEAAAAAAAAAlHSUYmgjSwRLBUsBh5RSlEsCh5RSlGgLaA5oEUsAhZRoE4eUUpQoSwFLAUsBhpRoLolDCAAAAAAAAPh/lHSUYmgjSwVLBksBh5RSlEsCh5RSlHSUXZQojBhwYW5kYXMuY29yZS5pbmRleGVzLmJhc2WUjApfbmV3X0luZGV4lJOUaFGMBUluZGV4lJOUfZQojARkYXRhlGgOaBFLAIWUaBOHlFKUKEsBSwaFlGgbiV2UKIwJc3Vic3RyYXRllIwLdGVtcGVyYXR1cmWUjA1nYXNfZmxvd19yYXRllIwQcmVmcmFjdGl2ZV9pbmRleJSMB0JhdGNoTnKUjAVGaXROcpRldJRijARuYW1llE51hpRSlGhTjBlwYW5kYXMuY29yZS5pbmRleGVzLnJhbmdllIwKUmFuZ2VJbmRleJSTlH2UKGhkTowFc3RhcnSUSwCMBHN0b3CUSwGMBHN0ZXCUSwF1hpRSlGWGlFKUjARfdHlwlIwJZGF0YWZyYW1llIwJX21ldGFkYXRhlF2UjAVhdHRyc5R9lIwGX2ZsYWdzlH2UjBdhbGxvd3NfZHVwbGljYXRlX2xhYmVsc5SIc3ViLg==",
+ "figures": [
+ {
+ "label": "Optimization results",
+ "figure": {
+ "data": [
+ {
+ "hovertemplate": "x=%{x}
y=%{y}",
+ "legendgroup": "",
+ "marker": {
+ "color": "#636efa",
+ "symbol": "circle"
+ },
+ "mode": "markers",
+ "name": "",
+ "orientation": "v",
+ "showlegend": false,
+ "x": [
+ NaN
+ ],
+ "xaxis": "x",
+ "y": [
+ 1.802604114762339
+ ],
+ "yaxis": "y",
+ "type": "scatter"
+ }
+ ],
+ "layout": {
+ "template": {
+ "data": {
+ "histogram2dcontour": [
+ {
+ "type": "histogram2dcontour",
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0.0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1.0,
+ "#f0f921"
+ ]
+ ]
+ }
+ ],
+ "choropleth": [
+ {
+ "type": "choropleth",
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ }
+ ],
+ "histogram2d": [
+ {
+ "type": "histogram2d",
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0.0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1.0,
+ "#f0f921"
+ ]
+ ]
+ }
+ ],
+ "heatmap": [
+ {
+ "type": "heatmap",
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0.0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1.0,
+ "#f0f921"
+ ]
+ ]
+ }
+ ],
+ "heatmapgl": [
+ {
+ "type": "heatmapgl",
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0.0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1.0,
+ "#f0f921"
+ ]
+ ]
+ }
+ ],
+ "contourcarpet": [
+ {
+ "type": "contourcarpet",
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ }
+ ],
+ "contour": [
+ {
+ "type": "contour",
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0.0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1.0,
+ "#f0f921"
+ ]
+ ]
+ }
+ ],
+ "surface": [
+ {
+ "type": "surface",
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ },
+ "colorscale": [
+ [
+ 0.0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1.0,
+ "#f0f921"
+ ]
+ ]
+ }
+ ],
+ "mesh3d": [
+ {
+ "type": "mesh3d",
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ }
+ ],
+ "scatter": [
+ {
+ "fillpattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ },
+ "type": "scatter"
+ }
+ ],
+ "parcoords": [
+ {
+ "type": "parcoords",
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ }
+ }
+ ],
+ "scatterpolargl": [
+ {
+ "type": "scatterpolargl",
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ }
+ }
+ ],
+ "bar": [
+ {
+ "error_x": {
+ "color": "#2a3f5f"
+ },
+ "error_y": {
+ "color": "#2a3f5f"
+ },
+ "marker": {
+ "line": {
+ "color": "#E5ECF6",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "bar"
+ }
+ ],
+ "scattergeo": [
+ {
+ "type": "scattergeo",
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ }
+ }
+ ],
+ "scatterpolar": [
+ {
+ "type": "scatterpolar",
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ }
+ }
+ ],
+ "histogram": [
+ {
+ "marker": {
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "histogram"
+ }
+ ],
+ "scattergl": [
+ {
+ "type": "scattergl",
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ }
+ }
+ ],
+ "scatter3d": [
+ {
+ "type": "scatter3d",
+ "line": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ }
+ }
+ ],
+ "scattermapbox": [
+ {
+ "type": "scattermapbox",
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ }
+ }
+ ],
+ "scatterternary": [
+ {
+ "type": "scatterternary",
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ }
+ }
+ ],
+ "scattercarpet": [
+ {
+ "type": "scattercarpet",
+ "marker": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ }
+ }
+ ],
+ "carpet": [
+ {
+ "aaxis": {
+ "endlinecolor": "#2a3f5f",
+ "gridcolor": "white",
+ "linecolor": "white",
+ "minorgridcolor": "white",
+ "startlinecolor": "#2a3f5f"
+ },
+ "baxis": {
+ "endlinecolor": "#2a3f5f",
+ "gridcolor": "white",
+ "linecolor": "white",
+ "minorgridcolor": "white",
+ "startlinecolor": "#2a3f5f"
+ },
+ "type": "carpet"
+ }
+ ],
+ "table": [
+ {
+ "cells": {
+ "fill": {
+ "color": "#EBF0F8"
+ },
+ "line": {
+ "color": "white"
+ }
+ },
+ "header": {
+ "fill": {
+ "color": "#C8D4E3"
+ },
+ "line": {
+ "color": "white"
+ }
+ },
+ "type": "table"
+ }
+ ],
+ "barpolar": [
+ {
+ "marker": {
+ "line": {
+ "color": "#E5ECF6",
+ "width": 0.5
+ },
+ "pattern": {
+ "fillmode": "overlay",
+ "size": 10,
+ "solidity": 0.2
+ }
+ },
+ "type": "barpolar"
+ }
+ ],
+ "pie": [
+ {
+ "automargin": true,
+ "type": "pie"
+ }
+ ]
+ },
+ "layout": {
+ "autotypenumbers": "strict",
+ "colorway": [
+ "#636efa",
+ "#EF553B",
+ "#00cc96",
+ "#ab63fa",
+ "#FFA15A",
+ "#19d3f3",
+ "#FF6692",
+ "#B6E880",
+ "#FF97FF",
+ "#FECB52"
+ ],
+ "font": {
+ "color": "#2a3f5f"
+ },
+ "hovermode": "closest",
+ "hoverlabel": {
+ "align": "left"
+ },
+ "paper_bgcolor": "white",
+ "plot_bgcolor": "#E5ECF6",
+ "polar": {
+ "bgcolor": "#E5ECF6",
+ "angularaxis": {
+ "gridcolor": "white",
+ "linecolor": "white",
+ "ticks": ""
+ },
+ "radialaxis": {
+ "gridcolor": "white",
+ "linecolor": "white",
+ "ticks": ""
+ }
+ },
+ "ternary": {
+ "bgcolor": "#E5ECF6",
+ "aaxis": {
+ "gridcolor": "white",
+ "linecolor": "white",
+ "ticks": ""
+ },
+ "baxis": {
+ "gridcolor": "white",
+ "linecolor": "white",
+ "ticks": ""
+ },
+ "caxis": {
+ "gridcolor": "white",
+ "linecolor": "white",
+ "ticks": ""
+ }
+ },
+ "coloraxis": {
+ "colorbar": {
+ "outlinewidth": 0,
+ "ticks": ""
+ }
+ },
+ "colorscale": {
+ "sequential": [
+ [
+ 0.0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1.0,
+ "#f0f921"
+ ]
+ ],
+ "sequentialminus": [
+ [
+ 0.0,
+ "#0d0887"
+ ],
+ [
+ 0.1111111111111111,
+ "#46039f"
+ ],
+ [
+ 0.2222222222222222,
+ "#7201a8"
+ ],
+ [
+ 0.3333333333333333,
+ "#9c179e"
+ ],
+ [
+ 0.4444444444444444,
+ "#bd3786"
+ ],
+ [
+ 0.5555555555555556,
+ "#d8576b"
+ ],
+ [
+ 0.6666666666666666,
+ "#ed7953"
+ ],
+ [
+ 0.7777777777777778,
+ "#fb9f3a"
+ ],
+ [
+ 0.8888888888888888,
+ "#fdca26"
+ ],
+ [
+ 1.0,
+ "#f0f921"
+ ]
+ ],
+ "diverging": [
+ [
+ 0,
+ "#8e0152"
+ ],
+ [
+ 0.1,
+ "#c51b7d"
+ ],
+ [
+ 0.2,
+ "#de77ae"
+ ],
+ [
+ 0.3,
+ "#f1b6da"
+ ],
+ [
+ 0.4,
+ "#fde0ef"
+ ],
+ [
+ 0.5,
+ "#f7f7f7"
+ ],
+ [
+ 0.6,
+ "#e6f5d0"
+ ],
+ [
+ 0.7,
+ "#b8e186"
+ ],
+ [
+ 0.8,
+ "#7fbc41"
+ ],
+ [
+ 0.9,
+ "#4d9221"
+ ],
+ [
+ 1,
+ "#276419"
+ ]
+ ]
+ },
+ "xaxis": {
+ "gridcolor": "white",
+ "linecolor": "white",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "white",
+ "automargin": true,
+ "zerolinewidth": 2
+ },
+ "yaxis": {
+ "gridcolor": "white",
+ "linecolor": "white",
+ "ticks": "",
+ "title": {
+ "standoff": 15
+ },
+ "zerolinecolor": "white",
+ "automargin": true,
+ "zerolinewidth": 2
+ },
+ "scene": {
+ "xaxis": {
+ "backgroundcolor": "#E5ECF6",
+ "gridcolor": "white",
+ "linecolor": "white",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "white",
+ "gridwidth": 2
+ },
+ "yaxis": {
+ "backgroundcolor": "#E5ECF6",
+ "gridcolor": "white",
+ "linecolor": "white",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "white",
+ "gridwidth": 2
+ },
+ "zaxis": {
+ "backgroundcolor": "#E5ECF6",
+ "gridcolor": "white",
+ "linecolor": "white",
+ "showbackground": true,
+ "ticks": "",
+ "zerolinecolor": "white",
+ "gridwidth": 2
+ }
+ },
+ "shapedefaults": {
+ "line": {
+ "color": "#2a3f5f"
+ }
+ },
+ "annotationdefaults": {
+ "arrowcolor": "#2a3f5f",
+ "arrowhead": 0,
+ "arrowwidth": 1
+ },
+ "geo": {
+ "bgcolor": "white",
+ "landcolor": "#E5ECF6",
+ "subunitcolor": "white",
+ "showland": true,
+ "showlakes": true,
+ "lakecolor": "white"
+ },
+ "title": {
+ "x": 0.05
+ },
+ "mapbox": {
+ "style": "light"
+ }
+ }
+ },
+ "xaxis": {
+ "anchor": "y",
+ "domain": [
+ 0.0,
+ 0.45
+ ]
+ },
+ "yaxis": {
+ "anchor": "x",
+ "domain": [
+ 0.0,
+ 1.0
+ ]
+ },
+ "xaxis2": {
+ "anchor": "y2",
+ "domain": [
+ 0.55,
+ 1.0
+ ]
+ },
+ "yaxis2": {
+ "anchor": "x2",
+ "domain": [
+ 0.0,
+ 1.0
+ ],
+ "matches": "y",
+ "showticklabels": false
+ },
+ "title": {
+ "text": "Optimization results"
+ },
+ "height": 400,
+ "width": 716
+ }
+ }
+ }
+ ],
+ "searchspace": {
+ "discrete": {
+ "parameters": [
+ {
+ "type": "CategoricalParameter",
+ "name": "substrate",
+ "values": [
+ "Silicon carbide",
+ "Silicon",
+ "Gallium nitride"
+ ],
+ "encoding": "OHE"
+ }
+ ]
+ },
+ "continuous": {
+ "parameters": [
+ {
+ "type": "NumericalContinuousParameter",
+ "name": "temperature",
+ "bounds": {
+ "lower": "300.0",
+ "upper": "600.0"
+ }
+ },
+ {
+ "type": "NumericalContinuousParameter",
+ "name": "gas_flow_rate",
+ "bounds": {
+ "lower": "0.2",
+ "upper": "5.0"
+ }
+ }
+ ]
+ }
+ },
+ "objective": {
+ "type": "SingleTargetObjective",
+ "target": {
+ "type": "NumericalTarget",
+ "name": "refractive_index",
+ "mode": "MATCH",
+ "transformation": "BELL",
+ "bounds": {
+ "lower": "2.4473",
+ "upper": "2.8473"
+ }
+ }
+ },
+ "recommender": {
+ "type": "TwoPhaseMetaRecommender"
+ }
+ },
+ "results": {}
+}
\ No newline at end of file
diff --git a/src/nomad_bayesian_optimization/example_uploads/getting_started/example.py b/src/nomad_bayesian_optimization/example_uploads/getting_started/example.py
new file mode 100644
index 0000000..b959073
--- /dev/null
+++ b/src/nomad_bayesian_optimization/example_uploads/getting_started/example.py
@@ -0,0 +1,146 @@
+api_url = ''
+schema_name = 'nomad_bayesian_optimization.schema_packages.experiments.CVDExperiment'
+
+# ======================================================================================
+# Define the seach space
+from baybe.parameters import CategoricalParameter, NumericalContinuousParameter
+from baybe.searchspace import SearchSpace
+
+parameters = [
+ CategoricalParameter(
+ name='substrate',
+ values=['Silicon carbide', 'Silicon', 'Gallium nitride'],
+ encoding='OHE', # one-hot encoding of categories
+ ),
+ NumericalContinuousParameter(
+ name='temperature',
+ bounds=(300, 600),
+ ),
+ NumericalContinuousParameter(
+ name='gas_flow_rate',
+ bounds=(0.2, 5),
+ ),
+]
+
+searchspace = SearchSpace.from_product(parameters)
+
+# ======================================================================================
+# Define the optimization target
+from baybe.objectives import SingleTargetObjective
+from baybe.targets import NumericalTarget
+
+refractive_index_target = 2.6473
+refractive_index_sigma = 0.2
+target = NumericalTarget(
+ name='refractive_index',
+ mode='MATCH',
+ bounds=(
+ refractive_index_target - refractive_index_sigma,
+ refractive_index_target + refractive_index_sigma,
+ ),
+ transformation='BELL',
+)
+objective = SingleTargetObjective(target=target)
+
+# ======================================================================================
+# Define the acquisition strategy
+from baybe.recommenders import SequentialGreedyRecommender, TwoPhaseMetaRecommender
+
+recommender = TwoPhaseMetaRecommender(
+ recommender=SequentialGreedyRecommender(
+ hybrid_sampler='Farthest', sampling_percentage=0.3
+ ),
+)
+
+# ======================================================================================
+# Prepare upload to store the generated data
+
+# ======================================================================================
+# Start optimization loop
+import time
+
+import numpy as np
+from baybe import Campaign
+
+from nomad_bayesian_optimization.schema_packages.experiments import CVDExperiment
+
+campaign = Campaign(searchspace, objective, recommender)
+
+
+def get_samples(recommendations):
+ """In this function you can decide how the actual experiment/simulation is
+ performed. There are several alternatives:
+
+ - Maybe you can control measurement devices directly through API calls.
+ - Maybe you create a loop that waits until someone manually inserts the
+ experiment results into NOMAD, and then query the results from it using
+ the NOMAD API.
+ - Maybe you run a simulation in this notebook
+ - Maybe you run a simulation using an HPC batch system
+
+ In this example, we will create entries by sampling from a
+ fake model.
+ """
+ for _, row in recommendations.iterrows():
+ cvd_experiment = CVDExperiment().m_from_dict(row.to_dict())
+ temp_mu = 400
+ temp_sigma = 200
+ gas_flow_mu = 2
+ gas_flow_sigma = 3
+ ideal_substrate = 'Silicon carbide'
+ refractive_index = float(
+ 2.6473
+ * np.exp(-((cvd_experiment.temperature.m - temp_mu) ** 2 / temp_sigma**2))
+ * np.exp(
+ -(
+ (cvd_experiment.gas_flow_rate.m - gas_flow_mu) ** 2
+ / gas_flow_sigma**2
+ )
+ )
+ )
+ if cvd_experiment.substrate != ideal_substrate:
+ refractive_index *= 0.9
+ cvd_experiment.refractive_index = refractive_index
+ time.sleep(2)
+ return cvd_experiment
+
+
+i = 0
+result = 0
+threshold = 1
+while abs(refractive_index_target - result) > threshold:
+ df = campaign.recommend(batch_size=1)
+ print('New recommendation:')
+ print(df)
+ print('Testing recommendation...')
+ archive = get_samples(df)
+ print('Testing finished!')
+ result = archive.refractive_index
+ df['refractive_index'] = [result]
+ campaign.add_measurements(df)
+ i += 1
+
+# At the end of the run, lets store the whole optimization run into an entry
+import json
+
+from nomad.datamodel import EntryArchive
+
+from nomad_bayesian_optimization.schema_packages.bayesian_optimization import (
+ BayesianOptimization,
+)
+
+archive = EntryArchive()
+bopt = BayesianOptimization.from_baybe_campaign(campaign)
+archive.data = bopt
+bopt.normalize(archive, None)
+
+with open('archive.json', 'w') as fout:
+ json.dump(archive.m_to_dict(), fout, indent=2)
+# print(bopt.search_space)
+# campaign_dict = campaign.to_dict()
+# recommendation = deserialize_dataframe(campaign_dict['_cached_recommendation'])
+# measurements = deserialize_dataframe(campaign_dict['_measurements_exp'])
+# print(measurements)
+# with open("campaign.json", 'w') as fout:
+# json.dump(fout, campaign.to_dict())
+# print(f'Optimal refractive index {result} found after {i} loops')
diff --git a/src/nomad_bayesian_optimization/example_uploads/getting_started/tutorial.ipynb b/src/nomad_bayesian_optimization/example_uploads/getting_started/tutorial.ipynb
new file mode 100644
index 0000000..ca25e27
--- /dev/null
+++ b/src/nomad_bayesian_optimization/example_uploads/getting_started/tutorial.ipynb
@@ -0,0 +1,262 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "tags": []
+ },
+ "source": [
+ "\n",
+ "\n",
+ "\n",
+ "
\n",
+ " Getting started with Baysian Optimization for automated workflows
\n",
+ "
\n",
+ " Lauri Himanen
\n",
+ "
"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "tags": []
+ },
+ "source": [
+ "# Introduction\n",
+ "\n",
+ "This tutorial will help you get started with using Baysian Optimation for automating the sampling of experiments/simulations. The main goal is this: you want to optimize certain parameters in your data (e.g. yield, efficiency, energy), but because there are several input parameters that control the optimization target, it is hard to guide this optimization manually or through analytic reasoning. This is where Baysian Optimization can help.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Install dependencies"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "vscode": {
+ "languageId": "plaintext"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "!pip install baybe"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "jp-MarkdownHeadingCollapsed": true,
+ "tags": []
+ },
+ "source": [
+ "# Define the search space"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "vscode": {
+ "languageId": "plaintext"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "from baybe.parameters import (\n",
+ " CategoricalParameter,\n",
+ " NumericalDiscreteParameter,\n",
+ " SubstanceParameter,\n",
+ ")\n",
+ "\n",
+ "parameters = [\n",
+ " CategoricalParameter(\n",
+ " name=\"Granularity\",\n",
+ " values=[\"coarse\", \"medium\", \"fine\"],\n",
+ " encoding=\"OHE\", # one-hot encoding of categories\n",
+ " ),\n",
+ " NumericalDiscreteParameter(\n",
+ " name=\"Pressure[bar]\",\n",
+ " values=[1, 5, 10],\n",
+ " tolerance=0.2, # allows experimental inaccuracies up to 0.2 when reading values\n",
+ " ),\n",
+ " SubstanceParameter(\n",
+ " name=\"Solvent\",\n",
+ " data={\n",
+ " \"Solvent A\": \"COC\",\n",
+ " \"Solvent B\": \"CCC\", # label-SMILES pairs\n",
+ " \"Solvent C\": \"O\",\n",
+ " \"Solvent D\": \"CS(=O)C\",\n",
+ " },\n",
+ " encoding=\"MORDRED\", # chemical encoding via mordred package\n",
+ " ),\n",
+ "]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Defining the optimization objective\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from baybe.targets import NumericalTarget\n",
+ "from baybe.objectives import SingleTargetObjective\n",
+ "\n",
+ "target = NumericalTarget(\n",
+ " name=\"Yield\",\n",
+ " mode=\"MAX\",\n",
+ ")\n",
+ "objective = SingleTargetObjective(target=target)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Define acquisition strategy"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from baybe.recommenders import (\n",
+ " BotorchRecommender,\n",
+ " FPSRecommender,\n",
+ " TwoPhaseMetaRecommender,\n",
+ ")\n",
+ "\n",
+ "recommender = TwoPhaseMetaRecommender(\n",
+ " initial_recommender=FPSRecommender(), # farthest point sampling\n",
+ " recommender=BotorchRecommender(), # Bayesian model-based optimization\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# The optimization loop"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from baybe import Campaign\n",
+ "\n",
+ "campaign = Campaign(searchspace, objective, recommender)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Get initial recommendations"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "vscode": {
+ "languageId": "plaintext"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "df = campaign.recommend(batch_size=3)\n",
+ "print(df)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "vscode": {
+ "languageId": "plaintext"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "def create_entry():\n",
+ " \"\"\"In this function you can decide how the actual experiment/simulation is performed. There are several alternatives:\n",
+ "\t- Maybe you can control measurement devices directly through API calls\n",
+ "\t- Maybe you wait until someone manually inserts the experiment results into NOMAD\n",
+ "\t- Maybe you run the simulation in this notebook\n",
+ "\t- Maybe you run the simulation using an HPC batch system\n",
+ "\t- etc.\n",
+ "\t\"\"\"\"\n",
+ "\tpass"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "vscode": {
+ "languageId": "plaintext"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "target = 0.1\n",
+ "result = 0\n",
+ "while(result < target):\n",
+ " df = campaign.recommend(batch_size=1)\n",
+ "\tarchive = create_entry()\n",
+ "\tresult = archive.yield\n",
+ "\tcampaign.add_measurements(archive.yield)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
diff --git a/src/nomad_bayesian_optimization/schema_packages/__init__.py b/src/nomad_bayesian_optimization/schema_packages/__init__.py
new file mode 100644
index 0000000..fe68227
--- /dev/null
+++ b/src/nomad_bayesian_optimization/schema_packages/__init__.py
@@ -0,0 +1,29 @@
+from nomad.config.models.plugins import SchemaPackageEntryPoint
+from pydantic import Field
+
+
+class BayesianOptimizationPackageEntryPoint(SchemaPackageEntryPoint):
+ def load(self):
+ from nomad_bayesian_optimization.schema_packages.bayesian_optimization import (
+ m_package,
+ )
+
+ return m_package
+
+
+class ExperimentsPackageEntryPoint(SchemaPackageEntryPoint):
+ def load(self):
+ from nomad_bayesian_optimization.schema_packages.experiments import m_package
+
+ return m_package
+
+
+experiments = ExperimentsPackageEntryPoint(
+ name='Experiments',
+ description='Dummy schema package for experiments.',
+)
+
+bayesian_optimization = BayesianOptimizationPackageEntryPoint(
+ name='Bayesian Optimization',
+ description='Schema package for Bayesian optimization runs.',
+)
diff --git a/src/nomad_bayesian_optimization/schema_packages/bayesian_optimization.py b/src/nomad_bayesian_optimization/schema_packages/bayesian_optimization.py
new file mode 100644
index 0000000..0a140e8
--- /dev/null
+++ b/src/nomad_bayesian_optimization/schema_packages/bayesian_optimization.py
@@ -0,0 +1,93 @@
+import plotly.express as px
+from baybe.serialization.utils import deserialize_dataframe
+from nomad.datamodel.data import Schema
+from nomad.datamodel.metainfo.plot import PlotlyFigure, PlotSection
+from nomad.metainfo import MEnum, MSection, Quantity, SchemaPackage, SubSection
+from plotly.subplots import make_subplots
+
+m_package = SchemaPackage()
+
+
+class Bounds(MSection):
+ lower = Quantity(type=MEnum('CategoricalParameter', 'NumericalContinuousParameter'))
+ upper = Quantity(type=str)
+
+
+class Parameter(MSection):
+ """Baysian optimization run."""
+
+ type = Quantity(type=MEnum('CategoricalParameter', 'NumericalContinuousParameter'))
+ name = Quantity(type=str)
+ values = Quantity(type=str, shape=['*'])
+ bounds = SubSection(section_def=Bounds)
+ encoding = Quantity(type=str)
+
+
+class Discrete(MSection):
+ parameters = SubSection(section_def=Parameter, repeats=True)
+
+
+class Continuous(MSection):
+ parameters = SubSection(section_def=Parameter, repeats=True)
+
+
+class SearchSpace(MSection):
+ discrete = SubSection(section_def=Discrete)
+ continuous = SubSection(section_def=Continuous)
+
+
+class Target(MSection):
+ type = Quantity(type=MEnum('NumericalTarget'))
+ name = Quantity(type=str)
+ mode = Quantity(type=MEnum('MATCH'))
+ transformation = Quantity(type=MEnum('BELL'))
+ bounds = SubSection(section_def=Bounds)
+
+
+class Objective(MSection):
+ type = Quantity(type=MEnum('SingleTargetObjective'))
+ target = SubSection(section_def=Target)
+
+
+class Recommender(MSection):
+ type = Quantity(type=MEnum('TwoPhaseMetaRecommender'))
+
+
+class Step(MSection):
+ type = Quantity(type=MEnum('TwoPhaseMetaRecommender'))
+
+
+class BayesianOptimization(PlotSection, Schema):
+ """Baysian optimization run."""
+
+ searchspace = SubSection(section_def=SearchSpace)
+ objective = SubSection(section_def=Objective)
+ recommender = SubSection(section_def=Recommender)
+ optimization = Quantity(type=str, description='base64 encoded optimization run')
+ entries = Quantity(
+ type=str,
+ shape=['*'],
+ description='List of entries connected to the optimization.',
+ )
+
+ def from_baybe_campaign(campaign):
+ dictionary = campaign.to_dict()
+ result = BayesianOptimization.m_from_dict(dictionary)
+ result.optimization = dictionary['_measurements_exp']
+ return result
+
+ def normalize(self, archive, logger):
+ super().normalize(archive, logger)
+
+ df = deserialize_dataframe(self.optimization)
+ target_name = self.objective.target.name
+ first_line = px.scatter(x=df['FitNr'], y=df[target_name])
+ figure1 = make_subplots(rows=1, cols=2, shared_yaxes=True)
+ figure1.add_trace(first_line.data[0], row=1, col=1)
+ figure1.update_layout(height=400, width=716, title_text='Optimization results')
+ self.figures.append(
+ PlotlyFigure(label='Optimization results', figure=figure1.to_plotly_json())
+ )
+
+
+m_package.__init_metainfo__()
diff --git a/src/nomad_bayesian_optimization/schema_packages/experiments.py b/src/nomad_bayesian_optimization/schema_packages/experiments.py
new file mode 100644
index 0000000..255155f
--- /dev/null
+++ b/src/nomad_bayesian_optimization/schema_packages/experiments.py
@@ -0,0 +1,36 @@
+from nomad.datamodel.data import Schema
+from nomad.datamodel.metainfo.annotations import ELNAnnotation, ELNComponentEnum
+from nomad.metainfo import MEnum, Quantity, SchemaPackage
+
+m_package = SchemaPackage()
+
+
+class CVDExperiment(Schema):
+ """Experiment for growing thin films using chemical vapor deposition."""
+
+ substrate = Quantity(
+ type=MEnum('Silicon carbide', 'Silicon', 'Gallium nitride'),
+ a_eln=ELNAnnotation(
+ component=ELNComponentEnum.EnumEditQuantity,
+ ),
+ )
+ gas_flow_rate = Quantity(
+ type=float,
+ unit='liter/minute',
+ a_eln=ELNAnnotation(component=ELNComponentEnum.NumberEditQuantity),
+ description='Gas flow rate.',
+ )
+ temperature = Quantity(
+ type=float,
+ unit='K',
+ a_eln=ELNAnnotation(component=ELNComponentEnum.NumberEditQuantity),
+ description='Temperature during experiment.',
+ )
+ refractive_index = Quantity(
+ type=float,
+ a_eln=ELNAnnotation(component=ELNComponentEnum.NumberEditQuantity),
+ description='Refractive index of the thin-film sample.',
+ )
+
+
+m_package.__init_metainfo__()
diff --git a/tests/apps/test_app.py b/tests/apps/test_app.py
new file mode 100644
index 0000000..14e00be
--- /dev/null
+++ b/tests/apps/test_app.py
@@ -0,0 +1,4 @@
+def test_importing_app():
+ # this will raise an exception if pydantic model validation fails for th app
+ from nomad_bayesian_optimization.apps import myapp
+
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..336bace
--- /dev/null
+++ b/tests/data/test.archive.yaml
@@ -0,0 +1,3 @@
+data:
+ m_def: nomad_bayesian_optimization.schema_packages.mypackage.MySchema
+ name: Markus
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!'