From 2d0d76dc19e4578bfabd174934caab7a5678a080 Mon Sep 17 00:00:00 2001 From: Benedikt Date: Thu, 28 Nov 2024 14:39:00 +0000 Subject: [PATCH 01/10] Initial commit of new docs --- .gitignore | 2 + docs/Makefile | 20 ++++++++ docs/_static/logo_100px.png | Bin 0 -> 19977 bytes docs/_static/ptypyicon.ico | Bin 0 -> 7406 bytes docs/conf.py | 58 ++++++++++++++++++++++ docs/index.rst | 18 +++++++ docs/make.bat | 35 ++++++++++++++ docs/reference/index.rst | 8 +++ docs/reference/utils.rst | 94 ++++++++++++++++++++++++++++++++++++ 9 files changed, 235 insertions(+) create mode 100644 docs/Makefile create mode 100644 docs/_static/logo_100px.png create mode 100644 docs/_static/ptypyicon.ico create mode 100644 docs/conf.py create mode 100644 docs/index.rst create mode 100644 docs/make.bat create mode 100644 docs/reference/index.rst create mode 100644 docs/reference/utils.rst diff --git a/.gitignore b/.gitignore index 3bebd583d..8e328a81a 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ ghostdriver* .ipynb_checkpoints .clang-format pip-wheel-metadata/ +.venv/ +docs/_build diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 000000000..d4bb2cbb9 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# 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 = . +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/logo_100px.png b/docs/_static/logo_100px.png new file mode 100644 index 0000000000000000000000000000000000000000..57059e0cda8314f49f5b0ce82088014efb67d0bb GIT binary patch literal 19977 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⋙p@g+!gT}e-NutXGW(S$4gO%uY*%^7)-G4Ox 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 b3F!X=@QK&teD#bt00000NkvXXu0mjfQhXK* literal 0 HcmV?d00001 diff --git a/docs/_static/ptypyicon.ico b/docs/_static/ptypyicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..daa25d385a77ee78bf570775c6d30be1b9f8c34c GIT binary patch literal 7406 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 literal 0 HcmV?d00001 diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 000000000..a79956707 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,58 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +import sys +from pathlib import Path + +sys.path.insert(0, str(Path('..', 'ptypy').resolve())) + +project = 'PtyPy' +copyright = '2024, AUTHORS' +author = 'AUTHORS' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.doctest', + 'sphinx.ext.extlinks', + 'sphinx.ext.intersphinx', + 'sphinx.ext.mathjax', + 'sphinx.ext.napoleon', + # 'sphinx.ext.linkcode', +] + +templates_path = ['_templates'] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'pydata_sphinx_theme' +html_static_path = ['_static'] +html_logo = '_static/logo_100px.png' +html_favicon = '_static/ptypyicon.ico' + +html_theme_options = { + "icon_links": [ + { + "name": "GitHub", + "url": "https://github.com/ptycho/ptypy", + "icon": "fab fa-github-square", + }, + { + "name": "ptypy.org", + "url": "https://ptypy.org/", + "icon": "fab fa-twitter-square ", + }, + ], +} diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 000000000..af2e871a8 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,18 @@ +.. PtyPy documentation master file, created by + sphinx-quickstart on Sun Oct 6 10:31:05 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +PtyPy documentation +=================== + +Add your content using ``reStructuredText`` syntax. See the +`reStructuredText `_ +documentation for details. + + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + reference/index \ No newline at end of file diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 000000000..954237b9b --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +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/index.rst b/docs/reference/index.rst new file mode 100644 index 000000000..d997a431c --- /dev/null +++ b/docs/reference/index.rst @@ -0,0 +1,8 @@ +API Reference +============= + + +.. toctree:: + :maxdepth: 2 + + utils \ No newline at end of file diff --git a/docs/reference/utils.rst b/docs/reference/utils.rst new file mode 100644 index 000000000..fb59aeea1 --- /dev/null +++ b/docs/reference/utils.rst @@ -0,0 +1,94 @@ +ptypy.utils package +=================== + +Submodules +---------- + +ptypy.utils.array_utils module +------------------------------ + +.. automodule:: ptypy.utils.array_utils + :members: + :undoc-members: + :show-inheritance: + +ptypy.utils.math_utils module +----------------------------- + +.. automodule:: ptypy.utils.math_utils + :members: + :undoc-members: + :show-inheritance: + +ptypy.utils.misc module +----------------------- + +.. automodule:: ptypy.utils.misc + :members: + :undoc-members: + :show-inheritance: + +ptypy.utils.parallel module +--------------------------- + +.. automodule:: ptypy.utils.parallel + :members: + :undoc-members: + :show-inheritance: + +ptypy.utils.parameters module +----------------------------- + +.. automodule:: ptypy.utils.parameters + :members: + :undoc-members: + :show-inheritance: + +ptypy.utils.plot_client module +------------------------------ + +.. automodule:: ptypy.utils.plot_client + :members: + :undoc-members: + :show-inheritance: + +ptypy.utils.plot_utils module +----------------------------- + +.. automodule:: ptypy.utils.plot_utils + :members: + :undoc-members: + :show-inheritance: + +ptypy.utils.scripts module +-------------------------- + +.. automodule:: ptypy.utils.scripts + :members: + :undoc-members: + :show-inheritance: + +ptypy.utils.descriptor module +----------------------------- + +.. automodule:: ptypy.utils.descriptor + :members: + :undoc-members: + :show-inheritance: + +ptypy.utils.verbose module +-------------------------- + +.. automodule:: ptypy.utils.verbose + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: ptypy.utils + :members: + :undoc-members: + :show-inheritance: From d0a455a2a00a0a4d4b4f5607afaffdeb62ce5879 Mon Sep 17 00:00:00 2001 From: Benedikt Daurer Date: Thu, 28 Nov 2024 15:37:55 +0000 Subject: [PATCH 02/10] Added CI for building docs --- .github/workflows/docs.yaml | 135 +++++++++++++++++++++ .github/workflows/{test.yml => tests.yaml} | 5 + docs/conf.py | 3 + docs/index.rst | 2 +- docs/reference/index.rst | 2 +- docs/requirements.txt | 1 + 6 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/docs.yaml rename .github/workflows/{test.yml => tests.yaml} (97%) create mode 100644 docs/requirements.txt diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml new file mode 100644 index 000000000..5319e7c53 --- /dev/null +++ b/.github/workflows/docs.yaml @@ -0,0 +1,135 @@ +name: Documentation + +on: + push: + branches: + - master + +jobs: + build_docs_old: + runs-on: ubuntu-latest + steps: + - name: Checkout PtyPy Code + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + check-latest: true + + - name: Setup MPI + uses: mpi4py/setup-mpi@v1 + with: + mpi: mpich + + - name: Install Sphinx + run: pip install sphinx + + - name: Install PtyPy + run: pip install .[full] + + - name: Prepare Tutorials + working-directory: doc + run: python script2rst.py + + - name: Prepare Templates + working-directory: doc + run: python tmp2rst.py + + - name: Prepare Parameters + working-directory: doc + run: python parameters2rst.py + + - name: Set Path to Sphinx Build + run: echo "SPHINXBUILD=`which sphinx-build`" >> $GITHUB_ENV + + - name: Build Sphinx Documentation + working-directory: doc + run: make html + + - name: Upload Docs Artifact + uses: actions/upload-artifact@v4.4.3 + with: + name: old-docs + path: doc/build/html/ + + build_docs: + runs-on: ubuntu-latest + steps: + - name: Checkout PtyPy Code + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + check-latest: true + + - name: Setup MPI + uses: mpi4py/setup-mpi@v1 + with: + mpi: mpich + + - name: Install Sphinx + run: pip install sphinx + + - name: Install PtyPy + run: pip install .[full] + + - name: Install docs dependencies + run: pip install -r docs/requirements.txt + + - name: Set Path to Sphinx Build + run: echo "SPHINXBUILD=`which sphinx-build`" >> $GITHUB_ENV + + - name: Build Sphinx Documentation + working-directory: docs + run: make html + + - name: Upload Docs Artifact + uses: actions/upload-artifact@v4.4.3 + with: + name: new-docs + path: docs/_build/html/ + + publish_pages: + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + needs: + - build_docs_old + - build_docs + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Setup Pages + uses: actions/configure-pages@v5.0.0 + + - name: Download Old Docs Artifact + uses: actions/download-artifact@v4.1.8 + with: + name: old-docs + path: ./ + + - name: Download Docs Artifact + uses: actions/download-artifact@v4.1.8 + with: + name: new-docs + path: ./docs + + - name: Fix File Permissions for Pages + run: | + chmod -R +rX . + + - name: Upload Merged Artifact + uses: actions/upload-pages-artifact@v3.0.1 + with: + path: ./ + + - name: Publish Docs to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4.0.5 diff --git a/.github/workflows/test.yml b/.github/workflows/tests.yaml similarity index 97% rename from .github/workflows/test.yml rename to .github/workflows/tests.yaml index b37bc8c30..0e6bf2ed1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/tests.yaml @@ -6,11 +6,16 @@ on: push: branches: - master + paths-ignore: + - "docs/**" + - ".github/workflows/**" pull_request: branches: - master - dev - hotfixes + paths-ignore: + - "docs/**" # Also trigger on page_build, as well as release created events page_build: release: diff --git a/docs/conf.py b/docs/conf.py index a79956707..8e818a671 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,6 +11,8 @@ sys.path.insert(0, str(Path('..', 'ptypy').resolve())) +print(sys.path) + project = 'PtyPy' copyright = '2024, AUTHORS' author = 'AUTHORS' @@ -33,6 +35,7 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +#autodoc_mock_imports = ["numpy", "scipy"] # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output diff --git a/docs/index.rst b/docs/index.rst index af2e871a8..749f75bc7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -15,4 +15,4 @@ documentation for details. :maxdepth: 2 :caption: Contents: - reference/index \ No newline at end of file + reference/index diff --git a/docs/reference/index.rst b/docs/reference/index.rst index d997a431c..90233f608 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -5,4 +5,4 @@ API Reference .. toctree:: :maxdepth: 2 - utils \ No newline at end of file + utils diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 000000000..e47016789 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1 @@ +pydata-sphinx-theme From 3f6d61f2e83ca3bcb6b4a46cce6f73de7d15cbc7 Mon Sep 17 00:00:00 2001 From: Benedikt Daurer Date: Mon, 9 Dec 2024 14:48:11 +0000 Subject: [PATCH 03/10] Added main page, full API reference and license banner --- .github/workflows/docs.yaml | 2 +- docs/.gitignore | 2 + docs/Makefile | 2 +- docs/conf.py | 61 -------- docs/index.rst | 18 --- docs/reference/index.rst | 8 -- docs/reference/utils.rst | 94 ------------- docs/source/_static/banner.html | 14 ++ docs/{ => source}/_static/logo_100px.png | Bin docs/source/_static/ptypy.css | 18 +++ docs/{ => source}/_static/ptypyicon.ico | Bin .../_templates/custom-class-template.rst | 32 +++++ .../_templates/custom-module-template.rst | 65 +++++++++ docs/source/conf.py | 133 ++++++++++++++++++ docs/source/index.rst | 33 +++++ docs/source/overview.rst | 91 ++++++++++++ docs/source/reference/core.rst | 40 ++++++ docs/source/reference/engines.rst | 43 ++++++ docs/source/reference/experiment.rst | 57 ++++++++ docs/source/reference/index.rst | 22 +++ docs/source/reference/io.rst | 27 ++++ docs/source/reference/utils.rst | 54 +++++++ 22 files changed, 633 insertions(+), 183 deletions(-) create mode 100644 docs/.gitignore delete mode 100644 docs/conf.py delete mode 100644 docs/index.rst delete mode 100644 docs/reference/index.rst delete mode 100644 docs/reference/utils.rst create mode 100644 docs/source/_static/banner.html rename docs/{ => source}/_static/logo_100px.png (100%) create mode 100644 docs/source/_static/ptypy.css rename docs/{ => source}/_static/ptypyicon.ico (100%) create mode 100644 docs/source/_templates/custom-class-template.rst create mode 100644 docs/source/_templates/custom-module-template.rst create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst create mode 100644 docs/source/overview.rst create mode 100644 docs/source/reference/core.rst create mode 100644 docs/source/reference/engines.rst create mode 100644 docs/source/reference/experiment.rst create mode 100644 docs/source/reference/index.rst create mode 100644 docs/source/reference/io.rst create mode 100644 docs/source/reference/utils.rst diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 5319e7c53..f93956dd7 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -72,7 +72,7 @@ jobs: mpi: mpich - name: Install Sphinx - run: pip install sphinx + run: pip install sphinx myst_parser - name: Install PtyPy run: pip install .[full] diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..71307bd2c --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,2 @@ +source/reference/generated/ +_build/ \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile index d4bb2cbb9..92dd33a1a 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -5,7 +5,7 @@ # from the environment for the first two. SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build -SOURCEDIR = . +SOURCEDIR = source BUILDDIR = _build # Put it first so that "make" without argument is like "make help". diff --git a/docs/conf.py b/docs/conf.py deleted file mode 100644 index 8e818a671..000000000 --- a/docs/conf.py +++ /dev/null @@ -1,61 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# For the full list of built-in configuration values, see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Project information ----------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information - -import sys -from pathlib import Path - -sys.path.insert(0, str(Path('..', 'ptypy').resolve())) - -print(sys.path) - -project = 'PtyPy' -copyright = '2024, AUTHORS' -author = 'AUTHORS' - -# -- General configuration --------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration - -extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.doctest', - 'sphinx.ext.extlinks', - 'sphinx.ext.intersphinx', - 'sphinx.ext.mathjax', - 'sphinx.ext.napoleon', - # 'sphinx.ext.linkcode', -] - -templates_path = ['_templates'] -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - - -#autodoc_mock_imports = ["numpy", "scipy"] - -# -- Options for HTML output ------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output - -html_theme = 'pydata_sphinx_theme' -html_static_path = ['_static'] -html_logo = '_static/logo_100px.png' -html_favicon = '_static/ptypyicon.ico' - -html_theme_options = { - "icon_links": [ - { - "name": "GitHub", - "url": "https://github.com/ptycho/ptypy", - "icon": "fab fa-github-square", - }, - { - "name": "ptypy.org", - "url": "https://ptypy.org/", - "icon": "fab fa-twitter-square ", - }, - ], -} diff --git a/docs/index.rst b/docs/index.rst deleted file mode 100644 index 749f75bc7..000000000 --- a/docs/index.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. PtyPy documentation master file, created by - sphinx-quickstart on Sun Oct 6 10:31:05 2024. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -PtyPy documentation -=================== - -Add your content using ``reStructuredText`` syntax. See the -`reStructuredText `_ -documentation for details. - - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - reference/index diff --git a/docs/reference/index.rst b/docs/reference/index.rst deleted file mode 100644 index 90233f608..000000000 --- a/docs/reference/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -API Reference -============= - - -.. toctree:: - :maxdepth: 2 - - utils diff --git a/docs/reference/utils.rst b/docs/reference/utils.rst deleted file mode 100644 index fb59aeea1..000000000 --- a/docs/reference/utils.rst +++ /dev/null @@ -1,94 +0,0 @@ -ptypy.utils package -=================== - -Submodules ----------- - -ptypy.utils.array_utils module ------------------------------- - -.. automodule:: ptypy.utils.array_utils - :members: - :undoc-members: - :show-inheritance: - -ptypy.utils.math_utils module ------------------------------ - -.. automodule:: ptypy.utils.math_utils - :members: - :undoc-members: - :show-inheritance: - -ptypy.utils.misc module ------------------------ - -.. automodule:: ptypy.utils.misc - :members: - :undoc-members: - :show-inheritance: - -ptypy.utils.parallel module ---------------------------- - -.. automodule:: ptypy.utils.parallel - :members: - :undoc-members: - :show-inheritance: - -ptypy.utils.parameters module ------------------------------ - -.. automodule:: ptypy.utils.parameters - :members: - :undoc-members: - :show-inheritance: - -ptypy.utils.plot_client module ------------------------------- - -.. automodule:: ptypy.utils.plot_client - :members: - :undoc-members: - :show-inheritance: - -ptypy.utils.plot_utils module ------------------------------ - -.. automodule:: ptypy.utils.plot_utils - :members: - :undoc-members: - :show-inheritance: - -ptypy.utils.scripts module --------------------------- - -.. automodule:: ptypy.utils.scripts - :members: - :undoc-members: - :show-inheritance: - -ptypy.utils.descriptor module ------------------------------ - -.. automodule:: ptypy.utils.descriptor - :members: - :undoc-members: - :show-inheritance: - -ptypy.utils.verbose module --------------------------- - -.. automodule:: ptypy.utils.verbose - :members: - :undoc-members: - :show-inheritance: - - -Module contents ---------------- - -.. automodule:: ptypy.utils - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/_static/banner.html b/docs/source/_static/banner.html new file mode 100644 index 000000000..de23007f9 --- /dev/null +++ b/docs/source/_static/banner.html @@ -0,0 +1,14 @@ +
+PtyPy is a community project. If you'd like to contribute or participate in one of our workshops, check out our website. +
+
+
+
+

Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate to ptychography. A current list is available here.

