diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e572922c..b1ffa939 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -23,7 +23,7 @@ jobs: pip install .[docs,featurizer] - name: Sphinx build run: | - sphinx-build docs/source _build + sphinx-build docs _build - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v3 if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 6576e00f..cdb99064 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -99,4 +99,4 @@ jobs: pip install .[docs,featurizer] - name: Build - run: sphinx-build docs/source docs_build + run: sphinx-build -W docs _build diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a6dcc76..7c977141 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +# Changelog +======= ## v0.3.3 - fixing which_bonds by @JonasGrandel in https://github.com/JaGeo/LobsterPy/pull/168 - fix create inputs alias not working; update test for the same by @naik-aakash in https://github.com/JaGeo/LobsterPy/pull/171 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..bec89392 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,33 @@ +# Contributing to LobsterPy + +We would love your input to further extend and improve our code. Contribution of any kind are welcome, for example it can be: + +- Reporting a bug +- Discussing the current state of the code +- Submitting a fix +- Proposing or implementing new features +- Or simply updating the documentation + +## Reporting bugs, getting help, and discussion + +You can submit questions and bugs to the +[GitHub issues page](https://github.com/JaGeo/LobsterPy/issues). + +When creating a bug report, its best if you include some of the pointers mentioned below: + +- A quick summary and/or background. +- Steps to reproduce - be specific! **Provide sample code.** +- What was expected and what actually happened. +- Screenshots of any errors you encounter. + +## Contributing code improvements or additions through Github + +- Fork the repo and create your branch from master. +- If working using IDE, clone the repo and install the package in development mode `pip install -e lobsterpy[featurizer,dev,tests]` in a separate conda or virtual environment. +- run `pre-commit install` (This will install all the hooks from `.pre-commit-config.yaml` and make adapting your code to match linting standards) +- Commit your improvements to your branch and push to your Github fork (repo). +- Make sure you write tests and update documentation when needed. We use pytest framework and check out our existing tests for inspiration. +- Try to reuse existing test data when possible. +- When you're finished, go to your fork and make a Pull Request (PR). It will + automatically update if you need to make further changes. +- If you have raised a PR but are actively working on it, please add `[WIP] in the title.(This will let us know it is still not ready for review or merged) diff --git a/README.md b/README.md index 7a73a134..55af7f52 100644 --- a/README.md +++ b/README.md @@ -3,63 +3,85 @@ # Getting started LobsterPy Logo which consists of a green Python and a red Lobster -This is a package that enables automatic plotting and summaries of Lobster outputs. You can download Lobster on [http://www.cohp.de](http://www.cohp.de). Currently, only VASP/Lobster computations are supported. +LobsterPy is a package that enables automatic analysis of LOBTSER outputs to get summarized bonding information and relevant bond plots. Additionally, one can also generate features for machine learning studies from LOBSTER outputs. One can download LOBSTER from [http://www.cohp.de](http://www.cohp.de). -Please note that LobsterPy relies on your Lobster outputs. Thus, please make sure that the outputs have enough information for our (automatic) analysis. +
+
+ Important +
+
+ +Recently released [LOBSTER 5.0](https://schmeling.ac.rwth-aachen.de/cohp/index.php?menuID=6) now generates `POSCAR.lobster` for any kind of LOBSTER calculation by default (This file has same format as the POSCAR from VASP). Thus, LobsterPy in principle, now supports usage with **all** DFT codes supported by LOBSTER and is **no** longer limited to `VASP`. Almost all of the core functionalities of LobsterPy could be used. The user must use `POSCAR.lobster` for `path_to_poscar` and `-fstruct` argument in python and cli interface, respectively. + +The only functionality limited to VASP is DOS comparisons and basis set analysis in the `calc_quality_summary` method of the `Analysis` class, as it relies on VASP output files, namely `vasprun.xml` and `POTCAR`. +
+ +Please note that LobsterPy relies on the LOBSTER computation output files. Thus, it will be only able to analyze data that has been computed in the LOBSTER run. ![LobsterPyAnimation](https://github.com/JaGeo/LobsterPy/assets/22094846/8f06b84c-db6d-414c-8590-aa04c957c728) ## Installation +### Standard installation +Install using ``pip install lobsterpy`` -You can now use ``pip install lobsterpy`` to install it. +### Installation with featurizer +Install using ``pip install lobsterpy[featurizer]`` -You can also pip install the package in development mode by writing ``pip install -e .``. It will then use setup.py to install the package. One requirement of this package is [pymatgen](https://github.com/materialsproject/pymatgen). ## Basic usage -* **Automatic analysis and plotting of COHPs:** +* **Automatic analysis and plotting of COHPs / COBIS / COOPs:** Output Automatic Analysis +You can use ``lobsterpy description`` for an automated analysis of COHPs for relevant cation-anion bonds or ``lobsterpy automatic-plot`` to plot the results automatically. +It will evaluate all COHPs with ICOHP values down to 10% of the strongest ICOHP. +You can enforce an analysis of all bonds by using ``lobsterpy automatic-plot --allbonds``. +You can also switch the automatic analysis to use the ICOBIs or ICOOPs. You need to add `--cobis` or `--coops` along with the mentioned commands +for e.g.like ``lobsterpy description --cobis`` + +An interactive plotter is available via ``lobsterpy automatic-plot-ia``. + +Currently, the computed Mulliken charges will be used to determine cations and anions. If no ``CHARGE.lobster`` is available, the algorithm will fall back to the BondValence analysis from pymatgen. - You can use ``lobsterpy description`` for an automated analysis of COHPs for relevant cation-anion bonds or ``lobsterpy automatic-plot`` to plot the results automatically. It will evaluate all COHPs with ICOHP values down to 10% of the strongest ICOHP. You can enforce an analysis of all bonds by using ``lobsterpy automatic-plot --allbonds`` . Currently, the computed Mulliken charges will be used to determine cations and anions. If no ``CHARGE.lobster`` is available, the algorithm will fall back to the BondValence analysis from pymatgen. Please be aware that LobsterPy can only analyze bonds that have been included in the initial Lobster computation. Thus, please use the cohpgenerator within Lobster. We have also added functionality to base the automatic analysis on the COBIs and COOPs. +*Please be aware that LobsterPy can only analyze bonds that have been included in the initial Lobster computation. Thus, please use the cohpgenerator within Lobster.* - An interactive plotter is available via ``lobsterpy automatic-plot-ia``. And you can also plot densities of states from LOBSTER with ``lobsterpy plot-dos``. - It is also possible to start this automatic analysis from a Python script. See "examples" for scripts. +It is also possible to start this automatic analysis from a Python script. See "examples" for scripts. +* **Plotting DOS from LOBSTER computations:** -* **Command line plotter**: + To plot densities of states obtained from LOBSTER use ``lobsterpy plot-dos``. - We included options to plot COHPs/COBIs/COOPs from the command line. - ``lobsterpy plot 1 2`` will plot COHPs of the first and second bond from ``COHPCAR.lobster``. It is possible to sum or integrate the COHPs as well (``--summed``, ``--integrated``). You can switch to COBIs or COOPs by using ``--cobis`` or ``--coops``, respectively. + +* **Generic COHP/ COOP / COBI plotter**: + + We included options to plot COHPs/COBIs/COOPs from the command line. +``lobsterpy plot 1 2`` will plot COHPs of the first and second bond from ``COHPCAR.lobster``. It is possible to sum or integrate the COHPs as well (``--summed``, ``--integrated``). You can switch to COBIs or COOPs by using ``--cobis`` or ``--coops``, respectively. * **Other command line tools**: ``lobsterpy create-inputs`` will create standard inputs based on existing POSCAR, POTCAR, INCAR files. It will allow to test for different basis sets that are available in Lobster. Currently only available for PBE_54 POTCARs. - * **Further help?** - You can get further information by using ``lobsterpy --help`` and also by typing ``lobsterpy description --help``, ``lobsterpy automatic-plot --help``, ``lobsterpy plot --help`` + You can get further information by using ``lobsterpy --help`` and also by typing ``lobsterpy description --help``, +``lobsterpy automatic-plot --help``, ``lobsterpy plot --help``. + +## Comprehensive documentation +* Checkout the [documentation and tutorials](https://jageo.github.io/LobsterPy/) for more details. ## How to cite? Please cite our paper: J. George, G. Petretto, A. Naik, M. Esters, A. J. Jackson, R. Nelson, R. Dronskowski, G.-M. Rignanese, G. Hautier, **ChemPlusChem**, [https://doi.org/10.1002/cplu.202200123](https://doi.org/10.1002/cplu.202200123). Please cite [pymatgen](https://github.com/materialsproject/pymatgen), [Lobster](https://www.cohp.de), and [ChemEnv](https://doi.org/10.1107/S2052520620007994) correctly as well. -## LobsterPy as part of an atomate2 workflow +## LobsterPy is now a part of an atomate2 workflow ![LobsterWorkflow](https://github.com/JaGeo/LobsterPy/assets/22094846/337615ac-542e-446c-bc63-fb5946b16544) We have now also included the automatic analysis into a fully automatic workflow using VASP and Lobster in [atomate2](https://github.com/materialsproject/atomate2). More documentation and information will follow soon. -## Future plans: -* Include orbitals into automatic plotting - -## Contributions -* Contributions and suggestions for features are also welcome. Please write an Issue to describe your potential contribution or feature request. -* We are planning to submit a paper for the code LobsterPy when more features have been added (~ mid of 2023). Major contributors will of course have the chance to be co-authors. Please talk to us if you are interested in contributing :). ## Acknowledgements The development of the program has been supported by a computing time grant. We gratefully acknowledge the Gauss Centre for Supercomputing e.V.(www.gauss-centre.eu) for funding this project by providing computing time on the GCS Supercomputer SuperMUC-NG at Leibniz Supercomputing Centre (www.lrz.de) (project pn73da). diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index d0c3cbf1..00000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/_static/.gitkeep b/docs/_static/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 00000000..e1fad460 --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,128 @@ +/******************************************************************************* +* light theme +* +* all the variables used for light theme coloring +*/ +html[data-theme="light"] { + /***************************************************************************** + * main colors + */ + --pst-color-primary: rgb(82, 165, 171); + --pst-color-secondary: rgb(200, 30, 109); + --pst-color-success: rgb(40, 167, 69); + --pst-color-info: var(--pst-color-primary); + --pst-color-warning: var(--pst-color-secondary); + --pst-color-danger: rgb(220, 53, 69); + --pst-color-text-base: rgb(51, 51, 51); + --pst-color-text-muted: rgb(77, 77, 77); + --pst-color-border: rgb(201, 201, 201); + --pst-color-shadow: rgb(216, 216, 216); + + /***************************************************************************** + * depth colors + * + * background: the more in depth color + * on-background: the object directly set on the background, use of shadows in light theme + * surface: object set on the background (without shadows) + * on_surface: object set on surface object (without shadows) + */ + --pst-color-background: rgb(255, 255, 255); + --pst-color-on-background: rgb(242, 239, 233); + --pst-color-surface: rgb(242, 239, 233); + --pst-color-on-surface: rgb(242, 239, 233); + + /***************************************************************************** + * extentions + */ + + --pst-color-panel-background: var(--pst-color-background); + + /***************************************************************************** + * layout + */ + + // links + --pst-color-link: var(--pst-color-primary); + --pst-color-link-hover: var(--pst-color-secondary); + + // inline code + --pst-color-inline-code: rgb(232, 62, 140); + + // targeted content + --pst-color-target: rgb(251, 229, 78); + + // hide any content that should not be displayed in the light theme + .only-dark { + display: none !important; + } +} + +/******************************************************************************* +* dark theme +* +* all the variables used for dark theme coloring +*/ +html[data-theme="dark"] { + /***************************************************************************** + * main colors + */ + --pst-color-primary: rgb(82, 165, 171); + --pst-color-secondary: rgb(200, 30, 109); + --pst-color-success: rgb(72, 135, 87); + --pst-color-info: var(--pst-color-primary); + --pst-color-warning: var(--pst-color-secondary); + --pst-color-danger: rgb(203, 70, 83); + --pst-color-text-base: rgb(201, 209, 217); + --pst-color-text-muted: rgb(192, 192, 192); + --pst-color-border: rgb(192, 192, 192); + --pst-color-shadow: var(--pst-color-background); + + /***************************************************************************** + * depth colors + * + * background: the more in depth color + * on-background: the object directly set on the background, use of a light grey in dark theme + * surface: object set on the background (without shadows) + * on_surface: object set on surface object (without shadows) + */ + --pst-color-background: rgb(18, 18, 18); + --pst-color-on-background: rgb(30, 30, 30); + --pst-color-surface: rgb(41, 41, 41); + --pst-color-on-surface: rgb(55, 55, 55); + + /***************************************************************************** + * extentions + */ + + --pst-color-panel-background: var(--pst-color-background-up); + + /***************************************************************************** + * layout + */ + + // links + --pst-color-link: var(--pst-color-primary); + --pst-color-link-hover: var(--pst-color-secondary); + + // inline code + --pst-color-inline-code: rgb(221, 158, 194); + + // targeted content + --pst-color-target: rgb(71, 39, 0); + + // hide any content that should not be displayed in the dark theme + .only-light { + display: none !important; + } + + // specific brightness applied on images + img { + filter: brightness(0.8) contrast(1.2); + } +} + + +.bg-light { + background-color:rgba(80, 164, 171, 0.52)!important +} + diff --git a/docs/_static/logo.png b/docs/_static/logo.png new file mode 100644 index 00000000..db104cc1 Binary files /dev/null and b/docs/_static/logo.png differ diff --git a/docs/_templates/autosummary/base.rst b/docs/_templates/autosummary/base.rst new file mode 100644 index 00000000..5536fa10 --- /dev/null +++ b/docs/_templates/autosummary/base.rst @@ -0,0 +1,5 @@ +{{ name | escape | underline}} + +.. currentmodule:: {{ module }} + +.. auto{{ objtype }}:: {{ objname }} diff --git a/docs/_templates/autosummary/class.rst b/docs/_templates/autosummary/class.rst new file mode 100644 index 00000000..df3dbb3a --- /dev/null +++ b/docs/_templates/autosummary/class.rst @@ -0,0 +1,7 @@ +{{ name | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + :show-inheritance: + :members: diff --git a/docs/_templates/autosummary/function.rst b/docs/_templates/autosummary/function.rst new file mode 100644 index 00000000..5ffed09e --- /dev/null +++ b/docs/_templates/autosummary/function.rst @@ -0,0 +1,5 @@ +{{ name | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autofunction:: {{ objname }} diff --git a/docs/_templates/autosummary/module.rst b/docs/_templates/autosummary/module.rst new file mode 100644 index 00000000..3535c8de --- /dev/null +++ b/docs/_templates/autosummary/module.rst @@ -0,0 +1,53 @@ +{% extends "!autosummary/module.rst" %} + +{# This file is almost the same as the default, but adds :toctree: and :nosignatures: to + the autosummary directives. The original can be found at + ``sphinx/ext/autosummary/templates/autosummary/module.rst``. #} + +{% block attributes %} +{% if attributes %} + .. rubric:: Module Attributes + + .. autosummary:: + :toctree: + :nosignatures: + {% for item in attributes %} + {{ item }} + {%- endfor %} +{% endif %} +{% endblock %} + +{% block functions %} +{% if functions %} + .. rubric:: Functions + + .. autosummary:: + :toctree: + :nosignatures: + {% for item in functions %} + {{ item }} + {%- endfor %} +{% endif %} +{% endblock %} + +{% block classes %} + +{% set types = [] %} +{% for item in members %} + {% if not item.startswith('_') and not (item in functions or item in attributes or item in exceptions) %} + {% set _ = types.append(item) %} + {% endif %} +{%- endfor %} + +{% if types %} + .. rubric:: Classes + + .. autosummary:: + :toctree: + :nosignatures: + {% for item in types %} + {{ item }} + {%- endfor %} + +{% endif %} +{% endblock %} diff --git a/docs/about/changelog.md b/docs/about/changelog.md new file mode 100644 index 00000000..3139cd42 --- /dev/null +++ b/docs/about/changelog.md @@ -0,0 +1,2 @@ +```{include} ../../CHANGELOG.md +``` diff --git a/docs/about/license.md b/docs/about/license.md new file mode 100644 index 00000000..b5e808da --- /dev/null +++ b/docs/about/license.md @@ -0,0 +1,32 @@ +License +======= + +BSD 3-Clause License + +Copyright (c) 2021, LobsterPy Development Team +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/docs/source/conf.py b/docs/conf.py similarity index 63% rename from docs/source/conf.py rename to docs/conf.py index adc8e63a..ebbe14a0 100644 --- a/docs/source/conf.py +++ b/docs/conf.py @@ -13,7 +13,7 @@ import os import sys -sys.path.insert(0, os.path.abspath("../")) +sys.path.insert(0, os.path.abspath("../../")) # -- Project information ----------------------------------------------------- @@ -33,16 +33,21 @@ "sphinx.ext.napoleon", "sphinx.ext.autodoc", "sphinx.ext.viewcode", + "sphinx.ext.autosummary", "sphinx.ext.coverage", + "sphinx_toolbox.more_autodoc.autonamedtuple", "sphinxarg.ext", - "m2r2", + "myst_nb", + "sphinx_design", + "sphinx_copybutton", ] -napoleon_include_private_with_doc = True -napoleon_include_special_with_doc = True -autoclass_content = "both" +# napoleon_include_private_with_doc = True +# napoleon_include_special_with_doc = True +# autoclass_content = "both" -source_suffix = [".rst", ".md"] + +source_suffix = [".rst", ".md", ".ipynb"] # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] @@ -52,35 +57,33 @@ # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [ - "../../tests", + "test*.py", + "test", "Thumbs.db", ".DS_Store", ] +myst_heading_anchors = 2 # enable headings as link targets +myst_enable_extensions = [ + "amsmath", + "colon_fence", + "dollarmath", + "html_admonition", + "html_image", +] -def run_apidoc(_): - import subprocess - import glob - - output_path = os.path.abspath(os.path.dirname(__file__)) - excludes = glob.glob(os.path.join(output_path, "../../tests")) - module = os.path.join(output_path, "../../lobsterpy") - cmd_path = "sphinx-apidoc" - command = [ - cmd_path, - "-e", - "-o", - output_path, - module, - " ".join(excludes), - "--force", - ] - subprocess.check_call(command) +nb_execution_timeout = 500 -def setup(app): - app.connect("builder-inited", run_apidoc) +# use type hints +autodoc_typehints = "description" +autoclass_content = "class" +autodoc_member_order = "bysource" +# better napoleon support +napoleon_use_param = True +napoleon_use_rtype = True +napoleon_use_ivar = True # -- Options for HTML output ------------------------------------------------- @@ -88,8 +91,24 @@ def setup(app): # a list of builtin themes. # html_theme = "sphinx_book_theme" +html_logo = "_static/logo.png" + +html_theme_options = { + "repository_provider": "github", + "repository_url": "https://github.com/JaGeo/LobsterPy", + "use_repository_button": True, + "use_issues_button": True, +} + # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] + +html_css_files = ['custom.css'] + +# hide sphinx footer +html_show_sphinx = False +html_show_sourcelink = False +html_title = "lobsterpy" diff --git a/docs/dev/contributing.md b/docs/dev/contributing.md new file mode 100644 index 00000000..ef6daa82 --- /dev/null +++ b/docs/dev/contributing.md @@ -0,0 +1,2 @@ +```{include} ../../CONTRIBUTING.md +``` diff --git a/docs/dev/dev_installation.md b/docs/dev/dev_installation.md new file mode 100644 index 00000000..9146df0a --- /dev/null +++ b/docs/dev/dev_installation.md @@ -0,0 +1,53 @@ +# Developer Installation + +Install Lobsterpy from source, by cloning the repository from [github](https://github.com/JaGeo/LobsterPy.git) + +```bash +git clone https://github.com/JaGeo/LobsterPy.git +cd LobsterPy +pip install -e .[featurizer,docs,tests,dev] +``` +This will install LobsterPy will all dependencies for tests, pre-commit and docs building. + +## Running unit tests + +Unit tests can be run from the source folder using `pytest`. + +```bash +pytest +``` +This will run all the tests. + +To get a detailed report of test coverage you can use following command +```bash +pytest --cov=lobsterpy --cov-report term-missing --cov-append +``` + +If you feel test execution takes too long locally, you can speedup the execution using [pytest-xdist](https://pypi.org/project/pytest-xdist/). Install this in library in your environment using + +```bash +pip install pytest-xdist +``` + +Once installed, you can now use multiple processors to run your tests. For example, if you want to use 8 processors to run tests in parallel, run + +```bash +pytest -n 8 +``` + +We rely on pytest-split to run tests in parallel on github workflow, thus it is necessary to update the test-durations files in the repo, incase you add new tests. To generate this file, use + +```bash +pytest --cov=lobsterpy --cov-append --splits 1 --group 1 --durations-path ./tests/test_data/.pytest-split-durations --store-durations +``` + +## Building the documentation locally + +The atomate2 documentation can be built using the sphinx package. + +The docs can be built to the `_build` directory: + +```bash +sphinx-build -W docs _build +``` + diff --git a/docs/fundamentals/fundamentals_assets/LobsterEnv_schema.png b/docs/fundamentals/fundamentals_assets/LobsterEnv_schema.png new file mode 100755 index 00000000..2ec580ae Binary files /dev/null and b/docs/fundamentals/fundamentals_assets/LobsterEnv_schema.png differ diff --git a/docs/fundamentals/fundamentals_assets/bonding_percentage.png b/docs/fundamentals/fundamentals_assets/bonding_percentage.png new file mode 100644 index 00000000..27ed6106 Binary files /dev/null and b/docs/fundamentals/fundamentals_assets/bonding_percentage.png differ diff --git a/docs/fundamentals/fundamentals_assets/orbital_wise_illustration.png b/docs/fundamentals/fundamentals_assets/orbital_wise_illustration.png new file mode 100644 index 00000000..f188542f Binary files /dev/null and b/docs/fundamentals/fundamentals_assets/orbital_wise_illustration.png differ diff --git a/docs/fundamentals/index.ipynb b/docs/fundamentals/index.ipynb new file mode 100644 index 00000000..ff7b888f --- /dev/null +++ b/docs/fundamentals/index.ipynb @@ -0,0 +1,306 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e4746f4b", + "metadata": {}, + "source": [ + "# Fundamental Aspects\n", + "\n", + "This document aims to provide an overview of important algorithms and implementations that should help users understand the results one obtains from LobsterPy." + ] + }, + { + "cell_type": "markdown", + "id": "50cc984c", + "metadata": {}, + "source": [ + ":::{important}\n", + "In the following sections the implementations are described using ICOHPs/COHPs. \n", + "\n", + "It is implied that the procedure followed is the same even for analyzing and curating features for ML for ICOOPs/COOPs or ICOBIs/COBIs.\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "id": "43408e8b", + "metadata": {}, + "source": [ + "## LobsterEnv : Detect coordination environments based on the electronic structure" + ] + }, + { + "cell_type": "markdown", + "id": "efcea299", + "metadata": {}, + "source": [ + ":::{admonition} New in LobsterEnv\n", + ":class: versionadded\n", + "* Can handle ICOBIs and ICOOPs to detect co-ordination environments and relevant bonds.\n", + "* Provide structure graphs with ICOHPs/ ICOBIs/ ICOOPs as edge properties\n", + ":::\n", + "\n", + "Lobsterenv is the central algorithm on which LobsterPy depends for automatic bonding analysis. \n", + "\n", + "Below is a schematic depicting how this algorithm works. The image is from a talk given by Prof. Dr. George at [MC16 2023 Dublin](https://opus4.kobv.de/opus4-bam/frontdoor/index/index/start/0/rows/10/sortfield/year/sortorder/desc/searchtype/simple/query/George/author_facetfq/George%2C+Janine/doctypefq/lecture/docId/57876) \n", + "\n", + "![Schema depicting working of LobsterEnv algorithm](fundamentals_assets/LobsterEnv_schema.png)\n", + "\n", + "Unlike purely geometry-based algorithms, e.g., Voronoi construction, which depends on angle and distance cutoffs, LobsterEnv needs only one parameter that influences neighbor selection, i.e., ICOHPs.\n", + "\n", + "Thus, when running automatic analysis using the Analysis module, `cutoff_icohp` is the parameter to be paid attention to. This value is set to 10% by default. This means that, depending on the type of bond (cation-anion or all), only ICOHPs with a value of more than 10% of the largest ICOHPs (this value also changes depending on the type of bonds considered for analysis, cation-anion/all bonds) are considered in the analysis.\n", + "\n", + "The `noise_cutoff` parameter takes care of numerical noise, which always exists in theoretical computations. So, ICOHPs, which are negligible, will not be considered in the bonding analysis.\n", + "\n", + ":::{caution}\n", + "So far LobsterEnv has only been tested for ICOHPs. ICOOP and ICOBI implementations are recently added.\n", + ":::\n", + "\n", + ":::{seealso}\n", + ":class: dropdown\n", + "\n", + "Please refer to the following sources for `ChemEnv` and `LobsterEnv` for more details on these algorithms.\n", + "\n", + "* [D. Waroquiers, J. George, M. Horton, S. Schenk, K. A. Persson, G.-M. Rignanese, X. Gonze, G. Hautier, Acta Cryst B 2020, 76, 683–695.](https://scripts.iucr.org/cgi-bin/paper?S2052520620007994)\n", + "* [J. George, G. Petretto, A. Naik, M. Esters, A. J. Jackson, R. Nelson, R. Dronskowski, G.-M. Rignanese, G. Hautier, ChemPlusChem 2022, e202200123](https://chemistry-europe.onlinelibrary.wiley.com/doi/full/10.1002/cplu.202200123)\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "id": "44546121", + "metadata": {}, + "source": [ + "## Evaluating bonding and anti-bonding percentages" + ] + }, + { + "cell_type": "markdown", + "id": "a81a04cc", + "metadata": {}, + "source": [ + "LobsterPy follows the following steps to evaluate the bonding and anti-bonding percentages at each symmetrically independent site:\n", + "\n", + "1. All the relevant bonds are identified for the site in the structure using ICOHPs via LobsterEnv (bond labels from `ICOHPLIST.lobster` are also stored, along with ICOHP values).\n", + "2. Read the COHP data from `COHPCAR.lobster` corresponding to bond labels from step 1 and get summed COHPs data for each site separately.\n", + "3. Perform numerical integration of the summed COHPs at each site to evaluate the bonding and antibonding integral and percentages below efermi.\n", + "4. One can also set the `start` parameter when initializing the Analysis class object to set the start point of energy range below efermi for the integration. (Optional and useful if one wants to look at specific energy range below efermi)\n", + "\n", + "Below is a visual depiction of the evaluation of bonding percentage (Step 3) from COHP data for a site.\n", + "\n", + "![Bonding percentage evaluation](fundamentals_assets/bonding_percentage.png)\n", + "\n", + "Similarly, the antibonding percentage is evaluated for the site from the COHP data.\n", + "\n", + ":::{note}\n", + "Ideally, the $(bonding-antibonding) $ integral values should equal the summed ICOHP values at each site. However, as it is a known fact, numerical integration is bound to have some errors. Thus, we might not see this corroborate well for all cases.\n", + "\n", + "Another crucial factor influencing the results of the numerical integration is the number of points on which the integration is performed. Thus, having a finer grid, i.e., setting `COHPSteps` to `2000` or more in your LOBSTER run, will help one get better estimates. From our experience, setting `COHPSteps` to `10000` provided very consistent results. (Be mindful that the sizes of files generated from such setting can become quite large depending on the complexity of the structure)\n", + "\n", + "Also, it is important to note that the ICOHP values from `ICOHPLIST.lobster` consider the entire range below efermi. Thus, if the `COHPCAR.lobster` is not computed for the entire energy range below efermi, then your results will also not corroborate to the summed ICOHPs at the site.\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "id": "6094b839", + "metadata": {}, + "source": [ + "## Automatic orbital-wise analysis implementation" + ] + }, + { + "cell_type": "markdown", + "id": "82d92b02", + "metadata": {}, + "source": [ + "LobsterPy follows the following steps to evaluate the relevant orbitals contributing to the bonds automatically. Steps 1 to 3 are identical to the **Evaluating bonding and anti-bonding percentages**. Thus, for brevity, we will not relist them here and only list the steps further. The steps mentioned below are repeated for each symmetrically independent site:\n", + "\n", + "4. Read the list of available orbitals from `COHPCAR.lobster` at the site\n", + "5. Get summed cohps for each orbital using the bond label list (step 1)\n", + "6. Check if the total bonding and antibonding integrals obtained in step 3 are each greater than 0\n", + "7. Evaluate the bonding integral (area under the curve) from COHP data for each orbital and store these values in two lists. One will have orbital pair names, and the other will have corresponding evaluated bonding integrals. Similarly, create two more lists with antibonding orbital pair names and corresponding antibonding integrals.\n", + "8. Evaluate the orbital contribution percentages using the following formula:\n", + "\n", + "$$\\text{(Anti) bonding contribution for each orbital}=\\frac{\\text{each orbital (anti)bonding integral}}{\\text{sum(orbital (anti)bonding integral)}}$$\n", + "\n", + "9. If the orbital contribution is more than the `orbital_cutoff` set in the Analysis class object, include that orbital pair interaction as relevant (do this for bonding and antibonding separately using contribution percentages as evaluated in step 8.\n", + "10. Get max anti(bonding) contribution using contribution percentages evaluated in step 8 and add it to the orbital summary dict (this dict is used in description text output generation). \n", + "\n", + "As mentioned in step 9, the results will vary a lot depending on the `orbital_cutoff` set when initializing the Analysis class object. The default value is set to 0.05 (i.e. 5%).\n", + "\n", + "Below is a visual depiction of the evaluation of orbital contribution percentage (Step 7) from summed orbital COHP data for a site. Subfigure (a) and (b) depict the evaluation of orbital contribution for bonding and antibonding interactions relative to summed orbital COHPs at the site.\n", + "\n", + "![Orbital contribution percentage evaluation](fundamentals_assets/orbital_wise_illustration.png)\n" + ] + }, + { + "cell_type": "markdown", + "id": "6f631f31", + "metadata": {}, + "source": [ + "## Features curated for ML via Featurizer" + ] + }, + { + "cell_type": "markdown", + "id": "e5952139", + "metadata": {}, + "source": [ + "### DOS based features" + ] + }, + { + "cell_type": "markdown", + "id": "f215c734", + "metadata": {}, + "source": [ + "

Moment based features

\n", + "\n", + "These features are implemented for DOS in [pymatgen](https://github.com/materialsproject/pymatgen/tree/master) by Rosen et.al. as part of their [A. S. Rosen, S. Vijay, K. A. Persson, Chem. Sci. 2023, 14, 1503–1511.](https://pubs.rsc.org/en/content/articlelanding/2023/SC/D2SC05772G) work\n", + "\n", + "\n", + "1. [Center](https://github.com/materialsproject/pymatgen/blob/2ccbfa16cbffb1016501c18117e70a3f96a83de2/pymatgen/electronic_structure/dos.py#L833)\n", + "2. [Width](https://github.com/materialsproject/pymatgen/blob/2ccbfa16cbffb1016501c18117e70a3f96a83de2/pymatgen/electronic_structure/dos.py#L862)\n", + "3. [Skewness](https://github.com/materialsproject/pymatgen/blob/2ccbfa16cbffb1016501c18117e70a3f96a83de2/pymatgen/electronic_structure/dos.py#L889)\n", + "4. [Kurtosis](https://github.com/materialsproject/pymatgen/blob/2ccbfa16cbffb1016501c18117e70a3f96a83de2/pymatgen/electronic_structure/dos.py#L919)\n", + "5. [Edge](https://github.com/materialsproject/pymatgen/blob/2ccbfa16cbffb1016501c18117e70a3f96a83de2/pymatgen/electronic_structure/dos.py#L1056)\n", + "\n", + "The $n^{th}$ moment for projected dos (PDOS) is computed using following relation\n", + "\n", + "$n^{th}_{moment} = \\frac{\\int (p^n \\cdot \\text{PDOS} \\, dE)}{\\int \\text{PDOS} \\, dE}$\n", + "\n", + "The resulting $1^{st}$, $2^{nd}$, $3^{rd}$ and $4^{th}$ moment are named as *_band_center, *_band_width, *_band_skew, *_band_kurtosis, respectively. Here `*` denotes the orbital names, namely `s,p,d, or f`.\n", + "\n", + "Similar features for elements can also be obtained, element DOS will be used instead of PDOS. Please check the tutorials for example usage.\n", + "\n", + ":::{seealso}\n", + ":class: dropdown\n", + "\n", + "Please refer to the following sources for more details on these.\n", + "\n", + "* [B. Hammer, J. K. Nørskov, Surface Science 1995, 343, 211–220.](https://doi.org/10.1016/0039-6028(96)80007-0)\n", + "* [H. Xin, A. Vojvodic, J. Voss, J. K. Nørskov, F. Abild-Pedersen, Phys. Rev. B 2014, 89, 115114.](https://doi.org/10.1103/PhysRevB.89.115114)\n", + ":::\n", + "\n", + "

Fingerprints

\n", + "\n", + "DOS [Fingerprints](https://github.com/materialsproject/pymatgen/blob/2ccbfa16cbffb1016501c18117e70a3f96a83de2/pymatgen/electronic_structure/dos.py#L1093) are basically DOS data discretized into histograms that will allow to compute similarity between DOS/PDOS of different materials numerically.\n", + "\n", + "This feature was implemented in [pymatgen](https://github.com/materialsproject/pymatgen/tree/master) as part of our LOBSTER database publication [A. A. Naik, C. Ertural, N. Dhamrait, P. Benner, J. George, Sci Data 2023, 10, 610.](https://www.nature.com/articles/s41597-023-02477-5)" + ] + }, + { + "cell_type": "markdown", + "id": "8f8f7deb", + "metadata": {}, + "source": [ + "### COXX based features (COXX: COHP / COBI / COOP)" + ] + }, + { + "cell_type": "markdown", + "id": "ffd726d1", + "metadata": {}, + "source": [ + "

Average features

\n", + "\n", + "The below mentioned features are implemented based on the work of \n", + "\n", + "[R. Nelson, C. Ertural, P. C. Müller, R. Dronskowski, in Compr. Inorg. Chem. III, Elsevier, 2023, pp. 141–201.](https://linkinghub.elsevier.com/retrieve/pii/B9780128231449001205)\n", + "\n", + "\n", + "The $\\overline{\\mathrm{ICOHP}}$ can be interpreted as the average bond strength inside the given material.\n", + "\n", + "$\\overline{\\mathrm{COHP}}(E) =\\sum_i\\left(w_i \\cdot \\operatorname{COHP}_i(E)\\right)$ \n", + "\n", + "$w_i =\\frac{\\mathrm{ICOHP}_i}{\\mathrm{ICOHP}_{\\text {total}}}$\n", + "\n", + "$\\overline{\\mathrm{ICOHP}}=\\int_{-\\infty}^{\\varepsilon_{\\mathrm{F}}} \\overline{\\mathrm{COHP}}(E) \\mathrm{d}E $\n", + "\n", + "The EIN is comparable to a coordination number\n", + "\n", + "$\\mathrm{EIN}=\\frac{\\mathrm{ICOHP}_{\\text {total }}}{\\overline{\\mathrm{ICOHP}}} \\cdot \\frac{2}{N_{\\text {Atoms }}}$\n" + ] + }, + { + "cell_type": "markdown", + "id": "b486f6f8", + "metadata": {}, + "source": [ + "

Moment based features and fingerprints

\n", + "\n", + "These features are inspired from the features implemented for DOS in [pymatgen](https://github.com/materialsproject/pymatgen/tree/master) as described in DOS based features section above. Following features are accessible\n", + "1. Center\n", + "2. Width\n", + "3. Skewness\n", + "4. Kurtosis\n", + "5. Edge\n", + "6. Fingerprints\n", + "\n", + "For the case of COXXs, the $n^{th}$ moment is computed using following relation\n", + "\n", + "$n^{th}_{moment} = \\frac{\\int (p^n \\cdot \\text{COXXs} \\, dE)}{\\int \\text{COXXs} \\, dE}$\n", + "\n", + "The resulting $1^{st}$, $2^{nd}$, $3^{rd}$ and $4^{th}$ moment are named as center_COXX, width_COXX, skewness_COXX, kurtosis_COXX, respectively.\n", + "\n", + "To generate COXX fingerprints we discretize COXX data into histograms that will allow to compute similarity between COXX curves of different materials numerically.\n", + "\n", + ":::{tip}\n", + "One can select the range of energy and type of interactions (bonding, antibonding, overall) one would like to compute these features.\n", + ":::" + ] + }, + { + "cell_type": "markdown", + "id": "2a1f1a31", + "metadata": {}, + "source": [ + "

Summary stats features from LobsterPy condensed bonding analysis dicts

\n", + "\n", + "These features were first implemented as part of our Database publication : [A. A. Naik, C. Ertural, N. Dhamrait, P. Benner, J. George, Sci. Data 2023, 10, 610.](https://doi.org/10.1038/s41597-023-02477-5)\n", + "\n", + "The source code can be found [here](https://github.com/naik-aakash/lobster-database-paper-analysis-scripts/blob/e274cc66fe5cdef981c9de0609eaba4368226c9a/ML_model/featurizer/lobster_featurizer.py#L33).\n", + "\n", + "This is code have been intergrated in our Package and it is extended to also work for COBI/COOP condensed bonding analysis dicts and can user can now also include orbital wise analysis summary stats (Optional)." + ] + }, + { + "cell_type": "markdown", + "id": "7d4e224f", + "metadata": {}, + "source": [ + "### Charge based features\n", + "\n", + "As Ionicity quantifies the strength of an ionic bond in the compound, there are several approaches to quantify it. Here we use the formulation as per [R. Nelson, C. Ertural, P. C. Müller, R. Dronskowski, in Compr. Inorg. Chem. III, Elsevier, 2023, pp. 141–201.](https://linkinghub.elsevier.com/retrieve/pii/B9780128231449001205), which use following relation: \n", + "\n", + "$I_{\\text {Charges }}=\\frac{1}{N_{\\text {Atoms }}} \\sum_i^{N_{\\text {Atoms }}}\\left(\\frac{q_i}{v_{\\text {eff }, i}}\\right)$\n", + "\n", + "It is possible to compute ionicity based on above mentioned formula using either the Mulliken or Löwdin charges obtained from LOBSTER run." + ] + } + ], + "metadata": { + "hide_input": false, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..2e89c73d --- /dev/null +++ b/docs/index.md @@ -0,0 +1,84 @@ +```{toctree} +:caption: User Guide +:hidden: +installation/index +fundamentals/index +tutorial/index +``` + +```{toctree} +:caption: Reference +:hidden: +reference/index +reference/cli +``` + +```{toctree} +:caption: Contributing Guide +:hidden: +dev/dev_installation +dev/contributing +``` + +```{toctree} +:caption: About +:hidden: +about/changelog +about/license +``` + +# LobsterPy documentation + +**Date**: {sub-ref}`today` + +**Useful links**: +[Github Repository](https://github.com/JaGeo/LobsterPy) | +[PyPI](https://pypi.org/project/lobsterpy/) | +[Issues & Ideas](https://github.com/JaGeo/LobsterPy/issues) | + +LobsterPy is a package that enables automatic analysis of LOBTSER outputs to get summarized bonding information and relevant bond plots. Additionally, one can also generate features for machine learning studies from LOBSTER outputs. + +::::{grid} 1 1 2 2 +:class-container: text-center +:gutter: 3 + + +:::{grid-item-card} +:link: fundamentals/index +:link-type: doc +:class-header: bg-light +**Fundamental Aspects** +^^^ +This guide contains a detailed explanation of the key functionalites on +which LobsterPy automatic analysis is based on. +::: + +:::{grid-item-card} +:link: installation/index +:link-type: doc +:class-header: bg-light +**User Guide** +^^^ +This guide provides in-depth information for getting started and tutorials for *LobsterPy*. +::: + +:::{grid-item-card} +:link: https://materialsproject.github.io/atomate2/user/codes/vasp.html#lobster +:class-header: bg-light +**LOBSTER Workflow** +^^^ +Here you can find how to use our completely automated workflow to perform bonding analysis with +LOBSTER and Lobsterpy via atomate2. +::: + + +:::{grid-item-card} +:link: dev/dev_installation +:link-type: doc +:class-header: bg-light +**Developer guide** +^^^ +Do you want contribute or improve existing functionalities? +Check out the developer guide. +::: +:::: diff --git a/docs/installation/index.md b/docs/installation/index.md new file mode 100644 index 00000000..9398c614 --- /dev/null +++ b/docs/installation/index.md @@ -0,0 +1,7 @@ +Getting started +================ +```{include} ../../README.md +--- +start-line: 5 +--- +``` diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index dc1312ab..00000000 --- a/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF - -pushd %~dp0 - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set SOURCEDIR=source -set BUILDDIR=build - -%SPHINXBUILD% >NUL 2>NUL -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.https://www.sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "" goto help - -%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% -goto end - -:help -%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% - -:end -popd diff --git a/docs/reference/cli.rst b/docs/reference/cli.rst new file mode 100644 index 00000000..dcb7d8f9 --- /dev/null +++ b/docs/reference/cli.rst @@ -0,0 +1,14 @@ +CLI Reference +============== + +.. toctree:: + :maxdepth: 1 + + cli_subcommands/createinputs + cli_subcommands/description + cli_subcommands/descriptionquality + cli_subcommands/plotauto + cli_subcommands/plotautoia + cli_subcommands/plotdos + cli_subcommands/ploticohpdistance + cli_subcommands/plot diff --git a/docs/reference/cli_subcommands/createinputs.rst b/docs/reference/cli_subcommands/createinputs.rst new file mode 100644 index 00000000..bf25a332 --- /dev/null +++ b/docs/reference/cli_subcommands/createinputs.rst @@ -0,0 +1,16 @@ +create-inputs +============== + +Create inputs for lobster computation. It works only with PBE POTCARs. + +.. hint:: Aliases available + + - createinputs + + +.. argparse:: + :module: lobsterpy.cli + :func: get_parser + :prog: lobsterpy + :path: create-inputs + diff --git a/docs/reference/cli_subcommands/description.rst b/docs/reference/cli_subcommands/description.rst new file mode 100644 index 00000000..e401d213 --- /dev/null +++ b/docs/reference/cli_subcommands/description.rst @@ -0,0 +1,11 @@ +description +============ + +Deliver a text description of the COHPs or COBIS or COOP results from Lobster and VASP + +.. argparse:: + :module: lobsterpy.cli + :func: get_parser + :prog: lobsterpy + :path: description + diff --git a/docs/reference/cli_subcommands/descriptionquality.rst b/docs/reference/cli_subcommands/descriptionquality.rst new file mode 100644 index 00000000..ef0308ed --- /dev/null +++ b/docs/reference/cli_subcommands/descriptionquality.rst @@ -0,0 +1,10 @@ +description-quality +=================== + +Deliver a text description of the LOBSTER calc quality analysis. Mandatory required files: POSCAR, POTCAR, lobsterout, lobsterin. Optional files (BVA comparison): CHARGE.lobster, (DOS comparison): DOSCAR.lobster/ DOSCAR.LSO.lobster, Vasprun.xml. + +.. argparse:: + :module: lobsterpy.cli + :func: get_parser + :prog: lobsterpy + :path: description-quality diff --git a/docs/reference/cli_subcommands/plot.rst b/docs/reference/cli_subcommands/plot.rst new file mode 100644 index 00000000..3d91f0b0 --- /dev/null +++ b/docs/reference/cli_subcommands/plot.rst @@ -0,0 +1,11 @@ +plot +==== + +Plot specific COHPs/COBIs/COOPs based on bond numbers. + +.. argparse:: + :module: lobsterpy.cli + :func: get_parser + :prog: lobsterpy + :path: plot + diff --git a/docs/reference/cli_subcommands/plotauto.rst b/docs/reference/cli_subcommands/plotauto.rst new file mode 100644 index 00000000..2d7efafb --- /dev/null +++ b/docs/reference/cli_subcommands/plotauto.rst @@ -0,0 +1,19 @@ +plot-automatic +============== + +Plot most important COHPs or COBIs or COOPs automatically. This option also includes an automatic description. + +.. hint:: Aliases available + + - plot-auto + - auto-plot + - autoplot + - automatic-plot + - automaticplot + +.. argparse:: + :module: lobsterpy.cli + :func: get_parser + :prog: lobsterpy + :path: plot-automatic + diff --git a/docs/reference/cli_subcommands/plotautoia.rst b/docs/reference/cli_subcommands/plotautoia.rst new file mode 100644 index 00000000..d9faee35 --- /dev/null +++ b/docs/reference/cli_subcommands/plotautoia.rst @@ -0,0 +1,18 @@ +plot-automatic-ia +================== + +Creates an interactive plot of most important COHPs or COBIs or COOPs automatically. + +.. hint:: Aliases available + + - plot-auto-ia + - auto-plot-ia + - autoplotia + - automatic-plot-ia + - automaticplot-ia + +.. argparse:: + :module: lobsterpy.cli + :func: get_parser + :prog: lobsterpy + :path: plot-automatic-ia diff --git a/docs/reference/cli_subcommands/plotdos.rst b/docs/reference/cli_subcommands/plotdos.rst new file mode 100644 index 00000000..5a1ee12e --- /dev/null +++ b/docs/reference/cli_subcommands/plotdos.rst @@ -0,0 +1,11 @@ +plot-dos +========= + +Plots DOS from lobster computation. + +.. argparse:: + :module: lobsterpy.cli + :func: get_parser + :prog: lobsterpy + :path: plot-dos + diff --git a/docs/reference/cli_subcommands/ploticohpdistance.rst b/docs/reference/cli_subcommands/ploticohpdistance.rst new file mode 100644 index 00000000..0f6e13e4 --- /dev/null +++ b/docs/reference/cli_subcommands/ploticohpdistance.rst @@ -0,0 +1,15 @@ +plot-icohp-distance +==================== + +Plot ICOHPs or ICOOPs or ICOBIs with respect to bond lengths. + +.. hint:: Aliases available + + - ploticohpdistance + +.. argparse:: + :module: lobsterpy.cli + :func: get_parser + :prog: lobsterpy + :path: plot-icohp-distance + diff --git a/docs/reference/index.rst b/docs/reference/index.rst new file mode 100644 index 00000000..053b7a14 --- /dev/null +++ b/docs/reference/index.rst @@ -0,0 +1,15 @@ +Python API reference +==================== + + +.. currentmodule:: lobsterpy + +.. autosummary:: + :recursive: + :toctree: + :nosignatures: + + cohp + featurize + plotting + structuregraph diff --git a/docs/source/Lobsterpy_tutorial_files/CdF2.html b/docs/source/Lobsterpy_tutorial_files/CdF2.html deleted file mode 100644 index e213d8c7..00000000 --- a/docs/source/Lobsterpy_tutorial_files/CdF2.html +++ /dev/null @@ -1,14 +0,0 @@ - - - -
-
- - \ No newline at end of file diff --git a/docs/source/atomateauto.rst b/docs/source/atomateauto.rst deleted file mode 100644 index 39e7fa50..00000000 --- a/docs/source/atomateauto.rst +++ /dev/null @@ -1,5 +0,0 @@ -Automation via atomate (For high-throughput calcs) -================================================== - -Please refer to our previously published tutorial that showcases a test -case `here `_. diff --git a/docs/source/changelog_link.rst b/docs/source/changelog_link.rst deleted file mode 100644 index c0068a69..00000000 --- a/docs/source/changelog_link.rst +++ /dev/null @@ -1,4 +0,0 @@ -CHANGELOG -================ - -.. mdinclude:: ../../CHANGELOG.md diff --git a/docs/source/index.rst b/docs/source/index.rst deleted file mode 100644 index c6f8ca1d..00000000 --- a/docs/source/index.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. Lobsterpy documentation master file, created by - sphinx-quickstart on Fri Sep 23 11:23:25 2022. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to Lobsterpy's documentation! -===================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - readme_link - tutorials - modules - changelog_link - license_link - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/docs/source/installation.rst b/docs/source/installation.rst deleted file mode 100644 index 0de9a08c..00000000 --- a/docs/source/installation.rst +++ /dev/null @@ -1,14 +0,0 @@ -Installation -============ - -1. Create a conda environment with any suitable name eg:- conda create - -n Test python==3.9 (This step is optional but it is better to have - separate environments to avoid conflicts with other packages) -2. Activate the newly created environment ``conda activate Test`` -3. Use ``pip install lobsterpy`` to install the package and all its - dependencies. - -Now that you have installed the lobsterpy, one can use the built-in -command-line interface of this package to adapt the standard VASP input -file (INCAR) and create lobster input files needed for successfully -performing bonding analysis. diff --git a/docs/source/license_link.rst b/docs/source/license_link.rst deleted file mode 100644 index 257b8e30..00000000 --- a/docs/source/license_link.rst +++ /dev/null @@ -1,3 +0,0 @@ -LICENSE -======== -.. mdinclude:: ../../LICENSE diff --git a/docs/source/modules.rst b/docs/source/modules.rst deleted file mode 100644 index 4c641fd8..00000000 --- a/docs/source/modules.rst +++ /dev/null @@ -1,7 +0,0 @@ -lobsterpy -========= - -.. toctree:: - :maxdepth: 4 - - lobsterpy diff --git a/docs/source/pythoninterface.rst b/docs/source/pythoninterface.rst deleted file mode 100644 index e678e773..00000000 --- a/docs/source/pythoninterface.rst +++ /dev/null @@ -1,84 +0,0 @@ -Python interface -================ - -Import the necessary modules - -.. code:: ipython3 - - import os - from lobsterpy.cohp.analyze import Analysis - from lobsterpy.cohp.describe import Description - import warnings - warnings.filterwarnings('ignore') - -.. code:: ipython3 - - directory = "Basis_0" #Directory of your VASP and Lobster computations - # Setup analysis dict - analyse = Analysis( - path_to_poscar=os.path.join(directory, "POSCAR"), - path_to_icohplist=os.path.join(directory, "ICOHPLIST.lobster"), - path_to_cohpcar=os.path.join(directory, "COHPCAR.lobster"), - path_to_charge=os.path.join(directory, "CHARGE.lobster"), - which_bonds="cation-anion", - ) - -.. code:: ipython3 - - # Setup Description dict - describe = Description(analysis_object=analyse) - describe.write_description() - - -.. parsed-literal:: - - The compound CdF2 has 1 symmetry-independent cation(s) with relevant cation-anion interactions: Cd1. - Cd1 has a cubic (CN=8) coordination environment. It has 8 Cd-F (mean ICOHP: -0.62 eV, antibonding interaction below EFermi) bonds. - - -.. code:: ipython3 - - # Automatic plots - describe.plot_cohps(ylim=[-10, 2], xlim=[-4, 4]) - -.. image:: Lobsterpy_tutorial_files/Lobsterpy_tutorial_38_0.png - -.. code:: ipython3 - - # Automatic interactive plots - describe.plot_interactive_cohps() - -.. raw:: html - :file: Lobsterpy_tutorial_files/CdF2.html - - -.. code:: ipython3 - - print(analyse.condensed_bonding_analysis) # dicts that summarize the results - - -.. parsed-literal:: - - {'formula': 'CdF2', 'max_considered_bond_length': 5.98538, 'limit_icohp': (-100000, -0.1), 'number_of_considered_ions': 1, 'sites': {0: {'env': 'C:8', 'bonds': {'F': {'ICOHP_mean': '-0.62', 'ICOHP_sum': '-4.97', 'has_antibdg_states_below_Efermi': True, 'number_of_bonds': 8}}, 'ion': 'Cd', 'charge': 1.57, 'relevant_bonds': ['29', '30', '33', '40', '53', '60', '63', '64']}}, 'type_charges': 'Mulliken'} - - -.. code:: ipython3 - - print(analyse.final_dict_bonds) # dicts that summarize the results - - -.. parsed-literal:: - - {'Cd-F': {'ICOHP_mean': -0.62125, 'has_antbdg': True}} - - -.. code:: ipython3 - - print(analyse.final_dict_ions) # dicts that summarize the results - - -.. parsed-literal:: - - {'Cd': {'C:8': 1}} - - diff --git a/docs/source/readme_link.rst b/docs/source/readme_link.rst deleted file mode 100644 index 3bd447c4..00000000 --- a/docs/source/readme_link.rst +++ /dev/null @@ -1 +0,0 @@ -.. mdinclude:: ../../README.md diff --git a/docs/source/tutorials.rst b/docs/source/tutorials.rst deleted file mode 100644 index 52f724d3..00000000 --- a/docs/source/tutorials.rst +++ /dev/null @@ -1,33 +0,0 @@ -Tutorial -========= - -.. raw:: html - -
- -Written by Aakash Naik (aakash.naik@bam.de) based on suggestions -provided by Dr. Janine George (janine.george@bam.de) - -.. raw:: html - -
- -.. note:: - - To download Lobster, please visit http://www.cohp.de. Currently, only VASP/Lobster computations are supported. - - -This tutorial will demonstrate how the Lobsterpy package can be used to: - -1. Create input files necessary for VASP and lobster runs -2. Use generated inputs files to run VASP and Lobster -3. Analyze the lobster outputs with automation - -.. toctree:: - :maxdepth: 2 - - installation.rst - commandlineinterface - pythoninterface - computingtimes - atomateauto diff --git a/docs/tutorial/atomateauto.rst b/docs/tutorial/atomateauto.rst new file mode 100644 index 00000000..46924df0 --- /dev/null +++ b/docs/tutorial/atomateauto.rst @@ -0,0 +1,6 @@ +High-throughput LOBSTER calcs +============================== + + 1. In *atomate_v2*, the LobsterPy is has been made an integral part of LOBSTER workflow. Check the link which shows how to use our this workflow to perform bonding analysis with LOBSTER via `atomate2 `_. + + 2. Older *atomate_v1* workflow tutorial can be found `here `_. diff --git a/docs/source/commandlineinterface.rst b/docs/tutorial/commandlineinterface.rst similarity index 62% rename from docs/source/commandlineinterface.rst rename to docs/tutorial/commandlineinterface.rst index 95224945..2c4f6e27 100644 --- a/docs/source/commandlineinterface.rst +++ b/docs/tutorial/commandlineinterface.rst @@ -6,45 +6,33 @@ Creating input files .. note:: - Important tags in INCAR of VASP to be paid attention before - performing lobster runs are NBANDS, NSW and ISYM. It is absolutely - necessary that VASP static run is performed (no movements of atoms, - NSW = 0) before running lobster program. LOBSTER can only deal with - VASP WAVECAR that contain results for the entire mesh or only half of - it. To do this, in the INCAR set ISYM = -1 (entire mesh / symmetry - switched off) or ISYM = 0 (half mesh/time-reversal). And to make sure - WAVECAR are written set LWAVE = .TRUE. For pCOHP analyses one needs - to have as many bands as there are orbitals in local basis. For pCOHP - analyses using LOBSTER, however, you need to manually set NBANDS in - the INCAR file. - -With lobsterpy these intricate details are taken care of with single -command. We need the standard VASP input files i.e -``INCAR, KPOINTS, POTCAR and POSCAR`` in the calculation directory. Once -you have these files, one simply needs to run the following command : + Important tags in INCAR of VASP to be paid attention before performing lobster runs are NBANDS, NSW and ISYM. It is absolutely necessary + that VASP static run is performed (no movements of atoms, NSW = 0) before running lobster program. LOBSTER can only deal with VASP WAVECAR + that contain results for the entire mesh or only half of it. + + To do this, in the INCAR set ISYM = -1 (entire mesh / symmetry switched off) or ISYM = 0 (half mesh/time-reversal). And to make sure WAVECAR + are written set LWAVE = .TRUE. For pCOHP analyses one needs to have as many bands as there are orbitals in local basis. + + And for pCOHP analyses using LOBSTER, however, you need to manually set NBANDS in the INCAR file. + + +With lobsterpy these intricate details are taken care of with single command. We need the standard VASP input files i.e +``INCAR, KPOINTS, POTCAR and POSCAR`` in the calculation directory. Once you have these files, one simply needs to run the following command : ``lobsterpy create-inputs`` -The above command will create set of input files (INCAR and lobsterin) -depending on the basis sets that are available in Lobster. +The above command will create set of input files (INCAR and lobsterin) depending on the basis sets that are available in Lobster. -The NBANDS, NSW, ISYM tag will be changed in existing INCAR file and new -INCAR files will be written in the existing directory. The newly created -INCAR file will be named ``INCAR.lobsterpy``\ by default. Simultaneously -``lobsterin.lobsterpy`` files are created that is necessary for lobster -run (this is the file that instructs lobster program what computations -needed to be performed). +The NBANDS, NSW, ISYM tag will be changed in existing INCAR file and new INCAR files will be written in the existing directory. +The newly created INCAR file will be named ``INCAR.lobsterpy`` by default. +Simultaneously ``lobsterin.lobsterpy`` files are created that is necessary for lobster run (this is the file that instructs lobster program what computations needed to be performed). -You can also change the names of output files and path where they are -saved using following optional tags: +You can also change the names of output files and path where they are saved using following optional tags: ``lobsterpy create-inputs --incar-out /INCAR --lobsterin-out /lobsterin`` -You can also use help to know addtional options using -``lobsterpy create-inputs -h`` -In our example ``Cd`` element has two basis sets ``4d 5s`` ``4d 5s 5p``, -thus following files are created: +For example if ``Cd`` element has two basis sets ``4d 5s`` ``4d 5s 5p``, thus following files are created: :: @@ -53,15 +41,12 @@ thus following files are created: lobsterin.lobsterpy-0 lobsterin.lobsterpy-1 -The suffix “-0” & “-1” indicate input files corresponding to smaller and -larger basis of ``Cd`` respectively. +The suffix “-0” & “-1” indicate input files corresponding to smaller and larger basis of ``Cd`` respectively. .. warning:: - The ‘KPOINTS’ file is not adapted, it is important for user - to select appropriate grid density before starting VASP - computations. Usually a factor of 50 x reciprocal lattice vectors - is sufficient to get reliable bonding analysis results. + The ‘KPOINTS’ file is not adapted, it is important for user to select appropriate grid density before starting VASP + computations. Usually a factor of 50 x reciprocal lattice vectors is sufficient to get reliable bonding analysis results. Running VASP and Lobster program -------------------------------- @@ -143,14 +128,15 @@ Analyze the lobster outputs with automation option to save output in json file. Below is an example output of this command. +.. code:: bash + + lobsterpy description --json description.json + .. code:: bash The compound CdF2 has 1 symmetry-independent cation(s) with relevant cation-anion interactions: Cd1. Cd1 has a cubic (CN=8) coordination environment. It has 8 Cd-F (mean ICOHP: -0.62 eV, 27.843 percent antibonding interaction below EFermi) bonds. - -:: - lobsterpy description --json description.json Following is the json file produced. @@ -199,7 +185,24 @@ Following is the json file produced. }, "type_charges": "Mulliken" } + + +- ``lobsterpy calc-description --potcar-symbols "Na_pv Cl" --bvacomp --doscomp`` command will perform an automated analysis of your lobster calculation quality. +.. note:: + The LOBSTER calculation directory need to have POTCAR, POSCAR, LOBSTER calculation input and output files to run the **lobsterpy calc-description** command sucessfully. + If POTCAR is not available then you need to suppy **--potcar-symbols** along with the command. Other optional files are vasprun.xml if **--doscomp** is switched on. + +.. code:: bash + + lobsterpy calc-description --potcar-symbols "Na_pv Cl" --bvacomp --doscomp --calcqualityjson calc_quality_description.json + +.. code:: bash + + The LOBSTER calculation used minimal basis. The absolute and total charge spilling for the calculation is 0.3 and 5.58 %, respectively. The projected wave function is completely orthonormalized as no + bandOverlaps.lobster file is generated during the LOBSTER run. The atomic charge signs from Mulliken population analysis agree with the bond valence analysis. The atomic charge signs from Loewdin + population analysis agree with the bond valence analysis. The Tanimoto index from DOS comparisons in the energy range between -5, 0 eV for s, p, summed orbitals are: 0.9785, 0.9973, 0.9953. + - ``lobsterpy automatic-plot`` command will plot the results automatically. It will evaluate all COHPs with ICOHP values down to 10% of the strongest ICOHP. You can enforce an analysis of all bonds @@ -211,21 +214,21 @@ Following is the json file produced. initial Lobster computation. Below is an example and sample output using this command. -:: +.. code:: bash lobsterpy automatic-plot --title 'Automatic COHP plot' --save-plot COHP.png -.. image:: Lobsterpy_tutorial_files/COHP.png +.. image:: tutorial_assets/COHP.png You can also plot integrated ICOHP computed by lobster by turning on ``--integrated`` flag when executing ``lobsterpy automatic-plot`` command. Below is an example and sample output using this command. -:: +.. code:: bash lobsterpy automatic-plot --title 'Automatic ICOHP plot' --integrated --save-plot ICOHP.png -.. image:: Lobsterpy_tutorial_files/ICOHP.png +.. image:: tutorial_assets/ICOHP.png - ``lobsterpy automatic-plot-ia`` command can be used to obtain a interactive plot of analysis automatically. It will evaluate all COHPs with ICOHP values down to 10% of the strongest ICOHP. You can enforce an analysis of all bonds @@ -239,7 +242,9 @@ command. Below is an example and sample output using this command. ``lobsterpy automatic-plot-ia --allbonds --label-resolved`` option .. raw:: html - :file: Lobsterpy_tutorial_files/CdF2.html + + :file: tutorial_assets/CdF2.html + 2. Plotting of COHPs/COBIs/COOPs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -252,40 +257,42 @@ well (–summed, –integrated). You can switch to COBIs or COOPs by using –cobis or –coops, respectively. Below is an example output of command to plot COHP and COOP for bond 3 and 30. -``lobsterpy plot 3 30 --save-plot COHP_330.png`` +.. code:: bash -``lobsterpy plot 3 30 --coops --save-plot COOP_330.png`` + lobsterpy plot 3 30 --save-plot COHP_330.png -.. image:: Lobsterpy_tutorial_files/COHP_330.png - :width: 49 % -.. image:: Lobsterpy_tutorial_files/COOP_330.png - :width: 49 % +.. image:: tutorial_assets/COHP_330.png -.. raw:: html +.. code:: bash - + lobsterpy plot 3 30 --coops --save-plot COOP_330.png -.. raw:: html +.. image:: tutorial_assets/COOP_330.png - -.. raw:: html +3. Plotting of DOS +~~~~~~~~~~~~~~~~~~~ - +- ``lobsterpy plot-dos --summedspins`` will plot total and element DOS. Example output plot is shown below. -.. raw:: html +.. code:: bash - + lobsterpy plot-dos --summedspins -.. raw:: html +.. image:: tutorial_assets/DOS_example.png - +4. Plotting of ICOHPs/ ICOOPs/ICOBIS againsts bond lengths +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. raw:: html +- ``lobsterpy plot-icohps-distances`` will plot ICOHPs against bond lengths. Example output plot is shown below. + +.. code:: bash + + lobsterpy plot-icohps-distances - +.. image:: tutorial_assets/ICOHPs_distance_example.png -3. Additional Options +5. Additional Options ~~~~~~~~~~~~~~~~~~~~~ You can also customize the style and parameters of the plots generated @@ -294,10 +301,33 @@ either of these commands: .. code:: bash - lobsterpy automatic-plot --help - lobsterpy plot --help + lobsterpy automatic-plot --help + +.. code:: bash + lobsterpy automatic-plot-ia --help -.. code:: ipython3 +.. code:: bash + + lobsterpy calc-description -help + +.. code:: bash + + lobsterpy create-inputs --help + +.. code:: bash + + lobsterpy description --help + +.. code:: bash + + lobsterpy plot-dos --help + +.. code:: bash + + lobsterpy plot-icohps-distances --help + +.. code:: bash + + lobsterpy plot --help - os.chdir('..') # Return to parent directory diff --git a/docs/source/computingtimes.rst b/docs/tutorial/computingtimes.rst similarity index 92% rename from docs/source/computingtimes.rst rename to docs/tutorial/computingtimes.rst index 29586480..1def3378 100644 --- a/docs/source/computingtimes.rst +++ b/docs/tutorial/computingtimes.rst @@ -1,7 +1,7 @@ Computing times ================ -The reported computing times below are for CdF\ :sub:`2` \(Materials project ID : mp-241) +Exemplar computing time for CdF\ :sub:`2` \(Materials project ID : mp-241) +-----------------+------------------------+---------+--------+-------------------------+--------------------+ | Calc Type | Computing time (secs) | NCORES | NODES | CPU | RAM per Node (GB) | diff --git a/docs/tutorial/index.rst b/docs/tutorial/index.rst new file mode 100644 index 00000000..8080be40 --- /dev/null +++ b/docs/tutorial/index.rst @@ -0,0 +1,28 @@ +Tutorial +========= + +Written by Aakash Naik (aakash.naik@bam.de) based on suggestions provided by Prof. Dr. Janine George (janine.george@bam.de) + + +Prerequisites + +* Familiar with `LOBSTER software `_ and its output files +* Familiar with the :doc:`../fundamentals/index` guide. If not please read that guide before proceeding. +* Basic Python knowledge + + +This tutorial will demonstrate how to use the Lobsterpy package using example code snippets. By the end of this tutorial you will be able to use the package to: + +1. Automatically analyze the lobster outputs using python interface +2. Generate custom plots via plotting utilities +3. Use structuregraph to generate graph objects consisiting of LOBSTER data +4. Use featurizer to extract LOBSTER bonding analysis data as features for ML studies +5. Get automatic analysis results and plots using command line utilities + +.. toctree:: + :maxdepth: 2 + + tutorial + commandlineinterface + atomateauto + computingtimes diff --git a/docs/tutorial/tutorial.ipynb b/docs/tutorial/tutorial.ipynb new file mode 100644 index 00000000..014c5bc2 --- /dev/null +++ b/docs/tutorial/tutorial.ipynb @@ -0,0 +1,1014 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a711d82b", + "metadata": {}, + "source": [ + "# Python interface" + ] + }, + { + "cell_type": "markdown", + "id": "dddc8754", + "metadata": {}, + "source": [ + "For this tutorial we will use the [test data](https://github.com/JaGeo/LobsterPy/tests/test_data) that can be downloaded from our git repository using the following commands.\n", + "\n", + "```bash\n", + "git clone --filter=blob:none --no-checkout https://github.com/JaGeo/LobsterPy.git\n", + "cd LobsterPy\n", + "git sparse-checkout set tests/test_data/*\n", + "git read-tree -mu HEAD\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "42969be6", + "metadata": {}, + "source": [ + "## Usage of Analysis, Description class and automatic plotting" + ] + }, + { + "cell_type": "markdown", + "id": "33ffc7dc", + "metadata": {}, + "source": [ + "### Basic usage : Analysis, Description\n", + "\n", + "Lets first import the necessary modules" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "30e6f55a", + "metadata": { + "hide_input": false + }, + "outputs": [], + "source": [ + "import os\n", + "from lobsterpy.cohp.analyze import Analysis\n", + "from lobsterpy.cohp.describe import Description\n", + "import warnings\n", + "warnings.filterwarnings('ignore')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8662ed50", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Directory of your VASP and Lobster computations\n", + "directory = \"../../tests/test_data/CdF_comp_range/\"" + ] + }, + { + "cell_type": "markdown", + "id": "50161895", + "metadata": {}, + "source": [ + "```python\n", + "#### Change directory to your Lobster computations (Change this cell block type to Code and remove formatting when executing locally)\n", + "directory = \"Lobsterpy/tests/test_data/CdF_comp_range/\"\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2ca066a3", + "metadata": {}, + "outputs": [], + "source": [ + "# Initialize Analysis object\n", + "analyse = Analysis(\n", + " path_to_poscar=os.path.join(directory, \"POSCAR.gz\"),\n", + " path_to_icohplist=os.path.join(directory, \"ICOHPLIST.lobster.gz\"),\n", + " path_to_cohpcar=os.path.join(directory, \"COHPCAR.lobster.gz\"),\n", + " path_to_charge=os.path.join(directory, \"CHARGE.lobster.gz\"),\n", + " which_bonds=\"cation-anion\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "87f41407", + "metadata": {}, + "outputs": [], + "source": [ + "# Initialize Description object and to get text description of the analysis\n", + "describe = Description(analysis_object=analyse)\n", + "describe.write_description()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a0e3916", + "metadata": {}, + "outputs": [], + "source": [ + "# Get static plots for detected relevant bonds\n", + "describe.plot_cohps(ylim=[-10, 2], xlim=[-4, 4])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "89b6a906", + "metadata": {}, + "outputs": [], + "source": [ + "# Get interactive plots of relevant bonds, \n", + "\n", + "# Setting label_resolved arg to True will plot each COHP curve seperately, alongside summed COHP for the bonds.\n", + "\n", + "fig = describe.plot_interactive_cohps(label_resolved=True, hide=True)\n", + "fig.show(renderer='notebook')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3c695d06", + "metadata": {}, + "outputs": [], + "source": [ + "# Dict summarizing the automatic analysis results\n", + "analyse.condensed_bonding_analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b079043b", + "metadata": {}, + "outputs": [], + "source": [ + "# Dict with bonds identified\n", + "analyse.final_dict_bonds" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bcab3c31", + "metadata": {}, + "outputs": [], + "source": [ + "# Dict with ions and thier co-ordination environments\n", + "analyse.final_dict_ions" + ] + }, + { + "cell_type": "markdown", + "id": "af3bba2b", + "metadata": {}, + "source": [ + ":::{note}\n", + "You can also perform automatic analysis using `COBICAR(ICOBILIST.lobster)` or `COOPCAR(ICOOPLIST.lobster)`. You would need to set `are_cobis`/`are_coops` to `True` depending on type of file you decide to analyze when you initialize Analysis object. And also change the default `noise_cutoff` value to 0.001 or lower as ICOOP and ICOBI have typicall smaller values and have different units compared to ICOHP. Below is an example code snippet\n", + ":::\n", + "\n", + "```python\n", + "analyse = Analysis(\n", + " path_to_poscar=os.path.join(directory, \"POSCAR.gz\"),\n", + " path_to_icohplist=os.path.join(directory, \"ICOBILIST.lobster.gz\"),\n", + " path_to_cohpcar=os.path.join(directory, \"COBICAR.lobster.gz\"),\n", + " path_to_charge=os.path.join(directory, \"CHARGE.lobster.gz\"),\n", + " which_bonds=\"cation-anion\",\n", + " are_cobis=True,\n", + " noise_cutoff=0.001,\n", + ")\n", + "```\n", + "\n", + "Rest of the things to access the results and plots are same as above." + ] + }, + { + "cell_type": "markdown", + "id": "bb1c58c6", + "metadata": {}, + "source": [ + "### Advanced usage : Analysis, Description" + ] + }, + { + "cell_type": "markdown", + "id": "de5ee6ab", + "metadata": {}, + "source": [ + "LobsterPy, now also provides the possibility to also perform automatic orbialtwise analysis and plotting of COHPs, COBIs and COOPs. To switch on orbialtwise analysis, one needs to set `orbital_resolved` arg to `True`. By default orbitals contributing 5% or more relative to summed ICOHPs are considered in analysis. One can change this default threshold using `orbital_cutoff` argument. Here we will set this cutoff value to 3%" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ae5c791f", + "metadata": {}, + "outputs": [], + "source": [ + "analyse = Analysis(\n", + " path_to_poscar=os.path.join(directory, \"POSCAR.gz\"),\n", + " path_to_icohplist=os.path.join(directory, \"ICOHPLIST.lobster.gz\"),\n", + " path_to_cohpcar=os.path.join(directory, \"COHPCAR.lobster.gz\"),\n", + " path_to_charge=os.path.join(directory, \"CHARGE.lobster.gz\"),\n", + " which_bonds=\"cation-anion\",\n", + " orbital_resolved=True,\n", + " orbital_cutoff=0.03,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "468a2478", + "metadata": {}, + "outputs": [], + "source": [ + "# Access the dict summarizing the results including orbital wise analysis data \n", + "analyse.condensed_bonding_analysis" + ] + }, + { + "cell_type": "markdown", + "id": "ea49c3d4", + "metadata": {}, + "source": [ + "In the above ouput you will see, now a field named `orbital_data` associated to each relevant bond identified. The `orbital_summary_stats` field contains the orbitals that contribute the most to the bonding and antibonding interactions and values are reported there in percent." + ] + }, + { + "cell_type": "markdown", + "id": "90503028", + "metadata": {}, + "source": [ + ":::{note}\n", + "You can get plots from orbital resolved anaylsis only when `orbital_resolved` arg to `True` when initializing Analysis object. If this is not done, you will run into errors. Also only interactive plotter will plot the results of orbital resolved anaylsis as static plots will not be much readable. In anycase you can generate static plots if you need to, you will find how to use the plotters available in LobsterPy further in the Plotter usage section of the tutorial\n", + ":::" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2df4b44a", + "metadata": {}, + "outputs": [], + "source": [ + "# Initialize Description object\n", + "describe = Description(analysis_object=analyse)\n", + "describe.write_description()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "15606ec3", + "metadata": {}, + "outputs": [], + "source": [ + "# Automatic interactive plots\n", + "fig = describe.plot_interactive_cohps(orbital_resolved=True, ylim=[-15,5], hide=True)\n", + "fig.show(renderer='notebook')" + ] + }, + { + "cell_type": "markdown", + "id": "c1b80a34", + "metadata": {}, + "source": [ + "### Get LOBSTER calculation quality and description\n", + "\n", + "This utility provides a quick overview of your LOBSTER calculation quality by reading the charge spilling and band overlaps file (if these are generated during LOBSTER runs). Optionally one can also obtain atoms charge classification comparisons with BVA method and comparison between DOS from LOBSTER and VASP.\n", + "\n", + ":::{note}\n", + "The DOS comparisons and basis set utilized analysis at the moment is Limited to VASP calculations only. Support to other code output will be added in future. \n", + ":::" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a968f712", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Directory to your VASP and Lobster computations\n", + "directory = \"../../tests/test_data/K3Sb/\"" + ] + }, + { + "cell_type": "markdown", + "id": "f96ea7e6", + "metadata": {}, + "source": [ + "```python\n", + "#### Change directory to your Lobster computations (Change this cell block type to Code and remove formatting when executing locally)\n", + "directory = \"LobsterPy/tests/test_data/K3Sb/\"\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "87a8eb35", + "metadata": {}, + "outputs": [], + "source": [ + "# Get calculation quality summary dict\n", + "calc_quality_K3Sb = Analysis.get_lobster_calc_quality_summary(\n", + " path_to_poscar=os.path.join(directory, \"POSCAR.gz\"),\n", + " path_to_charge=os.path.join(directory, \"CHARGE.lobster.gz\"),\n", + " path_to_lobsterin=os.path.join(directory,\"lobsterin.gz\"),\n", + " path_to_lobsterout=os.path.join(directory,\"lobsterout.gz\"),\n", + " potcar_symbols=[\"K_sv\", \"Sb\"], # if POTCAR exists, then provide path_to_potcar and set this to None \n", + " path_to_bandoverlaps=os.path.join(directory,\"bandOverlaps.lobster.gz\"),\n", + " dos_comparison=True, # set to false to disable DOS comparisons \n", + " bva_comp=True, # set to false to disable LOBSTER charge classification comparisons with BVA method\n", + " path_to_doscar=os.path.join(directory,\"DOSCAR.LSO.lobster.gz\"),\n", + " e_range=[-20, 0],\n", + " path_to_vasprun=os.path.join(directory,\"vasprun.xml.gz\"),\n", + " n_bins=256,\n", + " )\n", + "calc_quality_K3Sb" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8bca8893", + "metadata": {}, + "outputs": [], + "source": [ + "# Get a text description from calculation quality summary dictionary\n", + "calc_quality_k3sb_des = Description.get_calc_quality_description(\n", + " calc_quality_K3Sb\n", + " )\n", + "Description.write_calc_quality_description(calc_quality_k3sb_des)" + ] + }, + { + "cell_type": "markdown", + "id": "952f79a1", + "metadata": {}, + "source": [ + "## Using plotting utilities" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "240ae59d", + "metadata": {}, + "outputs": [], + "source": [ + "from matplotlib import style\n", + "from pymatgen.io.lobster import Doscar\n", + "from lobsterpy.plotting import InteractiveCohpPlotter, IcohpDistancePlotter, PlainCohpPlotter, PlainDosPlotter, get_style_list" + ] + }, + { + "cell_type": "markdown", + "id": "5a0318f2", + "metadata": {}, + "source": [ + "You can alter the apperance of the static plots using the style sheet that comes with LobsterPy or use any of the readily available matplotlib style sheets" + ] + }, + { + "cell_type": "markdown", + "id": "affedb37", + "metadata": {}, + "source": [ + "### Plot COHPs / COBIS / COOPs from Analysis object\n", + "\n", + "It is important the `are_cobis`/`are_coops` args are set to `True` in the plotter depending on type of files you analyzed or want to plot. Here we will keep them false are we are plotting COHPs" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3da81099", + "metadata": {}, + "outputs": [], + "source": [ + "# Using PlainCohpPlotter to get static plots of relevant bonds from Analysis object\n", + "\n", + "style.use(get_style_list()[0]) # Use the LobsterPy style sheet for the generated plots\n", + "\n", + "cohp_plot_static = PlainCohpPlotter(are_cobis=False, are_coops=False)\n", + "for plot_label, label_list in analyse.get_site_bond_resolved_labels().items():\n", + " cohp = analyse.chemenv.completecohp.get_summed_cohp_by_label_list(label_list=label_list)\n", + " cohp_plot_static.add_cohp(plot_label, cohp)\n", + "cohp_plot_static.get_plot(ylim=[-15,2]);" + ] + }, + { + "cell_type": "markdown", + "id": "ee858f84", + "metadata": {}, + "source": [ + ":::{note}\n", + "You can get plots from orbital resolved anaylsis only when `orbital_resolved` arg is set to `True` when initializing Analysis object.\n", + ":::" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b01bf48a", + "metadata": {}, + "outputs": [], + "source": [ + "# Using PlainCohpPlotter to get static plots of relevant orbitals COHPs from Analysis object\n", + "\n", + "style.use('default') # Complete reset the matplotlib figure style\n", + "style.use('seaborn-v0_8-ticks') # use exsiting matplotlib style\n", + "\n", + "cohp_plot_static = PlainCohpPlotter()\n", + "for plot_label , orb_data in analyse.get_site_orbital_resolved_labels().items():\n", + " for orb, label_list in orb_data.items():\n", + " cohp = analyse.chemenv.completecohp.get_summed_cohp_by_label_and_orbital_list(label_list=label_list, \n", + " orbital_list=[orb]*len(label_list))\n", + " cohp_plot_static.add_cohp(orb, cohp)\n", + "cohp_plot_static.get_plot(ylim=[-15,2]);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "866cd67a", + "metadata": {}, + "outputs": [], + "source": [ + "# Using interactive plotter to add relevant cohps\n", + "interactive_cohp_plot = InteractiveCohpPlotter()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60f64578", + "metadata": {}, + "outputs": [], + "source": [ + "interactive_cohp_plot.add_all_relevant_cohps(analyse=analyse, label_resolved=False,orbital_resolved=True,suffix='')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b180bdfe", + "metadata": {}, + "outputs": [], + "source": [ + "fig = interactive_cohp_plot.get_plot()\n", + "fig.show(renderer='notebook')" + ] + }, + { + "cell_type": "markdown", + "id": "62780a77", + "metadata": {}, + "source": [ + "### Plot DOS from Lobster" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b3a9758b", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Load Lobster DOS\n", + "dos = Doscar(doscar='../../tests/test_data/NaCl_comp_range/DOSCAR.lobster.gz',\n", + " structure_file='../../tests/test_data/NaCl_comp_range/POSCAR.gz')" + ] + }, + { + "cell_type": "raw", + "id": "644a8c1c", + "metadata": {}, + "source": [ + "# Load Lobster DOS (Change this cell block type to Code when executing locally)\n", + "dos = Doscar(doscar='LobsterPy/tests/test_data/NaCl_comp_range/DOSCAR.lobster.gz',\n", + " structure_file='LobsterPy/tests/test_data/NaCl_comp_range/POSCAR.gz')" + ] + }, + { + "cell_type": "markdown", + "id": "6b75cf61", + "metadata": {}, + "source": [ + "Plot total, element and spd dos" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f0c863e3", + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "style.use('default') # Complete reset the matplotlib figure style\n", + "style.use(get_style_list()[0]) # Use the LobsterPy style sheet for the generated plots\n", + "\n", + "dos_plotter = PlainDosPlotter(summed=True, stack=False, sigma=None)\n", + "dos_plotter.add_dos(dos=dos.completedos, label='Total DOS')\n", + "dos_plotter.add_dos_dict(dos_dict=dos.completedos.get_element_dos()) # Add element dos\n", + "dos_plotter.add_dos_dict(dos_dict=dos.completedos.get_spd_dos()) # add spd dos\n", + "dos_plotter.get_plot(xlim=[-10, 3]);" + ] + }, + { + "cell_type": "markdown", + "id": "0c06ae48", + "metadata": {}, + "source": [ + "Plotting DOS at particular site and orbital" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "660b35ad", + "metadata": {}, + "outputs": [], + "source": [ + "dos_plotter = PlainDosPlotter(summed=True, stack=False, sigma=0.03)\n", + "dos_plotter.add_site_orbital_dos(dos = dos.completedos, site_index=0, orbital='3s')\n", + "dos_plotter.get_plot(xlim=[-10, 3]);" + ] + }, + { + "cell_type": "markdown", + "id": "e0d2525e", + "metadata": {}, + "source": [ + "## Generate structure graph objects with LOBSTER data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45988996", + "metadata": {}, + "outputs": [], + "source": [ + "from lobsterpy.structuregraph.graph import LobsterGraph" + ] + }, + { + "cell_type": "markdown", + "id": "f61fa956", + "metadata": {}, + "source": [ + "Below code snippet will generate a networkx graph object with ICOHP, ICOOP and ICOBI data as edge properites and charges as node properties." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29bea103", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "graph_NaCl_all = LobsterGraph(\n", + " path_to_poscar=\"../../tests/test_data/NaCl_comp_range/POSCAR.gz\",\n", + " path_to_charge=\"../../tests/test_data/NaCl_comp_range/CHARGE.lobster.gz\",\n", + " path_to_cohpcar=\"../../tests/test_data/NaCl_comp_range/COHPCAR.lobster.gz\",\n", + " path_to_icohplist=\"../../tests/test_data/NaCl_comp_range/ICOHPLIST.lobster.gz\",\n", + " add_additional_data_sg=True,\n", + " path_to_icooplist=\"../../tests/test_data/NaCl_comp_range/ICOOPLIST.lobster.gz\",\n", + " path_to_icobilist=\"../../tests/test_data/NaCl_comp_range/ICOBILIST.lobster.gz\",\n", + " path_to_madelung=\"../../tests/test_data/NaCl_comp_range/MadelungEnergies.lobster.gz\",\n", + " which_bonds=\"all\",\n", + " start=None,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "d6f47c59", + "metadata": {}, + "source": [ + "```python\n", + "#### (Change this cell block type to Code or copy when executing locally)\n", + "graph_NaCl_all = LobsterGraph(\n", + " path_to_poscar=\"LobsterPy/tests/test_data/NaCl_comp_range/POSCAR.gz\",\n", + " path_to_charge=\"LobsterPy/tests/test_data/NaCl_comp_range/CHARGE.lobster.gz\",\n", + " path_to_cohpcar=\"LobsterPy/tests/test_data/NaCl_comp_range/COHPCAR.lobster.gz\",\n", + " path_to_icohplist=\"LobsterPy/tests/test_data/NaCl_comp_range/ICOHPLIST.lobster.gz\",\n", + " add_additional_data_sg=True,\n", + " path_to_icooplist=\"LobsterPy/tests/test_data/NaCl_comp_range/ICOOPLIST.lobster.gz\",\n", + " path_to_icobilist=\"LobsterPy/tests/test_data/NaCl_comp_range/ICOBILIST.lobster.gz\",\n", + " path_to_madelung=\"LobsterPy/tests/test_data/NaCl_comp_range/MadelungEnergies.lobster.gz\",\n", + " which_bonds=\"all\",\n", + " start=None,\n", + ")\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "604bfa7e", + "metadata": {}, + "outputs": [], + "source": [ + "graph_NaCl_all.sg.graph.nodes.data() # view node data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c77c2b06", + "metadata": {}, + "outputs": [], + "source": [ + "graph_NaCl_all.sg.graph.edges.data() # view edge data" + ] + }, + { + "cell_type": "markdown", + "id": "b308aea8", + "metadata": {}, + "source": [ + "## Featurizer usage examples (Generates features from LOBSTER data for ML studies)" + ] + }, + { + "cell_type": "markdown", + "id": "8ae894fc", + "metadata": {}, + "source": [ + ":::{note}\n", + "To use the batch featurizers, the path to parent directory containing LOBSTER calculation outputs needs to be provided. For example your directory structure needs to be like this: \n", + "\n", + "parent_dir/lobster_calc_output_dir_for_compound_1/\n", + "parent_dir/lobster_calc_output_dir_for_compound_2/\n", + "parent_dir/lobster_calc_output_dir_for_compound_3/\n", + "\n", + "the `lobster_calc_output_dir_for_compound_*` directory should contain all your LOBSTER outputs and POSCAR file.\n", + "\n", + "In such a case `path_to_lobster_calcs=\"parent_dir\"` needs to be set \n", + ":::" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8882b3f5", + "metadata": {}, + "outputs": [], + "source": [ + "from lobsterpy.featurize.batch import (BatchCoxxFingerprint, BatchDosFeaturizer,\n", + " BatchSummaryFeaturizer, BatchStructureGraphs)" + ] + }, + { + "cell_type": "markdown", + "id": "5916fc58", + "metadata": {}, + "source": [ + "### BatchCoxxFingerprint" + ] + }, + { + "cell_type": "markdown", + "id": "8f6886ef", + "metadata": {}, + "source": [ + "`BatchCoxxFingerprint` provides an convenient way to directly generate fingerprint objects from COHP / COBI/ COOPCAR.lobster data. Generating fingerprints specificaly for `bonding`, `antibonding` and `overall` interactions is feasible. \n", + "\n", + "One can also generate a pair-wise fingerprint similarity matrix dataframe (currently only simple vector dot product or tanimoto index are implemented)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f4f0b721", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Initialize batch COXX featurizer \n", + "fp_cohp_bonding = BatchCoxxFingerprint(\n", + " path_to_lobster_calcs=\"../../tests/test_data/Featurizer_test_data/Lobster_calcs\",\n", + " e_range=[-15, 0], \n", + " feature_type=\"bonding\",\n", + " normalize=True, # affects the fingerprint similarity matrix computation\n", + " tanimoto=True, # affects the fingerprint similarity matrix computation\n", + " n_jobs=3,\n", + " fingerprint_for='cohp' # changing this to cobi/coop will result in reading cobicar/coopcar file\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "4d80d960", + "metadata": {}, + "source": [ + "```python\n", + "## Initialize batch COXX featurizer (Change this cell block type to Code and remove formatting when executing locally)\n", + "fp_cohp_bonding = BatchCoxxFingerprint(\n", + " path_to_lobster_calcs=\"LobsterPy/tests/test_data/Featurizer_test_data/Lobster_calcs\",\n", + " e_range=[-15, 0], \n", + " feature_type=\"bonding\",\n", + " normalize=True, # affects the fingerprint similarity matrix computation\n", + " tanimoto=True, # affects the fingerprint similarity matrix computation\n", + " n_jobs=3,\n", + " fingerprint_for='cohp' # changing this to cobi/coop will result in reading cobicar/coopcar file\n", + ")\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "823768ca", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Access fingerprint dataframe\n", + "fp_cohp_bonding.fingerprint_df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cafc1f90", + "metadata": {}, + "outputs": [], + "source": [ + "# Get fingerprint similarity matrix\n", + "fp_cohp_bonding.get_similarity_matrix_df()" + ] + }, + { + "cell_type": "markdown", + "id": "54277969", + "metadata": {}, + "source": [ + "### BatchDosFeaturizer" + ] + }, + { + "cell_type": "markdown", + "id": "99f617c6", + "metadata": {}, + "source": [ + "`BatchDosFeaturizer` provides an convenient way to extract LOBSTER DOS moment features and fingerprints in the form of pandas dataframe from LOBSTER calculation directory. The extracted features consist of following:\n", + "\n", + "\n", + "1. Element and PDOS center, width, skewness , kurtosis and edges \n", + "2. PDOS or total DOS fingerprint objects" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37e0c3b9", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Initialize batch DOS featurizer\n", + "batch_dos = BatchDosFeaturizer(path_to_lobster_calcs='../../tests/test_data/Featurizer_test_data/Lobster_calcs/', # path to parent lobster calcs\n", + " use_lso_dos=True, # will enforce using DOSCAR.LSO.lobster\n", + " add_element_dos_moments=True, # set to false to not have element moments dos features \n", + " e_range=None, # Can Set this to none for entire energy range \n", + " fingerprint_type=\"summed_pdos\", # fingerprint type (s,p,d,f, summed_pdos)\n", + " n_bins=256,\n", + " n_jobs=3,)" + ] + }, + { + "cell_type": "markdown", + "id": "a5cee556", + "metadata": {}, + "source": [ + "```python\n", + "## Initialize batch DOS featurizer (Change this cell block type to Code and remove formatting when executing locally)\n", + "batch_dos = BatchDosFeaturizer(path_to_lobster_calcs='LobsterPy/tests/test_data/Featurizer_test_data/Lobster_calcs/', # path to parent lobster calcs\n", + " use_lso_dos=True, # will enforce using DOSCAR.LSO.lobster\n", + " add_element_dos_moments=True, # set to false to not have element moments dos features \n", + " e_range=None, # Can Set this to none for entire energy range \n", + " fingerprint_type=\"summed_pdos\", # fingerprint type (s,p,d,f, summed_pdos)\n", + " n_bins=256,\n", + " n_jobs=3,)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3b958625", + "metadata": {}, + "outputs": [], + "source": [ + "# get dos moments df\n", + "batch_dos.get_df()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9ad30a1", + "metadata": {}, + "outputs": [], + "source": [ + "# get dos fingerprints df\n", + "batch_dos.get_fingerprints_df()" + ] + }, + { + "cell_type": "markdown", + "id": "13e2e7e6", + "metadata": {}, + "source": [ + "### BatchSummaryFeaturizer" + ] + }, + { + "cell_type": "markdown", + "id": "480f7ad9", + "metadata": {}, + "source": [ + "`BatchSummaryFeaturizer` provides an convenient way to extract summary stats in the form of pandas dataframe from LOBSTER calculation directory. The summary stats consist of following:\n", + "\n", + "1. ICOHP, bonding , antibonding percent (mean, min, max , standard deviation) of relevant bonds from LobsterPy analysis (Orbital wise anaylsis stats data can also be included : Optional)\n", + "2. Weighted ICOHP ( ICOOP/ ICOBI : Optional)\n", + "3. COHP center, width, skewness , kurtosis, edge (COOP/ COBI : Optional)\n", + "4. Ionicity and Madelung energies for the structure based on Mulliken and Loewdin charges" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bd0a22d9", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "# Initialize batch summary featurizer\n", + "summary_features = BatchSummaryFeaturizer(\n", + " path_to_lobster_calcs=\"../../tests/test_data/Featurizer_test_data/Lobster_calcs\",\n", + " bonds=\"all\",\n", + " include_cobi_data=False,\n", + " include_coop_data=False,\n", + " e_range=[-15, 0],\n", + " n_jobs=3,\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "cdded6c3", + "metadata": { + "scrolled": false + }, + "source": [ + "```python\n", + "## Initialize batch summary featurizer (Change this cell block type to Code and remove formatting when executing locally)\n", + "summary_features = BatchSummaryFeaturizer(\n", + " path_to_lobster_calcs=\"LobsterPy/tests/test_data/Featurizer_test_data/Lobster_calcs\",\n", + " bonds=\"all\",\n", + " include_cobi_data=False,\n", + " include_coop_data=False,\n", + " e_range=[-15, 0],\n", + " n_jobs=3,\n", + " )\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1bfad526", + "metadata": {}, + "outputs": [], + "source": [ + "summary_features.get_df()" + ] + }, + { + "cell_type": "markdown", + "id": "d273b59e", + "metadata": {}, + "source": [ + "### BatchStructureGraphs" + ] + }, + { + "cell_type": "markdown", + "id": "c0b4f493", + "metadata": {}, + "source": [ + "`BatchStructureGraphs` provides an convenient way to generate structure graph objects with LOBSTER data in the form of pandas dataframe from a set of LOBSTER calculation directories." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "25fa713b", + "metadata": { + "tags": [ + "remove-cell" + ] + }, + "outputs": [], + "source": [ + "batch_sg = BatchStructureGraphs(path_to_lobster_calcs='../../tests/test_data/Featurizer_test_data/Lobster_calcs/',\n", + " add_additional_data_sg=True,\n", + " which_bonds='all',\n", + " n_jobs=3,\n", + " start=None)" + ] + }, + { + "cell_type": "markdown", + "id": "7c784757", + "metadata": {}, + "source": [ + "```python\n", + "## Initialize batch structure graphs featurizer (Change this cell block type to Code and remove formatting when executing locally)\n", + "batch_sg = BatchStructureGraphs(path_to_lobster_calcs='LobsterPy/tests/test_data/Featurizer_test_data/Lobster_calcs/',\n", + " add_additional_data_sg=True,\n", + " which_bonds='all',\n", + " n_jobs=3,\n", + " start=None)\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a8178bc", + "metadata": {}, + "outputs": [], + "source": [ + "# get structure graphs df\n", + "batch_sg.get_df()" + ] + } + ], + "metadata": { + "hide_input": false, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/Lobsterpy_tutorial_files/COBI_330.png b/docs/tutorial/tutorial_assets/COBI_330.png similarity index 100% rename from docs/source/Lobsterpy_tutorial_files/COBI_330.png rename to docs/tutorial/tutorial_assets/COBI_330.png diff --git a/docs/source/Lobsterpy_tutorial_files/COHP.png b/docs/tutorial/tutorial_assets/COHP.png similarity index 100% rename from docs/source/Lobsterpy_tutorial_files/COHP.png rename to docs/tutorial/tutorial_assets/COHP.png diff --git a/docs/source/Lobsterpy_tutorial_files/COHP_330.png b/docs/tutorial/tutorial_assets/COHP_330.png similarity index 100% rename from docs/source/Lobsterpy_tutorial_files/COHP_330.png rename to docs/tutorial/tutorial_assets/COHP_330.png diff --git a/docs/source/Lobsterpy_tutorial_files/COOP_330.png b/docs/tutorial/tutorial_assets/COOP_330.png similarity index 100% rename from docs/source/Lobsterpy_tutorial_files/COOP_330.png rename to docs/tutorial/tutorial_assets/COOP_330.png diff --git a/docs/tutorial/tutorial_assets/CdF2.html b/docs/tutorial/tutorial_assets/CdF2.html new file mode 100755 index 00000000..7fe4e694 --- /dev/null +++ b/docs/tutorial/tutorial_assets/CdF2.html @@ -0,0 +1,14 @@ + + + +
+
+ + \ No newline at end of file diff --git a/docs/tutorial/tutorial_assets/CdF2_orb.html b/docs/tutorial/tutorial_assets/CdF2_orb.html new file mode 100755 index 00000000..b0b16460 --- /dev/null +++ b/docs/tutorial/tutorial_assets/CdF2_orb.html @@ -0,0 +1,14 @@ + + + +
+
+ + \ No newline at end of file diff --git a/docs/tutorial/tutorial_assets/DOS_example.png b/docs/tutorial/tutorial_assets/DOS_example.png new file mode 100644 index 00000000..a9f9f5ae Binary files /dev/null and b/docs/tutorial/tutorial_assets/DOS_example.png differ diff --git a/docs/source/Lobsterpy_tutorial_files/ICOHP.png b/docs/tutorial/tutorial_assets/ICOHP.png similarity index 100% rename from docs/source/Lobsterpy_tutorial_files/ICOHP.png rename to docs/tutorial/tutorial_assets/ICOHP.png diff --git a/docs/tutorial/tutorial_assets/ICOHPs_distance_example.png b/docs/tutorial/tutorial_assets/ICOHPs_distance_example.png new file mode 100644 index 00000000..eac2140c Binary files /dev/null and b/docs/tutorial/tutorial_assets/ICOHPs_distance_example.png differ diff --git a/docs/source/Lobsterpy_tutorial_files/Lobsterpy_tutorial_38_0.png b/docs/tutorial/tutorial_assets/Lobsterpy_tutorial_38_0.png similarity index 100% rename from docs/source/Lobsterpy_tutorial_files/Lobsterpy_tutorial_38_0.png rename to docs/tutorial/tutorial_assets/Lobsterpy_tutorial_38_0.png diff --git a/examples/example_script_NaCl_orbitalwise.py b/examples/example_script_NaCl_orbitalwise.py new file mode 100644 index 00000000..d33371fb --- /dev/null +++ b/examples/example_script_NaCl_orbitalwise.py @@ -0,0 +1,31 @@ +import os + +from lobsterpy.cohp.analyze import Analysis +from lobsterpy.cohp.describe import Description + +directory = "NaCl" + +# Setup analysis dict +analyse = Analysis( + path_to_poscar=os.path.join(directory, "POSCAR"), + path_to_icohplist=os.path.join(directory, "ICOHPLIST.lobster"), + path_to_cohpcar=os.path.join(directory, "COHPCAR.lobster"), + path_to_charge=os.path.join(directory, "CHARGE.lobster"), + which_bonds="all", + orbital_resolved=True, + orbital_cutoff=0.05, +) + +# Setup Description dict +describe = Description(analysis_object=analyse) +describe.write_description() + + + +# Automatic interactive plots +describe.plot_interactive_cohps(ylim=[-10, 2], xlim=[-4, 4], orbital_resolved=True, label_resolved=False) + +# different dicts that summarize the results +print(analyse.condensed_bonding_analysis) +print(analyse.final_dict_bonds) +print(analyse.final_dict_ions) diff --git a/lobsterpy/cli.py b/lobsterpy/cli.py index 5c656a44..1238263f 100644 --- a/lobsterpy/cli.py +++ b/lobsterpy/cli.py @@ -65,7 +65,9 @@ def get_parser() -> argparse.ArgumentParser: default="POSCAR", dest="structure", type=Path, - help='path to structure file. Default is "POSCAR"', + help='path to structure file. Default is "POSCAR". ' + 'Can also read "POSCAR.lobster" file or any ' + 'suitable file format supported by pymatgen "Structure.from_file" method.', ) potcar_file = argparse.ArgumentParser(add_help=False) @@ -95,7 +97,7 @@ def get_parser() -> argparse.ArgumentParser: default="COHPCAR.lobster", dest="cohpcar", type=Path, - help='path to COHPCAR.lobster. Default is "COHPCAR.lobster". This argument' + help='path to COHPCAR.lobster. Default is "COHPCAR.lobster". This argument ' "can also read COBICARs or COOPCARs. One needs to use appropriate --cobis or " "--coops options along with this argument when plotting", ) @@ -128,7 +130,7 @@ def get_parser() -> argparse.ArgumentParser: # Input args for specifically needed for calculation quality description calc_quality_description_file_group = ( - calc_quality_description_file_parent.add_argument_group() + calc_quality_description_file_parent.add_argument_group("") ) calc_quality_description_file_group.add_argument( "-fvasprun", @@ -435,7 +437,7 @@ def get_parser() -> argparse.ArgumentParser: # Argument that will help to switch automatic analysis analysis_switch = argparse.ArgumentParser(add_help=False) analysis_group = analysis_switch.add_argument_group( - "Arguments to switches type of files analyzed during automatic analysis" + "Arguments to switch type of files analyzed during automatic analysis" " (Also indicates file type for 'plot/plot-icohp-distance' action in cli)" ) analysis_group.add_argument( @@ -549,8 +551,8 @@ def get_parser() -> argparse.ArgumentParser: analysis_switch, ], help=( - "Deliver a text description of the COHPs or COBIS or COOP results from Lobster " - "and VASP" + "Deliver a text description from automatic analysis of COHPs or COBIS or COOP results " + "from Lobster run" ), ) subparsers.add_parser( @@ -688,8 +690,7 @@ def _element_basis(string: str): """ Parse element and basis from string. - Args: - string: string to parse + :param string: string to parse Returns: element, basis @@ -704,8 +705,7 @@ def _potcar_symbols(string: str): """ Parse string of potcar symbols and return a list. - Args: - string: string of potcar symbols + :param string: string of potcar symbols Returns: list of potcar symbols @@ -738,8 +738,7 @@ def run(args): """ Run actions based on args. - Args: - args: args for cli + :param args: args for cli """ if args.action in [ diff --git a/lobsterpy/cohp/analyze.py b/lobsterpy/cohp/analyze.py index 26c1708d..44724549 100644 --- a/lobsterpy/cohp/analyze.py +++ b/lobsterpy/cohp/analyze.py @@ -21,39 +21,51 @@ class Analysis: """ - Class to analyze COHP/COOP/COBI data from Lobster. + Class to automatically analyze COHP/COOP/COBI populations from Lobster. + + :param are_cobis: bool indicating if file contains COBI/ICOBI data + :param are_coops: bool indicating if file contains COOP/ICOOP data + :param cutoff_icohp: Cutoff in percentage for evaluating neighbors based on ICOHP values. + cutoff_icohp*max_icohp limits the number of considered neighbours for evaluating environments. + :param path_to_charge: path to `CHARGE.lobster`. + :param path_to_cohpcar: path to `COHPCAR.lobster` or `COBICAR.lobster` or `COOPCAR.lobster` . + :param path_to_icohplist: path to `ICOHPLIST.lobster` or `ICOBILIST.lobster` or `ICOOPLIST.lobster`. + :param path_to_poscar: path to structure (e.g., `POSCAR` or `POSCAR.lobster`) + :param path_to_madelung: path to `MadelungEnergies.lobster`. + :param noise_cutoff: Sets the lower limit tolerance for ICOHPs or ICOOPs or ICOBIs considered + in analysis. + :param orbital_cutoff: Sets the minimum percentage for the orbital contribution considered to be + relevant in orbital resolved analysis. (Affects only when orbital_resolved argument is set to True) + Set it to 0 to get results of all orbitals in the detected relevant bonds. Default is to 0.05 i.e. + only analyzes if orbital contribution is 5 % or more. + :param orbital_resolved: bool indicating whether orbital wise analysis is performed + :param type_charge: If no path_to_charge is given, Valences will be used. Otherwise, Mulliken charges. + Löwdin charges cannot be selected at the moment. + :param which_bonds: Selects kinds of bonds that are analyzed. `cation-anion` is the default. + Alternatively, `all` bonds can also be selected. Support to other kinds of bonds will be + added soon. + :param summed_spins: if True, COHP `Spin.up` and `Spin.down` populations will be summed + :param start: sets the lower limit of energy for evaluation of bonding and antibonding + percentages below efermi. Defaults to None (i.e., all populations below efermi are included) Attributes: - condensed_bonding_analysis: dict including a summary of the most important bonding properties - final_dict_bonds: dict including information on ICOHPs per bond type - final_dict_ions: dict including information on environments of cations - chemenv: pymatgen.io.lobster.lobsterenv.LobsterNeighbors object - lse: LightStructureEnvironment from pymatgen - cutoff_icohp: Cutoff in percentage for evaluating neighbors based on ICOHP values. - cutoff_icohp*max_icohp limits the number of considered environments - anion_types: Set of Element objects from pymatgen - list_equivalent_sites: list of site indices of sites that indicate which sites are equivalent - e.g., [0 1 2 2 2] where site 0, 1, 2 indicate sites that are independent from each other - path_to_charge: str that describes the path to CHARGE.lobster - path_to_cohpcar: str that describes the path to COHPCAR.lobster - path_to_icohplist: str that describes the path to ICOHPLIST.lobster - path_to_poscar: str that describes path to POSCAR - path_to_madelung: str that describes path to POSCAR - are_cobis : bool indicating if file contains COBI/ICOBI data - are_coops : bool indicating if file contains COOP/ICOOP data - noise_cutoff : float that sets the lower limit of icohps or icoops or icobis considered - seq_cohps: list of cohps - seq_coord_ions: list of co-ordination environment strings for each cation - seq_equivalent_sites: seq of inequivalent sites - seq_ineq_ions: seq of inequivalent cations/sites in the structure - seq_infos_bonds (list): information on cation anion bonds (lists - of pymatgen.io.lobster.lobsterenv.ICOHPNeighborsInfo) - spg: space group information - structure: Structure object - type_charge: which charges are considered here - orbital_resolved: bool indicating whether analysis is performed - orbital wise - which_bonds: which bonds will be considered in analysis + - condensed_bonding_analysis: dict including a summary of the most important bonding properties + - final_dict_bonds: dict including information on ICOHPs per bond type + - final_dict_ions: dict including information on environments of cations + - chemenv: pymatgen.io.lobster.lobsterenv.LobsterNeighbors object + - lse: LightStructureEnvironment from pymatgen + - anion_types: Set of Element objects from pymatgen + - list_equivalent_sites: list of site indices of sites that indicate which sites are equivalent + e.g., [0 1 2 2 2] where site 0, 1, 2 indicate sites that are independent from each other + - seq_cohps: list of cohps + - seq_coord_ions: list of co-ordination environment strings for each cation + - seq_equivalent_sites: seq of inequivalent sites + - seq_ineq_ions: seq of inequivalent cations/sites in the structure + - seq_infos_bonds (list): information on cation anion bonds (lists + of pymatgen.io.lobster.lobsterenv.ICOHPNeighborsInfo) + - spg: space group information + - structure: Structure object + """ def __init__( @@ -63,40 +75,44 @@ def __init__( path_to_cohpcar: str | Path, path_to_charge: str | Path | None = None, path_to_madelung: str | Path | None = None, - which_bonds: str = "cation-anion", + are_cobis: bool = False, + are_coops: bool = False, cutoff_icohp: float = 0.1, noise_cutoff: float = 0.1, orbital_cutoff: float = 0.05, - summed_spins=True, - are_cobis=False, - are_coops=False, - type_charge=None, - start=None, - orbital_resolved=False, + orbital_resolved: bool = False, + start: float | None = None, + summed_spins: bool = True, + type_charge: str | None = None, + which_bonds: str = "cation-anion", ): """ - Automatically analyze bonding information with this class. - - Args: - path_to_poscar: path to POSCAR (e.g., "POSCAR") - path_to_icohplist: path to ICOHPLIST.lobster (e.g., "ICOHPLIST.lobster") - path_to_cohpcar: path to COHPCAR.lobster (e.g., "COHPCAR.lobster") - path_to_charge: path to CHARGE.lobster (e.g., "CHARGE.lobster") - path_to_madelung: path to MadelungEnergies.lobster (e.g., "MadelungEnergies.lobster") - are_cobis : bool indicating if file contains COBI/ICOBI data - are_coops : bool indicating if file contains COOP/ICOOP data - noise_cutoff : float that sets the lower limit of icohps or icoops or icobis considered - orbital_cutoff : float that sets the minimum percentage for the orbital resolved analysis. - (Affects only when orbital_resolved argument is set to True) Set it to 0 to get results - of all orbitals in the detected relevant bonds. Default is to 0.05 i.e. only analyzes - if orbital contribution is 5 % or more. - which_bonds: selects which kind of bonds are analyzed. "cation-anion" is the default - cutoff_icohp: only bonds that are stronger than cutoff_icohp*strongest ICOHP will be considered - summed_spins: if true, spins will be summed - type_charge: If no path_to_charge is given, Valences will be used. Otherwise, Mulliken charges. - Löwdin charges cannot be selected at the moment. - orbital_resolved: bool indicating whether analysis is performed orbital wise - start: start energy for integration + Initialize automatic bonding analysis. + + :param are_cobis: bool indicating if file contains COBI/ICOBI data + :param are_coops: bool indicating if file contains COOP/ICOOP data + :param cutoff_icohp: Cutoff in percentage for evaluating neighbors based on ICOHP values. + cutoff_icohp*max_icohp limits the number of considered neighbours for evaluating environments. + :param path_to_charge: path to `CHARGE.lobster`. + :param path_to_cohpcar: path to `COHPCAR.lobster` or `COBICAR.lobster` or `COOPCAR.lobster` . + :param path_to_icohplist: path to `ICOHPLIST.lobster` or `ICOBILIST.lobster` or `ICOOPLIST.lobster`. + :param path_to_poscar: path to structure (e.g., `POSCAR` or `POSCAR.lobster`) + :param path_to_madelung: path to `MadelungEnergies.lobster`. + :param noise_cutoff: Sets the lower limit tolerance for ICOHPs or ICOOPs or ICOBIs considered + in analysis. + :param orbital_cutoff: Sets the minimum percentage for the orbital contribution considered to be + relevant in orbital resolved analysis. (Affects only when orbital_resolved argument is set to True) + Set it to 0 to get results of all orbitals in the detected relevant bonds. Default is to 0.05 i.e. + only analyzes if orbital contribution is 5 % or more. + :param orbital_resolved: bool indicating whether orbital wise analysis is performed + :param type_charge: If no path_to_charge is given, Valences will be used. Otherwise, Mulliken charges. + Löwdin charges cannot be selected at the moment. + :param which_bonds: Selects kinds of bonds that are analyzed. `cation-anion` is the default. + Alternatively, `all` bonds can also be selected. Support to other kinds of bonds will be + added soon. + :param summed_spins: if True, COHP `Spin.up` and `Spin.down` populations will be summed + :param start: sets the lower limit of energy for evaluation of bonding and antibonding + percentages below efermi. Defaults to None (i.e., all populations below efermi are included) """ self.start = start @@ -215,9 +231,8 @@ def __init__(self, chemenv, valences=None): """ Test class when error was raised. - Args: - chemenv (LobsterNeighbors): LobsterNeighbors object - valences: list of valences + :param chemenv: LobsterNeighbors object + :param valences: list of valences """ if valences is None: @@ -243,7 +258,7 @@ def __init__(self, chemenv, valences=None): # make a new list self.lse = Lse(self.chemenv.list_coords, self.chemenv.valences) - def get_information_all_bonds(self, summed_spins=True): + def get_information_all_bonds(self, summed_spins: bool = True): """ Gather all information on the bonds within the compound with this method. @@ -370,17 +385,21 @@ def get_site_bond_resolved_labels(self): return label_data def _get_orbital_resolved_data( - self, nameion, iion, labels, bond_resolved_labels, type_pop + self, + nameion: str, + iion: int, + labels: list[str], + bond_resolved_labels: dict[str, list[str]], + type_pop: str, ): """ Retrieve orbital-wise analysis data. - Args: - nameion: name of symmetrically relevant cation or anion - iion: index of symmetrically relevant cation or anion - labels: list of bond label names - bond_resolved_labels: dict of bond labels from ICOHPLIST resolved for each bond - type_pop: population type analyzed. e.g. COHP or COOP or COBI + :param nameion: name of symmetrically relevant cation or anion + :param iion: index of symmetrically relevant cation or anion + :param labels: list of bond label names + :param bond_resolved_labels: dict of bond labels from ICOHPLIST resolved for each bond + :param type_pop: population type analyzed. e.g. COHP or COOP or COBI Returns: dict consisting of relevant orbitals (contribution > 5 % to overall ICOHP or ICOBI or ICOOP), @@ -430,7 +449,7 @@ def _get_orbital_resolved_data( cohp=cohp_summed, start=self.start ) - orb_bonding_dict_data = {} + orb_bonding_dict_data = {} # type: ignore # For each orbital collect the contributions of summed bonding # and antibonding interactions separately for orb in available_orbitals: @@ -576,7 +595,7 @@ def _get_orbital_resolved_data( }, } - orb_bonding_dict_data["relevant_bonds"] = bond_labels + orb_bonding_dict_data["relevant_bonds"] = bond_labels # type: ignore orb_resolved_bond_info[bond_resolved_label_key] = orb_bonding_dict_data @@ -586,8 +605,7 @@ def _get_bond_resolved_data_stats(self, orb_resolved_bond_data: dict): """ Retrieve the maximum bonding and anti-bonding orbital contributions. - Args: - orb_resolved_bond_data: A dictionary with orbital names as keys and corresponding bonding data + :param orb_resolved_bond_data: A dictionary with orbital names as keys and corresponding bonding data Returns: dict with orbital data stats the site for relevant orbitals, e.g. @@ -681,14 +699,15 @@ def get_site_orbital_resolved_labels(self): return orb_plot_data @staticmethod - def _get_strenghts_for_each_bond(pairs, strengths, nameion=None): + def _get_strenghts_for_each_bond( + pairs: list[list[str]], strengths: list[float], nameion: str | None = None + ): """ Return a dictionary of bond strengths. - Args: - pairs: list of list including labels for the atoms, e.g., [['O3', 'Cu1'], ['O3', 'Cu1']] - strengths (list of float): list that gives the icohp strengths as a float, [-1.86287, -1.86288] - nameion: string including the name of the cation in the list, e.g Cu1 + :param pairs: list of list including labels for the atoms, e.g., [['O3', 'Cu1'], ['O3', 'Cu1']] + :param strengths: list that gives the icohp strengths as a float, [-1.86287, -1.86288] + :param nameion: string including the name of the cation in the list, e.g Cu1 Returns: dict including inormation on icohps for each bond type, e.g. @@ -696,7 +715,7 @@ def _get_strenghts_for_each_bond(pairs, strengths, nameion=None): """ - dict_strenghts = {} + dict_strenghts = {} # type: ignore for pair, strength in zip(pairs, strengths): if nameion is not None: @@ -721,13 +740,12 @@ def _get_strenghts_for_each_bond(pairs, strengths, nameion=None): return dict_strenghts @staticmethod - def _sort_name(pair, nameion=None): + def _sort_name(pair: list[str], nameion: str | None = None): """ Place the cation first in a list of name strings. - Args: - pair: ["O","Cu"] - nameion: "Cu" + :param pair: ["O","Cu"] + :param nameion: "Cu" Returns: will return list of str, e.g. ["Cu", "O"] @@ -747,7 +765,7 @@ def _sort_name(pair, nameion=None): @staticmethod def _sort_orbital_atom_pair( - atom_pair: list, + atom_pair: list[str], label: str, complete_cohp: CompleteCohp, orb_pair: str, @@ -755,11 +773,10 @@ def _sort_orbital_atom_pair( """ Place the cation first in a list of name strings and add the associated orbital name alongside the atom name. - Args: - atom_pair: list of atom pair with cation first eg., ["Cl","Na"] - label: LOBSTER relevant bond label eg ., "3" - complete_cohp: pymatgen CompleteCohp object - orb_pair: relevant orbital pair eg., "2px-3s" + :param atom_pair: list of atom pair with cation first eg., ["Cl","Na"] + :param label: LOBSTER relevant bond label eg ., "3" + :param complete_cohp: pymatgen CompleteCohp object + :param orb_pair: relevant orbital pair eg., "2px-3s" Returns: will return list of str, e.g. ["Na(2px)", "Cl(3s)"] @@ -790,17 +807,18 @@ def _sort_orbital_atom_pair( return orb_atom_list - def _get_antibdg_states(self, cohps, labels, nameion=None, limit=0.01): + def _get_antibdg_states( + self, cohps, labels: list[str], nameion: str | None = None, limit=0.01 + ): """ Return a dictionary containing information on anti-bonding states. e.g., similar to: {'Cu-O': True, 'Cu-F': True} - Args: - cohps: list of pymatgen.electronic_structure.cohp.Cohp objects - labels: ['2 x Cu-O', '4 x Cu-F'] - nameion: string of the cation name, e.g. "Cu" - limit: limit to detect antibonding states + :param cohps: list of pymatgen.electronic_structure.cohp.Cohp objects + :param labels: ['2 x Cu-O', '4 x Cu-F'] + :param nameion: string of the cation name, e.g. "Cu" + :param limit: limit to detect antibonding states Returns: dict including in formation on whether antibonding interactions exist, @@ -828,7 +846,9 @@ def _get_antibdg_states(self, cohps, labels, nameion=None, limit=0.01): return dict_antibd - def _integrate_antbdstates_below_efermi_for_set_cohps(self, labels, cohps, nameion): + def _integrate_antbdstates_below_efermi_for_set_cohps( + self, labels: list[str], cohps, nameion: str + ): """ Return a dictionary containing information on antibonding states. @@ -840,10 +860,9 @@ def _integrate_antbdstates_below_efermi_for_set_cohps(self, labels, cohps, namei e.g. output: {'Cu-O': {'integral': 4.24374775705, 'perc': 5.7437713186999995}, 'Cu-F': {'integral': 3.07098300965, 'perc': 4.25800841445}} - Args: - cohps: list of pymatgen.electronic_structure.cohp.Cohp objects - labels: ['2 x Cu-O', '4 x Cu-F'] - nameion: string of the cation name, e.g. "Cu" + :param cohps: list of pymatgen.electronic_structure.cohp.Cohp objects + :param labels: ['2 x Cu-O', '4 x Cu-F'] + :param nameion: string of the cation name, e.g. "Cu" Returns: dict including in formation on whether antibonding interactions exist, @@ -894,7 +913,7 @@ def _integrate_antbdstates_below_efermi_for_set_cohps(self, labels, cohps, namei return dict_bd_antibd - def _integrate_antbdstates_below_efermi(self, cohp, start): + def _integrate_antbdstates_below_efermi(self, cohp, start: float | None): """ Integrate the cohp data to compute bonding and anti-bonding contribution below efermi. @@ -907,9 +926,8 @@ def _integrate_antbdstates_below_efermi(self, cohp, start): If COHPstartEnergy value does not cover entire range of VASP calculations then absolute value of ICOHP_sum might not be equivalent to (bonding- antibonding) integral values. - Args: - cohp: cohp object - start: integration start energy in eV , eg start = -15 + :param cohp: cohp object + :param start: integration start energy in eV , eg start = -15 Returns: absolute value of antibonding, percentage value of antibonding, @@ -928,9 +946,8 @@ def integrate_positive(y, x): """ Integrate only bonding interactions of COHPs. - Args: - y: COHP values - x: Energy values + :param y: COHP values + :param x: Energy values Returns: integrated value of bonding interactions @@ -946,9 +963,8 @@ def integrate_negative(y, x): """ Integrate only anti-bonding interactions of COHPs. - Args: - y: COHP values - x: Energy values + :param y: COHP values + :param x: Energy values Returns: integrated value of anti-bonding interactions @@ -1023,21 +1039,20 @@ def _get_pop_type(self): @staticmethod def _get_bond_dict( - bond_strength_dict, - small_antbd_dict, - nameion=None, - large_antbd_dict=None, - type_pop=None, + bond_strength_dict: dict, + small_antbd_dict: dict, + nameion: str | None = None, + large_antbd_dict: dict | None = None, + type_pop: str | None = None, ): """ Return a bond_dict that contains information for each site. - Args: - bond_strength_dict (dict): dict with bond names as key and lists of bond strengths as items - small_antbd_dict (dict): dict including if there are antibonding interactions, {'Yb-Sb': False} - nameion (str): name of the cation, e.g. Yb - large_antbd_dict: will be implemented later - type_pop: population type analyzed. eg. COHP + :param bond_strength_dict: dict with bond names as key and lists of bond strengths as items + :param small_antbd_dict: dict including if there are antibonding interactions, {'Yb-Sb': False} + :param nameion: name of the cation, e.g. Yb + :param large_antbd_dict: will be implemented later + :param type_pop: population type analyzed. eg. COHP Returns: Eg., if type_pop == 'COHP', will return @@ -1432,20 +1447,19 @@ def get_lobster_calc_quality_summary( """ Analyze LOBSTER calculation quality. - Args: - path_to_poscar: path to structure file - path_to_lobsterout: path to lobsterout file - path_to_lobsterin: path to lobsterin file - path_to_potcar: path to VASP potcar file - potcar_symbols: list of potcar symbols from postcar file (can be used if no potcar available) - path_to_charge: path to CHARGE.lobster file - path_to_bandoverlaps: path to bandOverlaps.lobster file - path_to_doscar: path to DOSCAR.lobster or DOSCAR.LSO.lobster file - path_to_vasprun: path to vasprun.xml file - dos_comparison: will compare DOS from VASP and LOBSTER and return tanimoto index - e_range: energy range for DOS comparisons - n_bins: number of bins to discretize DOS for comparisons - bva_comp: Compares LOBSTER charge signs with Bond valence charge signs + :param path_to_poscar: path to structure file + :param path_to_lobsterout: path to lobsterout file + :param path_to_lobsterin: path to lobsterin file + :param path_to_potcar: path to VASP potcar file + :param potcar_symbols: list of potcar symbols from postcar file (can be used if no potcar available) + :param path_to_charge: path to CHARGE.lobster file + :param path_to_bandoverlaps: path to bandOverlaps.lobster file + :param path_to_doscar: path to DOSCAR.lobster or DOSCAR.LSO.lobster file + :param path_to_vasprun: path to vasprun.xml file + :param dos_comparison: will compare DOS from VASP and LOBSTER and return tanimoto index + :param e_range: energy range for DOS comparisons + :param n_bins: number of bins to discretize DOS for comparisons + :param bva_comp: Compares LOBSTER charge signs with Bond valence charge signs Returns: A dict of summary of LOBSTER calculation quality by analyzing basis set used, diff --git a/lobsterpy/cohp/describe.py b/lobsterpy/cohp/describe.py index 2c3dfa42..cbc75bf7 100644 --- a/lobsterpy/cohp/describe.py +++ b/lobsterpy/cohp/describe.py @@ -21,8 +21,7 @@ def __init__(self, analysis_object): """ Generate a text description for all relevant bonds. - Args: - analysis_object: Analysis object from lobsterpy.analysis + :param analysis_object: Analysis object from lobsterpy.analysis """ self.analysis_object = analysis_object self.set_description() @@ -274,11 +273,10 @@ def _generate_orbital_resolved_analysis_text( """ Generate text from orbital-resolved analysis data of the most relevant COHP, COOP, or COBI. - Args: - orbital_resolved_data : dict of orbital data from condensed bonding analysis object - ion: name of ion at the site - atom_name: name of atomic speice to which ion is bonded - type_pop: population type analysed could be "COHP" or "COOP" or "COBI" + :param orbital_resolved_data: dict of orbital data from condensed bonding analysis object + :param ion: name of ion at the site + :param atom_name: name of atomic speice to which ion is bonded + :param type_pop: population type analysed could be "COHP" or "COOP" or "COBI" Returns: A python list with text describing the orbital which contributes @@ -438,28 +436,27 @@ def _generate_orbital_resolved_analysis_text( def plot_cohps( self, - save=False, - filename=None, - ylim=[-4, 2], - xlim=None, - integrated=False, - title="", - sigma=None, - hide=False, + xlim: list[float] | None = None, + ylim: list[float] | None = [-4, 2], + integrated: bool = False, + title: str = "", + save: bool = False, + filename: str | None = None, + sigma: float | None = None, + hide: bool = False, ): """ Automatically generate plots of the most relevant COHPs, COOPs, or COBIs. - Args: - save (bool): will save the plot to a file - filename (str/Path): name of the file to save the plot. - ylim (list of float): energy scale that is shown in plot (eV) - xlim(list of float): energy range for COHPs in eV - integrated (bool): if True, integrated COHPs will be shown - sigma: Standard deviation of Gaussian broadening applied to + :param save: will save the plot to a file + :param filename: name of the file to save the plot. + :param ylim: energy scale that is shown in plot (eV) + :param xlim: energy range for COHPs in eV + :param integrated: if True, integrated COHPs will be shown + :param sigma: Standard deviation of Gaussian broadening applied to population data. If None, no broadening will be added. - title: sets the title of figure generated - hide (bool): if True, the plot will not be shown. + :param title: sets the title of figure generated + :param hide: if True, the plot will not be shown. Returns: A matplotlib object. @@ -495,9 +492,9 @@ def plot_cohps( if save: if len(seq_ineq_cations) > 1: if isinstance(filename, str): - filename = Path(filename) + filename = Path(filename) # type: ignore filename_new = ( - filename.parent / f"{filename.stem}-{iplot}{filename.suffix}" + filename.parent / f"{filename.stem}-{iplot}{filename.suffix}" # type: ignore ) else: filename_new = filename @@ -510,32 +507,31 @@ def plot_cohps( def plot_interactive_cohps( self, - save_as_html=False, - filename=None, - ylim=None, - xlim=None, - integrated=False, - title="", - sigma=None, - label_resolved=False, - orbital_resolved=False, - hide=False, + ylim: list[float] | None = None, + xlim: list[float] | None = None, + save_as_html: bool = False, + filename: str | None = None, + integrated: bool = False, + title: str = "", + sigma: float | None = None, + label_resolved: bool = False, + orbital_resolved: bool = False, + hide: bool = False, ): """ Automatically generate interactive plots of the most relevant COHPs, COBIs or COOPs. - Args: - save_as_html (bool): will save the plot to a html file - filename (str/Path): name of the file to save the plot. - ylim (list of float): energy scale that is shown in plot (eV) - xlim (list of float): energy range for COHPs in eV - integrated (bool): if True, integrated COHPs will be shown - sigma: Standard deviation of Gaussian broadening applied to + :param save_as_html: will save the plot to a html file + :param filename: name of the file to save the plot. + :param ylim: energy scale that is shown in plot (eV) + :param xlim: energy range for COHPs in eV + :param integrated: if True, integrated COHPs will be shown + :param sigma: Standard deviation of Gaussian broadening applied to population data. If None, no broadening will be added. - label_resolved: if true, relevant cohp curves will be further resolved based on band labels - orbital_resolved: if true, relevant orbital interactions in cohp curves will be added to figure - title : Title of the interactive plot - hide (bool): if True, the plot will not be shown. + :param label_resolved: if true, relevant cohp curves will be further resolved based on band labels + :param orbital_resolved: if true, relevant orbital interactions in cohp curves will be added to figure + :param title: Title of the interactive plot + :param hide: if True, the plot will not be shown. Returns: A plotly.graph_objects.Figure object. @@ -578,12 +574,11 @@ def plot_interactive_cohps( return plot @staticmethod - def _coordination_environment_to_text(ce): + def _coordination_environment_to_text(ce: str): """ Convert a coordination environment string into a text description of the environment. - Args: - ce (str): output from ChemEnv package (e.g., "O:6") + :param ce: output from ChemEnv package (e.g., "O:6") Returns: A text description of coordination environment @@ -794,8 +789,7 @@ def get_calc_quality_description(quality_dict): """ Generate a text description of the LOBSTER calculation quality. - Args: - quality_dict: python dictionary from lobsterpy.analysis.get_lobster_calc_quality_summary + :param quality_dict: python dictionary from lobsterpy.analysis.get_lobster_calc_quality_summary """ text_des = [] diff --git a/lobsterpy/featurize/batch.py b/lobsterpy/featurize/batch.py index 8e1a4daf..3c572ecd 100644 --- a/lobsterpy/featurize/batch.py +++ b/lobsterpy/featurize/batch.py @@ -9,7 +9,6 @@ import os import warnings from pathlib import Path -from typing import NamedTuple import numpy as np import pandas as pd @@ -17,6 +16,7 @@ from tqdm.autonotebook import tqdm from lobsterpy.featurize.core import ( + CoxxFingerprint, FeaturizeCharges, FeaturizeCOXX, FeaturizeDoscar, @@ -31,22 +31,18 @@ class BatchSummaryFeaturizer: """ Batch Featurizer sets that generates summary features from lobster data. - Args: - path_to_lobster_calcs: path to root directory consisting of all lobster calc - path_to_jsons: path to root directory consisting of all lobster lightweight jsons - feature_type: set the feature type for moment features. - Possible options are "bonding", "antibonding" or "overall" - charge_type : set charge type used for computing ionicity. Possible options are - "mulliken", "loewdin or "both" - bonds: "all_bonds" or "cation_anion_bonds" - orbital_resolved: bool indicating whether LobsterPy analysis is performed orbital wise - include_cobi_data : bool stating to include COBICAR.lobster features - include_coop_data: bool stating to include COOPCAR.lobster features - e_range : range of energy relative to fermi for which moment features needs to be computed - n_jobs : parallel processes to run - - Attributes: - get_df: A pandas dataframe with summary features + :param path_to_lobster_calcs: path to root directory consisting of all lobster calc + :param path_to_jsons: path to root directory consisting of all lobster lightweight jsons + :param feature_type: set the feature type for moment features. + Possible options are `bonding`, `antibonding` or `overall` + :param charge_type: set charge type used for computing ionicity. Possible options are + `mulliken`, `loewdin` or `both`. + :param bonds: `all_bonds` or `cation_anion_bonds` + :param orbital_resolved: bool indicating whether LobsterPy analysis is performed orbital wise + :param include_cobi_data: bool stating to include COBICAR.lobster features + :param include_coop_data: bool stating to include COOPCAR.lobster features + :param e_range: range of energy relative to fermi for which moment features needs to be computed + :param n_jobs: parallel processes to run """ def __init__( @@ -65,20 +61,18 @@ def __init__( """ Featurize lobster data via multiprocessing for large number of compounds. - Args: - path_to_lobster_calcs: path to root directory consisting of all lobster calc - path_to_jsons: path to root directory consisting of all lobster lightweight jsons - feature_type: set the feature type for moment features. - Possible options are "bonding", "antibonding" or "overall" - charge_type : set charge type used for computing ionicity. Possible options are - "mulliken", "loewdin or "both" - bonds: "all_bonds" or "cation_anion_bonds" - orbital_resolved: bool indicating whether LobsterPy analysis is performed orbital wise - include_cobi_data : bool stating to include COBICAR.lobster features - include_coop_data: bool stating to include COOPCAR.lobster features - e_range : range of energy relative to fermi for which moment features needs to be computed - n_jobs : parallel processes to run - + :param path_to_lobster_calcs: path to root directory consisting of all lobster calc + :param path_to_jsons: path to root directory consisting of all lobster lightweight jsons + :param feature_type: set the feature type for moment features. + Possible options are `bonding`, `antibonding` or `overall` + :param charge_type: set charge type used for computing ionicity. Possible options are + `mulliken`, `loewdin` or `both`. + :param bonds: `all_bonds` or `cation_anion_bonds` + :param orbital_resolved: bool indicating whether LobsterPy analysis is performed orbital wise + :param include_cobi_data: bool stating to include COBICAR.lobster features + :param include_coop_data: bool stating to include COOPCAR.lobster features + :param e_range: range of energy relative to fermi for which moment features needs to be computed + :param n_jobs: parallel processes to run """ self.path_to_lobster_calcs = path_to_lobster_calcs self.path_to_jsons = path_to_jsons @@ -91,11 +85,14 @@ def __init__( self.e_range = e_range self.n_jobs = n_jobs - def _featurizelobsterpy(self, file_name_or_path) -> pd.DataFrame: + def _featurizelobsterpy(self, file_name_or_path: str | Path) -> pd.DataFrame: """ Featurize Lobsterpy condensed bonding analysis data. - if lightweight json file exists loads that or invokes LobsterPy Analysis class + if lightweight json file exists loads that or invokes LobsterPy Analysis class. + + :param file_name_or_path: path to the LOBSTER calc directory or + lightweight condensed bonding analysis json file name. Returns: A pandas dataframe with ICOHP stats like mean, min, max of relevant bonds and @@ -117,10 +114,12 @@ def _featurizelobsterpy(self, file_name_or_path) -> pd.DataFrame: return featurize_lobsterpy.get_df() - def _featurizecoxx(self, path_to_lobster_calc) -> pd.DataFrame: + def _featurizecoxx(self, path_to_lobster_calc: str | Path) -> pd.DataFrame: """ Featurize COHP/COBI/COOPCAR data using FeaturizeCOXX. + :param path_to_lobster_calc: path to root LOBSTER calc directory + Returns: A pandas dataframe with COHP summary stats data mainly weighted ICOHP/ICOOP/ICOBI, Effective interaction number and moment features (center, width, skewness and kurtosis) @@ -258,10 +257,12 @@ def _featurizecoxx(self, path_to_lobster_calc) -> pd.DataFrame: return df - def _featurizecharges(self, path_to_lobster_calc) -> pd.DataFrame: + def _featurizecharges(self, path_to_lobster_calc: str | Path) -> pd.DataFrame: """ Featurize CHARGE.lobster.gz data that using FeaturizeCharges. + :param path_to_lobster_calc: path to root LOBSTER calc directory + Returns: A pandas dataframe with computed ionicity for the structure @@ -413,24 +414,21 @@ class BatchCoxxFingerprint: """ BatchFeaturizer to generate COHP/COOP/COBI fingerprints and Tanimoto index similarity matrix. - Args: - path_to_lobster_calcs: path to root directory consisting of all lobster calc - feature_type: set the feature type for moment features. - Possible options are "bonding", "antibonding" or "overall" - label_list: bond labels list for which fingerprints needs to be generated. - tanimoto : bool to state to compute tanimoto index between fingerprint objects - normalize: bool to state to normalize the fingerprint data - n_bins: sets number for bins for fingerprint objects - e_range : range of energy relative to fermi for which moment features needs to be computed - n_jobs : number of parallel processes to run - fingerprint_for: Possible options are 'cohp/cobi/coop'. + :param path_to_lobster_calcs: path to root directory consisting of all lobster calc + :param feature_type: set the feature type for moment features. + Possible options are `bonding`, `antibonding` or `overall` + :param label_list: bond labels list for which fingerprints needs to be generated. + :param tanimoto: bool to state to compute tanimoto index between fingerprint objects + :param normalize: bool to state to normalize the fingerprint data + :param spin_type: can be `summed` or `up` or `down`. + :param n_bins: sets number for bins for fingerprint objects + :param e_range: range of energy relative to fermi for which moment features needs to be computed + :param n_jobs: number of parallel processes to run + :param fingerprint_for: Possible options are `cohp` or `cobi` or `coop`. Based on this fingerprints will be computed for COHPCAR/COOBICAR/COOPCAR.lobster files Attributes: fingerprint_df: A pandas dataframe with fingerprint objects - get_similarity_matrix_df: A symmetric pandas dataframe consisting of - similarity index (tanimoto/normalized dot product/dot product) - computed between all pairs of compounds """ def __init__( @@ -449,20 +447,18 @@ def __init__( """ Generate COHP/COOP/COBI fingerprints and pair-wise Tanimoto index similarity matrix. - Args: - path_to_lobster_calcs: path to root directory consisting of all lobster calc - feature_type: set the feature type for moment features. - Possible options are "bonding", "antibonding" or "overall" - label_list: bond labels list for which fingerprints needs to be generated. - tanimoto : bool to state to compute tanimoto index between fingerprint objects - normalize: bool to state to normalize the fingerprint data - spin_type: can be summed or up or down. - n_bins: sets number for bins for fingerprint objects - e_range : range of energy relative to fermi for which moment features needs to be computed - n_jobs : number of parallel processes to run - fingerprint_for: Possible options are 'cohp/cobi/coop'. + :param path_to_lobster_calcs: path to root directory consisting of all lobster calc + :param feature_type: set the feature type for moment features. + Possible options are `bonding`, `antibonding` or `overall` + :param label_list: bond labels list for which fingerprints needs to be generated. + :param tanimoto: bool to state to compute tanimoto index between fingerprint objects + :param normalize: bool to state to normalize the fingerprint data + :param spin_type: can be `summed` or `up` or `down`. + :param n_bins: sets number for bins for fingerprint objects + :param e_range: range of energy relative to fermi for which moment features needs to be computed + :param n_jobs: number of parallel processes to run + :param fingerprint_for: Possible options are `cohp` or `cobi` or `coop`. Based on this fingerprints will be computed for COHPCAR/COOBICAR/COOPCAR.lobster files - """ self.path_to_lobster_calcs = path_to_lobster_calcs self.feature_type = feature_type @@ -512,12 +508,11 @@ def get_similarity_matrix_df(self) -> pd.DataFrame: ) @staticmethod - def _fp_to_dict(fp) -> dict: + def _fp_to_dict(fp: CoxxFingerprint) -> dict: """ Convert a fingerprint obj into a dictionary. - Args: - fp: The fingerprint to be converted into a dictionary + :param fp: The fingerprint to be converted into a dictionary Returns: dict: A dict of the fingerprint Keys=type, Values=np.ndarray(energies, cohp) @@ -529,8 +524,8 @@ def _fp_to_dict(fp) -> dict: @staticmethod def _get_fp_similarity( - fp1: NamedTuple, - fp2: NamedTuple, + fp1: CoxxFingerprint, + fp2: CoxxFingerprint, col: int = 1, pt: int | str = "All", normalize: bool = False, @@ -539,13 +534,12 @@ def _get_fp_similarity( """ Calculate the similarity index (dot product) of two fingerprints. - Args: - fp1 (NamedTuple): The 1st dos fingerprint object - fp2 (NamedTuple): The 2nd dos fingerprint object - col (int): The item in the fingerprints (0:energies,1: coxxs) to take the dot product of (default is 1) - pt (int or str) : The index of the point that the dot product is to be taken (default is All) - normalize (bool): If True normalize the scalar product to 1 (default is False) - tanimoto (bool): If True will compute Tanimoto index (default is False) + :param fp1 The 1st CoxxFingerprint object + :param fp2: The 2nd CoxxFingerprint object + :param col: The item in the fingerprints (0:energies,1: coxxs) to take the dot product of (default is 1) + :param pt: The index of the point that the dot product is to be taken (default is All) + :param normalize: If True normalize the scalar product to 1 (default is False) + :param tanimoto: If True will compute Tanimoto index (default is False) Raises: ValueError: If both tanimoto and normalize are set to True. @@ -566,8 +560,8 @@ def _get_fp_similarity( vec1 = np.array([pt[col] for pt in fp1_dict.values()]).flatten() vec2 = np.array([pt[col] for pt in fp2_dict.values()]).flatten() else: - vec1 = fp1_dict[fp1[2][pt]][col] - vec2 = fp2_dict[fp2[2][pt]][col] + vec1 = fp1_dict[fp1[2][pt]][col] # type: ignore + vec2 = fp2_dict[fp2[2][pt]][col] # type: ignore if not normalize and tanimoto: rescale = ( @@ -588,11 +582,13 @@ def _get_fp_similarity( ) return np.dot(vec1, vec2) / rescale - def _fingerprint_df(self, path_to_lobster_calc) -> pd.DataFrame: + def _fingerprint_df(self, path_to_lobster_calc: str | Path) -> pd.DataFrame: """ Get fingerprint object dataframe via FeaturizeCOXX.get_coxx_fingerprint_df. - Also helps to generate the data used for fingerprint generation + Also helps to generate the data used for fingerprint generation. + + :param path_to_lobster_calc: path to root LOBSTER calculation directory. Returns: A pandas dataframe with COXX fingerprint object @@ -662,12 +658,6 @@ def _fingerprint_df(self, path_to_lobster_calc) -> pd.DataFrame: structure_path = gz_file_path # type: ignore break - # structure_path = dir_name / "POSCAR" - # if not structure_path.exists(): - # gz_file_path = Path(zpath(structure_path)) - # if gz_file_path.exists(): - # structure_path = gz_file_path - coxx = FeaturizeCOXX( path_to_coxxcar=str(coxxcar_path), path_to_icoxxlist=str(icoxxlist_path), @@ -722,15 +712,11 @@ class BatchStructureGraphs: """ Batch Featurizer that generates structure graphs with lobster data. - Args: - path_to_lobster_calcs: path to root directory consisting of all lobster calc - add_additional_data_sg: bool indicating whether to include icoop and icobi data as edge properties - which_bonds : selects which kind of bonds are analyzed. "all" is the default - start: start energy for bonding antibonding percent integration - n_jobs : parallel processes to run - - Attributes: - get_df: A pandas dataframe with summary features + :param path_to_lobster_calcs: path to root directory consisting of all lobster calc + :param add_additional_data_sg: bool indicating whether to include `icoop` and `icobi` data as edge properties + :param which_bonds: selects which kind of bonds are analyzed. "all" is the default + :param start: start energy for bonding antibonding percent integration + :param n_jobs: parallel processes to run """ @@ -745,12 +731,11 @@ def __init__( """ Generate structure graphs with LOBSTER data via multiprocessing. - Args: - path_to_lobster_calcs: path to root directory consisting of all lobster calc - add_additional_data_sg: bool indicating whether to include icoop and icobi data as edge properties - which_bonds : selects which kind of bonds are analyzed. "all" is the default - start: start energy for bonding antibonding percent integration - n_jobs : parallel processes to run + :param path_to_lobster_calcs: path to root directory consisting of all lobster calc + :param add_additional_data_sg: bool indicating whether to include `icoop` and `icobi` data as edge properties + :param which_bonds: selects which kind of bonds are analyzed. "all" is the default + :param start: start energy for bonding antibonding percent integration + :param n_jobs: parallel processes to run """ self.path_to_lobster_calcs = path_to_lobster_calcs @@ -759,10 +744,12 @@ def __init__( self.start = start self.n_jobs = n_jobs - def _get_sg_df(self, path_to_lobster_calc) -> pd.DataFrame: + def _get_sg_df(self, path_to_lobster_calc: str | Path) -> pd.DataFrame: """ Generate a structure graph with LOBSTER data bonding analysis data. + :param path_to_lobster_calc: path to root LOBSTER calculation directory + Returns: A structure graph with LOBSTER data as edge and node properties in structure graph objects """ @@ -860,21 +847,18 @@ def get_df(self) -> pd.DataFrame: class BatchDosFeaturizer: """ - BatchFeaturizer to generate Lobster DOS moment features and fingerprints. - - Attributes: - path_to_lobster_calcs: path to root directory consisting of all lobster calc - add_element_dos_moments : add element dos moment features alongside orbital dos - normalize: bool to state to normalize the fingerprint data - n_bins: sets number for bins for fingerprint objects - e_range : range of energy relative to fermi for which moment features needs to be computed - n_jobs : number of parallel processes to run - fingerprint_type: Specify fingerprint type to compute, can accept `{s/p/d/f/}summed_{pdos/tdos}` + BatchFeaturizer to generate Lobster DOS moment features and fingerprints. + + :param path_to_lobster_calcs: path to root directory consisting of all lobster calc + :param add_element_dos_moments: add element dos moment features alongside orbital dos + :param normalize: bool to state to normalize the fingerprint data + :param n_bins: sets number for bins for fingerprint objects + :param e_range: range of energy relative to fermi for which moment features needs to be computed + :param n_jobs: number of parallel processes to run + :param fingerprint_type: Specify fingerprint type to compute, can accept `{s/p/d/f/}summed_{pdos/tdos}` (default is summed_pdos) + :param use_lso_dos: Will force featurizer to use DOSCAR.LSO.lobster instead of DOSCAR.lobster - Methods: - get_df: A pandas dataframe with DOS moment features as columns - get_fingerprints_df: A pandas dataframe with DOS fingerprint object as columns """ def __init__( @@ -889,18 +873,17 @@ def __init__( use_lso_dos: bool = True, ): """ - Initialize BatchDosFeaturizer attributes. - - Args: - path_to_lobster_calcs: path to root directory consisting of all lobster calc - add_element_dos_moments : add element dos moment features alongside orbital dos - normalize: bool to state to normalize the fingerprint data - n_bins: sets number for bins for fingerprint objects - e_range : range of energy relative to fermi for which moment features needs to be computed - n_jobs : number of parallel processes to run - fingerprint_type: Specify fingerprint type to compute, can accept `{s/p/d/f/}summed_{pdos/tdos}` + Initialize BatchDosFeaturizer. + + :param path_to_lobster_calcs: path to root directory consisting of all lobster calc + :param add_element_dos_moments: add element dos moment features alongside orbital dos + :param normalize: bool to state to normalize the fingerprint data + :param n_bins: sets number for bins for fingerprint objects + :param e_range: range of energy relative to fermi for which moment features needs to be computed + :param n_jobs: number of parallel processes to run + :param fingerprint_type: Specify fingerprint type to compute, can accept `{s/p/d/f/}summed_{pdos/tdos}` (default is summed_pdos) - use_lso_dos: Will force feeaturizer to use DOSCAR.LSO.lobster instead of DOSCAR.lobster + :param use_lso_dos: Will force featurizer to use DOSCAR.LSO.lobster instead of DOSCAR.lobster """ self.path_to_lobster_calcs = path_to_lobster_calcs self.add_element_dos_moments = add_element_dos_moments @@ -911,7 +894,7 @@ def __init__( self.n_bins = n_bins self.use_lso_dos = use_lso_dos - def _get_dos_moments_df(self, path_to_lobster_calc) -> pd.DataFrame: + def _get_dos_moments_df(self, path_to_lobster_calc: str | Path) -> pd.DataFrame: """ Featurize DOSCAR.lobster data using FeaturizeDOSCAR. @@ -961,12 +944,16 @@ def _get_dos_moments_df(self, path_to_lobster_calc) -> pd.DataFrame: return df - def _get_dos_fingerprints_df(self, path_to_lobster_calc) -> pd.DataFrame: + def _get_dos_fingerprints_df( + self, path_to_lobster_calc: str | Path + ) -> pd.DataFrame: """ Featurize DOSCAR.lobster data into fingerprints using FeaturizeDOSCAR. + :param path_to_lobster_calc: path to root LOBSTER calculation directory. + Returns: - A pandas dataframe with DOS finerprint objects + A pandas dataframe with DOS fingerprint objects """ dir_name = Path(path_to_lobster_calc) @@ -1017,12 +1004,13 @@ def _get_dos_fingerprints_df(self, path_to_lobster_calc) -> pd.DataFrame: def get_df(self) -> pd.DataFrame: """ - Generate a pandas dataframe with moment features. + Generate a pandas dataframe with all moment features. - Moment features are PDOS center, width, skewness, kurtosis and upper band edge. + Moment features are PDOS (optional: element dos) center, width, skewness, kurtosis + and upper band edge. Returns: - A pandas dataframe + A pandas dataframe with moment features """ paths = [ os.path.join(self.path_to_lobster_calcs, f) diff --git a/lobsterpy/featurize/core.py b/lobsterpy/featurize/core.py index d0042f66..b909073a 100644 --- a/lobsterpy/featurize/core.py +++ b/lobsterpy/featurize/core.py @@ -8,8 +8,8 @@ import gzip import json import warnings -from collections import namedtuple from pathlib import Path +from typing import NamedTuple import numpy as np import pandas as pd @@ -32,15 +32,10 @@ class FeaturizeLobsterpy: """ Class to featurize lobsterpy data. - Args: - path_to_lobster_calc: path to parent directory containing lobster calc outputs - path_to_json: path to lobster lightweight json - bonds: "all" or "cation-anion" bonds - orbital_resolved: bool indicating whether LobsterPy analysis is performed orbital wise - Attributes: - get_df: returns a pandas dataframe with relevant icohp statistical data as columns from - lobsterpy automatic bonding analysis - + :param path_to_lobster_calc: path to parent directory containing lobster calc outputs + :param path_to_json: path to lobster lightweight json + :param bonds: "all" or "cation-anion" bonds + :param orbital_resolved: bool indicating whether LobsterPy analysis is performed orbital wise """ def __init__( @@ -50,16 +45,7 @@ def __init__( orbital_resolved: bool = False, bonds: str = "all", ): - """ - Extract features from Lobster calculations. - - Args: - path_to_lobster_calc: path to parent directory containing lobster calc outputs - path_to_json: path to lobster lightweight json - orbital_resolved: bool indicating whether LobsterPy analysis is performed orbital wise - bonds: "all" or "cation-anion" bonds - - """ + """Initialize featurizer.""" self.path_to_json = path_to_json self.path_to_lobster_calc = path_to_lobster_calc self.orbital_resolved = orbital_resolved @@ -69,9 +55,11 @@ def get_df(self, ids: str | None = None) -> pd.DataFrame: """ Featurize LobsterPy condensed bonding analysis data. + :param ids: set index name in the pandas dataframe. Default is None. + When None, LOBSTER calc directory name is used as index name. + Returns: Returns a pandas dataframe with lobsterpy icohp statistics - """ if self.path_to_json and not self.path_to_lobster_calc: # read the lightweight lobster json files using read_lobster_lightweight_json method @@ -330,8 +318,7 @@ def read_lobster_lightweight_json(path_to_json: str | Path) -> dict: """ Read the lightweight JSON.gz files and return a Python dictionary object. - Args: - path_to_json: path to lobsterpy lightweight json file + :param path_to_json: path to lobsterpy lightweight json file Returns: Returns a dictionary with lobster summarized bonding analysis data @@ -364,10 +351,9 @@ def get_lobsterpy_cba_dict( """ Generate a Python dictionary object using the Analysis class with condensed bonding analysis data. - Args: - path_to_lobster_calc: path to lobsterpy lightweight json file - bonds: "all" or "cation-anion" bonds - orbital_resolved: bool indicating whether analysis is performed orbital wise + :param path_to_lobster_calc: path to lobsterpy lightweight json file + :param bonds: "all" or "cation-anion" bonds + :param orbital_resolved: bool indicating whether analysis is performed orbital wise Returns: Returns a dictionary with lobster summarized bonding analysis data @@ -464,29 +450,41 @@ def get_lobsterpy_cba_dict( return data -coxx_fingerprint = namedtuple( - "coxx_fingerprint", "energies coxx fp_type spin_type n_bins bin_width" -) +class CoxxFingerprint(NamedTuple): + """ + Represents a Coxx fingerprint. + This named tuple is used to store information related to a Coxx fingerprint, which + includes energies, Coxx values, fingerprint type, spin type, number of bins, and bin width. -class FeaturizeCOXX: + :param energies: The energy values associated with the Coxx fingerprint. + :param coxx: The Coxx values corresponding to each energy. + :param fp_type: The type of the Coxx fingerprint. + :param spin_type: The spin type associated with the fingerprint. + :param n_bins: The number of bins used in the Coxx fingerprint. + :param bin_width: The width of each bin in the Coxx fingerprint. """ - Class to featurize COHPCAR, COBICAR or COOPCAR data. - Args: - path_to_coxxcar: path to COXXCAR.lobster (e.g., "COXXCAR.lobster") - path_to_icoxxlist : path to ICOXXLIST.lobster (e.g., "ICOXXLIST.lobster") - path_to_structure : path to structure file (e.g., "POSCAR") - feature_type: set the feature type for moment features and fingerprints. - Possible options are "bonding", "antibonding" or "overall" - are_cobis : bool indicating if file contains COBI/ICOBI data - are_coops : bool indicating if file contains COOP/ICOOP data - e_range : range of energy relative to fermi for which moment features needs to be computed + energies: np.ndarray + coxx: np.ndarray + fp_type: str + spin_type: str + n_bins: int + bin_width: float - Attributes: - get_df: pandas dataframe - get_coxx_fingerprint_df: pandas dataframe +class FeaturizeCOXX: + """ + Class to featurize COHPCAR, COBICAR or COOPCAR data. + + :param path_to_coxxcar: path to COXXCAR.lobster (e.g., `COXXCAR.lobster`) + :param path_to_icoxxlist: path to ICOXXLIST.lobster (e.g., `ICOXXLIST.lobster`) + :param path_to_structure: path to structure file (e.g., `POSCAR`) + :param feature_type: set the feature type for moment features and fingerprints. + Possible options are `bonding`, `antibonding` or `overall`. + :param are_cobis: bool indicating if file contains COBI/ICOBI data. + :param are_coops: bool indicating if file contains COOP/ICOOP data. + :param e_range: range of energy relative to fermi for which moment features needs to be computed """ def __init__( @@ -502,15 +500,14 @@ def __init__( """ Featurize COHPCAR, COBICAR or COOPCAR data. - Args: - path_to_coxxcar: path to COXXCAR.lobster (e.g., "COXXCAR.lobster") - path_to_icoxxlist : path to ICOXXLIST.lobster (e.g., "ICOXXLIST.lobster") - path_to_structure : path to structure file (e.g., "POSCAR") - feature_type: set the feature type for moment features and fingerprints. - Possible options are "bonding", "antibonding" or "overall" - are_cobis : bool indicating if file contains COBI/ICOBI data - are_coops : bool indicating if file contains COOP/ICOOP data - e_range : range of energy relative to fermi for which moment features needs to be computed + :param path_to_coxxcar: path to COXXCAR.lobster (e.g., `COXXCAR.lobster`) + :param path_to_icoxxlist: path to ICOXXLIST.lobster (e.g., `ICOXXLIST.lobster`) + :param path_to_structure: path to structure file (e.g., `POSCAR`) + :param feature_type: set the feature type for moment features and fingerprints. + Possible options are `bonding`, `antibonding` or `overall`. + :param are_cobis: bool indicating if file contains COBI/ICOBI data + :param are_coops: bool indicating if file contains COOP/ICOOP data + :param e_range: range of energy relative to fermi for which moment features needs to be computed """ self.path_to_coxxcar = path_to_coxxcar @@ -547,17 +544,17 @@ def get_coxx_fingerprint_df( """ Generate a COXX fingerprints dataframe. - Args: - ids: sets index of pandas dataframe - spin_type: Specify spin type. Can accept '{summed/up/down}' + :param ids: set index name in the pandas dataframe. Default is None. + When None, LOBSTER calc directory name is used as index name. + :param spin_type: Specify spin type. Can accept '{summed/up/down}' (default is summed) - binning: If true coxxs will be binned - n_bins: Number of bins to be used in the fingerprint (default is 256) - normalize: If true, normalizes the area under fp to equal to 1 (default is True) - label_list: Specify bond labels as a list for which cohp fingerprints are needed - orbital: Orbital for which fingerprint needs is to be computed. Cannot be used independently. + :param binning: If true coxxs will be binned + :param n_bins: Number of bins to be used in the fingerprint (default is 256) + :param normalize: If true, normalizes the area under fp to equal to 1 (default is True) + :param label_list: Specify bond labels as a list for which cohp fingerprints are needed + :param orbital: Orbital for which fingerprint needs is to be computed. Cannot be used independently. Always a needs label_list. - per_bond: Will scale cohp values by number of bonds i.e. length of label_list arg + :param per_bond: Will scale cohp values by number of bonds i.e. length of label_list arg (Only affects when label_list is not None) Raises: @@ -645,7 +642,7 @@ def get_coxx_fingerprint_df( coxxs = coxx_dict[self.feature_type] if len(energies) < n_bins: inds = np.where((energies >= min_e - tol) & (energies <= max_e + tol)) - fp = coxx_fingerprint( + fp = CoxxFingerprint( energies[inds], coxxs[inds], self.feature_type, @@ -679,7 +676,7 @@ def get_coxx_fingerprint_df( else: coxx_rebin_sc = coxx_rebin - fp = coxx_fingerprint( + fp = CoxxFingerprint( np.array([ener]), coxx_rebin_sc, self.feature_type, @@ -786,19 +783,18 @@ def _calc_moment_features( e_range: list[float], label_list: list[str] | None = None, orbital: str | None = None, - per_bond=True, + per_bond: bool = True, ) -> tuple[float, float, float, float, float]: """ Calculate band center,width, skewness, and kurtosis of the COXX. - Args: - complete_coxx_obj: CompleteCohp object - feature_type: feature type for moment features calculation - e_range: range of energy relative to fermi for which moment features needs to be computed - label_list: List of bond labels - orbital: orbital for which moment features need to be calculated. Cannot be used independently. + :param complete_coxx_obj: CompleteCohp object + :param feature_type: feature type for moment features calculation + :param e_range: range of energy relative to fermi for which moment features needs to be computed + :param label_list: List of bond labels + :param orbital: orbital for which moment features need to be calculated. Cannot be used independently. Always needs a label_list. - per_bond: Will scale cohp values by number of bonds i.e. length of label_list arg + :param per_bond: Will scale cohp values by number of bonds i.e. length of label_list arg (Only affects when label_list is not None) Returns: @@ -909,10 +905,9 @@ def get_coxx_center( """ Get the bandwidth, defined as the first moment of the COXX. - Args: - coxx: COXX array - energies: energies corresponding COXX - e_range: range of energy to compute coxx center + :param coxx: COXX array + :param energies: energies corresponding COXX + :param e_range: range of energy to compute coxx center Returns: coxx center in eV @@ -932,13 +927,12 @@ def get_n_moment( """ Get the nth moment of COXX. - Args: - n: The order for the moment - coxx: COXX array - energies: energies array - e_range: range of energy to compute nth moment - center: Take moments with respect to the COXX center - e_range: range of energy to compute nth moment + :param n: The order for the moment + :param coxx: COXX array + :param energies: energies array + :param e_range: range of energy to compute nth moment + :param center: Take moments with respect to the COXX center + :param e_range: range of energy to compute nth moment Returns: COXX nth moment in eV @@ -980,10 +974,9 @@ def get_cohp_edge( """ Get the highest peak position of hilbert transformed COXX. - Args: - coxx: COXX array - energies: energies array - e_range: range of energy to coxx edge (max peak position) + :param coxx: COXX array + :param energies: energies array + :param e_range: range of energy to coxx edge (max peak position) Returns: COXX edge (max peak position) in eV @@ -1014,7 +1007,7 @@ def get_summarized_coxx_df( self, ids: str | None = None, label_list: list[str] | None = None, - per_bond=True, + per_bond: bool = True, ) -> pd.DataFrame: """ Get a pandas dataframe with COXX features. @@ -1022,6 +1015,14 @@ def get_summarized_coxx_df( Features consist of weighted ICOXX, effective interaction number and moment features of COXX in the selected energy range. + :param ids: set index name in the pandas dataframe. Default is None. + When None, LOBSTER calc directory name is used as index name. + :param label_list: list of bond labels to be used for generating features from + COHPCAR.lobster or COOPCAR.lobster or COBICAR.lobster. Default is None. + When None, all bond labels are used. + :param per_bond: Defaults to True. When True, features are normalized + by total number of bonds in the structure. + Returns: Returns a pandas dataframe with cohp/cobi/coop related features as per input file @@ -1071,14 +1072,10 @@ class FeaturizeCharges: """ Class to compute ionicity from CHARGE.lobster data. - Args: - path_to_structure: path to POSCAR - path_to_charge : path to CHARGE.lobster (e.g., "CHARGE.lobster") - charge_type : set charge type used for computing ionicity. Possible options are "Mulliken" or "Loewdin" - - Attributes: - get_df: pandas dataframe - + :param path_to_structure: path to POSCAR + :param path_to_charge: path to CHARGE.lobster (e.g., `CHARGE.lobster`) + :param charge_type: set charge type used for computing ionicity. + Possible options are `Mulliken` or `Loewdin` """ def __init__( @@ -1090,11 +1087,10 @@ def __init__( """ Compute the Ionicity of the structure from CHARGE.lobster data. - Args: - path_to_structure: path to POSCAR - path_to_charge : path to CHARGE.lobster (e.g., "CHARGE.lobster") - charge_type : set charge type used for computing ionicity. Possible options are "Mulliken" or "Loewdin" - + :param path_to_structure: path to POSCAR + :param path_to_charge: path to CHARGE.lobster (e.g., `CHARGE.lobster`) + :param charge_type: set charge type used for computing ionicity. + Possible options are `Mulliken` or `Loewdin` """ self.path_to_structure = path_to_structure self.path_to_charge = path_to_charge @@ -1184,6 +1180,9 @@ def get_df(self, ids: str | None = None) -> pd.DataFrame: """ Return a pandas dataframe with computed ionicity as columns. + :param ids: set index name in the pandas dataframe. Default is None. + When None, LOBSTER calc directory name is used as index name. + Returns: Returns a pandas dataframe with ionicity @@ -1202,23 +1201,36 @@ def get_df(self, ids: str | None = None) -> pd.DataFrame: return df -dos_fingerprint = namedtuple( - "dos_fingerprint", "energies densities type n_bins bin_width" -) +class DosFingerprint(NamedTuple): + """ + Represents a Density of States (DOS) fingerprint. + This named tuple is used to store information related to the Density of States (DOS) + in a material. It includes the energies, densities, type, number of bins, and bin width. -class FeaturizeDoscar: + :param energies: The energy values associated with the DOS. + :param densities: The corresponding density values for each energy. + :param type: The type of DOS fingerprint. + :param n_bins: The number of bins used in the fingerprint. + :param bin_width: The width of each bin in the DOS fingerprint. """ - Class to compute DOS moments and fingerprints from DOSCAR.lobster / DOSCAR.LSO.lobster. - Attributes: - path_to_structure: path to POSCAR - path_to_doscar : path to DOSCAR.lobster or DOSCAR.LSO.lobster - e_range : range of energy relative to fermi for which moment features and features needs to be computed + energies: np.ndarray + densities: np.ndarray + type: str + n_bins: int + bin_width: float - Methods: - get_df: pandas dataframe +class FeaturizeDoscar: + """ + Class to compute DOS moments and fingerprints from DOSCAR.lobster / DOSCAR.LSO.lobster. + + :param path_to_structure: path to POSCAR + :param path_to_doscar: path to DOSCAR.lobster or DOSCAR.LSO.lobster + :param e_range: range of energy relative to fermi for which moment features and + features needs to be computed + :param add_element_dos_moments: add element dos moment features alongside orbital dos """ def __init__( @@ -1231,12 +1243,11 @@ def __init__( """ Featurize DOSCAR.lobster or DOSCAR.LSO.lobster data. - Args: - path_to_structure: path to POSCAR - path_to_doscar : path to DOSCAR.lobster or DOSCAR.LSO.lobster - e_range : range of energy relative to fermi for which moment features and features needs to be computed - add_element_dos_moments : add element dos moment features alongside orbital dos - + :param path_to_structure: path to POSCAR + :param path_to_doscar: path to DOSCAR.lobster or DOSCAR.LSO.lobster + :param e_range: range of energy relative to fermi for which moment features and + features needs to be computed + :param add_element_dos_moments: add element dos moment features alongside orbital dos """ self.path_to_structure = path_to_structure self.path_to_doscar = path_to_doscar @@ -1250,6 +1261,9 @@ def get_df(self, ids: str | None = None) -> pd.DataFrame: """ Return a pandas dataframe with computed DOS moment features as columns. + :param ids: set index name in the pandas dataframe. Default is None. + When None, LOBSTER calc directory name is used as index name. + Moment features are PDOS center, width, skewness, kurtosis and upper band edge. Returns: @@ -1329,14 +1343,14 @@ def get_fingerprint_df( """ Generate a dataframe consisting of DOS fingerprint (fp). - Args: - ids: set index of pandas dataframe - fp_type: Specify fingerprint type to compute, can accept `s/p/d/f/summed_pdos` + :param ids: set index name in the pandas dataframe. Default is None. + When None, LOBSTER calc directory name is used as index name. + :param fp_type: Specify fingerprint type to compute, can accept `s/p/d/f/summed_pdos` (default is summed_pdos) - binning: If true, the DOS fingerprint is binned using np.linspace and n_bins. + :param binning: If true, the DOS fingerprint is binned using np.linspace and n_bins. Default is True. - n_bins: Number of bins to be used in the fingerprint (default is 256) - normalize: If true, normalizes the area under fp to equal to 1. Default is True. + :param n_bins: Number of bins to be used in the fingerprint (default is 256) + :param normalize: If true, normalizes the area under fp to equal to 1. Default is True. Returns: A pandas dataframe object with DOS fingerprints @@ -1356,6 +1370,6 @@ def get_fingerprint_df( min_e=self.e_range[0] if self.e_range is not None else None, )._asdict() - df.loc[ids, "DOS_FP"] = dos_fingerprint(**fp) + df.loc[ids, "DOS_FP"] = DosFingerprint(**fp) return df diff --git a/lobsterpy/plotting/__init__.py b/lobsterpy/plotting/__init__.py index a903b06d..6751ac4a 100644 --- a/lobsterpy/plotting/__init__.py +++ b/lobsterpy/plotting/__init__.py @@ -32,15 +32,16 @@ def get_style_list( styles: list[str | dict[str, Any]] | None = None, **kwargs, ) -> list[str | dict[str, Any]]: - """Get *args for matplotlib.style from user input. + """ + Get args for matplotlib.style from user input. + + Remaining kwargs are collected as a dict and take the highest priority. - Args: - no_base_style: If true, do not include lobsterpy_base.mplstyle - styles: User-requested styles. These can be paths to mplstyle files, + :param no_base_style: If true, do not include lobsterpy_base.mplstyle + :param styles: User-requested styles. These can be paths to mplstyle files, the names of known (matplotlib-supplied) styles, or dicts of rcParam options. - **kwargs: matplotlib-style sheet keyword arguments + :param kwargs: matplotlib-style sheet keyword arguments - Remaining kwargs are collected as a dict and take the highest priority. """ base = [] if no_base_style else [base_style] if styles is None: @@ -55,6 +56,13 @@ class PlainCohpPlotter(CohpPlotter): This allows the styling to be manipulated more easily using matplotlib style sheets. + + :param zero_at_efermi: Shift all populations to have zero + energy at the Fermi level. Defaults to True. + :param are_coops: Bool indicating that populations are COOPs, not COHPs. + Defaults to False for COHPs. + :param are_cobis: Bool indicating that populations are COBIs, not COHPs. + Defaults to False for COHPs. """ def get_plot( @@ -70,20 +78,19 @@ def get_plot( """ Get a matplotlib plot showing the COHP. - Args: - ax: Existing Matplotlib Axes object to plot to. - xlim: Specifies the x-axis limits. Defaults to None for + :param ax: Existing Matplotlib Axes object to plot to. + :param xlim: Specifies the x-axis limits. Defaults to None for automatic determination. - ylim: Specifies the y-axis limits. Defaults to None for + :param ylim: Specifies the y-axis limits. Defaults to None for automatic determination. - plot_negative: It is common to plot -COHP(E) so that the + :param plot_negative: It is common to plot -COHP(E) so that the sign means the same for COOPs and COHPs. Defaults to None for automatic determination: If are_coops is True, this will be set to False, else it will be set to True. - integrated: Switch to plot ICOHPs. Defaults to False. - invert_axes: Put the energies onto the y-axis, which is + :param integrated: Switch to plot ICOHPs. Defaults to False. + :param invert_axes: Put the energies onto the y-axis, which is common in chemistry. - sigma: Standard deviation of Gaussian broadening applied to + :param sigma: Standard deviation of Gaussian broadening applied to population data. If this is unset (None) no broadening will be added. @@ -199,17 +206,17 @@ def get_plot( @staticmethod def _broaden(energies: np.ndarray, population: np.ndarray, sigma=None, cutoff=4.0): - """Broaden the spectrum with a given standard deviation. + """ + Broaden the spectrum with a given standard deviation. The population is convolved with a normalised Gaussian kernel. This requires the energy grid to be regularly-spaced. - Args: - energies: Regularly-spaced energy series - population: Population data for broadening - sigma: Standard deviation for Gaussian broadening. If sigma is None + :param energies: Regularly-spaced energy series + :param population: Population data for broadening + :param sigma: Standard deviation for Gaussian broadening. If sigma is None then the input data is returned without any processing. - cutoff: Range cutoff for broadening kernel, as a multiple of sigma. + :param cutoff: Range cutoff for broadening kernel, as a multiple of sigma. Return: Broadened population @@ -243,37 +250,49 @@ class PlainDosPlotter(DosPlotter): This allows the styling to be manipulated more easily using matplotlib style sheets. It also adds additional functionalities to plotter + + :param zero_at_efermi: Shift all DOS to have zero + energy at the Fermi level. Defaults to True. + :param stack: Bool indicating that plot should be stacked + area graph. + :param sigma: Standard deviation for gaussian smearing. + :param summed: Will plot summed dos spin populations. + Defaults to False. """ def __init__( - self, zero_at_efermi: bool = True, stack: bool = False, sigma=None, summed=False + self, + zero_at_efermi: bool = True, + stack: bool = False, + summed: bool = False, + sigma: float | None = None, ) -> None: """ - Generate COHP or COOP or COBI plots. + Initialize DOS plotter. - Args: - zero_at_efermi (bool): Whether to shift all Dos to have zero energy at the + :param zero_at_efermi: Whether to shift all Dos to have zero energy at the fermi energy. Defaults to True. - stack (bool): Whether to plot the DOS as a stacked area graph - sigma (float): Specify a standard deviation for Gaussian smearing - the DOS for nicer looking plots. Defaults to None for no - smearing. - summed (bool): Whether to plot the summed DOS + :param stack: Whether to plot the DOS as a stacked area graph + :param summed: Whether to plot the summed spins DOS. + :param sigma: Specify a standard deviation for Gaussian smearing + the DOS for nicer looking plots. Defaults to None for no smearing. """ + super().__init__(zero_at_efermi, stack, sigma) self.zero_at_efermi = zero_at_efermi self.stack = stack self.sigma = sigma + self.summed = summed self._norm_val = True self._doses = {} # type: ignore - self.summed = summed def add_dos(self, label: str, dos: LobsterCompleteDos) -> None: - """Add a dos for plotting. + """ + Add a dos for plotting. + + :param label: label for the DOS. Must be unique. + :param dos: LobsterCompleteDos object - Args: - label: label for the DOS. Must be unique. - dos: LobsterCompleteDos object """ if dos.norm_vol is None: self._norm_val = False @@ -303,13 +322,16 @@ def add_dos(self, label: str, dos: LobsterCompleteDos) -> None: "efermi": efermi, } - def add_site_orbital_dos(self, dos: LobsterCompleteDos, orbital, site_index): - """Add orbital dos at particular site. + def add_site_orbital_dos( + self, dos: LobsterCompleteDos, orbital: str, site_index: int + ): + """ + Add orbital dos at particular site. + + :param dos: LobsterCompleteDos object + :param orbital: Orbitals name at the site. Must be unique. + :param site_index: site index in the structure - Args: - dos: LobsterCompleteDos object - orbital: Orbitals name at the site. Must be unique. - site_index: site index in the structure """ if dos.norm_vol is None: self._norm_val = False @@ -399,18 +421,16 @@ def get_plot( """ Get a matplotlib plot showing the COHP. - Args: - ax: Existing Matplotlib Axes object to plot to. - xlim: Specifies the x-axis limits. Defaults to None for + :param ax: Existing Matplotlib Axes object to plot to. + :param xlim: Specifies the x-axis limits. Defaults to None for automatic determination. - ylim: Specifies the y-axis limits. Defaults to None for + :param ylim: Specifies the y-axis limits. Defaults to None for automatic determination. - invert_axes: Put the energies onto the y-axis, which is + :param invert_axes: Put the energies onto the y-axis, which is common in chemistry. - beta_dashed: Plots the beta spin channel with a dashed line. Defaults to False - sigma: Standard deviation of Gaussian broadening applied to - population data. If this is unset (None) no broadening will be - added. + :param beta_dashed: Plots the beta spin channel with a dashed line. Defaults to False + :param sigma: Standard deviation of Gaussian broadening applied to population data. + If this is unset (None) no broadening will be added. Returns: A matplotlib object. @@ -533,7 +553,15 @@ def get_plot( class InteractiveCohpPlotter(CohpPlotter): - """Interactive COHP, COBI or COOP plotter to view all relevant bonds in one figure.""" + """Interactive COHP, COBI or COOP plotter to view all relevant bonds in one figure. + + :param zero_at_efermi: Shift all populations to have zero + energy at the Fermi level. Defaults to True. + :param are_coops: Bool indicating that populations are COOPs, not COHPs. + Defaults to False for COHPs. + :param are_cobis: Bool indicating that populations are COBIs, not COHPs. + Defaults to False for COHPs. + """ COLOR_PALETTE = [ "#e41a1c", @@ -547,13 +575,13 @@ class InteractiveCohpPlotter(CohpPlotter): "#999999", ] - def add_cohp(self, label, cohp): + def add_cohp(self, label: str, cohp: Cohp): """ Add COHP object to the plotter. - Args: - label: Label for the COHP. Must be unique. - cohp: COHP object. + :param label: Label for the COHP. Must be unique. + :param cohp: COHP object. + """ if "All" not in self._cohps: self._cohps["All"] = {} @@ -587,13 +615,13 @@ def add_all_relevant_cohps( """ Add all relevant COHPs from lobsterpy analyse object. - Args: - analyse: Analyse object from lobsterpy. - suffix: Optional addition to LOBSTER label to avoid key conflicts when plotting multiple + :param analyse: Analyse object from lobsterpy. + :param suffix: Optional addition to LOBSTER label to avoid key conflicts when plotting multiple calcs or just for additional legend information. - label_resolved: bool indicating to obtain label resolved interactive plots for relevant bonds. + :param label_resolved: bool indicating to obtain label resolved interactive plots for relevant bonds. If false, will return summed cohp curves of unique relevant bonds. - orbital_resolved: bool indicating to include orbital resolved interactive cohps for relevant bonds. + :param orbital_resolved: bool indicating to include orbital resolved interactive cohps for relevant bonds. + """ complete_cohp = analyse.chemenv.completecohp @@ -796,16 +824,16 @@ def add_all_relevant_cohps( ) def add_cohps_by_lobster_label( - self, analyse: Analysis, label_list: list, suffix: str = "" + self, analyse: Analysis, label_list: list[str], suffix: str = "" ): """ Add COHPs explicitly specified in label list. - Args: - analyse: Analyse object from lobsterpy. - label_list: List of COHP labels as from LOBSTER. - suffix: Optional addition to LOBSTER label to avoid key + :param analyse: Analyse object from lobsterpy. + :param label_list: List of COHP labels as from LOBSTER. + :param suffix: Optional addition to LOBSTER label to avoid key conflicts when plotting multiple calcs or just for additional legend information. + """ complete_cohp = analyse.chemenv.completecohp @@ -832,14 +860,16 @@ def add_cohps_by_lobster_label( } ) - def add_cohps_from_plot_data(self, plot_data_dict: dict, suffix: str = ""): + def add_cohps_from_plot_data( + self, plot_data_dict: dict[str, Cohp], suffix: str = "" + ): """ Add all relevant COHPs for specified bond type from lobster lightweight json.gz file. - Args: - plot_data_dict: Lobsterpy plot data dict - suffix: Optional addition to LOBSTER label to avoid key + :param plot_data_dict: Lobsterpy plot data dict + :param suffix: Optional addition to LOBSTER label to avoid key conflicts when plotting multiple calcs or just for additional legend information. + """ # convert to cohp objects plot_data_dict = plot_data_dict.copy() @@ -876,35 +906,34 @@ def add_cohps_from_plot_data(self, plot_data_dict: dict, suffix: str = ""): def get_plot( self, - xlim=None, - rangeslider=False, - ylim=None, - plot_negative=None, - integrated=False, - invert_axes=True, - sigma=None, - colors=None, + xlim: list[float] | None = None, + rangeslider: bool = False, + ylim: list[float] | None = None, + plot_negative: bool | None = None, + integrated: bool = False, + invert_axes: bool = True, + sigma: float | None = None, + colors: list[str] | None = None, ): """ Get an interactive plotly figure showing the COHPs. - Args: - xlim: Specifies the x-axis limits. Defaults to None for + :param xlim: Specifies the x-axis limits. Defaults to None for automatic determination. - rangeslider: Adds a plotly.graph_objs.layout.xaxis.Rangeslider + :param rangeslider: Adds a plotly.graph_objs.layout.xaxis.Rangeslider object to figure to allow easy manipulation of x-axis.. - ylim: Specifies the y-axis limits. Defaults to None for + :param ylim: Specifies the y-axis limits. Defaults to None for automatic determination. - plot_negative: It is common to plot -COHP(E) so that the + :param plot_negative: It is common to plot -COHP(E) so that the sign means the same for COOPs and COHPs. Defaults to None - for automatic determination: If are_coops is True, this + for automatic determination - If are_coops is True, this will be set to False, else it will be set to True. - integrated: Switch to plot ICOHPs. Defaults to False. - invert_axes: Put the energies onto the y-axis, which is + :param integrated: Switch to plot ICOHPs. Defaults to False. + :param invert_axes: Put the energies onto the y-axis, which is common in chemistry. - sigma: Standard deviation of Gaussian broadening applied to + :param sigma: Standard deviation of Gaussian broadening applied to population data. If this is unset (None) no broadening will be added. - colors: list of hex color codes to be used in plot + :param colors: list of hex color codes to be used in plot Returns: A plotly.graph_objects.Figure object. @@ -938,7 +967,7 @@ def get_plot( palette = InteractiveCohpPlotter.COLOR_PALETTE if colors is None else colors pal_iter = cycle(palette) - traces = {} + traces = {} # type: ignore for k, v in self._cohps.items(): traces.update({k: []}) for label in v: @@ -1060,10 +1089,9 @@ def _insert_number_of_bonds_in_label( For example : for input label 'Ba1: Ba-Ti', character ':', number_of_bonds: 3, Will return 'Ba1: 3 x Ba-Ti' - Args: - label: bond label to which number of bonds needs to be inserted - character: string character where number of bonds needs to be inserted - number_of_bonds: number of bonds corresponding to the label + :param label: bond label to which number of bonds needs to be inserted + :param character: string character where number of bonds needs to be inserted + :param number_of_bonds: number of bonds corresponding to the label Returns: bond label with number of bonds inserted @@ -1073,9 +1101,9 @@ def _insert_number_of_bonds_in_label( @staticmethod def _get_plot_label_for_label_resolved( structure: Structure, - label_list: list, + label_list: list[str], complete_cohp: CompleteCohp, - orb_list: list, + orb_list: list[str], label_resolved: bool = False, orbital_resolved: bool = False, ) -> str: @@ -1087,13 +1115,12 @@ def _get_plot_label_for_label_resolved( Will return '21: Cl2(3s)-Na1(3s) (2.85 Å)' If label and orbital resolved True Will return 'Cl(3s)-Na(3s) (2.85 Å)' if orbital_resolved is True and label_resolved is False - Args: - structure: pymatgen structure object - label_list: bond label to which number of bonds needs to be inserted - complete_cohp: complete cohp object - orb_list: relevant orbital - label_resolved: specifies type of label to be returned is for label_resolved case - orbital_resolved: specifies type of label to be returned is for orbital_resolved case + :param structure: pymatgen structure object + :param label_list: bond label to which number of bonds needs to be inserted + :param complete_cohp: complete cohp object + :param orb_list: relevant orbital + :param label_resolved: specifies type of label to be returned is for label_resolved case + :param orbital_resolved: specifies type of label to be returned is for orbital_resolved case Returns: plot label string @@ -1138,29 +1165,27 @@ def _get_plot_label_for_label_resolved( class IcohpDistancePlotter: - """Plotter to generate ICOHP or ICOBI or ICOOP vs bond lengths plots.""" + """ + Plotter to generate ICOHP or ICOBI or ICOOP vs bond lengths plots. - def __init__(self, are_coops: bool = False, are_cobis: bool = False): - """ - Plot ICOHPs or ICOBI or ICOOP vs bond lengths. + :param are_coops: Bool indicating that populations are ICOOPs, not ICOHPs. + Defaults to False for COHPs. + :param are_cobis: Bool indicating that populations are ICOBIs, not ICOHPs. + Defaults to False for COHPs. + """ - Args: - are_coops: Switch to indicate that these are ICOOPs, not ICOHPs. - Defaults to False for ICOHPs. - are_cobis: Switch to indicate that these are ICOBIs, not ICOHPs/COOPs. - Defaults to False for ICOHPs. - """ + def __init__(self, are_coops: bool = False, are_cobis: bool = False): + """Initialize ICOHPs or ICOBI or ICOOP vs bond lengths plotter.""" self.are_coops = are_coops self.are_cobis = are_cobis self._icohps = {} # type: ignore - def add_icohps(self, label, icohpcollection: IcohpCollection): + def add_icohps(self, label: str, icohpcollection: IcohpCollection): """ Add ICOHPs or ICOBIs or ICOOPS for plotting. - Args: - label: Label for the ICOHPs. Must be unique. - icohpcollection: IcohpCollection object. + :param label: Label for the ICOHPs. Must be unique. + :param icohpcollection: IcohpCollection object. """ icohps = [] @@ -1197,15 +1222,14 @@ def get_plot( """ Get a matplotlib plot showing the COHP or COBI or COOP with respect to bond lengths. - Args: - ax: Existing Matplotlib Axes object to plot to. - marker_size: sets the size of markers in scatter plots - marker_style: sets type of marker used in plot - xlim: Specifies the x-axis limits. Defaults to None for + :param ax: Existing Matplotlib Axes object to plot to. + :param marker_size: sets the size of markers in scatter plots + :param marker_style: sets type of marker used in plot + :param xlim: Specifies the x-axis limits. Defaults to None for automatic determination. - ylim: Specifies the y-axis limits. Defaults to None for + :param ylim: Specifies the y-axis limits. Defaults to None for automatic determination. - plot_negative: Will plot -1*ICOHPs. Works only for ICOHPs + :param plot_negative: Will plot -1*ICOHPs. Works only for ICOHPs Returns: A matplotlib object. diff --git a/lobsterpy/plotting/layout_dicts.py b/lobsterpy/plotting/layout_dicts.py index e986f4bd..0315a82b 100644 --- a/lobsterpy/plotting/layout_dicts.py +++ b/lobsterpy/plotting/layout_dicts.py @@ -5,29 +5,36 @@ https://github.com/materialsproject/crystaltoolkit/blob/main/crystal_toolkit/components/bandstructure.py Contains dicts for - - general figure layout - - axes ((I)COHP / energy) - - traces (Spin.up / Spin.down) - - legend -""" + 1. general figure layout + 2. axes ((I)COHP / energy) + 3. traces (Spin.up / Spin.down) + 4. legend +""" layout_dict = { "titlefont": {"size": 18}, "showlegend": True, "title_x": 0.1, "title_y": 0.9, - # height=500, - # width=1000, "hovermode": "closest", "paper_bgcolor": "rgba(0,0,0,0)", "plot_bgcolor": "rgba(0,0,0,0)", - # margin=dict(l=60, b=50, t=50, pad=0, r=30), } +""" + General layout of Plotly figure. + :param dict titlefont: Line style dictionary. + :param bool showlegend: Legend hide or show. + :param float title_x: x axis title size. + :param float title_y: y axis title size. + :param str hovermode: hover behaviour. + :param str paper_bgcolor: background color. + :param str plot_bgcolor: plot background color. +""" cohp_axis_style_dict = { - "titlefont": {"size": 20}, # dict(size=20), - "tickfont": {"size": 16}, # dict(size=16), + "titlefont": {"size": 20}, + "tickfont": {"size": 16}, "ticks": "inside", "tickwidth": 2, "showgrid": False, @@ -37,13 +44,27 @@ "zerolinewidth": 3, "mirror": True, "linewidth": 2, - # "linecolor": "rgb(71,71,71)", # maybe replace "linecolor": "black", } +""" + COXX axis style. + :param dict titlefont: axis title font style. + :param dict tickfont: axis tick font style. + :param str ticks: ticks style. + :param float tickwidth: width of ticks. + :param bool showgrid: show or hide axis grid. + :param bool showline: show or hide axis. + :param bool zeroline: show or hide zero line. + :param str zerolinecolor: color of zero line. + :param float zerolinewidth: width of zero line. + :param bool mirror: mirror axis. + :param float linewidth: width of axis line. + :param str linecolor: color of axis line. +""" energy_axis_style_dict = { - "titlefont": {"size": 20}, # dict(size=20), - "tickfont": {"size": 16}, # dict(size=16), + "titlefont": {"size": 20}, + "tickfont": {"size": 16}, "ticks": "inside", "tickwidth": 2, "showgrid": False, @@ -53,24 +74,58 @@ "zerolinewidth": 3, "mirror": True, "linewidth": 2, - # linecolor="rgb(71,71,71)" # maybe replace "linecolor": "black", } +""" + Energy axis style. + :param dict titlefont: axis title font style. + :param dict tickfont: axis tick font style. + :param str ticks: ticks style. + :param float tickwidth: width of ticks. + :param bool showgrid: show or hide axis grid. + :param bool showline: show or hide axis. + :param bool zeroline: show or hide zero line. + :param str zerolinecolor: color of zero line. + :param float zerolinewidth: width of zero line. + :param bool mirror: mirror axis. + :param float linewidth: width of axis line. + :param str linecolor: color of axis line. +""" spin_up_trace_style_dict = { "line": {"width": 3}, "mode": "lines", - "visible": "legendonly", # dict(width=3), + "visible": "legendonly", } +""" + Line style for Spin.up traces. + + :param dict line: Line style dictionary. + :param str mode: Plotly mode. + :param str visible: Trace visibility. +""" spin_down_trace_style_dict = { - "line": {"width": 3, "dash": "dash"}, # dict(width=3, dash="dash"), + "line": {"width": 3, "dash": "dash"}, "mode": "lines", "visible": "legendonly", } +""" + Line style for Spin.down traces. + :param dict line: Line style dictionary. + :param str mode: Plotly mode. + :param str visible: Trace visibility. +""" legend_style_dict = { "bordercolor": "black", "borderwidth": 2, "traceorder": "normal", } +""" + Legend style. + + :param str bordercolor: border color of legend. + :param int borderwidth: width of border. + :param str traceorder: order of trace. +""" diff --git a/lobsterpy/structuregraph/graph.py b/lobsterpy/structuregraph/graph.py index c4cc2a39..191bd75b 100644 --- a/lobsterpy/structuregraph/graph.py +++ b/lobsterpy/structuregraph/graph.py @@ -21,8 +21,28 @@ class LobsterGraph: """ Class to generate structure graph objects with bonding data from Lobster. + Mode of automatic bonding analysis can be `cation-anion` or `all` bonds. The strongest bond is + determined based on the ICOHPs. The coordination environments are determined based on + `cutoff_icohp * ICOHPs` values. If the path of ICOBILIST (ICOOPLIST) is provided, the ICOBI (ICOOP) + values corresponding to relevant bond labels obtained from the ICOHPLIST are also added as edge properties + to the structure graph objects. The Mulliken and Loewdin charges are added as node properties to + the structure graph objects. + Attributes: sg: return structure_graph object + + :param path_to_poscar: path to POSCAR (e.g., "POSCAR"). + :param path_to_charge: path to CHARGE.lobster (e.g., "CHARGE.lobster"). + :param path_to_cohpcar: path to COHPCAR.lobster (e.g., "COHPCAR.lobster"). + :param path_to_icohplist: path to ICOHPLIST.lobster (e.g., "ICOHPLIST.lobster"). + :param path_to_icooplist: path to ICOOPLIST.lobster (e.g., "ICOOPLIST.lobster"). + :param path_to_icobilist: path to ICOBILIST.lobster (e.g., "ICOBILIST.lobster"). + :param path_to_madelung: path to MadelungEnergies.lobster (e.g., "MadelungEnergies.lobster") + :param cutoff_icohp: only bonds that are stronger than cutoff_icohp * strongest ICOHP will be considered. + :param add_additional_data_sg: if True will add the information from ICOOPLIST.lobster + and ICOBILIST.lobster based on ICOHPLIST.lobster relevant bond. + :param which_bonds: selects which kind of bonds are analyzed. "all" is the default. + :param start: start energy for bonding antibonding percent integration. """ def __init__( @@ -32,39 +52,14 @@ def __init__( path_to_cohpcar: str | Path, path_to_icohplist: str | Path, path_to_madelung: str | Path, - add_additional_data_sg=True, + add_additional_data_sg: bool = True, path_to_icooplist: str | Path | None = None, path_to_icobilist: str | Path | None = None, which_bonds: str = "all", cutoff_icohp: float = 0.10, start: float | None = None, ): - """ - Return a structure graph objects with bonding information from Lobster data. - - Mode of automatic bonding analysis can be “cation-anion” or “all” bonds. The strongest bond is - determined based on the ICOHPs. The coordination environments are determined based on - cutoff_icohp *ICOHPs values. If the path of ICOBILIST (ICOOPLIST) is provided, the ICOBI (ICOOP) - values corresponding to relevant bond labels obtained from the ICOHPLIST are also added as edge properties - to the structure graph objects. The Mulliken and Loewdin charges are added as node properties to - the structure graph objects. - - - Args: - path_to_poscar: path to POSCAR (e.g., "POSCAR") - path_to_charge: path to CHARGE.lobster (e.g., "CHARGE.lobster") - path_to_cohpcar: path to COHPCAR.lobster (e.g., "COHPCAR.lobster") - path_to_icohplist: path to ICOHPLIST.lobster (e.g., "ICOHPLIST.lobster") - path_to_icooplist: path to ICOOPLIST.lobster (e.g., "ICOOPLIST.lobster") - path_to_icobilist: path to ICOBILIST.lobster (e.g., "ICOBILIST.lobster") - path_to_madelung: path to MadelungEnergies.lobster (e.g., "MadelungEnergies.lobster") - cutoff_icohp : only bonds that are stronger than cutoff_icohp*strongest ICOHP will be considered - add_additional_data_sg: (bool) if True will add the information from ICOOPLIST.lobster - and ICOBILIST.lobster based on ICOHPLIST.lobster relevant bond - which_bonds: selects which kind of bonds are analyzed. "all" is the default - start: start energy for bonding antibonding percent integration - - """ + """Initialize and return a structure graph object.""" if add_additional_data_sg: self.add_additional_data_sg = add_additional_data_sg if path_to_icooplist is not None and path_to_icobilist is not None: @@ -76,7 +71,7 @@ def __init__( "Please provide path_to_icooplist and path_to_icobilist" ) else: - self.add_additional_data_sg = add_additional_data_sg + self.add_additional_data_sg = add_additional_data_sg # type: ignore self.path_to_poscar = path_to_poscar self.path_to_charge = path_to_charge diff --git a/pyproject.toml b/pyproject.toml index cbcef1d7..460a937f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,17 +40,18 @@ changelog = "https://jageo.github.io/LobsterPy/changelog_link.html" [project.optional-dependencies] featurizer = ["mendeleev==0.14.0"] -docs = ["Sphinx==4.5.0", - "jupyter", - "sphinx-argparse", - "sphinx-book-theme==0.3.3", - "m2r2", - "myst-parser", - "docutils", - "mendeleev==0.14.0", - "pymatgen>=2023.9.10", +dev = ["pre-commit>=2.12.1"] +tests = ["flake8", "pytest", "pytest-mock", "pytest-split", "pytest-cov"] +docs = [ + "sphinx-copybutton==0.5.2", + "sphinx>=5,<6", + "sphinx_design==0.5.0", + "ipython==8.16.1", + "myst-nb==0.17.2", + "sphinx-book-theme==1.0.1", "sphinx-argparse==0.4.0", - "typing"] + "sphinx-toolbox==3.5.0", +] [project.scripts] lobsterpy = "lobsterpy.cli:main" diff --git a/tests/featurize/test_batch.py b/tests/featurize/test_batch.py index 33e72fba..ef4188ab 100644 --- a/tests/featurize/test_batch.py +++ b/tests/featurize/test_batch.py @@ -10,7 +10,7 @@ BatchStructureGraphs, BatchSummaryFeaturizer, ) -from lobsterpy.featurize.core import coxx_fingerprint, dos_fingerprint +from lobsterpy.featurize.core import CoxxFingerprint, DosFingerprint CurrentDir = Path(__file__).absolute().parent TestDir = CurrentDir / "../" @@ -463,7 +463,7 @@ def test_fp_cohp_bonding(self): ) df_fp_cohp = fp_cohp_bonding.fingerprint_df for fp in df_fp_cohp["COXX_FP"]: - assert isinstance(fp, coxx_fingerprint) + assert isinstance(fp, CoxxFingerprint) assert fp.fp_type == "bonding" df = fp_cohp_bonding.get_similarity_matrix_df() @@ -485,7 +485,7 @@ def test_fp_cobi(self): ) df_fp_cobi = fp_cobi.fingerprint_df for fp in df_fp_cobi["COXX_FP"]: - assert isinstance(fp, coxx_fingerprint) + assert isinstance(fp, CoxxFingerprint) assert fp.fp_type == "antibonding" df = fp_cobi.get_similarity_matrix_df() @@ -508,7 +508,7 @@ def test_fp_coop(self): ) df_fp_coop = fp_coop.fingerprint_df for fp in df_fp_coop["COXX_FP"]: - assert isinstance(fp, coxx_fingerprint) + assert isinstance(fp, CoxxFingerprint) assert fp.fp_type == "bonding" df = fp_coop.get_similarity_matrix_df() @@ -590,7 +590,7 @@ def test_batch_dos_featurizer_non_lso(self): assert isinstance(df_fp, pd.DataFrame) for dos_fp in df_fp["DOS_FP"]: - assert isinstance(dos_fp, dos_fingerprint) + assert isinstance(dos_fp, DosFingerprint) assert dos_fp.type == "p" assert dos_fp.n_bins == 100 @@ -683,7 +683,7 @@ def test_batch_dos_featurizer_lso(self): assert isinstance(df_fp_lso, pd.DataFrame) for dos_fp in df_fp_lso["DOS_FP"]: - assert isinstance(dos_fp, dos_fingerprint) + assert isinstance(dos_fp, DosFingerprint) assert dos_fp.type == "summed_pdos" assert dos_fp.n_bins == 256 diff --git a/tests/featurize/test_core.py b/tests/featurize/test_core.py index 56cc4092..e8ff5ca9 100644 --- a/tests/featurize/test_core.py +++ b/tests/featurize/test_core.py @@ -5,11 +5,11 @@ import pytest from lobsterpy.featurize.core import ( + DosFingerprint, FeaturizeCharges, FeaturizeCOXX, FeaturizeDoscar, FeaturizeLobsterpy, - dos_fingerprint, ) CurrentDir = Path(__file__).absolute().parent @@ -945,4 +945,4 @@ def test_featurize_k3sb_dos(self): # Test for the case where e_range is set to None and trying to get fingerprint df_fp = feat_dos.get_fingerprint_df() assert isinstance(df_fp, pd.DataFrame) - assert isinstance(df_fp.loc["K3Sb", "DOS_FP"], dos_fingerprint) + assert isinstance(df_fp.loc["K3Sb", "DOS_FP"], DosFingerprint)