diff --git a/docs/source/_static/aiida-custom.css b/docs/source/_static/aiida-custom.css
new file mode 100644
index 0000000..42d2fa2
--- /dev/null
+++ b/docs/source/_static/aiida-custom.css
@@ -0,0 +1,130 @@
+/* Fix CSS of top bar link icons */
+a.nav-link.nav-external i {
+ padding-left: 0.3em !important;
+ font-size: inherit !important;
+ vertical-align: inherit !important;
+}
+/* Current fix for https://github.com/pandas-dev/pydata-sphinx-theme/issues/193 */
+dl.field-list {
+ display: grid;
+ grid-template-columns: fit-content(30%) minmax(0, 1fr);
+}
+/* For icon unicodes see https://fontawesome.com/v4.7.0/icons/ */
+.title-icon-rocket .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f135"
+}
+.title-icon-info-circle .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f05a"
+}
+.title-icon-question-circle .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f059"
+}
+.title-icon-download .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f019"
+}
+.title-icon-external-link .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f08e"
+}
+.title-icon-lightbulb .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f0eb"
+}
+.title-icon-wrench .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f0ad"
+}
+.title-icon-cog .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f013"
+}
+.title-icon-cogs .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f085"
+}
+.title-icon-code-fork .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f126"
+}
+/* Semantic icon names */
+.title-icon-launch-software .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f135" /* rocket */
+}
+.title-icon-install-software .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f019" /* download */
+}
+.title-icon-information .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f05a" /* info-circle */
+}
+.title-icon-tip .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f0eb" /* lightbulb */
+}
+.title-icon-important .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f06a" /* exclamation-circle */
+}
+.title-icon-warning .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f071" /* exclamation-triangle */
+}
+.title-icon-troubleshoot .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f0ad" /* wrench */
+}
+.title-icon-read-more .admonition-title:before {
+ margin-right:.5rem;
+ content: "\f518" /* external-link */
+}
+
+.dropdown-group .dropdown .summary-title {
+ border-bottom: 0 !important;
+ font-weight:700 !important;
+}
+.dropdown-group .dropdown:not(:last-child) {
+ margin-bottom: 0 !important;
+ border-radius: 0 !important;
+}
+.dropdown-group .dropdown:first-child,
+.dropdown-group .dropdown:first-child .summary-title {
+ border-radius: 1rem 1rem 0rem 0rem !important;
+}
+.dropdown-group .dropdown:last-child,
+.dropdown-group .dropdown:last-child .summary-title {
+ border-radius: 0rem 0rem 1rem 1rem !important;
+}
+
+.dropdown-group .dropdown:last-child {
+ margin-bottom: 24px !important;
+}
+
+div.admonition :last-child {
+ margin-bottom: 0
+}
+
+div.highlight-bash div.highlight {
+ background-color: aliceblue;
+}
+
+div.highlight-console div.highlight {
+ background-color: aliceblue;
+}
+
+.aiida-green {
+ color: #32B805;
+}
+
+.aiida-blue {
+ color: #0496DE;
+}
+
+.aiida-orange {
+ color: #FF7D16;
+}
diff --git a/docs/source/conf.py b/docs/source/conf.py
index ea53586..b4b0dd6 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -13,16 +13,16 @@
"""
import os
import pathlib
-import subprocess
import sys
import time
import sphinx_rtd_theme
+from aiida.manage.configuration import Profile, load_profile
import aiida_aimall
# from aiida.manage.configuration import load_documentation_profile
-
+load_profile(Profile("docs", {"process_control": {}, "storage": {}}))
# -- AiiDA-related setup --------------------------------------------------
@@ -31,6 +31,26 @@
# -- General configuration ------------------------------------------------
+
+# General information about the project.
+project = "aiida-aimall"
+author = "Kevin Lefrancois-Gagnon, Robert Mawhinney"
+copyright_first_year = "2023"
+copyright_owners = "Kevin Lefrancois-Gagnon, Robert Mawhinney"
+
+current_year = str(time.localtime().tm_year)
+copyright_year_string = (
+ current_year
+ if current_year == copyright_first_year
+ else f"{copyright_first_year}-{current_year}"
+)
+# pylint: disable=redefined-builtin
+copyright = f"{copyright_year_string}, {copyright_owners}. All rights reserved"
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
@@ -39,27 +59,77 @@
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
- "sphinx.ext.autodoc",
+ # "sphinx.ext.autodoc",
"sphinx.ext.mathjax",
"sphinx.ext.intersphinx",
"sphinx.ext.viewcode",
- "sphinxcontrib.contentui",
+ "sphinx_copybutton",
+ "sphinx_click.ext",
+ "sphinx_design",
+ "myst_parser",
"aiida.sphinxext",
- "sphinx.ext.duration",
- "sphinx.ext.doctest",
- "sphinx.ext.autosummary",
- "sphinx.ext.coverage",
+ "autoapi.extension",
+ "sphinxcontrib.contentui",
+ "nbsphinx",
"sphinx.ext.napoleon",
+ "sphinx_gallery.load_style",
]
+# Setting the intersphinx mapping to other readthedocss
intersphinx_mapping = {
"python": ("https://docs.python.org/3", None),
"aiida": ("https://aiida.readthedocs.io/projects/aiida-core/en/latest", None),
+ "subproptools": ("https://subproptools.readthedocs.io/en/latest/", None),
}
+# settings for the autoapi.extension automatically generating API docs
+filepath_docs = pathlib.Path(__file__).parent.parent
+filepath_src = filepath_docs.parent / "src"
+autoapi_type = "python"
+autoapi_ignore = ["*tests*"]
+autoapi_dirs = [filepath_src]
+autoapi_root = str(filepath_docs / "source" / "reference" / "api" / "auto")
+autoapi_keep_files = True
+autoapi_add_toctree_entry = False
+
+
+# Settings for the `sphinx_copybutton` extension
+copybutton_selector = "div:not(.no-copy)>div.highlight pre"
+copybutton_prompt_text = (
+ r">>> |\.\.\. |(?:\(.*\) )?\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: "
+)
+copybutton_prompt_is_regexp = True
+
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = "en"
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = [
+ "**.ipynb_checkpoints"
+] # , 'reference/api/auto/aiida_aimall/index.rst'
+
+# -- MyST options
+myst_enable_extensions = [
+ "deflist",
+ "colon_fence",
+ "substitution",
+ "attrs_inline",
+ "substitution",
+]
+
+myst_substitutions = {
+ "aiida_logo": '',
+ "AimqbCalculation": "{class}`~aiida_aimall.calculations.AimqbCalculation`",
+ "AimqbParameters": "{class}`~aiida_aimall.data.AimqbParameters`",
+}
# The suffix of source filenames.
sys.path.insert(0, os.path.abspath("../.."))
sys.path.insert(0, pathlib.Path(__file__).parents[2].resolve().as_posix())
@@ -68,41 +138,6 @@
# The encoding of source files.
# source_encoding = 'utf-8-sig'
-# The master toctree document.
-# ~ master_doc = 'index'
-master_doc = "index"
-
-# General information about the project.
-project = "aiida-aimall"
-author = "Kevin Lefrancois-Gagnon, Robert Mawhinney"
-copyright_first_year = "2023"
-copyright_owners = "Kevin Lefrancois-Gagnon, Robert Mawhinney"
-
-current_year = str(time.localtime().tm_year)
-copyright_year_string = (
- current_year
- if current_year == copyright_first_year
- else f"{copyright_first_year}-{current_year}"
-)
-# pylint: disable=redefined-builtin
-copyright = f"{copyright_year_string}, {copyright_owners}. All rights reserved"
-
-# The version info for the project you're documenting, acts as replacement for
-# |version| and |release|, also used in various other places throughout the
-# built documents.
-#
-# The full version, including alpha/beta/rc tags.
-release = aiida_aimall.__version__
-# The short X.Y version.
-version = ".".join(release.split(".")[:2])
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#
-# This is also used if you do content translation via gettext catalogs.
-# Usually you set "language" from the command line for these cases.
-language = "en"
-
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
@@ -114,21 +149,44 @@
# exclude_patterns = ['doc.rst']
# ~ exclude_patterns = ['index.rst']
-# If true, sectionauthor and moduleauthor directives will be shown in the
-# output. They are ignored by default.
-show_authors = True
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = "sphinx"
-
# -- Options for HTML output ----------------------------------------------
-html_theme = "sphinx_rtd_theme"
+html_theme = "sphinx_book_theme"
+html_theme_options = {
+ "repository_url": "https://github.com/kmlefran/aiida-aimall",
+ "github_url": "https://github.com/kmlefran/aiida-aimall",
+ "use_edit_page_button": True,
+ "navigation_with_keys": False,
+}
+html_context = {
+ "github_user": "kmlefran",
+ "github_repo": "aiida-aimall",
+ "github_version": "main",
+ "doc_path": "docs/source",
+ "default_mode": "dark",
+}
+html_static_path = ["_static"]
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
-html_logo = "images/AiiDA_transparent_logo.png"
-html_title = f"aiida-aimall v{release}"
-html_theme_options = {}
-
+html_sidebars = {
+ "**": [
+ "navbar-logo.html",
+ "navbar-icon-links.html",
+ "search-field.html",
+ "sbt-sidebar-nav.html",
+ ]
+}
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+html_use_opensearch = "http://aiida-aimall.readthedocs.io"
+# Language to be used for generating the HTML full-text search index.
+# Sphinx supports the following languages:
+# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
+# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
+html_search_language = "en"
+# Output file base name for HTML help builder.
+htmlhelp_basename = "aiida-quantumespressodoc"
+# -------------------------------------------------------------------
# Add any paths that contain custom themes here, relative to this directory.
# ~ html_theme_path = ["."]
@@ -171,31 +229,24 @@
# If true, the index is split into individual pages for each letter.
# html_split_index = False
-# If true, links to the reST sources are added to the pages.
-html_show_sourcelink = False
-
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# ~ html_show_copyright = False
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-html_use_opensearch = "https://aiida-aimall.readthedocs.io"
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-# html_file_suffix = None
-
-# Language to be used for generating the HTML full-text search index.
-# Sphinx supports the following languages:
-# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
-# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
-html_search_language = "en"
# Warnings to ignore when using the -n (nitpicky) option
# We should ignore any python built-in exception, for instance
+nitpicky = True
+
+nitpick_ignore_regex = [
+ (r"py:.*", r"pydantic.*"),
+ (r"py:.*", r"con.*"),
+ (r".*", r"Literal.*"),
+ (r".*", r"Tuple.*"),
+]
+
nitpick_ignore = [
("py:class", "Logger"),
("py:class", "CalcJobNode"),
@@ -207,47 +258,5 @@
("py:class", "Int"),
("py:class", "Code"),
("py:class", "QbFields"),
+ ("py:obj", "aiida_submission_controller.FromGroupSubmissionController"),
]
-
-
-def run_apidoc(_):
- """Runs sphinx-apidoc when building the documentation.
-
- Needs to be done in conf.py in order to include the APIdoc in the
- build on readthedocs.
-
- See also https://github.com/rtfd/readthedocs.org/issues/1139
- """
- source_dir = os.path.abspath(os.path.dirname(__file__))
- apidoc_dir = os.path.join(source_dir, "apidoc")
- package_dir = os.path.join(source_dir, os.pardir, os.pardir, "aiida_aimall")
-
- # In #1139, they suggest the route below, but this ended up
- # calling sphinx-build, not sphinx-apidoc
- # from sphinx.apidoc import main
- # main([None, '-e', '-o', apidoc_dir, package_dir, '--force'])
-
- cmd_path = "sphinx-apidoc"
- if hasattr(sys, "real_prefix"): # Check to see if we are in a virtualenv
- # If we are, assemble the path manually
- cmd_path = os.path.abspath(os.path.join(sys.prefix, "bin", "sphinx-apidoc"))
-
- options = [
- "-o",
- apidoc_dir,
- package_dir,
- "--force",
- "--no-toc",
- ]
-
- # See https://stackoverflow.com/a/30144019
- env = os.environ.copy()
- env[
- "SPHINX_APIDOC_OPTIONS"
- ] = "members,special-members,undoc-members,show-inheritance"
- subprocess.check_call([cmd_path] + options, env=env)
-
-
-def setup(app):
- """setup app"""
- app.connect("builder-inited", run_apidoc)
diff --git a/docs/source/developer_guide/index.rst b/docs/source/developer_guide/index.rst
index 8a9fda5..0da996e 100644
--- a/docs/source/developer_guide/index.rst
+++ b/docs/source/developer_guide/index.rst
@@ -59,9 +59,8 @@ Building the documentation
docs/source/index.rst
docs/source/developer_guide/index.rst
- docs/source/user_guide/index.rst
- docs/source/user_guide/get_started.rst
- docs/source/user_guide/tutorial.rst
+ docs/source/installation/index.md
+ docs/source/tutorials/index.md
#. Use `Sphinx`_ to generate the html documentation::
diff --git a/docs/source/index.md b/docs/source/index.md
new file mode 100644
index 0000000..5c382b0
--- /dev/null
+++ b/docs/source/index.md
@@ -0,0 +1,95 @@
+---
+myst:
+ substitutions:
+ README.md of the repository: '`README.md` of the repository'
+ aiida-core documentation: '`aiida-core` documentation'
+ aiida-aimall: '`aiida-aimall`'
+---
+
+```{toctree}
+:hidden: true
+
+installation/index
+```
+
+```{toctree}
+:hidden: true
+
+tutorials/index
+```
+
+```{toctree}
+:hidden: true
+
+developer_guide/index
+```
+
+```{toctree}
+:hidden: true
+:caption: Reference
+reference/api/auto/aiida_aimall/index
+```
+
+# aiida-aimall
+
+An AiiDA plugin package to integrate the [AIMAll](https://aim.tkgristmill.com) software suite. Automate
+workflows integrating Gaussian calculations with AIMAll, or with any computational chemistry software
+that can be run through the command line. Workflows and controllers are provided to enable automation,
+starting with even just a SMILES string to generate geometries using RDKit, then perform
+Gaussian calculations, then AIMAll. Workflows to generate substituent parameters as defined by the authors
+are also provided.
+
+[![ci](https://github.com/kmlefran/aiida-aimall/actions/workflows/ci.yml/badge.svg)](https://github.com/kmlefran/aiida-aimall/actions/workflows/ci.yml)
+[![Coverage Status](https://coveralls.io/repos/github/kmlefran/aiida-aimall/badge.svg?branch=main)](https://coveralls.io/github/kmlefran/aiida-aimall?branch=main)
+[![Documentation Status](https://readthedocs.org/projects/aiida-aimall/badge/?version=latest)](https://aiida-aimall.readthedocs.io/en/latest/?badge=latest)
+[![PyPI version](https://badge.fury.io/py/aiida-aimall.svg)](https://badge.fury.io/py/aiida-aimall)
+
+
+______________________________________________________________________
+
+
+::::{grid} 1 2 2 2
+:gutter: 3
+
+:::{grid-item-card} {fa}`rocket;mr-1` Get started
+:text-align: center
+:shadow: md
+
+Instructions to install, configure and setup the plugin package.
+
++++
+
+```{button-ref} installation/index
+:ref-type: doc
+:click-parent:
+:expand:
+:color: primary
+:outline:
+
+To the installation guides
+```
+:::
+
+:::{grid-item-card} {fa}`info-circle;mr-1` Tutorials
+:text-align: center
+:shadow: md
+
+Easy examples to take the first steps with the plugin package.
+
++++
+
+```{button-ref} tutorials/index
+:ref-type: doc
+:click-parent:
+:expand:
+:color: primary
+:outline:
+
+To the tutorials
+```
+:::
+::::
+
+[aiida]: http://aiida.net
+[aiida-core documentation]: https://aiida.readthedocs.io/projects/aiida-core/en/latest/intro/get_started.html
+[subproptools documentation]: https://subproptools.readthedocs.io/
diff --git a/docs/source/index.rst b/docs/source/index.rst
deleted file mode 100755
index 887ed9d..0000000
--- a/docs/source/index.rst
+++ /dev/null
@@ -1,42 +0,0 @@
-The aiida-aimall plugin for `AiiDA`_
-=====================================================
-
-``aiida-aimall`` is available at http://github.com/kmlefran/aiida-aimall
-
-The documentation is mostly functional, but still a work in progress. Please contact the authors if you have any questions.
-
-.. toctree::
- :maxdepth: 2
-
-
- user_guide/index
- developer_guide/index
- apidoc/aiida_aimall
- AiiDA Documentation
- subproptools Documentation
- group_decomposition Documentation
-
-If you use this plugin for your research, please cite the following work:
-
-.. highlights:: Author Name1, Author Name2, *Paper title*, Jornal Name XXX, YYYY (Year).
-
-If you use AiiDA for your research, please cite the following work:
-
-.. highlights:: Giovanni Pizzi, Andrea Cepellotti, Riccardo Sabatini, Nicola Marzari,
- and Boris Kozinsky, *AiiDA: automated interactive infrastructure and database
- for computational science*, Comp. Mat. Sci 111, 218-230 (2016);
- https://doi.org/10.1016/j.commatsci.2015.09.013; http://www.aiida.net.
-
-``aiida-aimall`` is released under the MIT license.
-
-Please contact kgagnon@lakeheadu.ca for information concerning ``aiida-aimall`` and the `AiiDA mailing list `_ for questions concerning ``aiida``.
-
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
-
-.. _AiiDA: http://www.aiida.net
diff --git a/docs/source/installation/index.md b/docs/source/installation/index.md
new file mode 100644
index 0000000..6e1c049
--- /dev/null
+++ b/docs/source/installation/index.md
@@ -0,0 +1,224 @@
+---
+myst:
+ substitutions:
+ pip: '[`pip`](https://pip.pypa.io/en/stable/index.html)'
+ PyPI: '[PyPI](https://pypi.org/)'
+---
+
+# Get started
+
+(installation-requirements)=
+
+## Requirements
+
+To work with `aiida-aimall`, you should have:
+
+- installed `aiida-core`
+- configured an AiiDA profile.
+
+Please refer to the [documentation](https://aiida.readthedocs.io/projects/aiida-core/en/latest/intro/get_started.html) of `aiida-core` for detailed instructions.
+
+(installation-installation)=
+
+## Installation
+
+The Python package can be installed from the Python Package index {{ PyPI }} or directly from the source:
+
+::::{tab-set}
+
+:::{tab-item} PyPI
+The recommended method of installation is to use the Python package manager {{ pip }}:
+
+```console
+$ pip install aiida-aimall
+```
+
+This will install the latest stable version that was released to {{ PyPI }}.
+:::
+
+:::{tab-item} Source
+To install the package from source, first clone the repository and then install using {{ pip }}:
+
+```console
+$ git clone https://github.com/aiidateam/aiida-quantumespresso
+$ pip install -e aiida-aimall
+```
+
+The ``-e`` flag will install the package in editable mode, meaning that changes to the source code will be automatically picked up.
+:::
+
+::::
+
+
+(installation-setup)=
+
+## Setup
+
+(installation-setup-computer)=
+
+### Computer
+
+To run AIMAll calculations on a compute resource, the computer should first be set up in AiiDA.
+This can be done from the command line interface (CLI) or the Python application programming interface (API).
+In this example, we will set up the `localhost`, the computer where AiiDA itself is running:
+
+::::{tab-set}
+
+:::{tab-item} CLI
+
+To set up a computer, use the ``verdi`` CLI of ``aiida-core``.
+
+```console
+$ verdi computer setup -n -L localhost -H localhost -T core.local -S core.direct -w ~/aiida_work_dir
+```
+
+After creating the localhost computer, configure the `core.local` transport using:
+
+```console
+$ verdi computer configure core.local localhost -n --safe-interval 0
+```
+
+Verify that the computer was properly setup by running:
+
+```console
+$ verdi computer test localhost
+```
+:::
+
+:::{tab-item} API
+
+To setup a computer using the Python API, run the following code in a Python script with `verdi run` or in the `verdi` shell:
+
+```python
+from aiida.orm import Computer
+from pathlib import Path
+
+computer = Computer(
+ label='localhost',
+ hostname='localhost',
+ transport_type='core.local',
+ scheduler_type='core.direct',
+ workdir=Path('~/aiida_work_dir').resolve()
+).store()
+computer.configure()
+```
+:::
+::::
+
+For more detailed information, please refer to the documentation [on setting up compute resources](https://aiida.readthedocs.io/projects/aiida-core/en/latest/howto/run_codes.html#how-to-set-up-a-computer).
+
+(installation-setup-code)=
+
+### Code
+
+To run an AIMAll code, it should first be setup in AiiDA.
+This can be done from the command line interface (CLI) or the Python application programming interface (API).
+In this example, we will setup the `aimqb` code that is installed on the computer where AiiDA is running:
+
+::::{tab-set}
+
+:::{tab-item} CLI
+
+To setup a particular AIMAll code, use the ``verdi`` CLI of ``aiida-core``.
+
+```console
+$ verdi code create core.code.installed -n --computer localhost --label aimall --default-calc-job-plugin aimall.aimqb --filepath-executable aimqb
+```
+:::
+
+:::{tab-item} API
+
+To setup particular AIMAll code using the Python API, run the following code in a Python script with `verdi run` or in the `verdi` shell:
+
+```python
+from aiida.orm import InstalledCode
+
+computer = load_computer('localhost')
+code = InstalledCode(
+label='aimall',
+computer=computer,
+filepath_executable='aimqb',
+default_calc_job_plugin='aimall.aimqb',
+).store()
+```
+:::
+
+::::
+
+:::{important}
+Using the commands above, you will set up a code that uses the first `aimqb` binary your `PATH`.
+You can find out the absolute path to this binary using the `which` command:
+
+```console
+which aimall
+```
+
+If this is not the AIMQB version you want to run, pass the correct absolute path as the filepath executable.
+:::
+
+`aiida-aimall` also provides workflows to automatically interface with electronic structure programs. Many workflows, by default, interface with [Gaussian Software](https://gaussian.com). To use Gaussian software in these workflows,
+AiiDA code instance must also be setup for Gaussian Software, following similar steps to the above setup of AIMAll software.
+
+::::{tab-set}
+
+:::{tab-item} CLI
+
+To setup a particular Gaussian code, use the ``verdi`` CLI of ``aiida-core``.
+
+```console
+$ verdi code create core.code.installed -n --computer localhost --label gaussian --default-calc-job-plugin aimall.gaussianwfx --filepath-executable g16
+```
+:::
+
+:::{tab-item} API
+
+To setup particular AIMAll code using the Python API, run the following code in a Python script with `verdi run` or in the `verdi` shell:
+
+```python
+from aiida.orm import InstalledCode
+
+computer = load_computer('localhost')
+code = InstalledCode(
+label='gaussian',
+computer=computer,
+filepath_executable='g16',
+default_calc_job_plugin='aimall.gaussianwfx',
+).store()
+```
+:::
+
+::::
+
+Any electronic structure software that can be run through the command line can be used through workflows that utilise the `aiida-shell` package. For these calculations, either a string label of the command or a `ShellCode` object can be provided. To setup a `ShellCode`, you can also either create that via the command line, or a Python API. An example is given here for [ORCA](https://www.faccts.de/orca/).
+
+::::{tab-set}
+
+:::{tab-item} CLI
+
+To setup a particular ShellCode, (ORCA as an example here) use the ``verdi`` CLI of ``aiida-core``.
+
+```console
+$ verdi code create core.code.installed.shell -n --computer localhost --label orca --default-calc-job-plugin core.shell --filepath-executable orca
+```
+:::
+
+:::{tab-item} API
+
+To setup particular AIMAll code using the Python API, run the following code in a Python script with `verdi run` or in the `verdi` shell:
+
+```python
+from aiida_shell import ShellCode
+
+computer = load_computer('localhost')
+code = ShellCode(
+label='orca',
+computer=computer,
+filepath_executable='orca',
+default_calc_job_plugin='core.shell',
+).store()
+```
+:::
+
+::::
+
+For more detailed information, please refer to the documentation [on setting up codes](https://aiida.readthedocs.io/projects/aiida-core/en/latest/howto/run_codes.html#how-to-setup-a-code).
diff --git a/docs/source/reference/api/auto/aiida_aimall/calculations/index.rst b/docs/source/reference/api/auto/aiida_aimall/calculations/index.rst
new file mode 100644
index 0000000..070109e
--- /dev/null
+++ b/docs/source/reference/api/auto/aiida_aimall/calculations/index.rst
@@ -0,0 +1,238 @@
+:py:mod:`aiida_aimall.calculations`
+===================================
+
+.. py:module:: aiida_aimall.calculations
+
+.. autoapi-nested-parse::
+
+ Calculations provided by aiida_aimall.
+
+ Upon pip install, AimqbCalculation is accessible in AiiDA.calculations plugins
+ Using the 'aimall' entry point, and GaussianWFXCalculation is accessible with the 'gaussianwfx'
+ entry point
+
+
+
+Module Contents
+---------------
+
+Classes
+~~~~~~~
+
+.. autoapisummary::
+
+ aiida_aimall.calculations.AimqbCalculation
+ aiida_aimall.calculations.GaussianWFXCalculation
+
+
+
+
+Attributes
+~~~~~~~~~~
+
+.. autoapisummary::
+
+ aiida_aimall.calculations.AimqbParameters
+
+
+.. py:data:: AimqbParameters
+
+
+
+.. py:class:: AimqbCalculation(*args, **kwargs)
+
+
+ Bases: :py:obj:`aiida.engine.CalcJob`
+
+ AiiDA calculation plugin wrapping the aimqb executable.
+
+ .. attribute:: parameters
+
+ command line parameters for the AimqbCalculation
+
+ :type: AimqbParameters
+
+ .. attribute:: file
+
+ the wfx, wfn, or fchk file to be run
+
+ :type: SinglefileData
+
+ .. attribute:: code
+
+ code of the AIMQB executable
+
+ :type: Code
+
+ .. attribute:: attached_atom_int
+
+ the integer label of the atom in the group that is attached to the rest of the molecule
+
+ :type: Int
+
+ .. attribute:: group_atoms
+
+ integer ids of atoms comprising the group for AimqbGroupParser
+
+ :type: List(Int)
+
+ .. rubric:: Example
+
+ ::
+
+ code = orm.load_code('aimall@localhost')
+ AimqbParameters = DataFactory("aimall.aimqb")
+ aim_params = AimqbParameters(parameter_dict={"naat": 2, "nproc": 2, "atlaprhocps": True})
+ file = SinglefileData("/absolute/path/to/file")
+ # Alternatively, if you have the file as a string, you can build the file with:
+ # file=SinglefileData(io.BytesIO(file_string.encode()))
+ AimqbCalculation = CalculationFactory("aimall.aimqb")
+ builder = AimqbCalculation.get_builder()
+ builder.parameters = aim_params
+ builder.file = file
+ builder.code = code
+ builder.metadata.options.resources = {"num_machines": 1, "num_mpiprocs_per_machine": 2}
+ builder.submit()
+
+ .. note::
+
+ By default, the AimqbBaseParser is used, getting atomic, BCP, and (if applicable) LapRhoCps.
+ You can opt to use the AimqbGroupParser, which also returns the integrated group properties model
+ of a group, as well as the atomic graph descriptor of the group. This is done by providing this to the builder:
+
+ ::
+
+ builder.metadata.options.parser_name = "aimall.group"
+
+ .. py:attribute:: INPUT_FILE
+ :value: 'aiida.wfx'
+
+
+
+ .. py:attribute:: OUTPUT_FILE
+ :value: 'aiida.out'
+
+
+
+ .. py:attribute:: PARENT_FOLDER_NAME
+ :value: 'parent_calc'
+
+
+
+ .. py:attribute:: DEFAULT_PARSER
+ :value: 'aimall.base'
+
+
+
+ .. py:method:: define(spec)
+ :classmethod:
+
+ Define inputs and outputs of the calculation
+
+
+ .. py:method:: prepare_for_submission(folder)
+
+ Create input files.
+
+ :param folder: an `aiida.common.folders.Folder` where the plugin should temporarily
+ place all files needed by the calculation.
+ :return: `aiida.common.datastructures.CalcInfo` instance
+
+
+
+.. py:class:: GaussianWFXCalculation(*args, **kwargs)
+
+
+ Bases: :py:obj:`aiida.engine.CalcJob`
+
+ AiiDA calculation plugin wrapping Gaussian. Adapted from aiida-gaussian
+ https://github.com/nanotech-empa/aiida-gaussian, Copyright (c) 2020 Kristjan Eimre.
+ Additions made to enable providing molecule input as orm.Str,
+ and wfx files are retrieved by default. We further define another input wfxgroup in which you can provide an
+ optional group to store the wfx file in and fragment_label as an optional extra to add on the output.
+
+ Args:
+ structure: StructureData for molecule to be run. Do not provide structure AND structure_str, but provide
+ at least one
+ structure_str: Str for molecule to be run. e.g. orm.Str(H 0.0 0.0 0.0
+ H -1.0 0.0 0.0)
+ Do not provide structure AND structure_str, but provide at least one
+ wfxgroup: Str of a group to add the .wfx files to
+ parameters: required: Dict of Gaussian parameters, same as from aiida-gaussian. Note that the options provided should
+ generate a wfx file. See Example
+ settings: optional, additional input parameters
+ fragment_label: Str, optional: an extra to add to the wfx file node. Involved in the controllers,
+ which check extras
+ parent_calc_folder: RemoteData, optional: the folder of a completed gaussian calculation
+
+ Example:
+ ::
+
+ builder = GaussianCalculation.get_builder()
+ builder.structure_str = orm.Str("H 0.0 0.0 0.0 -1.0 0.0 0.0") # needs newline but docs doesn't like
+ builder.parameters = orm.Dict(dict={
+ 'link0_parameters': {
+ '%chk':'aiida.chk',
+ "%mem": "3200MB", # Currently set to use 8000 MB in .sh files
+ "%nprocshared": 4,
+ },
+ 'functional':'wb97xd',
+ 'basis_set':'aug-cc-pvtz',
+ 'charge': 0,
+ 'multiplicity': 1,
+ 'route_parameters': {'opt': None, 'Output':'WFX'},
+ "input_parameters": {"output.wfx": None},
+ })
+ builder.code = orm.load_code("g16@localhost")
+ builder.metadata.options.resources = {"num_machines": 1, "tot_num_mpiprocs": 4}
+ builder.metadata.options.max_memory_kb = int(6400 * 1.25) * 1024
+ builder.metadata.options.max_wallclock_seconds = 604800
+ submit(builder)
+
+
+
+ .. py:attribute:: INPUT_FILE
+ :value: 'aiida.inp'
+
+
+
+ .. py:attribute:: OUTPUT_FILE
+ :value: 'aiida.out'
+
+
+
+ .. py:attribute:: PARENT_FOLDER_NAME
+ :value: 'parent_calc'
+
+
+
+ .. py:attribute:: DEFAULT_PARSER
+ :value: 'aimall.gaussianwfx'
+
+
+
+ .. py:method:: define(spec)
+ :classmethod:
+
+ Define the process specification, including its inputs, outputs and known exit codes.
+
+ Ports are added to the `metadata` input namespace (inherited from the base Process),
+ and a `code` input Port, a `remote_folder` output Port and retrieved folder output Port
+ are added.
+
+ :param spec: the calculation job process spec to define.
+
+
+ .. py:method:: prepare_for_submission(folder)
+
+ This is the routine to be called when you want to create
+ the input files and related stuff with a plugin.
+
+ :param folder: a aiida.common.folders.Folder subclass where
+ the plugin should put all its files.
+
+
+ .. py:method:: _render_input_string_from_params(parameters, structure_string)
+ :classmethod:
+
+ Generate the Gaussian input file using pymatgen.
diff --git a/docs/source/reference/api/auto/aiida_aimall/controllers/index.rst b/docs/source/reference/api/auto/aiida_aimall/controllers/index.rst
new file mode 100644
index 0000000..39986c6
--- /dev/null
+++ b/docs/source/reference/api/auto/aiida_aimall/controllers/index.rst
@@ -0,0 +1,450 @@
+:py:mod:`aiida_aimall.controllers`
+==================================
+
+.. py:module:: aiida_aimall.controllers
+
+.. autoapi-nested-parse::
+
+ aiida_aimall.controllers
+
+ Subclasses of FromGroupSubmissionController designed to manage local traffic on lab Macs to prevent to many running processes
+
+ Provides controllers for the AimReor WorkChain, AimQBCalculations, and GaussianWFXCalculations
+
+
+
+Module Contents
+---------------
+
+Classes
+~~~~~~~
+
+.. autoapisummary::
+
+ aiida_aimall.controllers.SmilesToGaussianController
+ aiida_aimall.controllers.AimReorSubmissionController
+ aiida_aimall.controllers.AimAllSubmissionController
+ aiida_aimall.controllers.GaussianSubmissionController
+
+
+
+
+Attributes
+~~~~~~~~~~
+
+.. autoapisummary::
+
+ aiida_aimall.controllers.AimqbParameters
+ aiida_aimall.controllers.GaussianCalculation
+ aiida_aimall.controllers.AimqbCalculation
+
+
+.. py:data:: AimqbParameters
+
+
+
+.. py:data:: GaussianCalculation
+
+
+
+.. py:data:: AimqbCalculation
+
+
+
+.. py:class:: SmilesToGaussianController(code_label: str, g16_opt_params: dict, wfxgroup: str, nprocs: int, mem_mb: int, time_s: int, *args, **kwargs)
+
+
+ Bases: :py:obj:`aiida_submission_controller.FromGroupSubmissionController`
+
+ A controller for submitting SmilesToGaussianWorkchain
+
+ :param parent_group_label: the string of a group label which contains various SMILES as orm.Str nodes
+ :param group_label: the string of the group to put the GaussianCalculations in
+ :param max_concurrent: maximum number of concurrent processes.
+ :param code_label: label of code, e.g. gaussian@cedar
+ :param g16_opt_params: Dict of Gaussian parameters to use
+ :param wfxgroup: group in which to store the resulting wfx files
+ :param nprocs: number of processors for gaussian calculation
+ :param mem_mb: amount of memory in MB for Gaussian calculation
+ :param time_s: wallclock time in seconds for Gaussian calculation
+
+ :returns: Controller object, periodically use run_in_batches to submit new results
+
+ .. rubric:: Example
+
+ In a typical use case of controllers, it is beneficial to check for new jobs periodically to submit.
+ Either there may be new members of the parent_group to run, or some of the currently running jobs have run.
+ So once a controller is defined, we can run it in a loop.
+
+ ::
+
+ controller = SmilesToGaussianController(
+ code_label='gaussian@localhost',
+ parent_group_label = 'input_smiles', # Add structures to run to input_smiles group
+ group_label = 'gaussianopt', # Resulting nodes will be in the gaussianopt group
+ max_concurrent = 1,
+ wfxgroup = "opt_wfx"
+ g16_opt_params = Dict(dict={
+ 'link0_parameters': {
+ '%chk':'aiida.chk',
+ "%mem": "4000MB",
+ "%nprocshared": 4,
+ },
+ 'functional':'wb97xd',
+ 'basis_set':'aug-cc-pvtz',
+ 'route_parameters': { 'opt':None, 'freq':None},
+ })
+ )
+
+ while True:
+ #submit Gaussian batches every hour
+ controller.submit_new_batch()
+ time.sleep(3600)
+
+ .. py:attribute:: parent_group_label
+ :type: str
+
+
+
+ .. py:attribute:: group_label
+ :type: str
+
+
+
+ .. py:attribute:: code_label
+ :type: str
+
+
+
+ .. py:attribute:: max_concurrent
+ :type: int
+
+
+
+ .. py:attribute:: g16_opt_params
+ :type: dict
+
+
+
+ .. py:attribute:: wfxgroup
+ :type: str
+
+
+
+ .. py:attribute:: nprocs
+ :type: int
+
+
+
+ .. py:attribute:: mem_mb
+ :type: int
+
+
+
+ .. py:attribute:: time_s
+ :type: int
+
+
+
+ .. py:attribute:: WORKFLOW_ENTRY_POINT
+ :value: 'aimall.smitog16'
+
+
+
+ .. py:method:: get_extra_unique_keys()
+
+ Returns a tuple of extras keys in the order needed
+
+
+ .. py:method:: get_inputs_and_processclass_from_extras(extras_values)
+
+ Constructs input for a GaussianWFXCalculation from extra_values
+
+
+
+.. py:class:: AimReorSubmissionController(code_label: str, reor_group: str, aimparameters, *args, **kwargs)
+
+
+ Bases: :py:obj:`aiida_submission_controller.FromGroupSubmissionController`
+
+ A controller for submitting AIMReor Workchains.
+
+ :param parent_group_label: the string of a group label which contains various structures as orm.Str nodes
+ :param group_label: the string of the group to put the GaussianCalculations in
+ :param max_concurrent: maximum number of concurrent processes.
+ :param code_label: label of code, e.g. gaussian@cedar
+ :param reor_group: group in which to place the reoriented structures.
+ :param aimparameters: dict of parameters for running AimQB, to be converted to AimqbParameters by the controller
+
+ :returns: Controller object, periodically use run_in_batches to submit new results
+
+ .. note::
+
+ A typical use case is using this as a controller on wfx files created by GaussianWFXCalculation. In that case,
+ match the `parent_group_label` here to the `wfxgroup` provided to the GaussianWFXCalculation.
+ In GaussianOptWorkchain, this is `opt_wfx` by default
+
+ .. rubric:: Example
+
+ In a typical use case of controllers, it is beneficial to check for new jobs periodically to submit.
+ Either there may be new members of the parent_group to run, or some of the currently running jobs have run.
+ So once a controller is defined, we can run it in a loop.
+
+ ::
+
+ controller = AimReorSubmissionController(
+ code_label='aimall@localhost',
+ parent_group_label = 'wfx', # Add wfx files to run to group wfx
+ group_label = 'aim',
+ max_concurrent = 1,
+ reor_group = "reor_str"
+ aimparameters = {"naat": 2, "nproc": 2, "atlaprhocps": True}
+ )
+
+ while True:
+ #submit AIM batches every 5 minutes
+ i = i+1
+ controller.submit_new_batch()
+ time.sleep(300)
+
+ .. py:attribute:: parent_group_label
+ :type: str
+
+
+
+ .. py:attribute:: group_label
+ :type: str
+
+
+
+ .. py:attribute:: max_concurrent
+ :type: int
+
+
+
+ .. py:attribute:: code_label
+ :type: str
+
+
+
+ .. py:attribute:: reor_group
+ :type: str
+
+
+
+ .. py:attribute:: aimparameters
+ :type: dict
+
+
+
+ .. py:attribute:: WORKFLOW_ENTRY_POINT
+ :value: 'aimall.aimreor'
+
+
+
+ .. py:method:: get_extra_unique_keys()
+
+ Returns a tuple of extras keys in the order needed
+
+
+ .. py:method:: get_inputs_and_processclass_from_extras(extras_values)
+
+ Constructs input for a AimReor Workchain from extra_values
+
+
+
+.. py:class:: AimAllSubmissionController(code_label: str, aim_parser: str, aimparameters: dict, *args, **kwargs)
+
+
+ Bases: :py:obj:`aiida_submission_controller.FromGroupSubmissionController`
+
+ A controller for submitting AimQB calculations.
+
+ :param parent_group_label: the string of a group label which contains various structures as orm.Str nodes
+ :param group_label: the string of the group to put the GaussianCalculations in
+ :param max_concurrent: maximum number of concurrent processes. Expected behaviour is to set to a large number
+ since we will be submitting to Cedar which will manage
+ :param code_label: label of code, e.g. gaussian@cedar
+ :param aimparameters: dict of parameters for running AimQB, to be converted to AimqbParameters by the controller
+
+ :returns: Controller object, periodically use run_in_batches to submit new results
+
+ .. note::
+
+ A typical use case is using this as a controller on wfx files created by GaussianWFXCalculation. In that case,
+ match the `parent_group_label` here to the `wfxgroup` provided to the GaussianWFXCalculation.
+ In GaussianSubmissionController, this is `reor_wfx`
+
+ .. rubric:: Example
+
+ In a typical use case of controllers, it is beneficial to check for new jobs periodically to submit.
+ Either there may be new members of the parent_group to run, or some of the currently running jobs have run.
+ So once a controller is defined, we can run it in a loop.
+
+ ::
+
+ controller = AimAllSubmissionController(
+ code_label='aimall@localhost',
+ parent_group_label = 'wfx', # Add wfx files to run to group wfx
+ group_label = 'aim_reor',
+ max_concurrent = 1,
+ aim_parser = 'aimqb.group'
+ aimparameters = {"naat": 2, "nproc": 2, "atlaprhocps": True}
+ )
+
+ while True:
+ #submit AIM batches every 5 minutes
+ i = i+1
+ controller.submit_new_batch()
+ time.sleep(300)
+
+ .. py:attribute:: parent_group_label
+ :type: str
+
+
+
+ .. py:attribute:: group_label
+ :type: str
+
+
+
+ .. py:attribute:: max_concurrent
+ :type: int
+
+
+
+ .. py:attribute:: code_label
+ :type: str
+
+
+
+ .. py:attribute:: aim_parser
+ :type: str
+
+
+
+ .. py:attribute:: aimparameters
+ :type: dict
+
+
+
+ .. py:attribute:: CALCULATION_ENTRY_POINT
+ :value: 'aimall.aimqb'
+
+
+
+ .. py:method:: get_extra_unique_keys()
+
+ Returns a tuple of extras keys in the order needed
+
+
+ .. py:method:: get_inputs_and_processclass_from_extras(extras_values)
+
+ Constructs input for a AimQBCalculation from extra_values
+
+
+
+.. py:class:: GaussianSubmissionController(code_label: str, g16_sp_params: dict, wfxgroup: str, *args, **kwargs)
+
+
+ Bases: :py:obj:`aiida_submission_controller.FromGroupSubmissionController`
+
+ A controller for submitting Gaussian calculations.
+
+ :param parent_group_label: the string of a group label which contains various structures as orm.Str nodes
+ :param group_label: the string of the group to put the GaussianCalculations in
+ :param max_concurrent: maximum number of concurrent processes. Expected behaviour is to set to a large number
+ since we will be submitting to Cedar which will manage
+ :param code_label: label of code, e.g. gaussian@cedar
+ :param g16_sp_params: dictionary of parameters to use in gaussian calculation
+
+ :returns: Controller object, periodically use run_in_batches to submit new results
+
+ .. note::
+
+ A typical use case is using this as a controller on Str structures generated by AIMAllReor workchain. These are by
+ default assigned to the `reor_structs` group, so have `parent_group_label` match that
+
+ .. note::
+
+ In overall workchain(fragment->optimize->aim+rotate->single point->aim), this is the single point step.
+ Process continues and finishes in AimAllSubmissionController
+
+ .. rubric:: Example
+
+ In a typical use case of controllers, it is beneficial to check for new jobs periodically to submit.
+ Either there may be new members of the parent_group to run, or some of the currently running jobs have run.
+ So once a controller is defined, we can run it in a loop.
+
+ ::
+
+ controller = GaussianSubmissionController(
+ code_label='gaussian@localhost',
+ parent_group_label = 'struct', # Add structures to run to struct group
+ group_label = 'gaussiansp', # Resulting nodes will be in the gaussiansp group
+ max_concurrent = 1,
+ g16_sp_params = Dict(dict={
+ 'link0_parameters': {
+ '%chk':'aiida.chk',
+ "%mem": "4000MB",
+ "%nprocshared": 4,
+ },
+ 'functional':'wb97xd',
+ 'basis_set':'aug-cc-pvtz',
+ 'charge': 0,
+ 'multiplicity': 1,
+ 'route_parameters': {'nosymmetry':None, 'Output':'WFX'},
+ "input_parameters": {"output.wfx": None},
+ })
+ )
+
+ while True:
+ #submit Gaussian batches every hour
+ controller.submit_new_batch()
+ time.sleep(3600)
+
+ .. py:attribute:: parent_group_label
+ :type: str
+
+
+
+ .. py:attribute:: group_label
+ :type: str
+
+
+
+ .. py:attribute:: max_concurrent
+ :type: int
+
+
+
+ .. py:attribute:: code_label
+ :type: str
+
+
+
+ .. py:attribute:: g16_sp_params
+ :type: dict
+
+
+
+ .. py:attribute:: wfxgroup
+ :type: str
+
+
+
+ .. py:attribute:: CALCULATION_ENTRY_POINT
+ :value: 'aimall.gaussianwfx'
+
+
+
+ .. py:method:: get_extra_unique_keys()
+
+ Returns a tuple of extras keys in the order needed
+
+
+ .. py:method:: get_inputs_and_processclass_from_extras(extras_values)
+
+ Constructs input for a GaussianWFXCalculation from extra_values
+
+ Note: adjust the metadata options later for 6400MB and 7days runtime
diff --git a/docs/source/reference/api/auto/aiida_aimall/data/index.rst b/docs/source/reference/api/auto/aiida_aimall/data/index.rst
new file mode 100644
index 0000000..c3b9588
--- /dev/null
+++ b/docs/source/reference/api/auto/aiida_aimall/data/index.rst
@@ -0,0 +1,87 @@
+:py:mod:`aiida_aimall.data`
+===========================
+
+.. py:module:: aiida_aimall.data
+
+.. autoapi-nested-parse::
+
+ Data types provided by plugin
+
+ Upon pip install, AimqbParameters is accessible in AiiDA.data plugins
+ Using the 'aimall' entry point
+
+
+
+Package Contents
+----------------
+
+Classes
+~~~~~~~
+
+.. autoapisummary::
+
+ aiida_aimall.data.AimqbParameters
+
+
+
+
+Attributes
+~~~~~~~~~~
+
+.. autoapisummary::
+
+ aiida_aimall.data.cmdline_options
+
+
+.. py:data:: cmdline_options
+
+
+
+.. py:class:: AimqbParameters(parameter_dict=None, **kwargs)
+
+
+ Bases: :py:obj:`aiida.orm.Dict`
+
+ Command line options for aimqb.
+
+ This class represents a python dictionary used to
+ pass command line options to the executable.
+ The class takes a dictionary of parameters and validates
+ to ensure the aimqb command line parameters are correct
+
+ .. py:attribute:: schema
+
+
+
+ .. py:method:: validate(parameters_dict)
+
+ Validate command line options.
+
+ Uses the voluptuous package for validation. Find out about allowed keys using::
+
+ print(AimqbParameters).schema.schema
+
+ :param parameters_dict: dictionary with commandline parameters
+ :param type parameters_dict: dict
+ :returns: validated dictionary
+
+
+ .. py:method:: cmdline_params(file_name)
+
+ Synthesize command line parameters.
+
+ e.g. [ '-atlaprhocps=True',...,'-nogui', 'filename']
+
+ :param file_name: Name of wfx/fchk/wfn file
+ :param type file_name: str
+
+
+
+ .. py:method:: __str__()
+
+ String representation of node.
+
+ Append values of dictionary to usual representation. E.g.::
+
+ uuid: b416cbee-24e8-47a8-8c11-6d668770158b (pk: 590)
+ {'atlaprhocps': True}
diff --git a/docs/source/reference/api/auto/aiida_aimall/index.rst b/docs/source/reference/api/auto/aiida_aimall/index.rst
new file mode 100644
index 0000000..fad6edd
--- /dev/null
+++ b/docs/source/reference/api/auto/aiida_aimall/index.rst
@@ -0,0 +1,39 @@
+:py:mod:`aiida_aimall`
+======================
+
+.. py:module:: aiida_aimall
+
+.. autoapi-nested-parse::
+
+ aiida_aimall
+
+ A plugin to interface AIMAll with AiiDA
+
+
+
+Subpackages
+-----------
+.. toctree::
+ :titlesonly:
+ :maxdepth: 3
+
+ data/index.rst
+
+
+Submodules
+----------
+.. toctree::
+ :titlesonly:
+ :maxdepth: 1
+
+ calculations/index.rst
+ controllers/index.rst
+ parsers/index.rst
+ workchains/index.rst
+
+
+Package Contents
+----------------
+
+.. py:data:: __version__
+ :value: '0.7.5'
diff --git a/docs/source/reference/api/auto/aiida_aimall/parsers/index.rst b/docs/source/reference/api/auto/aiida_aimall/parsers/index.rst
new file mode 100644
index 0000000..1103f25
--- /dev/null
+++ b/docs/source/reference/api/auto/aiida_aimall/parsers/index.rst
@@ -0,0 +1,148 @@
+:py:mod:`aiida_aimall.parsers`
+==============================
+
+.. py:module:: aiida_aimall.parsers
+
+.. autoapi-nested-parse::
+
+ Parsers provided by aiida_aimall.
+
+ Register parsers via the "aiida.parsers" entry point in setup.json.
+
+
+
+Module Contents
+---------------
+
+Classes
+~~~~~~~
+
+.. autoapisummary::
+
+ aiida_aimall.parsers.AimqbBaseParser
+ aiida_aimall.parsers.GaussianWFXParser
+ aiida_aimall.parsers.AimqbGroupParser
+
+
+
+
+Attributes
+~~~~~~~~~~
+
+.. autoapisummary::
+
+ aiida_aimall.parsers.AimqbCalculation
+ aiida_aimall.parsers.NUM_RE
+ aiida_aimall.parsers.SinglefileData
+
+
+.. py:data:: AimqbCalculation
+
+
+
+.. py:class:: AimqbBaseParser(node)
+
+
+ Bases: :py:obj:`aiida.parsers.parser.Parser`
+
+ Parser class for parsing output of calculation.
+
+ .. py:method:: parse(**kwargs)
+
+ Parse outputs, store results in database.
+
+ :returns: an exit code, if parsing fails (or nothing if parsing succeeds)
+
+
+ .. py:method:: _parse_ldm(sum_lines)
+
+
+ .. py:method:: _parse_cc_props(atomic_properties)
+
+ Extract VSCC properties from output files
+ :param atomic_properties: dictionary of atomic properties from _parse_atomic_props
+ :param type atomic_properties: dict
+
+
+ .. py:method:: _parse_atomic_props(sum_file_string)
+
+ Extracts atomic properties from .sum file
+
+ :param sum_file_string: lines of .sum output file
+ :param type sum_file_string: str
+
+
+ .. py:method:: _parse_bcp_props(sum_file_string)
+
+ Extracts bcp properties from .sum file
+
+ :param sum_file_string: lines of .sum output file
+ :param type sum_file_string: str
+
+
+
+.. py:data:: NUM_RE
+ :value: '[-+]?(?:[0-9]*[.])?[0-9]+(?:[eE][-+]?\\d+)?'
+
+
+
+.. py:data:: SinglefileData
+
+
+
+.. py:class:: GaussianWFXParser(node: aiida.orm.CalcJobNode)
+
+
+ Bases: :py:obj:`aiida.parsers.parser.Parser`
+
+ Basic AiiDA parser for the output of Gaussian
+
+ Parses default cclib output as 'output_parameters' node and separates final SCF
+ energy as 'energy_ev' and output structure as 'output_structure' (if applicable)
+
+ Adapted from aiida-gaussian https://github.com/nanotech-empa/aiida-gaussian, Copyright (c) 2020 Kristjan Eimre.
+
+
+ .. py:method:: parse(**kwargs)
+
+ Receives in input a dictionary of retrieved nodes. Does all the logic here.
+
+
+ .. py:method:: _parse_log(log_file_string, inputs)
+
+
+ .. py:method:: _parse_electron_numbers(log_file_string)
+
+
+ .. py:method:: _parse_log_cclib(log_file_string)
+
+
+ .. py:method:: _set_output_structure(inputs, property_dict)
+
+
+ .. py:method:: _final_checks_on_log(log_file_string, property_dict, inputs)
+
+
+
+.. py:class:: AimqbGroupParser(node)
+
+
+ Bases: :py:obj:`AimqbBaseParser`
+
+ Parser class for parsing output of calculation.
+
+ .. py:method:: parse(**kwargs)
+
+ Parse outputs, store results in database.
+
+ :returns: an exit code, if parsing fails (or nothing if parsing succeeds)
+
+
+ .. py:method:: _parse_graph_descriptor(out_dict)
+
+ Get atomic, BCP, and VSCC properties of atom 1
+
+
+ .. py:method:: _parse_group_descriptor(atomic_properties, sub_atom_ints)
+
+ Convert atomic properties to group properties given atoms in group to use
diff --git a/docs/source/reference/api/auto/aiida_aimall/workchains/index.rst b/docs/source/reference/api/auto/aiida_aimall/workchains/index.rst
new file mode 100644
index 0000000..9b422b7
--- /dev/null
+++ b/docs/source/reference/api/auto/aiida_aimall/workchains/index.rst
@@ -0,0 +1,306 @@
+:py:mod:`aiida_aimall.workchains`
+=================================
+
+.. py:module:: aiida_aimall.workchains
+
+.. autoapi-nested-parse::
+
+ aiida_aimall.workchains
+ Workchains designed for a workflow starting from a set of cmls, then breaking off into fragment Gaussian Calculations
+ Needs to be run in part with aiida_aimall.controllers to control local traffic on lab Mac
+ Example in the works
+
+ Provided Workchains are
+ MultiFragmentWorkchain, entry point: multifrag
+ G16OptWorkChain, entry point: g16opt
+ AimAllReor WorkChain, entry point: aimreor
+
+
+
+Module Contents
+---------------
+
+Classes
+~~~~~~~
+
+.. autoapisummary::
+
+ aiida_aimall.workchains.QMToAIMWorkchain
+ aiida_aimall.workchains.SmilesToGaussianWorkchain
+ aiida_aimall.workchains.AIMAllReor
+ aiida_aimall.workchains.SubstituentParameterWorkChain
+
+
+
+Functions
+~~~~~~~~~
+
+.. autoapisummary::
+
+ aiida_aimall.workchains.generate_rotated_structure_aiida
+ aiida_aimall.workchains.dict_to_structure
+ aiida_aimall.workchains.calc_multiplicity
+ aiida_aimall.workchains.find_attachment_atoms
+ aiida_aimall.workchains.reorder_molecule
+ aiida_aimall.workchains.get_xyz
+ aiida_aimall.workchains.get_substituent_input
+ aiida_aimall.workchains.parameters_with_cm
+ aiida_aimall.workchains.validate_shell_code
+ aiida_aimall.workchains.validate_file_ext
+
+
+
+Attributes
+~~~~~~~~~~
+
+.. autoapisummary::
+
+ aiida_aimall.workchains.old_stdout
+ aiida_aimall.workchains.GaussianCalculation
+ aiida_aimall.workchains.AimqbParameters
+ aiida_aimall.workchains.AimqbCalculation
+ aiida_aimall.workchains.DictData
+ aiida_aimall.workchains.PDData
+
+
+.. py:data:: old_stdout
+
+
+
+.. py:data:: GaussianCalculation
+
+
+
+.. py:data:: AimqbParameters
+
+
+
+.. py:data:: AimqbCalculation
+
+
+
+.. py:data:: DictData
+
+
+
+.. py:data:: PDData
+
+
+
+.. py:function:: generate_rotated_structure_aiida(FolderData, atom_dict, cc_dict)
+
+ Rotates the fragment to the defined coordinate system
+
+ :param FolderData: aim calculation folder
+ :param atom_dict: AIM atom dict
+ :param cc_dict: AIM cc_dict
+
+
+.. py:function:: dict_to_structure(fragment_dict)
+
+ Generate a string of xyz coordinates for Gaussian input file
+
+ :param fragment_dict:
+ :param type fragment_dict: aiida.orm.nodes.data.dict.Dict
+
+
+.. py:function:: calc_multiplicity(mol)
+
+ Calculate the multiplicity of a molecule as 2S +1
+
+
+.. py:function:: find_attachment_atoms(mol)
+
+ Given molecule object, find the atoms corresponding to a * and the atom to which that is bound
+
+ :param mol: rdkit molecule object
+
+ :returns: molecule with added hydrogens, the * atom object, and the atom object to which that is attached
+
+ .. note:: Assumes that only one * is present in the molecule
+
+
+.. py:function:: reorder_molecule(h_mol_rw, zero_at, attached_atom)
+
+ Reindexes the atoms in a molecule, setting attached_atom to index 0, and zero_at to index 1
+
+ :param h_mol_rw: RWMol rdkit object with explicit hydrogens
+ :param zero_at: the placeholder * atom
+ :param attached_atom: the atom bonded to *
+
+ :returns: molecule with reordered indices
+
+
+.. py:function:: get_xyz(reorder_mol)
+
+ MMFF optimize the molecule to generate xyz coordiantes
+
+
+.. py:function:: get_substituent_input(smiles: str) -> dict
+
+ For a given smiles, determine xyz structure, charge, and multiplicity
+
+ :param smiles: SMILEs of substituent to run
+
+ :returns: Dict with keys xyz, charge, multiplicity
+
+
+.. py:function:: parameters_with_cm(parameters, smiles_dict)
+
+ Add charge and multiplicity keys to Gaussian Input
+
+
+.. py:function:: validate_shell_code(node, _)
+
+ Validate the shell code, ensuring that it is ShellCode or Str
+
+
+.. py:function:: validate_file_ext(node, _)
+
+ Validates that the file extension provided for AIM is wfx, wfn or fchk
+
+
+.. py:class:: QMToAIMWorkchain(inputs: dict | None = None, logger: logging.Logger | None = None, runner: aiida.engine.runners.Runner | None = None, enable_persistence: bool = True)
+
+
+ Bases: :py:obj:`aiida.engine.WorkChain`
+
+ Workchain to link quantum chemistry jobs without plugins to AIMAll
+
+ .. py:method:: define(spec)
+ :classmethod:
+
+ Define the specification of the process, including its inputs, outputs and known exit codes.
+
+ A `metadata` input namespace is defined, with optional ports that are not stored in the database.
+
+
+
+ .. py:method:: shell_job()
+
+ Launch a shell job
+
+
+ .. py:method:: aim()
+
+ Launch an AIMQB calculation
+
+
+ .. py:method:: result()
+
+ Put results in output node
+
+
+
+.. py:class:: SmilesToGaussianWorkchain(inputs: dict | None = None, logger: logging.Logger | None = None, runner: aiida.engine.runners.Runner | None = None, enable_persistence: bool = True)
+
+
+ Bases: :py:obj:`aiida.engine.WorkChain`
+
+ Workchain to take a SMILES, generate xyz, charge, and multiplicity
+
+ .. py:method:: define(spec)
+ :classmethod:
+
+ Define the specification of the process, including its inputs, outputs and known exit codes.
+
+ A `metadata` input namespace is defined, with optional ports that are not stored in the database.
+
+
+
+ .. py:method:: get_substituent_inputs_step()
+
+ Given list of substituents and previously done smiles, get input
+
+
+ .. py:method:: update_parameters_with_cm()
+
+ Update provided Gaussian parameters with charge and multiplicity of substituent
+
+
+ .. py:method:: submit_gaussian()
+
+ Submits the gaussian calculation
+
+
+ .. py:method:: results()
+
+ Store our relevant information as output
+
+
+
+.. py:class:: AIMAllReor(inputs: dict | None = None, logger: logging.Logger | None = None, runner: aiida.engine.runners.Runner | None = None, enable_persistence: bool = True)
+
+
+ Bases: :py:obj:`aiida.engine.WorkChain`
+
+ Workchain to run AIM and then reorient the molecule using the results
+
+ Process continues in GaussianSubmissionController
+
+ .. py:method:: define(spec)
+ :classmethod:
+
+ Define the specification of the process, including its inputs, outputs and known exit codes.
+
+ A `metadata` input namespace is defined, with optional ports that are not stored in the database.
+
+
+
+ .. py:method:: aimall()
+
+ submit the aimall calculation
+
+
+ .. py:method:: rotate()
+
+ perform the rotation
+
+
+ .. py:method:: dict_to_struct_reor()
+
+ generate the gaussian input from rotated structure
+
+
+ .. py:method:: result()
+
+ Parse results
+
+
+
+.. py:class:: SubstituentParameterWorkChain(inputs: dict | None = None, logger: logging.Logger | None = None, runner: aiida.engine.runners.Runner | None = None, enable_persistence: bool = True)
+
+
+ Bases: :py:obj:`aiida.engine.WorkChain`
+
+ A workchain to perform the full suite of KLG's substituent parameter determining
+
+ .. py:method:: define(spec)
+ :classmethod:
+
+ Define workchain steps
+
+
+ .. py:method:: g16_opt()
+
+ Submit the Gaussian optimization
+
+
+ .. py:method:: aim_reor()
+
+ Submit the Aimqb calculation and reorientation
+
+
+ .. py:method:: g16_sp()
+
+ Run Gaussian Single Point calculation
+
+
+ .. py:method:: aim()
+
+ Run Final AIM Calculation
+
+
+ .. py:method:: result()
+
+ Put results in output node
diff --git a/docs/source/tutorials/aimqbcalculation.ipynb b/docs/source/tutorials/aimqbcalculation.ipynb
new file mode 100644
index 0000000..5c67273
--- /dev/null
+++ b/docs/source/tutorials/aimqbcalculation.ipynb
@@ -0,0 +1,340 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Setting up and running AimqbCalculations"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The simplest use of `aiida-aimall` is in running `AIMQB` calculation jobs. This class can be found in `aiida-aimall.calculations`. Input for these calculations is simple and straightforward. Inputs that are required are\n",
+ " - parameters (`AimqbParameters`)\n",
+ " - file (`SinglefileData`)\n",
+ " - code (`Code`)\n",
+ " - metadata.resources (`dict`)\n",
+ "\n",
+ "There are two other inputs (`group_atoms` and `attached_atom_int`) that are required for using the `AimqbGroupParser` to compute group properties, but are not in use here in the default. Those will be explained in another tutorial.\n",
+ "\n",
+ "The `AimqbParameters` input can be generated following instructions in other tutorials. The `SinglefileData` input can either be created from an absolute path to the file, or by providing the file as a string.\n",
+ "\n",
+ " ```python\n",
+ "from aiida.orm import SinglefileData\n",
+ "import io\n",
+ "\n",
+ "input_file = SinglefileData('/absolute/path/to/file')\n",
+ "\n",
+ "input_file = SinglefileData('io.BytesIO(wfx_file_string.encode())')\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from aiida import load_profile\n",
+ "from aiida.orm import load_node,load_code\n",
+ "from aiida.plugins import DataFactory, CalculationFactory\n",
+ "from aiida.engine import submit\n",
+ "\n",
+ "load_profile()\n",
+ "\n",
+ "# create inputs\n",
+ "AimqbParameters = DataFactory('aimall.aimqb')\n",
+ "AimqbCalculation = CalculationFactory('aimall.aimqb')\n",
+ "\n",
+ "# this is a previously available wfx file node in the AiiDA profile\n",
+ "input_file = load_node('b6710cfe')\n",
+ "aim_code = load_code('aimall@localhost')\n",
+ "aim_input = AimqbParameters({'nproc':2,'naat':2,'atlaprhocps':True})\n",
+ "\n",
+ "# add inputs to the builder\n",
+ "builder = AimqbCalculation.get_builder()\n",
+ "builder.parameters = aim_input\n",
+ "builder.file = input_file\n",
+ "builder.code = aim_code\n",
+ "# tot_num_mpiprocs should match nproc from aim_input\n",
+ "builder.metadata.options.resources = {\"num_machines\": 1, \"tot_num_mpiprocs\": 2}\n",
+ "node = submit(builder)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can view the provenance graph to see what the inputs and outputs of this calculation look like."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from aiida.tools.visualization import Graph\n",
+ "graph = Graph(graph_attr={\"size\": \"6,6!\", \"rankdir\": \"LR\"})\n",
+ "graph.add_incoming(node.uuid,\n",
+ " annotate_links=\"both\")\n",
+ "graph.add_outgoing(node.uuid,\n",
+ " annotate_links=\"both\")\n",
+ "graph.graphviz"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The retrieved node is of type `FolderData`, by default only containing the output .sum file from the AIMQB calculation. The other main output node of interest is the `output_parameters` node. This node is a `Dict` object, with keys for the Localisation-Delocalization matrix of Matta (ldm), atomic properties for all atoms in the molecule (atomic_properties), all bond critical point properties (bcp_properties), and, if `atlaprhocps` was true in `aim_input`, a dictionary containing all valence shell charge concentrations (cc_properties). atomic_properties and cc_properties have keys corresponding to the labels of all atoms in the molecule. bcp_properties keys are all pairs of bonded atoms of format A1-B2 for atoms A1 and B2, for example."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Retrieved node contents\n",
+ "['_scheduler-stderr.txt', '_scheduler-stdout.txt', 'aiida.sum', 'aiida_atomicfiles']\n",
+ "Output dictionary keys\n",
+ "dict_keys(['ldm', 'cc_properties', 'bcp_properties', 'atomic_properties'])\n",
+ "Atomic Property Keys\n",
+ "dict_keys(['C1', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'H2', 'O9', 'H10', 'H11', 'H12', 'H13', 'H14', 'H15', 'H16', 'H17', 'H18'])\n",
+ "BCP Property Keys\n",
+ "dict_keys(['C1-H2', 'C3-C1', 'C3-O9', 'C4-C3', 'C5-C4', 'C6-C5', 'C6-C7', 'C7-C8', 'C8-O9', 'C8-H17', 'C8-H18', 'H10-C1', 'H11-C4', 'H12-C4', 'H13-C5', 'H14-C6', 'H15-C7', 'H16-C7'])\n",
+ "CC Property Keys\n",
+ "dict_keys(['C1', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'H2', 'O9', 'H10', 'H11', 'H12', 'H13', 'H14', 'H15', 'H16', 'H17', 'H18'])\n"
+ ]
+ }
+ ],
+ "source": [
+ "retrieved_node = load_node(114133)\n",
+ "print('Retrieved node contents')\n",
+ "print(retrieved_node.list_object_names())\n",
+ "\n",
+ "\n",
+ "output_node = load_node(114134)\n",
+ "output_dict = output_node.get_dict()\n",
+ "print('Output dictionary keys')\n",
+ "print(output_dict.keys())\n",
+ "print('Atomic Property Keys')\n",
+ "print(output_dict['atomic_properties'].keys())\n",
+ "print('BCP Property Keys')\n",
+ "print(output_dict['bcp_properties'].keys())\n",
+ "print('CC Property Keys')\n",
+ "print(output_dict['cc_properties'].keys())\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Each of these dictionaries of atom labels or atom label pairs are further dictionaries containing the extracted properties of the given type. Using these keys will then give you the requested property."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Extracted Atomic Properties\n",
+ "dict_keys(['K', 'q', 'R+1', 'R+2', 'Vol', 'xyz', 'Mu_X', 'Mu_Y', 'Mu_Z', 'Q_XX', 'Q_XY', 'Q_XZ', 'Q_YY', 'Q_YZ', 'Q_ZZ', '|Mu|', 'K_Scaled', 'Mu_Bond_X', 'Mu_Bond_Y', 'Mu_Bond_Z', '|Mu_Bond|', 'Mu_Intra_X', 'Mu_Intra_Y', 'Mu_Intra_Z', '|Mu_Intra|', 'quadContrib'])\n",
+ "BCP Property Keys\n",
+ "dict_keys(['G', 'H', 'V', 'rho', 'xyz', 'lambda1', 'lambda2', 'lambda3', 'DelSqRho', 'Ellipticity'])\n",
+ "CC Property Keys\n",
+ "dict_keys(['4', '5'])\n"
+ ]
+ }
+ ],
+ "source": [
+ "print('Extracted Atomic Properties')\n",
+ "print(output_dict['atomic_properties']['C1'].keys())\n",
+ "print('BCP Property Keys')\n",
+ "print(output_dict['bcp_properties']['C1-H2'].keys())\n",
+ "print('CC Property Keys')\n",
+ "print(output_dict['cc_properties']['O9'].keys())"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "aiida",
+ "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.12.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/source/tutorials/aimqbgroupcalculation.ipynb b/docs/source/tutorials/aimqbgroupcalculation.ipynb
new file mode 100644
index 0000000..808081c
--- /dev/null
+++ b/docs/source/tutorials/aimqbgroupcalculation.ipynb
@@ -0,0 +1,370 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Using AimqbGroup Parser to Compute Group Properties"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Background"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Properties of functional groups, R, are available to be computed in `aiida-aimall`. The authors have published numerous works calculating these properties. For most properties, group properties are available by simply summing the atomic properties of the atoms in the group. The exception is for quadrupole moments, where the formula from Laidig's 1991 paper is used.\n",
+ "\n",
+ "$$ \\textbf{Q}(R) = \\frac{1}{2}\\sum_{\\Omega\\in R} [ 3( q(\\Omega)\\chi_\\Omega^\\alpha\\chi_\\Omega^\\beta + \\frac{Q_{\\alpha\\beta}(\\Omega)+\\delta_{\\alpha\\beta}\\braket{r^2}_\\Omega}{3} + \\chi_\\Omega^\\beta \\mu^{p,\\alpha}(\\Omega) + \\chi_\\Omega^\\alpha \\mu^{p, \\beta}(\\Omega)) - \\delta_{\\alpha\\beta}(Q_{\\gamma\\gamma}) ]$$"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Further, delocalization indeces between the substituent and the substrate to which is attached are also calculated by summing pairwise delocalization indeces between atoms in the group and those not.\n",
+ "\n",
+ "$$ DI(R,G) = \\sum_{\\Omega\\in R}\\sum_{\\Lambda\\in G} DI(\\Omega,\\Lambda)$$"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The group properties are designed to be calculated in a molecule treated in only two parts - the substituent, R and the substrate, G. All atoms are either assigned to either the substrate or substituent, and the substituent should be connected amongst itself. Inputs for the atoms can be provided to `AimqbCalculation` to enable use of the `AimqbGroupParser`. These are provided as `group_atoms`, a List of atom integer numeric labels corresponding to the atom order in the input file. Further, the atom of the substituent attached to the substrate should be given as `attached_atom_int`. An example is shown here for the methyl substituent attached to a generic substrate G."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "![alt text](images/coordsystem.png \"Title\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Default parameters are provided. By the authors' convention, 1 is the default for the atom in the substituent that is attached to the substrate. Further, the default substrate is assumed to be a single atom, with numeric label 2. Therefore, the default value of `group_atoms` is every atom in the molecule whose label is not 2. If the `group_atoms` and `attached_atom_int` are not provided, these values are used. \n",
+ "\n",
+ "With the definitions in place, computing group properties with `AimqbGroupCalculation` is simple, providing this additional input, and specifying the `AimqbGroupParser`."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Setting Up `AimqbCalculations` with `AimqbGroupParser`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from aiida import load_profile\n",
+ "from aiida.orm import load_code, load_node, List, Int\n",
+ "from aiida.engine import submit\n",
+ "from aiida.plugins import CalculationFactory, DataFactory\n",
+ "\n",
+ "# Define inputs similarly to the base AimqbCalculation tutorial\n",
+ "load_profile()\n",
+ "AimqbParameters = DataFactory('aimall.aimqb')\n",
+ "AimqbCalculation = CalculationFactory('aimall.aimqb')\n",
+ "input_file = load_node('b6710cfe')\n",
+ "aim_code = load_code('aimall@localhost')\n",
+ "aim_input = AimqbParameters({'nproc':2,'naat':2,'atlaprhocps':True})\n",
+ "builder = AimqbCalculation.get_builder()\n",
+ "\n",
+ "builder.parameters = aim_input\n",
+ "builder.file = input_file\n",
+ "builder.code = aim_code\n",
+ "builder.metadata.options.resources = {\"num_machines\": 1, \"tot_num_mpiprocs\": 2}\n",
+ "\n",
+ "# New inputs for the group parser, here there are 18 atoms, and only atom 2 (index 1) is not in the substituent\n",
+ "builder.metadata.options.parser_name = \"aimall.group\"\n",
+ "builder.group_atoms = List([x + 1 for x in range(0, 18) if x != 1])\n",
+ "builder.attached_atom_int = Int(1)\n",
+ "calc_node = submit(builder)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## `AimqbGroupParser` Output"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The provenance graph will have the same structure as that for using the `AimqbBaseParser`. The difference is in the keys of output_parameters."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/svg+xml": [
+ "\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from aiida.tools.visualization import Graph\n",
+ "graph = Graph(graph_attr={\"size\": \"6,6!\", \"rankdir\": \"LR\"})\n",
+ "graph.add_incoming(calc_node.uuid,\n",
+ " annotate_links=\"both\")\n",
+ "graph.add_outgoing(calc_node.uuid,\n",
+ " annotate_links=\"both\")\n",
+ "graph.graphviz"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "dict_keys(['cc_properties', 'bcp_properties', 'graph_descriptor', 'group_descriptor', 'atomic_properties'])\n"
+ ]
+ }
+ ],
+ "source": [
+ "out_dict = load_node(114141).get_dict()\n",
+ "print(out_dict.keys())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Here, we see we have the usual output from before - cc_properties, bcp_properties, atomic_properties. These are identical to the AimqbBaseParser. The group parser additionall provides the graph_descriptor and group_descriptor keys. The graph descriptor focuses on properties of the atom that is attached to the substrate - it collects the atomic properties for that atom, and the CC and BCP properties for all charge concentrations and BCPs associated with it. In this way, the substituent is described by these properties."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "dict_keys(['attached_cc_props', 'attached_bcp_props', 'attached_atomic_props'])"
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "out_dict['graph_descriptor'].keys()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "\n",
+ "The group descriptor focuses on summing the integrated properties as described above. It has similar keys the keys of a given atom in atomic_properties, but summed over the atoms defined in group_atoms in the input."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "dict_keys(['K', 'q', 'Vol', 'Mu_X', 'Mu_Y', 'Mu_Z', 'Q_xx', 'Q_xy', 'Q_xz', 'Q_yy', 'Q_yz', 'Q_zz', '|Mu|', 'K_Scaled', 'Mu_Bond_X', 'Mu_Bond_Y', 'Mu_Bond_Z', '|Mu_Bond|', 'Mu_Intra_X', 'Mu_Intra_Y', 'Mu_Intra_Z', '|Mu_Intra|'])"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "out_dict['group_descriptor'].keys()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "aiida",
+ "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.12.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/source/tutorials/aimqbparameters.ipynb b/docs/source/tutorials/aimqbparameters.ipynb
new file mode 100644
index 0000000..20fe319
--- /dev/null
+++ b/docs/source/tutorials/aimqbparameters.ipynb
@@ -0,0 +1,194 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Creating AimqbParameters data types"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "`aiida-aimall` provides a data class to validate the inputs to `AIMQB`. This is provided throught the `AimqbParameters` from `aiida-aimall.data`. `AimqbParameters` takes a dictionary as input and validates that the keys are valid AIMQB command line input, and that their associated values of the correct datatype. Further, for use in `aiida-aimall` calculations and workflows, the `nogui` option is automatically added.\n",
+ "\n",
+ "## Supported Options\n",
+ "\n",
+ "The list of supported command line options match the documentation on [AIMAll's website](https://aim.tkgristmill.com/manual/aimqb/aimqb.html). For meaning of each option, please refer to the AIMQB manual. The list of supported options is given here. Currently, only the datatype is verified; checks are not in place to ensure that strings are in a set of accepted values, for instance.\n",
+ "\n",
+ "| Command Line | Data Type |\n",
+ "| ----------- | ----------- |\n",
+ "| bim | str |\n",
+ "| iasmesh | str |\n",
+ "| capture | str |\n",
+ "| boaq | str|\n",
+ "| ehren | int|\n",
+ "| feynman | bool | \n",
+ "| iasprops | bool |\n",
+ "| magprops | bool |\n",
+ "|source | bool |\n",
+ "| iaswrite |bool |\n",
+ "| atidsprop | str|\n",
+ "| encomp | int | \n",
+ "|warn | bool |\n",
+ "| scp | str|\n",
+ "|delmog | bool |\n",
+ "| skipint | bool |\n",
+ "| f2w | str | \n",
+ "| f2wonly | bool |\n",
+ "|atoms | str|\n",
+ "|mir | float|\n",
+ "|cpconn | str |\n",
+ "|intveeaa| str |\n",
+ "|atlaprhocps | bool |\n",
+ "|wsp | bool |\n",
+ "| nproc | int |\n",
+ "| naat | int |\n",
+ "|shm_lmax | int|\n",
+ "|maxmem | int |\n",
+ "|verifyw | str|\n",
+ "|saw| bool| \n",
+ "|autonnacps | bool|\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Creating AimqbParameters\n",
+ "\n",
+ "Creating `AimqbParameters` is straightforward, as presented in the following code."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from aiida.plugins import DataFactory\n",
+ "from aiida import load_profile\n",
+ "\n",
+ "load_profile()\n",
+ "AimqbParameters = DataFactory('aimall.aimqb')\n",
+ "\n",
+ "aim_input = AimqbParameters(parameter_dict={'naat': 2,'nproc':4})"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "You can view the command line parameters that an `AimqbCalculation` will synthesize from the generated data using the `cmdline_params` method, passing an example input file name."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['-naat=2', '-nproc=4', '-nogui', 'input_file.wfx']"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "aim_input.cmdline_params('input_file.wfx')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Further you can view the data as a string using the `__str__` method."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "\"uuid: 7fdc4972-c183-403f-98a2-55092e81467b (unstored)\\n{'naat': 2, 'nproc': 4}\""
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "aim_input.__str__()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Passing an incorrect datatype for any given key will result in an error."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "MultipleInvalid",
+ "evalue": "expected int for dictionary value @ data['naat']",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mMultipleInvalid\u001b[0m Traceback (most recent call last)",
+ "Cell \u001b[0;32mIn[9], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m aim_input \u001b[38;5;241m=\u001b[39m \u001b[43mAimqbParameters\u001b[49m\u001b[43m(\u001b[49m\u001b[43mparameter_dict\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m{\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mnaat\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mtwo\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mnproc\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m:\u001b[49m\u001b[38;5;241;43m4\u001b[39;49m\u001b[43m}\u001b[49m\u001b[43m)\u001b[49m\n",
+ "File \u001b[0;32m~/Documents/KLGNotes/PythonPackages/aiida-aimall/src/aiida_aimall/data/__init__.py:68\u001b[0m, in \u001b[0;36mAimqbParameters.__init__\u001b[0;34m(self, parameter_dict, **kwargs)\u001b[0m\n\u001b[1;32m 59\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__init__\u001b[39m(\u001b[38;5;28mself\u001b[39m, parameter_dict\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 60\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Constructor for the data class\u001b[39;00m\n\u001b[1;32m 61\u001b[0m \n\u001b[1;32m 62\u001b[0m \u001b[38;5;124;03m Usage: ``AimqbParameters(parameter_dict{'ignore-case': True})``\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 66\u001b[0m \n\u001b[1;32m 67\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 68\u001b[0m parameter_dict \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvalidate\u001b[49m\u001b[43m(\u001b[49m\u001b[43mparameter_dict\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 69\u001b[0m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39m\u001b[38;5;21m__init__\u001b[39m(\u001b[38;5;28mdict\u001b[39m\u001b[38;5;241m=\u001b[39mparameter_dict, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n",
+ "File \u001b[0;32m~/Documents/KLGNotes/PythonPackages/aiida-aimall/src/aiida_aimall/data/__init__.py:82\u001b[0m, in \u001b[0;36mAimqbParameters.validate\u001b[0;34m(self, parameters_dict)\u001b[0m\n\u001b[1;32m 71\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mvalidate\u001b[39m(\u001b[38;5;28mself\u001b[39m, parameters_dict):\n\u001b[1;32m 72\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Validate command line options.\u001b[39;00m\n\u001b[1;32m 73\u001b[0m \n\u001b[1;32m 74\u001b[0m \u001b[38;5;124;03m Uses the voluptuous package for validation. Find out about allowed keys using::\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 80\u001b[0m \u001b[38;5;124;03m :returns: validated dictionary\u001b[39;00m\n\u001b[1;32m 81\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 82\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mAimqbParameters\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mschema\u001b[49m\u001b[43m(\u001b[49m\u001b[43mparameters_dict\u001b[49m\u001b[43m)\u001b[49m\n",
+ "File \u001b[0;32m~/anaconda3/envs/aiida/lib/python3.12/site-packages/voluptuous/schema_builder.py:281\u001b[0m, in \u001b[0;36mSchema.__call__\u001b[0;34m(self, data)\u001b[0m\n\u001b[1;32m 279\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Validate data against this schema.\"\"\"\u001b[39;00m\n\u001b[1;32m 280\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 281\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_compiled\u001b[49m\u001b[43m(\u001b[49m\u001b[43m[\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 282\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m er\u001b[38;5;241m.\u001b[39mMultipleInvalid:\n\u001b[1;32m 283\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m\n",
+ "File \u001b[0;32m~/anaconda3/envs/aiida/lib/python3.12/site-packages/voluptuous/schema_builder.py:625\u001b[0m, in \u001b[0;36mSchema._compile_dict..validate_dict\u001b[0;34m(path, data)\u001b[0m\n\u001b[1;32m 622\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m er\u001b[38;5;241m.\u001b[39mMultipleInvalid(errors)\n\u001b[1;32m 624\u001b[0m out \u001b[38;5;241m=\u001b[39m data\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m()\n\u001b[0;32m--> 625\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mbase_validate\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mitems\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mout\u001b[49m\u001b[43m)\u001b[49m\n",
+ "File \u001b[0;32m~/anaconda3/envs/aiida/lib/python3.12/site-packages/voluptuous/schema_builder.py:458\u001b[0m, in \u001b[0;36mSchema._compile_mapping..validate_mapping\u001b[0;34m(path, iterable, out)\u001b[0m\n\u001b[1;32m 456\u001b[0m errors\u001b[38;5;241m.\u001b[39mappend(er\u001b[38;5;241m.\u001b[39mRequiredFieldInvalid(msg, path \u001b[38;5;241m+\u001b[39m [key]))\n\u001b[1;32m 457\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m errors:\n\u001b[0;32m--> 458\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m er\u001b[38;5;241m.\u001b[39mMultipleInvalid(errors)\n\u001b[1;32m 460\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m out\n",
+ "\u001b[0;31mMultipleInvalid\u001b[0m: expected int for dictionary value @ data['naat']"
+ ]
+ }
+ ],
+ "source": [
+ "aim_input = AimqbParameters(parameter_dict={'naat': 'two','nproc':4})"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "aiida",
+ "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.12.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/source/tutorials/aimtogaussian.ipynb b/docs/source/tutorials/aimtogaussian.ipynb
new file mode 100644
index 0000000..21fa0ce
--- /dev/null
+++ b/docs/source/tutorials/aimtogaussian.ipynb
@@ -0,0 +1,56 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Workflow to automate passing wavefunction files to AimqbCalculation"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "this is workbook 2\n"
+ ]
+ }
+ ],
+ "source": [
+ "print('this is workbook 2')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "aiida",
+ "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.12.3"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/docs/source/tutorials/images/coordsystem.png b/docs/source/tutorials/images/coordsystem.png
new file mode 100644
index 0000000..1ef938a
Binary files /dev/null and b/docs/source/tutorials/images/coordsystem.png differ
diff --git a/docs/source/tutorials/index.md b/docs/source/tutorials/index.md
new file mode 100644
index 0000000..c6c1b33
--- /dev/null
+++ b/docs/source/tutorials/index.md
@@ -0,0 +1,95 @@
+(tutorials)=
+
+# Tutorials
+
+`aiida-aimall` provides numerous `CalcFunctions`, `WorkChain`s, `FromGroupSubmissionController`s. Explore the documents below to learn how to use the numerous features provided.
+
+```{toctree}
+:hidden: true
+:maxdepth: 1
+
+aimqbparameters.ipynb
+aimqbcalculation.ipynb
+aimqbgroupcalculation.ipynb
+aimtogaussian.ipynb
+
+```
+::::{grid} 2
+:gutter: 3
+
+:::{grid-item-card} {fa}`rocket;mr-1` `AimqbParameters`
+:text-align: center
+:shadow: md
+
+Instructions to create the `AimqbParameters` datatype used throughout `aiida-aimall`
+
++++
+
+```{button-ref} aimqbparameters
+:ref-type: doc
+:click-parent:
+:expand:
+:color: primary
+:outline:
+```
+
+:::
+
+:::{grid-item-card} {fa}`rocket;mr-1` `AimqbCalculation`
+:text-align: center
+:shadow: md
+
+Instructions to setup, launch, and analyze the results of the `AimqbCalculation` `CalcJob` class.
+
++++
+
+```{button-ref} aimqbcalculation
+:ref-type: doc
+:click-parent:
+:expand:
+:color: primary
+:outline:
+```
+
+:::
+
+::::
+
+
+::::{grid} 2
+:gutter: 3
+
+:::{grid-item-card} {fa}`info-circle;mr-1` `Group Properties`
+:text-align: center
+:shadow: md
+
+Using `aiida-aimall` to compute group properties.
+
++++
+
+```{button-ref} aimqbgroupcalculation
+:ref-type: doc
+:click-parent:
+:expand:
+:color: primary
+:outline:
+```
+:::
+
+:::{grid-item-card} {fa}`info-circle;mr-1` Workflow
+:text-align: center
+:shadow: md
+
+The simplest workflow, linking a electronic structure software and AIMQB
+
++++
+
+```{button-ref} aimtogaussian
+:ref-type: doc
+:click-parent:
+:expand:
+:color: primary
+:outline:
+```
+:::
+::::
diff --git a/docs/source/user_guide/get_started.rst b/docs/source/user_guide/get_started.rst
deleted file mode 100644
index 1230c3a..0000000
--- a/docs/source/user_guide/get_started.rst
+++ /dev/null
@@ -1,263 +0,0 @@
-===============
-Getting started
-===============
-
-This guide was written for my group, but still including in docs for now - maybe you will find it useful. Near complete AiiDA setup and instructions.
-
-Installation
-++++++++++++
-
-These steps will guide you through the complete setup of AiiDA on Apple M1, OS Ventura 13.5.1. The steps are adapted from AiidaSetup_
-
-Step 1: Install Brew
---------------------
-Run the following in terminal to install homebrew::
-
- cd /opt/
- mkdir homebrew && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C homebrew
- eval "$(homebrew/bin/brew shellenv)"
- brew update --force --quiet
- chmod -R go-w "$(brew --prefix)/share/zsh"
-
-Make sure your conda environments appear in your path before /opt/bin. That is, in your .bash_profile/.zshrc make sure that the line adding opt/bin to path is before adding conda to path
-
-This may not be necessary generally, but I came across a case where it did. Caused by playing around with different python installations
-
-Step 2: Install Docker
-----------------------
-Using brew, install Docker::
-
- brew install --cask docker
-
-Run the app and do first time setup. Ensure it is running by seeing the whale in the top right. Make sure to launch this again on reboots
-
-Step 3: Install RabbitMQ with AiiDA compatible version
-------------------------------------------------------
-Run the following to setup rabbitmq with an AiiDA compatible version::
-
- brew install rabbitmq git python
- docker run --detach --hostname aiida-rabbitmq --name aiida-rabbitmq-server --restart=unless-stopped --publish=127.0.0.1:5671:5671 --publish=127.0.0.1:5672:5672 --mount=type=volume,src=rabbitmq-volume,dst=/var/lib/rabbitmq rabbitmq:3.7.28
- brew services start rabbitmq
-
-This should now start at launch.
-
-Step 4: Install graphviz
-------------------------
-This is for generating provenance graphs, we need graphviz on the system::
-
- brew install graphviz
-
-Step 5: Download and setup PostGresSQL
---------------------------------------
-Download PostGresSQL_
-
-Launch the app and click initialize
-
-In Terminal::
-
- sudo mkdir -p /etc/paths.d && echo /Applications/Postgres.app/Contents/Versions/latest/bin | sudo tee /etc/paths.d/postgresapp
-
-Should now be set up and running in the background. Note the elephant in the top right. Note that on reboots you should make sure you start this back up for AiiDA
-
-Step 6: install AiiDA
----------------------
-This assumes that conda is installed already. Conda_::
-
- conda create -n aiida-env python
- conda activate aiida-env
- pip install aiida-core
-
-Step 7: Setup profile
----------------------
-::
-
- verdi quicksetup
- verdi profile setdefault
-
-You will be prompted in the quicksetup command, answer as suits you for profile name etc
-
-Note that in the second line, should be whatever you set in the prompts for verdi quicksetup.
-
-Step 8: Launch Daemons and Verify
----------------------------------
-::
-
- verdi daemon start 2 #rerun every reboot
- verdi status
-
-Should result in all processes working
-
-Step 9: Install aiida-aimall
-----------------------------
-
-Note that first hdf5 headers need to be installed for the tables dependency of aiida dataframe, which can be installed using conda
-::
-
- conda install h5py
- pip install aiida-aimall
- #verify that entry points are registered
- verdi plugin list aiida.calculations # should show aimall.aimqb and aimall.gaussianwfx
- verdi plugin list aiida.parsers # should show aimall.base,aimall.group and aimall.gaussianwfx
- verdi plugin list aiida.data # should show aimall.aimqb
- verdi plugin list aiida.workflows # should show aimall.multifrag, aimall.aimreor, aimall.optaimreor, and aimall.g16opt
-
-Step 10: Computer Setup
------------------------
-You'll likely need to setup at least two computers: localhost(your desktop) and the remote cluster you are submitting to. To do this, it is easiest to use a .yml file.
-
-First though, you need to ensure that you have an ssh key setup for the remote cluster. That is if you ssh username@cluster.computecanada.ca, you don't need to enter your password. Follow sshSetup_
-
-Back to configuring the computer, here is an example yml file for the remote cluster cedar:
-::
-
- label: "cedar"
- hostname: "cedar.computecanada.ca"
- transport: "core.ssh"
- scheduler: "core.slurm"
- work_dir: "/home/kgagnon/project/kgagnon/aiida"
- mpirun_command: "mpirun -np {tot_num_mpiprocs}"
- mpiprocs_per_machine: "4"
- description: "Cedar computer"
- default_memory_per_machine: "6553600"
- prepend_text: ""
- append_text: ""
- shebang: "#!/bin/bash"
-
-In the directory that this cedar.yml is in, run::
-
- verdi computer setup --config cedar.yml
-
-You will be prompted asking if you want to escape commands in double quotes. Type "N". This should bring you back to the command line. You then need to configure the computer. Now run::
-
- verdi -p your_aiida_profile computer configure core.ssh cedar
-
-
-
-For username, enter your DRAC username. (e.g. kgagnon)
-Use the defaults for the rest as you are prompted. Defaults on Y/n options are shown in capitals. The full list here is:
-
-::
-
- User name [chemlab]: kgagnon
- Port number [22]:
- Look for keys [Y/n]: Y
- SSH key file []:
- Connection timeout in s [60]:
- Allow ssh agent [Y/n]: Y
- SSH proxy jump []:
- SSH proxy command []:
- Compress file transfers [Y/n]: Y
- GSS auth [False]:
- GSS kex [False]:
- GSS deleg_creds [False]:
- GSS host [cedar.computecanada.ca]:
- Load system host keys [Y/n]: Y
- Key policy (RejectPolicy, WarningPolicy, AutoAddPolicy) [RejectPolicy]:
- Use login shell when executing command [Y/n]: Y
- Connection cooldown time (s) [30.0]:
-
-Now, test to make sure that the computer workflows::
-
- verdi computer test cedar
-
-Should return all passes
-
-You need to do similar steps for the localhost computer. yml file. Here is the yml for localhost
-
-::
-
- hostname: "localhost"
- transport: "core.local"
- scheduler: "core.direct"
- work_dir: "/Users/chemlab/.aiida_run"
- mpirun_command: "mpirun -np {tot_num_mpiprocs}"
- mpiprocs_per_machine: "4"
- description: "localhost computer"
- prepend_text: ""
- append_text: ""
- shebang: "#!/bin/bash"
-
-Still use N for escaping command line arguments
-
-You need to configure and test it again, similar to before but with less prompts
-
-::
-
- verdi -p your_aiida_profile computer configure core.local localhost
-
- Use login shell when executing command [Y/n]: n
- Connection cooldown time (s) [0.0]:
-
- verdi computer test localhost
-
-Should return passes
-
-If you are having issues with using the yml files (in this step and Step 11), simply use the below instead, entering the information that is in the .yml file. Remember to still configure the computer matching previous prompt::
-
- verdi computer setup
- verdi code setup
-
-Step 11: Setup Code plugins
----------------------------
-Again, use .yml files like those shown here:
-
-e.g. for AIMAll:
-::
-
- label: 'aimall'
- description: 'aimall'
- default_calc_job_plugin: 'aimall'
- filepath_executable: '/Applications/AIMAll/AIMQB.app/Contents/MacOS/aimqb'
- computer: 'localhost'
- prepend_text: ' '
- append_text: ' '
-
-e.g. for gaussian::
-
- label: 'gaussian'
- description: 'gaussian'
- default_calc_job_plugin: 'gaussianwfx'
- filepath_executable: '/opt/software/gaussian/g16.c01/g16'
- computer: 'cedar'
- prepend_text: 'module load gaussian/g16.c01'
- append_text: ' '
-
-For both, run (changing yml file name)
-::
-
- verdi code create core.code.installed --config aimall.yml
-
-And N for double quotes again
-
-And with that, AiiDA should be all setup!
-
-
-
-Basic Usage
-+++++++++++
-
-aiida-aimall provides a Data class that validates the parameters you are supplying to AIMAll. You can create such a data type as follows, referring to the list of command line parameters set out in aimqbCMDLine_:
-::
-
- AimqbParameters = DataFactory('aimall.aimqb')
- aim_params = AimqbParameters(parameter_dict={"naat": 2, "nproc": 2, "atlaprhocps": True})
-
-Having created the parameters for the progra, we provide those parameters and a SinglefileData of a AIMQB input file (.fchk, .wfn, .wfx) to AimqbCalculation.
-::
-
- AimqbCalculation = CalculationFactory('aimall.aimqb')
- builder = AimqbCalculation.get_builder()
- builder.parameters = aim_params
- builder.code = orm.load_code('aimall@localhost')
- builder.file = SinglefileData('/absolute/path/to/file')
- # Alternatively, if you have file stored as a string:
- # builder.file = SinglefileData(io.BytesIO(wfx_file_string.encode()))
- submit(builder)
-
-
-
-.. _AiidaSetup: https://aiida.readthedocs.io/projects/aiida-core/en/latest/intro/install_conda.html#intro-get-started-conda-install
-.. _PostGresSQl: https://postgresapp.com/
-.. _Conda: https://docs.conda.io/en/latest/
-.. _sshSetup: https://docs.alliancecan.ca/wiki/SSH_Keys
-.. _aimqbCMDLine: https://aim.tkgristmill.com/manual/aimqb/aimqb.html#AIMQBCommandLine
diff --git a/docs/source/user_guide/index.rst b/docs/source/user_guide/index.rst
deleted file mode 100644
index 7a62c39..0000000
--- a/docs/source/user_guide/index.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-==========
-User guide
-==========
-
-.. toctree::
- :maxdepth: 3
-
- get_started
- tutorial
- query
diff --git a/docs/source/user_guide/query.rst b/docs/source/user_guide/query.rst
deleted file mode 100644
index dbc9276..0000000
--- a/docs/source/user_guide/query.rst
+++ /dev/null
@@ -1,25 +0,0 @@
-====================
-Querying for Results
-====================
-
-The following query will find the outputs of the AimqbCalculation on the reoriented structure, assuming that the AimqbCalculations are placed in the group "aim_reor".
-Queries are built one step at a time. So, here, we find the group, then we find AimqbCalculations in the group, then we find the Dict outputs of the group, which are the outputs of the parser chosen in the AimqbCalculation:"aimall.base" or "aimall.group".
-::
-
- query = QueryBuilder()
- query.append(
- Group,
- filters={
- 'label': 'aim_reor'
- },
- tag='group'
- )
- query.append(
- AimqbCalculation,
- tag = 'calculation',
- with_group = 'group'
- )
- query.append(
- Dict,
- with_incoming = 'calculation'
- )
diff --git a/docs/source/user_guide/tutorial.rst b/docs/source/user_guide/tutorial.rst
deleted file mode 100644
index 9bb0db2..0000000
--- a/docs/source/user_guide/tutorial.rst
+++ /dev/null
@@ -1,104 +0,0 @@
-========
-Tutorial
-========
-
-Basic Usage
-+++++++++++
-
-Create AimqbParameters instance
--------------------------------
-aiida-aimall provides a Data class that validates the parameters you are supplying to AIMAll. You can create such a data type as follows, referring to the list of command line parameters set out in aimqbCMDLine_:
-::
-
- AimqbParameters = DataFactory('aimall.aimqb')
- aim_params = AimqbParameters(parameter_dict={"naat": 2, "nproc": 2, "atlaprhocps": True})
-
-Create and Submit AimqbCalculation
-----------------------------------
-Having created the parameters for the program, we provide those parameters and a SinglefileData of an AIMQB input file (.fchk, .wfn, .wfx) to AimqbCalculation.
-::
-
- AimqbCalculation = CalculationFactory('aimall.aimqb')
- builder = AimqbCalculation.get_builder()
- builder.parameters = aim_params
- builder.file = SinglefileData('/absolute/path/to/file')
- # Alternatively, if you have file stored as a string as some of the workchains do
- # builder.file = SinglefileData(io.BytesIO(wfx_file_string.encode()))
- builder.code = orm.load_code('aimall@localhost')
- builder.metadata.options.resources = {"num_machines": 1, "tot_num_mpiprocs": 2}
- submit(builder)
-
-Using the AimqbGroupParser
---------------------------
-If you wish to extract group properties as defined by the authors, the steps are similar, but an additional option is provided to the builder.
-::
-
- AimqbCalculation = CalculationFactory('aimall.aimqb')
- builder = AimqbCalculation.get_builder()
- builder.parameters = aim_params
- builder.file = SinglefileData('/absolute/path/to/file')
- builder.code = orm.load_code('aimall@localhost')
- builder.metadata.options.resources = {"num_machines": 1, "tot_num_mpiprocs": 2}
- # set the parser to use to aimall.group
- builder.metadata.options.parser_name = "aimall.group"
- builder.group_atoms = List([x + 1 for x in range(0, num_atoms) if x != 1])
- submit(builder)
-
-Workflow Usage
-++++++++++++++
-
-Calculating KLG's AIM properties for a single molecule
-------------------------------------------------------
-Author KLG defines some QTAIM group properties to be used in evaluating properties. This generally involves a multistep
-calculation optimize, aim, reorient, single point, aim. The process can be automated on many files using controllers,
-see "Running on a set of CML files", below. But, a Workchain is presented that you can use to run single molecules as needed
-The code below shows this setup.
-
-::
-
- from aiida_aimall.workchains import SubstituentParameterWorkChain
- from aiida.engine import submit
- from aiida import orm
- from aiida.plugins.factories import DataFactory
- AimqbParameters = DataFactory("aimall.aimqb")
- builder = SubstituentParameterWorkChain.get_builder()
- builder.g16_opt_params=Dict(dict={
- 'link0_parameters': {
- '%chk':'aiida.chk',
- "%mem": "3200MB", # Currently set to use 8000 MB in .sh files
- "%nprocshared": 4,
- },
- 'functional':'wb97xd',
- 'basis_set':'aug-cc-pvtz',
- 'charge': 0,
- 'multiplicity': 1,
- 'route_parameters': {'opt': None, 'Output':'WFX'},
- "input_parameters": {"output.wfx": None},
- })
- builder.g16_sp_params = Dict(dict={
- 'link0_parameters': {
- '%chk':'aiida.chk',
- "%mem": "4000MB",
- "%nprocshared": 4,
- },
- 'functional':'wb97xd',
- 'basis_set':'aug-cc-pvtz',
- 'charge': 0,
- 'multiplicity': 1,
- 'route_parameters': {'nosymmetry':None, 'Output':'WFX'},
- "input_parameters": {"output.wfx": None},
- })
- builder.aim_params = AimqbParameters(parameter_dict = {"naat": 2, "nproc": 2, "atlaprhocps": True})
- builder.structure_str = orm.Str("H 0.0 0.0 0.0\n H -1.0 0.0 0.0") # simple H2 molecule
- builder.g16_code = orm.load_code("gaussian@localhost")
- builder.aim_code = orm.load_code("aimall@localhost")
- submit(builder)
-
-Running on a set SMILES
------------------------
-Coming soon!
-
-.. _aimqbCMDLine: https://aim.tkgristmill.com/manual/aimqb/aimqb.html#AIMQBCommandLine
-
-.. _groupdecomp: https://github.com/kmlefran/group_decomposition
-.. _subproptools: https://github.com/kmlefran/subproptools
diff --git a/pyproject.toml b/pyproject.toml
index 8fa4a7e..606a2e2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -31,11 +31,9 @@ dependencies = [
"aiida-submission-controller",
"pydantic",
"ase",
- "cclib",
- "aiida-dataframe",
+ "cclib @ git+https://github.com/cclib/cclib",
"multiprocess",
"subproptools",
- "group_decomposition",
"pymatgen",
"aiida-shell"
]
@@ -48,22 +46,9 @@ Home = "https://aiida-aimall.readthedocs.io"
[project.optional-dependencies]
testing = [
"pgtest~=1.3.1",
- "pandas<2.2",
- "wheel~=0.31",
- "coverage",
'pytest~=6.0',
"pytest-cov",
'pytest-regressions~=2.3',
- "numpy",
- "aiida-submission-controller",
- "pydantic",
- "ase",
- "sphinx-rtd-theme",
- "cclib",
- "aiida-dataframe",
- "multiprocess",
- "subproptools",
- "pymatgen",
"coveralls"
]
pre-commit = [
@@ -71,23 +56,16 @@ pre-commit = [
"pylint"
]
docs = [
- "aiida-core",
- "pandas<2.2",
"sphinx",
"sphinxcontrib-contentui",
"sphinxcontrib-details-directive",
- "furo",
- "markupsafe<2.1",
- "numpy",
- "aiida-submission-controller",
- "pydantic",
- "ase",
- "sphinx-rtd-theme",
- "cclib",
- "aiida-dataframe",
- "multiprocess",
- "subproptools",
- "group_decomposition"
+ "sphinx-copybutton~=0.5.2",
+ "sphinx-autoapi~=3.0.0",
+ "sphinx-design~=0.4.1",
+ "sphinx-click~=4.4.0",
+ "myst-parser~=1.0.0",
+ "sphinx-book-theme~=1.0.1",
+ 'sphinxcontrib-details-directive~=0.1.0',
]
[project.entry-points."aiida.data"]
@@ -111,6 +89,12 @@ docs = [
[tool.flit.module]
name = "aiida_aimall"
+[tool.flit.sdist]
+exclude = [
+ 'docs/',
+ 'tests/',
+]
+
[tool.pylint.format]
max-line-length = 125
diff --git a/aiida_aimall/__init__.py b/src/aiida_aimall/__init__.py
similarity index 100%
rename from aiida_aimall/__init__.py
rename to src/aiida_aimall/__init__.py
diff --git a/aiida_aimall/calculations.py b/src/aiida_aimall/calculations.py
similarity index 100%
rename from aiida_aimall/calculations.py
rename to src/aiida_aimall/calculations.py
diff --git a/aiida_aimall/controllers.py b/src/aiida_aimall/controllers.py
similarity index 100%
rename from aiida_aimall/controllers.py
rename to src/aiida_aimall/controllers.py
diff --git a/aiida_aimall/data/__init__.py b/src/aiida_aimall/data/__init__.py
similarity index 100%
rename from aiida_aimall/data/__init__.py
rename to src/aiida_aimall/data/__init__.py
diff --git a/aiida_aimall/parsers.py b/src/aiida_aimall/parsers.py
similarity index 100%
rename from aiida_aimall/parsers.py
rename to src/aiida_aimall/parsers.py
diff --git a/aiida_aimall/workchains.py b/src/aiida_aimall/workchains.py
similarity index 100%
rename from aiida_aimall/workchains.py
rename to src/aiida_aimall/workchains.py