+Phase Focus grants royalty free licences of its patent rights for non-commercial academic research use, for reconstruction of simulated data and for reconstruction of data obtained at synchrotrons at X-ray wavelengths. These licenses can be applied for online by clicking on this link.

+Phase Focus asserts that the software we have made available for download may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents. Phase Focus advises that you apply for a licence from it before downloading any software from this website.

+ +
+
diff --git a/docs/_static/logo_100px.png b/docs/source/_static/logo_100px.png similarity index 100% rename from docs/_static/logo_100px.png rename to docs/source/_static/logo_100px.png diff --git a/docs/source/_static/ptypy.css b/docs/source/_static/ptypy.css new file mode 100644 index 000000000..7efd31d83 --- /dev/null +++ b/docs/source/_static/ptypy.css @@ -0,0 +1,18 @@ +div.disclaimer { + /* background-color: #2c5d8a; + color: #f9eed0; */ + text-align: left; +} + +/* div.disclaimer a{ + color: #d8b340; +} */ + +html[data-theme="light"] { + --pst-color-border: black; +} + +html[data-theme="dark"] { + --pst-color-border: white; +} + diff --git a/docs/_static/ptypyicon.ico b/docs/source/_static/ptypyicon.ico similarity index 100% rename from docs/_static/ptypyicon.ico rename to docs/source/_static/ptypyicon.ico diff --git a/docs/source/_templates/custom-class-template.rst b/docs/source/_templates/custom-class-template.rst new file mode 100644 index 000000000..e7ebd6703 --- /dev/null +++ b/docs/source/_templates/custom-class-template.rst @@ -0,0 +1,32 @@ +{{ fullname | escape | underline}} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + :members: + :inherited-members: + :show-inheritance: + + {% block methods %} + .. automethod:: __init__ + + {% if methods %} + .. rubric:: {{ _('Methods') }} + + .. autosummary:: + {% for item in methods %} + ~{{ name }}.{{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Attributes') }} + + .. autosummary:: + {% for item in attributes %} + ~{{ name }}.{{ item }} + {%- endfor %} + {% endif %} + {% endblock %} diff --git a/docs/source/_templates/custom-module-template.rst b/docs/source/_templates/custom-module-template.rst new file mode 100644 index 000000000..a726085b9 --- /dev/null +++ b/docs/source/_templates/custom-module-template.rst @@ -0,0 +1,65 @@ +{{ fullname | escape | underline}} + +.. automodule:: {{ fullname }} + + {% block attributes %} + {% if attributes %} + .. rubric:: Module Attributes + + .. autosummary:: + {% for item in attributes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block functions %} + {% if functions %} + .. rubric:: {{ _('Functions') }} + + .. autosummary:: + :toctree: + {% for item in functions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block classes %} + {% if classes %} + .. rubric:: {{ _('Classes') }} + + .. autosummary:: + :toctree: + :template: custom-class-template.rst + {% for item in classes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block exceptions %} + {% if exceptions %} + .. rubric:: {{ _('Exceptions') }} + + .. autosummary:: + :toctree: + {% for item in exceptions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + +{% block modules %} +{% if modules %} +.. rubric:: Modules + +.. autosummary:: + :toctree: + :template: custom-module-template.rst + :recursive: +{% for item in modules %} + {{ item }} +{%- endfor %} +{% endif %} +{% endblock %} diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 000000000..9ab9b4dff --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,133 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +import sys +from pathlib import Path + +sys.path.insert(0, str(Path('../..', 'ptypy').resolve())) + + +project = 'PtyPy' +copyright = '2024, Pierre Thibault, Bjoern Enders, Benedikt Daurer and others' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.doctest', + 'sphinx.ext.extlinks', + 'sphinx.ext.intersphinx', + 'sphinx.ext.mathjax', + 'sphinx.ext.napoleon', + # 'sphinx.ext.linkcode', + 'myst_parser', +] + +templates_path = ['_templates'] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +rst_epilog = """ +.. |ptypy| replace:: PtyPy +.. _ptypy: https://www.github.com/ptycho/ptypy +""" + +autosummary_generate = True +autodoc_mock_imports = ["cupy", "pycuda", "reikna", "hdf5plugin", "bitshuffle", "fabio", "swmr_tools"] + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'pydata_sphinx_theme' +html_static_path = ['_static'] +html_css_files = ["ptypy.css"] +html_logo = '_static/logo_100px.png' +html_favicon = '_static/ptypyicon.ico' +html_sidebars = { + 'overview': [] + } + +html_theme_options = { + "icon_links": [ + { + "name": "GitHub", + "url": "https://github.com/ptycho/ptypy", + "icon": "fab fa-github-square", + }, + { + "name": "ptypy.org", + "url": "https://ptypy.org/", + "icon": "fa-solid fa-link ", + }, + ], + "announcement": "https://daurer.github.io/ptypy-new-docs/docs/_static/banner.html", +} + + +# -- Custom functions ---------------------------------------------------- + +def truncate_docstring(app, what, name, obj, options, lines): + """ + Remove the Default parameter entries. + """ + if not hasattr(obj, 'DEFAULT'): + return + if any(l.strip().startswith('Defaults:') for l in lines): + while True: + if lines.pop(-1).strip().startswith('Defaults:'): + break + + +def remove_mod_docstring(app, what, name, obj, options, lines): + from ptypy import utils as u + from ptypy import defaults_tree + u.verbose.report.headernewline='\n\n' + searchstr = ':py:data:' + + def get_refs(dct, pd, depth=2, indent=''): + if depth < 0: + return + + for k, value in dct.items(): + ref = ', see :py:data:`~%s`' % pd.children[k].entry_point if k in pd.children else '' + if hasattr(value, 'items'): + v = str(value.__class__.__name__) + elif str(value) == value: + v = '"%s"' % value + else: + v = str(value) + + lines.append(indent + '* *' + k + '* = ``' + v + '``' + ref) + + if hasattr(value, 'items'): + lines.append("") + get_refs(value, pd.children[k], depth=depth-1, indent=indent+' ') + lines.append("") + + if isinstance(obj, u.Param) or isinstance(obj, dict): + pd = None + + for l in lines: + start = l.find(searchstr) + if start > -1: + newstr = l[start:] + newstr = newstr.split('`')[1] + newstr = newstr.replace('~', '') + pd = defaults_tree.get(newstr) + break + + if pd is not None: + get_refs(obj, pd, depth=2, indent='') + + +def setup(app): + print("Custom setup") + app.connect('autodoc-process-docstring', remove_mod_docstring) + app.connect('autodoc-process-docstring', truncate_docstring) + pass diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 000000000..d2227bf68 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,33 @@ +Quicklinks +---------- + +* | Starting from a **clean slate**? + | Check out the :ref:`installation instructions ` + +* | You want to understand the **inner principles** of ptypy without + having to browse the source code? + | Have a look at the :ref:`tutorials about its special classes `. + +* | Only interested in |ptypy|'s **data file structure** and + **management**? + | Indulge yourself :ref:`here` for the structure and + :ref:`here` for the concepts. + +PtyPy Documentation Contents +============================ + +.. toctree:: + :maxdepth: 2 + + overview + installation + userguide/index + reference/index + + +Indices and Tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/docs/source/overview.rst b/docs/source/overview.rst new file mode 100644 index 000000000..5acee4347 --- /dev/null +++ b/docs/source/overview.rst @@ -0,0 +1,91 @@ +Overview +======== + +|ptypy| [#Enders2016]_ is a +framework for scientific ptychography compiled by +P.Thibault, B. Enders, and others (see AUTHORS). + +It is the result of years of experience in the field of ptychography condensed +into a versatile python package. The package covers the whole path of +ptychographic analysis after the actual experiment is completed +- from data management to reconstruction to visualization. + +The main idea of ptypy is: *"Flexibility and Scalabality through abstraction"*. +Most often, you will find a class for every concept of ptychography in +|ptypy|. Using these or other more abstract base classes, new ideas +may be developed in a rapid manner without the cumbersome overhead of +:py:mod:`data` management +, memory access or :py:mod:`distributed ` computing. Additionally, |ptypy| +provides a rich set of :py:mod:`utilities ` and helper functions, +especially for :py:mod:`input/output ` + +Get started quickly :ref:`here ` or with one of the examples in the ``templates`` directory. + + +Highlights +---------- + +* **Difference Map** [#dm]_ algorithm engine with power bound constraint [#power]_. +* **Maximum Likelihood** [#ml]_ engine with preconditioners and regularizers. +* A few more engines (RAAR, sDR, ePIE, ...). + +* **Fully parallelized** using the Massage Passing Interface + (`MPI `_). + Simply execute your script with:: + + $ mpiexec/mpirun -n [nodes] python .py + +* **GPU acceleration** based on custom kernels, CuPy or PyCUDA/reikna. + See examples in ``templates/accelerate``, ``templates/engines/cupy`` and ``templates/engines/pycuda``. + +* A **client-server** approach for visualization and control based on + `ZeroMQ `_ . + The reconstruction may run on a remote hpc cluster while your desktop + computer displays the reconstruction progress. + + +* **Mixed-state** reconstructions of probe and object [#Thi2013]_ for + overcoming partial coherence or related phenomena. + +* **On-the-fly** reconstructions (while data is being acquired) using the + the :py:class:`PtyScan` class in the linking mode :ref:`linking mode` + + +Quicklinks +---------- +* | The complete :ref:`documentation `. + +* | Starting from a **clean slate**? + | Check out the :ref:`installation instructions ` + +* | You want to understand the **inner principles** of ptypy without + having to browse the source code? + | Have a look at the :ref:`tutorials about its special classes `. + +* | Only interested in |ptypy|'s **data file structure** and + **management**? + | Indulge yourself :ref:`here` for the structure and + :ref:`here` for the concepts. + + +.. rubric:: Footnotes + +.. [#Enders2016] B.Enders and P.Thibault, **Proc. R. Soc. A** 472, 20160640 (2016), `doi `__ + +.. [#Thi2013] P.Thibault and A.Menzel, **Nature** 494, 68 (2013), `doi `__ + +.. [#ml] P.Thibault and M.Guizar-Sicairos, **New J. of Phys. 14**, 6 (2012), `doi `__ + +.. [#dm] P.Thibault, M.Dierolf *et al.*, **Ultramicroscopy 109**, 4 (2009), `doi `__ + +.. [#power] K.Giewekemeyer *et al.*, **PNAS 108**, 2 (2007), `suppl. material `__, `doi `__ + + +.. + .. include:: ../README.rst + :start-line: 26 + + +.. note:: | Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate to ptychography. A current list is available `here `_. + | Phase Focus grants royalty free licences of its patent rights for non-commercial academic research use, for reconstruction of simulated data and for reconstruction of data obtained at synchrotrons at X-ray wavelengths. These licenses can be applied for online by clicking on this `link `_. + | Phase Focus asserts that the software we have made available for download may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents. Phase Focus advises that you apply for a licence from it before downloading any software from this website. diff --git a/docs/source/reference/core.rst b/docs/source/reference/core.rst new file mode 100644 index 000000000..8843eaca9 --- /dev/null +++ b/docs/source/reference/core.rst @@ -0,0 +1,40 @@ +Core Functionalities +==================== + +Core Classes +------------ + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.core.classes + ptypy.core.ptycho + +Data Management +--------------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.core.data + ptypy.core.manager + ptypy.core.save_load + ptypy.core.paths + +Physics +------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.core.geometry + ptypy.core.illumination + ptypy.core.sample + ptypy.core.xy + diff --git a/docs/source/reference/engines.rst b/docs/source/reference/engines.rst new file mode 100644 index 000000000..702c069c7 --- /dev/null +++ b/docs/source/reference/engines.rst @@ -0,0 +1,43 @@ +Reconstruction Engines +====================== + +Base Classes and Utilities +-------------------------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.engines.base + ptypy.engines.utils + ptypy.engines.posref + +Core Engines +------------ + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.engines.projectional + ptypy.engines.stochastic + ptypy.engines.ML + +Additional (custom) Engines +--------------------------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.engines.Bragg3d_engines + ptypy.custom.DMOPR + ptypy.custom.MLOPR + ptypy.custom.DM_object_regul + ptypy.custom.WASP + ptypy.custom.ePIE_parallel + ptypy.custom.threepie + diff --git a/docs/source/reference/experiment.rst b/docs/source/reference/experiment.rst new file mode 100644 index 000000000..48b161231 --- /dev/null +++ b/docs/source/reference/experiment.rst @@ -0,0 +1,57 @@ +Data Loaders +============ + +Diamond Light Source Loaders +---------------------------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.experiment.hdf5_loader + ptypy.experiment.swmr_loader + ptypy.experiment.diamond_nexus + ptypy.experiment.diamond_streaming + ptypy.experiment.epsic_loader + +Max IV Loaders +-------------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.experiment.nanomax + ptypy.experiment.nanomax3d + ptypy.experiment.nanomax_streaming + +Other Synchrotron/FEL Loaders +----------------------------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.experiment.ALS_5321 + ptypy.experiment.AMO_LCLS + ptypy.experiment.DiProI_FERMI + ptypy.experiment.ID16Anfp + ptypy.experiment.cSAXS + ptypy.experiment.spec + +Miscellaneous Loaders +--------------------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.experiment.UCL + ptypy.experiment.optiklabor + ptypy.experiment.plugin + ptypy.experiment.savu + ptypy.experiment.spec diff --git a/docs/source/reference/index.rst b/docs/source/reference/index.rst new file mode 100644 index 000000000..7b26d79e1 --- /dev/null +++ b/docs/source/reference/index.rst @@ -0,0 +1,22 @@ +API Reference +============= + +Modules +------- + +.. toctree:: + :maxdepth: 2 + + core + engines + experiment + io + utils + +Module contents +--------------- + +.. automodule:: ptypy + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/source/reference/io.rst b/docs/source/reference/io.rst new file mode 100644 index 000000000..b4cf40678 --- /dev/null +++ b/docs/source/reference/io.rst @@ -0,0 +1,27 @@ +Input/Output +============ + +Read/Write with Files +--------------------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.io.edfIO + ptypy.io.h5rw + ptypy.io.json_rw + ptypy.io.rawIO + ptypy.io.imageIO + ptypy.io.image_read + +Client/Server Interaction +------------------------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.io.interaction diff --git a/docs/source/reference/utils.rst b/docs/source/reference/utils.rst new file mode 100644 index 000000000..51e066647 --- /dev/null +++ b/docs/source/reference/utils.rst @@ -0,0 +1,54 @@ +Utilities +========= + +General Utilities +----------------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.utils.array_utils + ptypy.utils.math_utils + ptypy.utils.misc + ptypy.utils.parallel + ptypy.utils.parameters + ptypy.utils.plot_client + ptypy.utils.plot_utils + ptypy.utils.scripts + ptypy.utils.descriptor + ptypy.utils.verbose + +Debugging Utilities +------------------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.debug.embedded_shell + ptypy.debug.ipython_kernel + +Simulation Utilities +-------------------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.simulations.detector + ptypy.simulations.ptysim_utils + ptypy.simulations.simscan + +Resources +--------- + +.. autosummary:: + :toctree: generated/ + :template: custom-module-template.rst + :recursive: + + ptypy.resources From ddfcc45ed8c412198de63625b4adeab9a60c92e6 Mon Sep 17 00:00:00 2001 From: Benedikt Daurer Date: Wed, 18 Dec 2024 13:00:33 +0000 Subject: [PATCH 04/10] Add documentation for parameter tree --- docs/.gitignore | 1 + docs/source/_param_generator.py | 143 +++++++++++++++++++++++++++++++ docs/source/conf.py | 21 ++++- docs/source/index.rst | 1 + docs/source/parameters/index.rst | 18 ++++ 5 files changed, 180 insertions(+), 4 deletions(-) create mode 100644 docs/source/_param_generator.py create mode 100644 docs/source/parameters/index.rst diff --git a/docs/.gitignore b/docs/.gitignore index 71307bd2c..7b78447c4 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,2 +1,3 @@ source/reference/generated/ +source/parameters/generated/ _build/ \ No newline at end of file diff --git a/docs/source/_param_generator.py b/docs/source/_param_generator.py new file mode 100644 index 000000000..d876018cb --- /dev/null +++ b/docs/source/_param_generator.py @@ -0,0 +1,143 @@ +import os +from ptypy import defaults_tree +from pathlib import Path + +def write_desc_recursive(prst, tree): + for path, desc in tree.children.items(): + print(path) + types = desc.type + default = desc.default + lowlim, uplim = desc.limits + is_wildcard = (desc.name == '*') + + if is_wildcard: + path = path.replace('*', desc.parent.name[:-1] + '_00') + + if path == '': + continue + + if desc.children or desc.is_symlink: + if desc.parent is desc.root: + prst.write('\n' + path + '\n') + prst.write('=' * len(path) + '\n\n') + if desc.parent.parent is desc.root: + prst.write('\n' + path + '\n') + prst.write('-' * len(path) + '\n\n') + + prst.write('.. py:data:: ' + path) + + if desc.is_symlink: + tp = 'Param' + else: + tp = ', '.join([str(t) for t in types]) + prst.write(' (' + tp + ')') + prst.write('\n\n') + + if is_wildcard: + prst.write(' *Wildcard*: multiple entries with arbitrary names are accepted.\n\n') + + # prst.write(' '+desc.help+'\n\n') + prst.write(' ' + desc.help.replace('', '\n').replace('\n', '\n ') + '\n\n') + prst.write(' ' + desc.doc.replace('', '\n').replace('\n', '\n ') + '\n\n') + + if desc.children: + print('recursion ' + path) + prst.write('\n') + write_desc_recursive(prst, desc) + elif desc.is_symlink: + print('following symlink ' + path) + prst.write('\n') + write_desc_recursive(prst, desc.type[0]) + else: + prst.write(' *default* = ``' + repr(default)) + if lowlim is not None and uplim is not None: + prst.write(' (>' + str(lowlim) + ', <' + str(uplim) + ')``\n') + elif lowlim is not None and uplim is None: + prst.write(' (>' + str(lowlim) + ')``\n') + elif lowlim is None and uplim is not None: + prst.write(' (<' + str(uplim) + ')``\n') + else: + prst.write('``\n') + + prst.write('\n') + + +def write_desc_tree(prst, tree): + for path, desc in tree.descendants: + + types = desc.type + default = desc.default + lowlim, uplim = desc.limits + is_wildcard = (desc.name == '*') + + if is_wildcard: + path = path.replace('*', desc.parent.name[:-1] + '_00') + + if path == '': + continue + if desc.children and desc.parent is desc.root: + prst.write('\n' + path + '\n') + prst.write('=' * len(path) + '\n\n') + if desc.children and desc.parent.parent is desc.root: + prst.write('\n' + path + '\n') + prst.write('-' * len(path) + '\n\n') + + prst.write('.. py:data:: ' + path) + + if desc.is_symlink: + tp = 'Param' + else: + tp = ', '.join([str(t) for t in types]) + prst.write(' (' + tp + ')') + prst.write('\n\n') + + if is_wildcard: + prst.write(' *Wildcard*: multiple entries with arbitrary names are accepted.\n\n') + + # prst.write(' '+desc.help+'\n\n') + prst.write(' ' + desc.help.replace('', '\n').replace('\n', '\n ') + '\n\n') + prst.write(' ' + desc.doc.replace('', '\n').replace('\n', '\n ') + '\n\n') + + if desc.is_symlink: + prst.write(' *default* = ' + ':py:data:`' + desc.type[0].path + '`\n') + else: + prst.write(' *default* = ``' + repr(default)) + if lowlim is not None and uplim is not None: + prst.write(' (>' + str(lowlim) + ', <' + str(uplim) + ')``\n') + elif lowlim is not None and uplim is None: + prst.write(' (>' + str(lowlim) + ')``\n') + elif lowlim is None and uplim is not None: + prst.write(' (<' + str(uplim) + ')``\n') + else: + prst.write('``\n') + + prst.write('\n') + +def generate_parameters_rst(root=None, outdir="./parameters/generated/", outfile="params.rst", title=None): + if root is not None: + try: + tree = defaults_tree[root] + except KeyError: + print("Cannot access defaults tree with root at {root}") + return + else: + tree = defaults_tree + + # Create ouput directory if needed + if not os.path.exists(outdir): + os.makedirs(outdir) + + # Title + if title is None: + title = root + + # Make header + title_underline = len(title)*"=" + + header = f"""{title}\n{title_underline}\n""" + + # Write rst file with parameter tree + outpath = Path(outdir, outfile).resolve() + with open(outpath,'w') as prst: + prst.write(header) + write_desc_tree(prst, tree) diff --git a/docs/source/conf.py b/docs/source/conf.py index 9ab9b4dff..09b8935c3 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -10,14 +10,24 @@ from pathlib import Path sys.path.insert(0, str(Path('../..', 'ptypy').resolve())) +sys.path.insert(0, str(Path(__file__).parent.resolve())) +from _param_generator import generate_parameters_rst + +# Generate List of Parameters +generate_parameters_rst("ptycho", outfile="ptycho.rst", title="Root/Ptycho (p)") +generate_parameters_rst("io", outfile="io.rst", title="Input/Output (p.io)") +generate_parameters_rst("scans", outfile="scans.rst", title="List of Scans (p.scans)") +generate_parameters_rst("scan", outfile="scan.rst", title="Scan Definition (p.scans.scan_00)") +generate_parameters_rst("scandata", outfile="scandata.rst", title="Scan Data Definition (p.scans.scan_00.data)") +generate_parameters_rst("engines", outfile="engines.rst", title="List of Engines (p.engines)") +generate_parameters_rst("engine", outfile="engine.rst", title="Engine Definition (p.engines.engine_00)") +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration project = 'PtyPy' copyright = '2024, Pierre Thibault, Bjoern Enders, Benedikt Daurer and others' -# -- General configuration --------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration - extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', @@ -26,7 +36,7 @@ 'sphinx.ext.intersphinx', 'sphinx.ext.mathjax', 'sphinx.ext.napoleon', - # 'sphinx.ext.linkcode', + 'sphinx.ext.todo', 'myst_parser', ] @@ -41,6 +51,8 @@ autosummary_generate = True autodoc_mock_imports = ["cupy", "pycuda", "reikna", "hdf5plugin", "bitshuffle", "fabio", "swmr_tools"] +todo_include_todos = True + # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output @@ -49,6 +61,7 @@ html_css_files = ["ptypy.css"] html_logo = '_static/logo_100px.png' html_favicon = '_static/ptypyicon.ico' +html_show_sourcelink = False html_sidebars = { 'overview': [] } diff --git a/docs/source/index.rst b/docs/source/index.rst index d2227bf68..77fb61a11 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -22,6 +22,7 @@ PtyPy Documentation Contents overview installation userguide/index + parameters/index reference/index diff --git a/docs/source/parameters/index.rst b/docs/source/parameters/index.rst new file mode 100644 index 000000000..332e79912 --- /dev/null +++ b/docs/source/parameters/index.rst @@ -0,0 +1,18 @@ +Parameters +========== + +.. todo:: Add short explanation of the parameter tree, possible with a simple graph. + +Parameter definitions +--------------------- + +.. toctree:: + :maxdepth: 1 + + generated/ptycho + generated/io + generated/scans + generated/scan + generated/scandata + generated/engines + generated/engine From be603ac50f784e0a8ecd2edc6d065e7eff5bc32c Mon Sep 17 00:00:00 2001 From: Benedikt Date: Fri, 20 Dec 2024 10:48:42 +0000 Subject: [PATCH 05/10] Reorganising CI for docs --- .github/workflows/_build_docs.yaml | 58 +++++++++ .github/workflows/_build_legacy_docs.yaml | 61 ++++++++++ .github/workflows/_github_pages.yaml | 35 ++++++ .github/workflows/docs.yaml | 137 ++-------------------- docs/index.html | 5 + 5 files changed, 172 insertions(+), 124 deletions(-) create mode 100644 .github/workflows/_build_docs.yaml create mode 100644 .github/workflows/_build_legacy_docs.yaml create mode 100644 .github/workflows/_github_pages.yaml create mode 100644 docs/index.html diff --git a/.github/workflows/_build_docs.yaml b/.github/workflows/_build_docs.yaml new file mode 100644 index 000000000..667819694 --- /dev/null +++ b/.github/workflows/_build_docs.yaml @@ -0,0 +1,58 @@ +on: + workflow_call: + inputs: + tag: + type: string + description: A tag for the docs artifact + required: true + +jobs: + build_new_docs: + runs-on: ubuntu-latest + steps: + - name: Checkout PtyPy Code + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + check-latest: true + + - name: Setup MPI + uses: mpi4py/setup-mpi@v1 + with: + mpi: mpich + + - name: Install Sphinx + run: pip install sphinx myst_parser + + - name: Install PtyPy + run: pip install .[full] + + - name: Install docs dependencies + run: pip install -r docs/requirements.txt + + - name: Set Path to Sphinx Build + run: echo "SPHINXBUILD=`which sphinx-build`" >> $GITHUB_ENV + + - name: Build Sphinx Documentation + working-directory: docs + run: make html + + - name: Rename Build Directory + run: | + mkdir artifacts + mv docs/_build/html artifacts/${{ inputs.tag }} + + - name: Upload Docs Artifact + uses: actions/upload-artifact@v4.4.3 + with: + name: docs-${{ inputs.tag }} + path: artifacts + + - name: Upload index.html as Artifact + uses: actions/upload-artifact@v4.4.3 + with: + name: docs-index-html + path: docs/index.html diff --git a/.github/workflows/_build_legacy_docs.yaml b/.github/workflows/_build_legacy_docs.yaml new file mode 100644 index 000000000..a3a638be4 --- /dev/null +++ b/.github/workflows/_build_legacy_docs.yaml @@ -0,0 +1,61 @@ +on: + workflow_call: + inputs: + tag: + type: string + description: A tag for the docs artifact + required: true + +jobs: + build_legacy_docs: + runs-on: ubuntu-latest + steps: + - name: Checkout PtyPy Code + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + check-latest: true + + - name: Setup MPI + uses: mpi4py/setup-mpi@v1 + with: + mpi: mpich + + - name: Install Sphinx + run: pip install sphinx + + - name: Install PtyPy + run: pip install .[full] + + - name: Prepare Tutorials + working-directory: doc + run: python script2rst.py + + - name: Prepare Templates + working-directory: doc + run: python tmp2rst.py + + - name: Prepare Parameters + working-directory: doc + run: python parameters2rst.py + + - name: Set Path to Sphinx Build + run: echo "SPHINXBUILD=`which sphinx-build`" >> $GITHUB_ENV + + - name: Build Sphinx Documentation + working-directory: doc + run: make html + + - name: Rename Build Directory + run: | + mkdir artifacts + mv doc/build/html artifacts/${{ inputs.tag }} + + - name: Upload Docs Artifact + uses: actions/upload-artifact@v4.4.3 + with: + name: docs-${{ inputs.tag }} + path: artifacts diff --git a/.github/workflows/_github_pages.yaml b/.github/workflows/_github_pages.yaml new file mode 100644 index 000000000..c754d8e53 --- /dev/null +++ b/.github/workflows/_github_pages.yaml @@ -0,0 +1,35 @@ +on: + workflow_call: + +jobs: + publish_pages: + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Setup Pages + uses: actions/configure-pages@v5.0.0 + + - name: Download Latest Docs Artifact + uses: actions/download-artifact@v4.1.8 + with: + pattern: docs-* + merge-multiple: true + path: ./ + + - name: Fix File Permissions for Pages + run: | + chmod -R +rX . + + - name: Upload Merged Artifact to Pages + uses: actions/upload-pages-artifact@v3.0.1 + with: + path: ./ + + - name: Publish Docs to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4.0.5 diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index f93956dd7..3aa6818ea 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -4,132 +4,21 @@ on: push: branches: - master + - dev jobs: - build_docs_old: - runs-on: ubuntu-latest - steps: - - name: Checkout PtyPy Code - uses: actions/checkout@v4 + legacy_docs: + uses: ./.github/workflows/_build_legacy_docs.yaml + with: + tag: legacy - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.13' - check-latest: true + new_docs: + uses: ./.github/workflows/_build_docs.yaml + with: + tag: ${{ github.ref_name }} - - name: Setup MPI - uses: mpi4py/setup-mpi@v1 - with: - mpi: mpich - - - name: Install Sphinx - run: pip install sphinx - - - name: Install PtyPy - run: pip install .[full] - - - name: Prepare Tutorials - working-directory: doc - run: python script2rst.py - - - name: Prepare Templates - working-directory: doc - run: python tmp2rst.py - - - name: Prepare Parameters - working-directory: doc - run: python parameters2rst.py - - - name: Set Path to Sphinx Build - run: echo "SPHINXBUILD=`which sphinx-build`" >> $GITHUB_ENV - - - name: Build Sphinx Documentation - working-directory: doc - run: make html - - - name: Upload Docs Artifact - uses: actions/upload-artifact@v4.4.3 - with: - name: old-docs - path: doc/build/html/ - - build_docs: - runs-on: ubuntu-latest - steps: - - name: Checkout PtyPy Code - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: '3.13' - check-latest: true - - - name: Setup MPI - uses: mpi4py/setup-mpi@v1 - with: - mpi: mpich - - - name: Install Sphinx - run: pip install sphinx myst_parser - - - name: Install PtyPy - run: pip install .[full] - - - name: Install docs dependencies - run: pip install -r docs/requirements.txt - - - name: Set Path to Sphinx Build - run: echo "SPHINXBUILD=`which sphinx-build`" >> $GITHUB_ENV - - - name: Build Sphinx Documentation - working-directory: docs - run: make html - - - name: Upload Docs Artifact - uses: actions/upload-artifact@v4.4.3 - with: - name: new-docs - path: docs/_build/html/ - - publish_pages: - if: github.event_name == 'push' && github.ref == 'refs/heads/master' + github_pages: needs: - - build_docs_old - - build_docs - runs-on: ubuntu-latest - permissions: - pages: write - id-token: write - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - steps: - - name: Setup Pages - uses: actions/configure-pages@v5.0.0 - - - name: Download Old Docs Artifact - uses: actions/download-artifact@v4.1.8 - with: - name: old-docs - path: ./ - - - name: Download Docs Artifact - uses: actions/download-artifact@v4.1.8 - with: - name: new-docs - path: ./docs - - - name: Fix File Permissions for Pages - run: | - chmod -R +rX . - - - name: Upload Merged Artifact - uses: actions/upload-pages-artifact@v3.0.1 - with: - path: ./ - - - name: Publish Docs to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4.0.5 + - legacy_docs + - new_docs + uses: ./.github/workflows/_github_pages.yaml diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 000000000..ce7572f9f --- /dev/null +++ b/docs/index.html @@ -0,0 +1,5 @@ + + + + + From d1be0096f0633de892b24286dfdaa5fa25a117cf Mon Sep 17 00:00:00 2001 From: Benedikt Date: Fri, 20 Dec 2024 14:22:22 +0000 Subject: [PATCH 06/10] Remove announcement banner --- docs/source/conf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 09b8935c3..f38164a11 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -79,7 +79,6 @@ "icon": "fa-solid fa-link ", }, ], - "announcement": "https://daurer.github.io/ptypy-new-docs/docs/_static/banner.html", } From dd30d8111a44d60ed759b0ed17ed6b68d377867f Mon Sep 17 00:00:00 2001 From: Benedikt Date: Fri, 20 Dec 2024 16:56:12 +0000 Subject: [PATCH 07/10] Adding version switcher to CI --- {docs => .github/pages}/index.html | 0 .github/pages/switcher.py | 41 ++++++++++++++++++++++++++++ .github/workflows/_build_docs.yaml | 6 ---- .github/workflows/_github_pages.yaml | 2 +- .github/workflows/_switcher.yaml | 32 ++++++++++++++++++++++ .github/workflows/docs.yaml | 8 +++++- 6 files changed, 81 insertions(+), 8 deletions(-) rename {docs => .github/pages}/index.html (100%) create mode 100644 .github/pages/switcher.py create mode 100644 .github/workflows/_switcher.yaml diff --git a/docs/index.html b/.github/pages/index.html similarity index 100% rename from docs/index.html rename to .github/pages/index.html diff --git a/.github/pages/switcher.py b/.github/pages/switcher.py new file mode 100644 index 000000000..bf8fb2646 --- /dev/null +++ b/.github/pages/switcher.py @@ -0,0 +1,41 @@ +"""Create/modify switcher.json to allow docs to switch between different versions.""" + +import json, os +from argparse import ArgumentParser +from pathlib import Path + + +def get_versions(root: str) -> list[str]: + """Generate a list of versions.""" + versions = sorted([ f.name for f in os.scandir(root) if f.is_dir() ]) + print(f"Sorted versions: {versions}") + return versions + + +def write_json(path: Path, repository: str, versions: list[str]): + """Write the JSON switcher to path.""" + org, repo_name = repository.split("/") + struct = [ + {"version": version, "url": f"https://{org}.github.io/{repo_name}/{version}/"} + for version in versions + ] + text = json.dumps(struct, indent=2) + print(f"JSON switcher:\n{text}") + path.write_text(text, encoding="utf-8") + + +def main(args=None): + """Parse args and write switcher.""" + parser = ArgumentParser(description="Make a versions.json file") + parser.add_argument("root", type=Path, help="Path to root directory with all versions of docs") + parser.add_argument("repository", help="The GitHub org and repository name: ORG/REPO") + parser.add_argument("output", type=Path, help="Path of write switcher.json to") + args = parser.parse_args(args) + + # Write the versions file + versions = get_versions(args.root) + write_json(args.output, args.repository, versions) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/.github/workflows/_build_docs.yaml b/.github/workflows/_build_docs.yaml index 667819694..f6a32df3d 100644 --- a/.github/workflows/_build_docs.yaml +++ b/.github/workflows/_build_docs.yaml @@ -50,9 +50,3 @@ jobs: with: name: docs-${{ inputs.tag }} path: artifacts - - - name: Upload index.html as Artifact - uses: actions/upload-artifact@v4.4.3 - with: - name: docs-index-html - path: docs/index.html diff --git a/.github/workflows/_github_pages.yaml b/.github/workflows/_github_pages.yaml index c754d8e53..5b71d1654 100644 --- a/.github/workflows/_github_pages.yaml +++ b/.github/workflows/_github_pages.yaml @@ -14,7 +14,7 @@ jobs: - name: Setup Pages uses: actions/configure-pages@v5.0.0 - - name: Download Latest Docs Artifact + - name: Download All Docs Artifact uses: actions/download-artifact@v4.1.8 with: pattern: docs-* diff --git a/.github/workflows/_switcher.yaml b/.github/workflows/_switcher.yaml new file mode 100644 index 000000000..44b3fcbc5 --- /dev/null +++ b/.github/workflows/_switcher.yaml @@ -0,0 +1,32 @@ +on: + workflow_call: + +jobs: + version_switcher: + runs-on: ubuntu-latest + steps: + - name: Checkout PtyPy Code + uses: actions/checkout@v4 + + - name: Upload index.html as Artifact + uses: actions/upload-artifact@v4.4.3 + with: + name: docs-index-html + path: .github/pages/index.html + + - name: Download All Docs Artifact + uses: actions/download-artifact@v4.1.8 + with: + pattern: docs-* + merge-multiple: true + path: ./doc_versions + + - name: Create Switcher File + run: python .github/pages/switcher.py ./doc_versions ${{ github.repository }} .github/pages/switcher.json + + - name: Upload switcher.json as Artifact + uses: actions/upload-artifact@v4.4.3 + with: + name: docs-switcher-json + path: .github/pages/switcher.json + \ No newline at end of file diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 3aa6818ea..7cc2ea589 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -5,6 +5,8 @@ on: branches: - master - dev + release: + type: [published] jobs: legacy_docs: @@ -17,8 +19,12 @@ jobs: with: tag: ${{ github.ref_name }} - github_pages: + switcher: + uses: ./.github/workflows/_switcher.yaml needs: - legacy_docs - new_docs + + github_pages: + needs: switcher uses: ./.github/workflows/_github_pages.yaml From 186a349c11000735b7fd72fca1b3e85814ad0f0e Mon Sep 17 00:00:00 2001 From: Benedikt Date: Fri, 20 Dec 2024 17:13:23 +0000 Subject: [PATCH 08/10] Add version switcher to docs page --- docs/source/conf.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index f38164a11..cf5b3f180 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -79,6 +79,11 @@ "icon": "fa-solid fa-link ", }, ], + "switcher": { + "json_url": "https://daurer.github.io/ptypy-new-docs/switcher.json", + "version_match": "master", + }, + "navbar_start": ["navbar-logo", "version-switcher"] } From 6815556fad139e69fb19647fcf82e97e59adcc73 Mon Sep 17 00:00:00 2001 From: Maik Kahnt Date: Wed, 17 Sep 2025 11:39:15 +0200 Subject: [PATCH 09/10] starting user guide section --- docs/source/_userguide_generator.py | 15 +++++++++++++++ docs/source/conf.py | 9 ++++++++- docs/source/userguide/index.md | 6 ++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 docs/source/_userguide_generator.py create mode 100644 docs/source/userguide/index.md diff --git a/docs/source/_userguide_generator.py b/docs/source/_userguide_generator.py new file mode 100644 index 000000000..757db9302 --- /dev/null +++ b/docs/source/_userguide_generator.py @@ -0,0 +1,15 @@ +import os +import numpy as np +import matplotlib.pyplot as plt +import ptypy + +# if output directory does not exist, create it +if not os.path.exists("./userguide/generated/"): + os.mkdir("./userguide/generated/") + +def create_test_image(outdir="./userguide/generated/", outfile="test.png"): + plt.figure() + plt.scatter(np.random.random(10), np.random.random(10), c='r') + plt.tight_layout() + plt.savefig(f'{outdir}{outfile}') + diff --git a/docs/source/conf.py b/docs/source/conf.py index cf5b3f180..07d3dd691 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -14,7 +14,7 @@ from _param_generator import generate_parameters_rst # Generate List of Parameters -generate_parameters_rst("ptycho", outfile="ptycho.rst", title="Root/Ptycho (p)") +#generate_parameters_rst("ptycho", outfile="ptycho.rst", title="Root/Ptycho (p)") generate_parameters_rst("io", outfile="io.rst", title="Input/Output (p.io)") generate_parameters_rst("scans", outfile="scans.rst", title="List of Scans (p.scans)") generate_parameters_rst("scan", outfile="scan.rst", title="Scan Definition (p.scans.scan_00)") @@ -22,6 +22,13 @@ generate_parameters_rst("engines", outfile="engines.rst", title="List of Engines (p.engines)") generate_parameters_rst("engine", outfile="engine.rst", title="Engine Definition (p.engines.engine_00)") +# Generate images for user guide +from _userguide_generator import create_test_image +create_test_image(outdir="./userguide/generated/", outfile="test.png") + + + + # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/docs/source/userguide/index.md b/docs/source/userguide/index.md new file mode 100644 index 000000000..3ef85c3a1 --- /dev/null +++ b/docs/source/userguide/index.md @@ -0,0 +1,6 @@ +# User guide + +![checking a test image](generated/test.png) + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. In dapibus dapibus dolor laoreet vehicula. Suspendisse malesuada massa eu congue placerat. Morbi et est sed libero gravida suscipit pharetra nec lorem. In gravida tortor eu velit convallis iaculis. Vestibulum viverra augue eu aliquam eleifend. Duis nec blandit leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam malesuada placerat nulla, et aliquam turpis aliquam id. Nunc eu faucibus neque. Integer vulputate ante a orci tincidunt euismod. Phasellus laoreet urna nec sagittis rutrum. Nullam ac tempor nunc, rutrum hendrerit massa. Donec nec orci justo. + From 116a419521a16a4c5a9d36ac281f9f84ea16edaa Mon Sep 17 00:00:00 2001 From: Maik Kahnt Date: Wed, 17 Sep 2025 16:59:10 +0200 Subject: [PATCH 10/10] added user guide section for creating initial probe estimates --- docs/source/_userguide_generator.py | 241 ++++++++++++- docs/source/conf.py | 3 +- docs/source/userguide/index.md | 9 +- docs/source/userguide/setting_probe_init.md | 366 ++++++++++++++++++++ 4 files changed, 614 insertions(+), 5 deletions(-) create mode 100644 docs/source/userguide/setting_probe_init.md diff --git a/docs/source/_userguide_generator.py b/docs/source/_userguide_generator.py index 757db9302..7d62ce185 100644 --- a/docs/source/_userguide_generator.py +++ b/docs/source/_userguide_generator.py @@ -1,15 +1,252 @@ import os import numpy as np import matplotlib.pyplot as plt -import ptypy +from ptypy import utils as u +from ptypy.core import geometry, illumination, Storage, Container, Ptycho # if output directory does not exist, create it if not os.path.exists("./userguide/generated/"): os.mkdir("./userguide/generated/") + + def create_test_image(outdir="./userguide/generated/", outfile="test.png"): + data = np.random.random((20,2)) plt.figure() - plt.scatter(np.random.random(10), np.random.random(10), c='r') + plt.plot(data[:,0], data[:,1], c='r', marker='>') + plt.tight_layout() + plt.savefig(f'{outdir}{outfile}') + + +def create_all_init_probe_figures(outdir="./userguide/generated/"): + create_one_init_probe_figure(p=make_probe_example_01(), outdir=outdir, outfile="init_probe_example_01.png") + create_one_init_probe_figure(p=make_probe_example_02(), outdir=outdir, outfile="init_probe_example_02.png") + #create_one_init_probe_figure(storage=make_probe_example_11(), outdir=outdir, outfile="init_probe_example_11.png") + create_one_init_probe_figure(p=make_probe_example_21(), outdir=outdir, outfile="init_probe_example_21.png") + create_one_init_probe_figure(p=make_probe_example_22(), outdir=outdir, outfile="init_probe_example_22.png") + create_one_init_probe_figure(p=make_probe_example_23(), outdir=outdir, outfile="init_probe_example_23.png") + create_one_init_probe_figure(p=make_probe_example_31(), outdir=outdir, outfile="init_probe_example_31.png") + create_one_init_probe_figure(p=make_probe_example_32(), outdir=outdir, outfile="init_probe_example_32.png") + create_one_init_probe_figure(p=make_probe_example_33(), outdir=outdir, outfile="init_probe_example_33.png") + create_one_init_probe_figure(p=make_probe_example_41(), outdir=outdir, outfile="init_probe_example_41.png") + create_one_init_probe_figure(p=make_probe_example_42(), outdir=outdir, outfile="init_probe_example_42.png") + create_one_init_probe_figure(p=make_probe_example_43(), outdir=outdir, outfile="init_probe_example_43.png") + create_one_init_probe_figure(p=make_probe_example_44(), outdir=outdir, outfile="init_probe_example_44.png") + create_one_init_probe_figure(p=make_probe_example_51(), outdir=outdir, outfile="init_probe_example_51.png") + create_one_init_probe_figure(p=make_probe_example_52(), outdir=outdir, outfile="init_probe_example_52.png") + create_one_init_probe_figure(p=make_probe_example_53(), outdir=outdir, outfile="init_probe_example_53.png") + create_one_init_probe_figure(p=make_probe_example_54(), outdir=outdir, outfile="init_probe_example_54.png") + create_one_init_probe_figure(p=make_probe_example_61(), outdir=outdir, outfile="init_probe_example_61.png") + create_one_init_probe_figure(p=make_probe_example_62(), outdir=outdir, outfile="init_probe_example_62.png") + create_one_init_probe_figure(p=make_probe_example_63(), outdir=outdir, outfile="init_probe_example_63.png") + + + +def create_one_init_probe_figure(p=None, outdir="./userguide/generated/", outfile="init_probe_test.png"): + G, g = make_geometry() + s = Storage(Container(ID='probe'), shape=(1, g.shape, g.shape), psize=G.resolution) + illumination.init_storage(s, p, energy=g.energy, shape=(g.shape,g. shape)) + extent = [0, np.shape(s.data)[2] * s._psize[1] * 1.e6, 0, np.shape(s.data)[1] * s._psize[0] * 1.e6] + + plt.figure(figsize=(8,3), dpi=100) + + plt.subplot(1,2,1) + plt.title('initlial probe - amplitude') + plt.imshow(np.abs(s.data[0]), interpolation='None', cmap='Greys_r', extent=extent) + plt.colorbar() + plt.xlabel('um') + plt.ylabel('um') + plt.subplot(1,2,2) + plt.title('initlial probe - phase') + plt.imshow(np.angle(s.data[0]), interpolation='None', cmap='hsv', extent=extent, vmin=-np.pi, vmax=np.pi) + plt.colorbar() + plt.xlabel('um') + plt.ylabel('um') plt.tight_layout() plt.savefig(f'{outdir}{outfile}') +def make_geometry(): + g = u.Param() + g.energy = 12.4 # photon energy in keV + g.distance = 3.16 # detector distance in m + g.psize = 75e-6 # detector pixel size in m + g.shape = 128 # size of the probe array + g.propagation = 'farfield' + G = geometry.Geo(owner=None, pars=g) + return G, g + +def make_probe_example_01(): + probe = np.zeros((1, 256,256), dtype=complex) + probe[0, 64:128, 64:128] = 1. * np.exp(1.j * -0.5 * np.pi) + probe[0, 128:192, 32:96] = 2. * np.exp(1.j * 0.5 * np.pi) + p = u.Param() + p.model = probe + p.aperture = u.Param() + p.aperture.form = 'rect' + p.aperture.size = 10e-6 + return p + +def make_probe_example_02(): + probe = np.zeros((1, 256,256), dtype=complex) + probe[0, 64:128, 64:128] = 1. * np.exp(1.j * -0.5 * np.pi) + probe[0, 128:192, 32:96] = 2. * np.exp(1.j * 0.5 * np.pi) + p = u.Param() + p.model = probe + p.aperture = u.Param() + return p + +def make_probe_example_11(): + # ToDo: implenet example with loading a probe from a previous reconstruction + pass + +def make_probe_example_21(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.size = 500e-9 # in meters + return p + +def make_probe_example_22(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.size = 2000e-9 # in meters + return p + +def make_probe_example_23(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.size = (2000e-9, 500e-9) + return p + +def make_probe_example_31(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'circ' # default + p.aperture.size = 2000e-9 + return p + +def make_probe_example_32(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'rect' + p.aperture.size = 2000e-9 + return p + +def make_probe_example_33(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'rect' + p.aperture.size = (500e-9, 2000e-9) + return p + +def make_probe_example_41(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'rect' + p.aperture.size = (500e-9, 2000e-9) + p.aperture.rotate = 0.15 * 3.1415 # angle in radians + return p + +def make_probe_example_42(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'rect' + p.aperture.size = 2000e-9 + p.aperture.central_stop = 0.20 + return p + +def make_probe_example_43(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'rect' + p.aperture.size = 2000e-9 + p.aperture.edge = 20 # in pixels + return p + +def make_probe_example_44(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'rect' + p.aperture.size = 2000e-9 + p.aperture.offset = (500e-9, 1000e-9) # in m + return p + +def make_probe_example_51(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'rect' + p.aperture.size = 2000e-9 + p.aperture.diffuser = (0.5 * 3.1415, 5) + return p + +def make_probe_example_52(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'rect' + p.aperture.size = 2000e-9 + p.aperture.diffuser = (1 * 3.1415, 2) + return p + +def make_probe_example_53(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'rect' + p.aperture.size = 2000e-9 + p.aperture.diffuser = (0 * 3.1415, 0 , 0.7, 5) + return p + +def make_probe_example_54(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'rect' + p.aperture.size = 2000e-9 + p.aperture.diffuser = (0.5 * 3.1415, 10 , 0.7, 5) + return p + +def make_probe_example_61(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'circ' + p.aperture.size = 1e-6 + p.propagation = u.Param() + p.propagation.parallel = 1e-3 # distance in m + return p + +def make_probe_example_62(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'rect' + p.aperture.size = 525e-6 # aperture diameter of the KB mirrors + p.propagation = u.Param() + p.propagation.focussed = 0.200 # focal length of the KB mirror(s) + p.propagation.parallel = 500e-6 # distance sample to focus + p.propagation.antialiasing = 1 + return p + +def make_probe_example_63(): + p = u.Param() + p.model = None + p.aperture = u.Param() + p.aperture.form = 'circ' + p.aperture.size = 100e-6 # aperture diameter of the FZP + p.aperture.central_stop = 25e-6 / p.aperture.size + p.propagation = u.Param() + p.propagation.focussed = 0.18 # focal length of FZP + #p.propagation.parallel = 100e-6 # distance sample to focus + p.propagation.antialiasing = 1 + return p diff --git a/docs/source/conf.py b/docs/source/conf.py index 07d3dd691..45c292a08 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -25,7 +25,8 @@ # Generate images for user guide from _userguide_generator import create_test_image create_test_image(outdir="./userguide/generated/", outfile="test.png") - +from _userguide_generator import create_all_init_probe_figures +create_all_init_probe_figures(outdir="./userguide/generated/") diff --git a/docs/source/userguide/index.md b/docs/source/userguide/index.md index 3ef85c3a1..c6aa9086d 100644 --- a/docs/source/userguide/index.md +++ b/docs/source/userguide/index.md @@ -1,6 +1,11 @@ # User guide -![checking a test image](generated/test.png) -Lorem ipsum dolor sit amet, consectetur adipiscing elit. In dapibus dapibus dolor laoreet vehicula. Suspendisse malesuada massa eu congue placerat. Morbi et est sed libero gravida suscipit pharetra nec lorem. In gravida tortor eu velit convallis iaculis. Vestibulum viverra augue eu aliquam eleifend. Duis nec blandit leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Nam malesuada placerat nulla, et aliquam turpis aliquam id. Nunc eu faucibus neque. Integer vulputate ante a orci tincidunt euismod. Phasellus laoreet urna nec sagittis rutrum. Nullam ac tempor nunc, rutrum hendrerit massa. Donec nec orci justo. +```{toctree} +--- +maxdepth: 1 +--- +setting_probe_init.md +``` + diff --git a/docs/source/userguide/setting_probe_init.md b/docs/source/userguide/setting_probe_init.md new file mode 100644 index 000000000..34a967860 --- /dev/null +++ b/docs/source/userguide/setting_probe_init.md @@ -0,0 +1,366 @@ +# setting the initial probe + +Starting a ptychography reconstruction with a good or bad initial estimate of the probe(s) can change the convergence speed of the reconstruction or even influence if the reconstruction converges at all or fails. +The closer the initial estimate is to the real probing wavefront on the sample, the better. +Hence it is important to know what kind of beam is expected on the sample. + +* What size? +* What shape? +* What phase profile? + +Having knowledge about the optics used to focus the beam, their parameters and what kind of focus they create and where the sample was roughly positioned with respect to the focus are important things to consider when choosing how to initialize the probe estimate(s) for a ptychographic reconstruction. +This true for all reconstruction algorithms (engines). + +```ptypy``` allows to initialize the probe estimate prior to the first iteration in various ways. +One way is simply using an arbitrary numpy array of the right size that the user build by whatever python capabilities she/he has. +Results from previous reconstructions can also be loaded. +The initial probe estimate can also be made from basic geometric shapes that can also be modified in various ways. + +## init by any numpy array + +If you know some numpy, you are able to create any probe estimate you like. +Just create a three-dimensional array where the first dimension is simply as long as the number of probe modes (in the most simple case =1) and the other two dimensions match the size of the 2D probe array depending on the cropping and binning. +Then give that array you created into the parameter tree as 'illumination.model'. + +```python +import numpy as np +probe = np.zeros((1, 256,256), dtype=complex) +# make sure to init as as complex otherwise the imaginary part will be discarded +probe[0, 64:128, 64:128] = 1. * np.exp(1.j * -0.5 * np.pi) +probe[0, 128:192, 32:96] = 2. * np.exp(1.j * 0.5 * np.pi) + +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = probe +# here we just give the numpy array we made above +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'rect' +# this aperture is not optional +p.scans.scan00.illumination.aperture.size = 10e-6 +# either make it very large, or you will cut down the probe +``` + +![init probe from numpy array](generated/init_probe_example_01.png) + + +Warning: not defining the aperture, will still apply a default aperture (round and about a third of the array size) and this cut down the probe you made. So define a large enough aperture. + +```python +import numpy as np +probe = np.zeros((1, 256,256), dtype=complex) +probe[0, 64:128, 64:128] = 1. * np.exp(1.j * -0.5 * np.pi) +probe[0, 128:192, 32:96] = 2. * np.exp(1.j * 0.5 * np.pi) + +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = probe +p.scans.scan00.illumination.aperture = u.Param() +``` + +![init probe from numpy array](generated/init_probe_example_02.png) + +## init by loading a previous reconstructions + +By setting 'illumination.model' to 'recon' one can load the probe of a previous reconstruction by giving the the relative or absolute file path of a previous reconstruction (the .ptyr file). + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = 'recon' +p.scans.scan00.illumination.recon = u.Param() +p.scans.scan00.illumination.recon.rfile = '/data//rec_24_ML_1000.ptyr' +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'rect' +# same thing with the needed aperture +p.scans.scan00.illumination.aperture.size = 10e-6 +``` + +[//]: # (ToDo: put a real probe somewhere to download and create a figure from it) +[//]: # (![init probe from a previous reconstruction](generated/init_probe_example_11.png)) + +Warning: When loading a probe from a previous reconstruction, things like pixel size, photon energy ect are all ignored. +The probe is simply loaded as the numpy array and used that way, pixel by pixel. +If the probe you load has fewer pixels than the probe your reconstruction calls for, the missing pixels will be padded on with 0. +Likewise, the other way around, the too large input array will simply be cropped to the smaller size. + +Again, if no aperture is defined, the default aperture (circle with a third of the array size as a diameter) is applied and might cut down the probe that you loaded. + +## init by geometric base shapes (illumination.aperture) + +Besides making a probe yourself or loading a previous reconstruction, it is also possible to define inital probe estimate(s) using simple geometric shapes with the 'illumination.aperture' parameter in the parameter tree. + +### illumination.aperture.size + +One important parameter is the size of the initial probe estimate. In ptypy this parameter is given in meters. Here an example for a 500nm sized probe. + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.size = 500e-9 # in meters +``` + +![init probe from base shapes](generated/init_probe_example_21.png) + +As expected, a larger value in 'aperture.size' will result in a larger probe estimate: + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.size = 2000e-9 # in meters +``` + +![init probe from base shapes](generated/init_probe_example_22.png) + +When giving a two-element list/tuple the two values are applied to the vertical and horizontal (python like, y before x) direction respectively. +This allows to create asymmetric probes: + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.size = (2000e-9, 500e-9) +# python like y first, then x +``` + +![init probe from base shapes](generated/init_probe_example_23.png) + +### illumination.aperture.form + +Of course the shape can also be changed. +This can be achieved by changing the 'aperture.form' parameter. +As we have seen in the previous example, a simple circle is the default setting: + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'circ' # default +p.scans.scan00.illumination.aperture.size = 2000e-9 +``` +![init probe from base shapes](generated/init_probe_example_31.png) + +The other option is 'rect' for rectangle. +This can of course also be used to create squares: + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'rect' +p.scans.scan00.illumination.aperture.size = 2000e-9 +``` + +![init probe from base shapes](generated/init_probe_example_32.png) + +But it can also be used for rectangles when giving two different numbers on the 'aperture.size' parameter. + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'rect' +p.scans.scan00.illumination.aperture.size = (500e-9, 2000e-9) +``` + +![init probe from base shapes](generated/init_probe_example_33.png) + +### illumination.aperture.rotate + +Any probe estimate created from a basic aperture can also be rotated. +The rotation is set via 'aperture.rotate' and is given in radians. + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'rect' +p.scans.scan00.illumination.aperture.size = (500e-9, 2000e-9) +p.scans.scan00.illumination.aperture.rotate = 0.15 * 3.1415 # angle in radians +``` + +![init probe from base shapes](generated/init_probe_example_41.png) + +### illumination.aperture.central_stop + +To account for illuminations from Fresnel zone plates, it is also possible to add a central stop. +Basically an aperture inside the aperture. +It has the same shape as the defined aperture. +Only its size can be defined as a relative fraction of the aperture size. +This way one can cut out a center bit of the created aperture: + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'rect' +p.scans.scan00.illumination.aperture.size = 2000e-9 +p.scans.scan00.illumination.aperture.central_stop = 0.20 +# relative fraction of the aperture size +``` + +![init probe from base shapes](generated/init_probe_example_42.png) + +### illumination.aperture.edge + +The edges of the probe estimates created via apertures can be softened. +The extend of this soft edge is given in pixels in the 'aperture.edge' parameter. +By default is set to 2 pixels. +Larger values can be used to make large fuzzy edges: + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'rect' +p.scans.scan00.illumination.aperture.size = 2000e-9 +p.scans.scan00.illumination.aperture.edge = 20 # in pixels +``` + +![init probe from base shapes](generated/init_probe_example_43.png) + +### illumination.aperture.offset + +So far all examples have been centered in the probe array. +It is also possible to put place the aperture somewhere else using the 'aperture.offset' parameter. +It is also given as a tuple (y-offset, x-offset) in meters: + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'rect' +p.scans.scan00.illumination.aperture.size = 2000e-9 +p.scans.scan00.illumination.aperture.offset = (500e-9, 1000e-9) # in m +``` + +![init probe from base shapes](generated/init_probe_example_44.png) + +### illumination.aperture.diffuser + +Up to now all probe estimates created using apertures show a flat amplitude profile and flat phase profile. +The 'aperture.diffusor' allows to add noise to either the amplitude profile, phase profile or both. +By default it is set to None, which creates these flat profiles + +The 'aperture.diffusor' is a tuple. +Defining a tuple with two elements allows to define a variation of (only) the phase profile. +The first number is the amplitude (rms) of the phase variants in radians and the second parameter is the minimum feature size in pixels: + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'rect' +p.scans.scan00.illumination.aperture.size = 2000e-9 +p.scans.scan00.illumination.aperture.diffuser = (0.5 * 3.1415, 5) +# noise in phase (amplitude (rms), minimum feature size) in radian +``` + +![init probe from base shapes](generated/init_probe_example_51.png) + +Larger amplitudes of the phase profile variation will create larger differences between the mountains and the valleys in the phase profile. +The minimum feature size defines the extend of the noise spots created: + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'rect' +p.scans.scan00.illumination.aperture.size = 2000e-9 +p.scans.scan00.illumination.aperture.diffuser = (1 * 3.1415, 2) +``` + +![init probe from base shapes](generated/init_probe_example_52.png) + +Giving the 'aperture.diffusor' two more entries allows to also add noise to the amplitude as well using the same syntax. +Setting the first two entries to zero allows to vary the amplitude, but keeping a flat phase. + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'rect' +p.scans.scan00.illumination.aperture.size = 2000e-9 +p.scans.scan00.illumination.aperture.diffuser = (0 * 3.1415, 0 , 0.7, 5) +# (zero) noise in phase and amplitude (rms_ph,mfs_ph,rms_mod) +``` + +![init probe from base shapes](generated/init_probe_example_53.png) + +Of course noise can be added to both amplitude and phase separately with different strength and size. + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'rect' +p.scans.scan00.illumination.aperture.size = 2000e-9 +p.scans.scan00.illumination.aperture.diffuser = (0.5 * 3.1415, 10 , 0.7, 5) +# (rms_ph,mfs_ph,rms_mod,mfs_mod) +``` + +![init probe from base shapes](generated/init_probe_example_54.png) + + +## propagation +A very powerful feature is the capability to propagate a probe estimate. +This works for probes given as numpy arrays, for loaded probes and also for probes defined as apertures. +This feature allows to give the initial probe estimate the right phase curvature, to kick the reconstruction in the right way. + +### illumination.propagation.parallel + +The first option to propagate is the the 'parallel' propagation. +This nearfield propagataion is usful when describing the wavefront very close to the sample plane. +In the following example a 1um pinhole is illumanted by a large flat (phase and amplitude) beam and placed 1mm upstream of the sample: + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = probe +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'circ' +p.scans.scan00.illumination.aperture.size = 1e-6 +p.scans.scan00.illumination.propagation = u.Param() +p.scans.scan00.illumination.propagation.parallel = 1e-3 +``` + +![init probe from base shapes](generated/init_probe_example_61.png) + +### illumination.propagation.focussed + +The second option to propagate is the the 'focussed' propagation. +This farfield propagataion is usful when describing the wavefront far away from the sample plane. + +In the following example a pair of KB mirrors is illumanted by a large flat (phase and amplitude) beam. +The mirrors have an idential NA (aperture of 525um and focal length of 200mm). +The sample is however not placed in focus, but 500um downstream of the focus. + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = probe +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.size = 525e-6 # aperture diameter +p.scans.scan00.illumination.propagation = u.Param() +p.scans.scan00.illumination.propagation.focussed = 0.200 # focal length +p.scans.scan00.illumination.propagation.parallel = 500e-6 # dist: sample<->focus +p.scans.scan00.illumination.propagation.antialiasing = 1 +``` + +![init probe from base shapes](generated/init_probe_example_62.png) + +In the next example an Fresnel Zone Plane (FZP) is illumanted by a large flat (phase and amplitude) beam. +The FZP has a diameter of 100um and focal length of 18mm). +A central stop of 25um was used. +The sample is again not placed in focus, but 500um downstream of the focus. + +```python +p.scans.scan00.illumination = u.Param() +p.scans.scan00.illumination.model = None +p.scans.scan00.illumination.aperture = u.Param() +p.scans.scan00.illumination.aperture.form = 'circ' +p.scans.scan00.illumination.aperture.size = 100e-6 # aperture diameter of the FZP +p.scans.scan00.illumination.aperture.central_stop = 25e-6 / p.aperture.size +p.scans.scan00.illumination.propagation = u.Param() +p.scans.scan00.illumination.propagation.focussed = 0.18 # focal length of FZP +p.scans.scan00.illumination.propagation.parallel = 100e-6 # distance sample to focus +p.scans.scan00.illumination.propagation.antialiasing = 1 +``` + +![init probe from base shapes](generated/init_probe_example_63.png) \ No newline at end of file