From 0342d7b1507b5f705e367f68176e2e925472c3ba Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 Aug 2025 12:24:15 +0200 Subject: [PATCH 1/9] Updates 'easydiffraction' dependency to 'visualization' extras --- .github/workflows/test-tutorials-colab.yaml | 2 +- docs/installation-and-setup/index.md | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test-tutorials-colab.yaml b/.github/workflows/test-tutorials-colab.yaml index 3327b37a..0c322352 100644 --- a/.github/workflows/test-tutorials-colab.yaml +++ b/.github/workflows/test-tutorials-colab.yaml @@ -49,7 +49,7 @@ jobs: - name: Install Python dependencies run: - python -m pip install 'easydiffraction[charts]' nbconvert nbmake + python -m pip install 'easydiffraction[visualization]' nbconvert nbmake pytest pytest-xdist - name: Check if Jupyter Notebooks run without errors diff --git a/docs/installation-and-setup/index.md b/docs/installation-and-setup/index.md index bb7c6c78..965eca69 100644 --- a/docs/installation-and-setup/index.md +++ b/docs/installation-and-setup/index.md @@ -83,13 +83,13 @@ installed using `pip`. We strongly recommend installing it within a virtual environment, as described in the [Environment Setup](#environment-setup) section. -We recommend installing the latest release of EasyDiffraction with the `charts` -extras, which include optional dependencies used for simplified visualization of -charts and tables. This can be especially useful for running the Jupyter -Notebook examples. To do so, use the following command: +We recommend installing the latest release of EasyDiffraction with the +`visualization` extras, which include optional dependencies used for simplified +visualization of charts and tables. This can be especially useful for running +the Jupyter Notebook examples. To do so, use the following command: ```console -pip install 'easydiffraction[charts]' +pip install 'easydiffraction[visualization]' ``` If only the core functionality is needed, the library can be installed simply @@ -128,10 +128,10 @@ To install EasyDiffraction from, e.g., the `develop` branch of GitHub: pip install git+https://github.com/easyscience/diffraction-lib@develop ``` -To include extra dependencies (e.g., charts): +To include extra dependencies (e.g., visualization): ```console -pip install 'easydiffraction[charts] @ git+https://github.com/easyscience/diffraction-lib@develop' +pip install 'easydiffraction[visualization] @ git+https://github.com/easyscience/diffraction-lib@develop' ``` ## How to Run Tutorials From 4023fb69c1199a54017112b44dfb0fe3b0517ded Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 Aug 2025 12:24:41 +0200 Subject: [PATCH 2/9] Removes Python 3.10 support --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ea48009e..0d80e0c3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,6 @@ classifiers = [ 'Operating System :: OS Independent', 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: 3', - "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", From f7271b8c232a9a62a196e2c8b900096e6d7ef99e Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 Aug 2025 14:27:37 +0200 Subject: [PATCH 3/9] Update workflows and notebooks --- .github/workflows/build-docs.yml | 3 ++- .github/workflows/test-tutorials-colab.yaml | 4 ++-- .github/workflows/test-tutorials.yaml | 2 ++ docs/installation-and-setup/index.md | 6 +++--- tutorials/advanced_joint-fit_pd-neut-xray-cwl_PbSO4.ipynb | 2 +- tutorials/basic_single-fit_pd-neut-cwl_LBCO-HRPT.ipynb | 2 +- tutorials/cryst-struct_pd-neut-cwl_CoSiO4-D20.ipynb | 2 +- tutorials/cryst-struct_pd-neut-cwl_HS-HRPT.ipynb | 2 +- tutorials/cryst-struct_pd-neut-tof_Si-SEPD.ipynb | 2 +- .../cryst-struct_pd-neut-tof_multidata_NCAF-WISH.ipynb | 2 +- ...cryst-struct_pd-neut-tof_multiphase-LBCO-Si_McStas.ipynb | 2 +- ...msc-summer-school-2025_analysis-powder-diffraction.ipynb | 2 +- tutorials/pdf_pd-neut-cwl_Ni.ipynb | 2 +- tutorials/pdf_pd-neut-tof_Si-NOMAD.ipynb | 2 +- tutorials/pdf_pd-xray_NaCl.ipynb | 2 +- tutorials/quick_single-fit_pd-neut-cwl_LBCO-HRPT.ipynb | 2 +- 16 files changed, 21 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index c104a841..1c7313fe 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -104,7 +104,7 @@ jobs: cp ../assets-branding/easyscience-org/icons/eso-icon_bw.svg overrides/.icons/easyscience.svg # Convert python scripts in the notebooks directory to Jupyter notebooks - # Strip output from the notebooks and simpify cell ids + # Strip output from the notebooks, simpify cell ids and replace '# !pip' with '!pip' # The notebooks are used to generate the documentation - name: Convert ${{ env.NOTEBOOKS_DIR }}/*.py to docs/${{env.NOTEBOOKS_DIR @@ -113,6 +113,7 @@ jobs: cp -R ${{ env.NOTEBOOKS_DIR }}/data docs/${{ env.NOTEBOOKS_DIR }}/ jupytext ${{ env.NOTEBOOKS_DIR }}/*.py --from py:percent --to ipynb nbstripout ${{ env.NOTEBOOKS_DIR }}/*.ipynb + sed -i '' 's/# !pip/!pip/g' ${{ env.NOTEBOOKS_DIR }}/*.ipynb mv ${{ env.NOTEBOOKS_DIR }}/*.ipynb docs/${{ env.NOTEBOOKS_DIR }}/ # The following step is needed to avoid the following message during the build: diff --git a/.github/workflows/test-tutorials-colab.yaml b/.github/workflows/test-tutorials-colab.yaml index 0c322352..02640df2 100644 --- a/.github/workflows/test-tutorials-colab.yaml +++ b/.github/workflows/test-tutorials-colab.yaml @@ -49,8 +49,8 @@ jobs: - name: Install Python dependencies run: - python -m pip install 'easydiffraction[visualization]' nbconvert nbmake - pytest pytest-xdist + python -m pip install 'easydiffraction[visualization]' nbconvert + nbmake pytest pytest-xdist - name: Check if Jupyter Notebooks run without errors run: > diff --git a/.github/workflows/test-tutorials.yaml b/.github/workflows/test-tutorials.yaml index 496b400d..df3acb2a 100644 --- a/.github/workflows/test-tutorials.yaml +++ b/.github/workflows/test-tutorials.yaml @@ -142,6 +142,7 @@ jobs: # Check if tutorials as Jupyter Notebooks run without errors # Convert all Python scripts in the folder tutorials/ to Jupyter Notebooks # Strip output from Jupyter Notebooks and rename cell ids + # Replace '# !pip' with '!pip' in Jupyter Notebooks # Run all Jupyter Notebooks in the folder tutorials/ in parallel # -n auto: run as many in parallel as you have cores (auto mode) # --nbmake-timeout=600: set timeout to 600 seconds @@ -150,6 +151,7 @@ jobs: run: | jupytext ${{ env.NOTEBOOKS_DIR }}/*.py --from py:percent --to ipynb nbstripout ${{ env.NOTEBOOKS_DIR }}/*.ipynb + sed -i '' 's/# !pip/!pip/g' ${{ env.NOTEBOOKS_DIR }}/*.ipynb - name: Run tutorials as Jupyter Notebooks (using src/ as the source dir) shell: bash diff --git a/docs/installation-and-setup/index.md b/docs/installation-and-setup/index.md index 965eca69..25220f91 100644 --- a/docs/installation-and-setup/index.md +++ b/docs/installation-and-setup/index.md @@ -83,9 +83,9 @@ installed using `pip`. We strongly recommend installing it within a virtual environment, as described in the [Environment Setup](#environment-setup) section. -We recommend installing the latest release of EasyDiffraction with the -`visualization` extras, which include optional dependencies used for simplified -visualization of charts and tables. This can be especially useful for running +We recommend installing the latest release of EasyDiffraction with the +`visualization` extras, which include optional dependencies used for simplified +visualization of charts and tables. This can be especially useful for running the Jupyter Notebook examples. To do so, use the following command: ```console diff --git a/tutorials/advanced_joint-fit_pd-neut-xray-cwl_PbSO4.ipynb b/tutorials/advanced_joint-fit_pd-neut-xray-cwl_PbSO4.ipynb index 5534d395..81adb316 100644 --- a/tutorials/advanced_joint-fit_pd-neut-xray-cwl_PbSO4.ipynb +++ b/tutorials/advanced_joint-fit_pd-neut-xray-cwl_PbSO4.ipynb @@ -45,7 +45,7 @@ "if hasattr(builtins, '__IPYTHON__'):\n", " if importlib.util.find_spec('easydiffraction') is None:\n", " print('Installing the easydiffraction library...')\n", - " # !pip install 'easydiffraction[visualization]'" + " !pip install 'easydiffraction[visualization]'" ] }, { diff --git a/tutorials/basic_single-fit_pd-neut-cwl_LBCO-HRPT.ipynb b/tutorials/basic_single-fit_pd-neut-cwl_LBCO-HRPT.ipynb index 1f262e1b..1362eb58 100644 --- a/tutorials/basic_single-fit_pd-neut-cwl_LBCO-HRPT.ipynb +++ b/tutorials/basic_single-fit_pd-neut-cwl_LBCO-HRPT.ipynb @@ -51,7 +51,7 @@ "if hasattr(builtins, '__IPYTHON__'):\n", " if importlib.util.find_spec('easydiffraction') is None:\n", " print('Installing the easydiffraction library...')\n", - " # !pip install 'easydiffraction[visualization]'" + " !pip install 'easydiffraction[visualization]'" ] }, { diff --git a/tutorials/cryst-struct_pd-neut-cwl_CoSiO4-D20.ipynb b/tutorials/cryst-struct_pd-neut-cwl_CoSiO4-D20.ipynb index f493bc93..90776439 100644 --- a/tutorials/cryst-struct_pd-neut-cwl_CoSiO4-D20.ipynb +++ b/tutorials/cryst-struct_pd-neut-cwl_CoSiO4-D20.ipynb @@ -39,7 +39,7 @@ "if hasattr(builtins, '__IPYTHON__'):\n", " if importlib.util.find_spec('easydiffraction') is None:\n", " print('Installing the easydiffraction library...')\n", - " # !pip install 'easydiffraction[visualization]'" + " !pip install 'easydiffraction[visualization]'" ] }, { diff --git a/tutorials/cryst-struct_pd-neut-cwl_HS-HRPT.ipynb b/tutorials/cryst-struct_pd-neut-cwl_HS-HRPT.ipynb index 8a07be6f..5a3445e8 100644 --- a/tutorials/cryst-struct_pd-neut-cwl_HS-HRPT.ipynb +++ b/tutorials/cryst-struct_pd-neut-cwl_HS-HRPT.ipynb @@ -39,7 +39,7 @@ "if hasattr(builtins, '__IPYTHON__'):\n", " if importlib.util.find_spec('easydiffraction') is None:\n", " print('Installing the easydiffraction library...')\n", - " # !pip install 'easydiffraction[visualization]'" + " !pip install 'easydiffraction[visualization]'" ] }, { diff --git a/tutorials/cryst-struct_pd-neut-tof_Si-SEPD.ipynb b/tutorials/cryst-struct_pd-neut-tof_Si-SEPD.ipynb index 74787584..ee9f64b0 100644 --- a/tutorials/cryst-struct_pd-neut-tof_Si-SEPD.ipynb +++ b/tutorials/cryst-struct_pd-neut-tof_Si-SEPD.ipynb @@ -39,7 +39,7 @@ "if hasattr(builtins, '__IPYTHON__'):\n", " if importlib.util.find_spec('easydiffraction') is None:\n", " print('Installing the easydiffraction library...')\n", - " # !pip install 'easydiffraction[visualization]'" + " !pip install 'easydiffraction[visualization]'" ] }, { diff --git a/tutorials/cryst-struct_pd-neut-tof_multidata_NCAF-WISH.ipynb b/tutorials/cryst-struct_pd-neut-tof_multidata_NCAF-WISH.ipynb index 1823e82f..5ca083c0 100644 --- a/tutorials/cryst-struct_pd-neut-tof_multidata_NCAF-WISH.ipynb +++ b/tutorials/cryst-struct_pd-neut-tof_multidata_NCAF-WISH.ipynb @@ -42,7 +42,7 @@ "if hasattr(builtins, '__IPYTHON__'):\n", " if importlib.util.find_spec('easydiffraction') is None:\n", " print('Installing the easydiffraction library...')\n", - " # !pip install 'easydiffraction[visualization]'" + " !pip install 'easydiffraction[visualization]'" ] }, { diff --git a/tutorials/cryst-struct_pd-neut-tof_multiphase-LBCO-Si_McStas.ipynb b/tutorials/cryst-struct_pd-neut-tof_multiphase-LBCO-Si_McStas.ipynb index 36f14857..e4fa9b1c 100644 --- a/tutorials/cryst-struct_pd-neut-tof_multiphase-LBCO-Si_McStas.ipynb +++ b/tutorials/cryst-struct_pd-neut-tof_multiphase-LBCO-Si_McStas.ipynb @@ -40,7 +40,7 @@ "if hasattr(builtins, '__IPYTHON__'):\n", " if importlib.util.find_spec('easydiffraction') is None:\n", " print('Installing the easydiffraction library...')\n", - " # !pip install 'easydiffraction[visualization]'" + " !pip install 'easydiffraction[visualization]'" ] }, { diff --git a/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.ipynb b/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.ipynb index fb94399c..40ae4b17 100644 --- a/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.ipynb +++ b/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.ipynb @@ -45,7 +45,7 @@ "if hasattr(builtins, '__IPYTHON__'):\n", " if importlib.util.find_spec('easydiffraction') is None:\n", " print('Installing the easydiffraction library...')\n", - " # !pip install 'easydiffraction[visualization]'" + " !pip install 'easydiffraction[visualization]'" ] }, { diff --git a/tutorials/pdf_pd-neut-cwl_Ni.ipynb b/tutorials/pdf_pd-neut-cwl_Ni.ipynb index 454227ab..57416ff9 100644 --- a/tutorials/pdf_pd-neut-cwl_Ni.ipynb +++ b/tutorials/pdf_pd-neut-cwl_Ni.ipynb @@ -43,7 +43,7 @@ "if hasattr(builtins, '__IPYTHON__'):\n", " if importlib.util.find_spec('easydiffraction') is None:\n", " print('Installing the easydiffraction library...')\n", - " # !pip install 'easydiffraction[visualization]'" + " !pip install 'easydiffraction[visualization]'" ] }, { diff --git a/tutorials/pdf_pd-neut-tof_Si-NOMAD.ipynb b/tutorials/pdf_pd-neut-tof_Si-NOMAD.ipynb index f11ab0f7..854c8183 100644 --- a/tutorials/pdf_pd-neut-tof_Si-NOMAD.ipynb +++ b/tutorials/pdf_pd-neut-tof_Si-NOMAD.ipynb @@ -40,7 +40,7 @@ "if hasattr(builtins, '__IPYTHON__'):\n", " if importlib.util.find_spec('easydiffraction') is None:\n", " print('Installing the easydiffraction library...')\n", - " # !pip install 'easydiffraction[visualization]'" + " !pip install 'easydiffraction[visualization]'" ] }, { diff --git a/tutorials/pdf_pd-xray_NaCl.ipynb b/tutorials/pdf_pd-xray_NaCl.ipynb index c2dd4fd7..be876d10 100644 --- a/tutorials/pdf_pd-xray_NaCl.ipynb +++ b/tutorials/pdf_pd-xray_NaCl.ipynb @@ -42,7 +42,7 @@ "if hasattr(builtins, '__IPYTHON__'):\n", " if importlib.util.find_spec('easydiffraction') is None:\n", " print('Installing the easydiffraction library...')\n", - " # !pip install 'easydiffraction[visualization]'" + " !pip install 'easydiffraction[visualization]'" ] }, { diff --git a/tutorials/quick_single-fit_pd-neut-cwl_LBCO-HRPT.ipynb b/tutorials/quick_single-fit_pd-neut-cwl_LBCO-HRPT.ipynb index bfe5281d..09ab7e0f 100644 --- a/tutorials/quick_single-fit_pd-neut-cwl_LBCO-HRPT.ipynb +++ b/tutorials/quick_single-fit_pd-neut-cwl_LBCO-HRPT.ipynb @@ -51,7 +51,7 @@ "if hasattr(builtins, '__IPYTHON__'):\n", " if importlib.util.find_spec('easydiffraction') is None:\n", " print('Installing the easydiffraction library...')\n", - " # !pip install 'easydiffraction[visualization]'" + " !pip install 'easydiffraction[visualization]'" ] }, { From 3066483dec02f321b35169bbf261d9375fc0fe68 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 Aug 2025 14:59:14 +0200 Subject: [PATCH 4/9] Updates workflow to trigger on 'patch' branch --- .github/workflows/build-docs.yml | 2 +- docs/mkdocs.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 1c7313fe..8cb2c63a 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -4,7 +4,7 @@ on: # Trigger the workflow on push push: # Selected branches - branches: [develop, master, docs] + branches: [develop, master, docs, patch] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 5e2528cf..d713a5f8 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -4,10 +4,10 @@ # Project information site_name: EasyDiffraction Library -site_url: https://docs.easydiffraction.org/lib +site_url: https://docs.easydiffraction.org/lib/ # Repository -repo_url: https://github.com/easyscience/diffraction-lib +repo_url: https://github.com/easyscience/diffraction-lib/ edit_uri: edit/develop/docs/ # Copyright From 68ca6a00f5c7d45bdafe8004fe7e64fc628a064f Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 Aug 2025 15:27:39 +0200 Subject: [PATCH 5/9] Update documentation URLs for EasyDiffraction --- pyproject.toml | 2 +- .../dmsc-summer-school-2025_analysis-powder-diffraction.ipynb | 4 ++-- .../dmsc-summer-school-2025_analysis-powder-diffraction.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0d80e0c3..f156cfb0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,7 +73,7 @@ visualization = [ [project.urls] homepage = 'https://easydiffraction.org' -documentation = 'https://easyscience.github.io/diffraction-lib' +documentation = 'https://docs.easydiffraction.org/lib' source = 'https://github.com/easyscience/diffraction-lib' tracker = 'https://github.com/easyscience/diffraction-lib/issues' diff --git a/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.ipynb b/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.ipynb index 40ae4b17..0ade4a5a 100644 --- a/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.ipynb +++ b/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.ipynb @@ -62,7 +62,7 @@ "This tutorial is self-contained and designed for hands-on learning.\n", "However, if you're interested in exploring more advanced features or learning\n", "about additional capabilities of the EasyDiffraction library, please refer to\n", - "the official documentation: https://easyscience.github.io/diffraction-lib\n", + "the official documentation: https://docs.easydiffraction.org/lib/tutorials/\n", "\n", "Depending on your requirements, you may choose to import only specific\n", "classes. However, for the sake of simplicity in this tutorial, we will import\n", @@ -1915,7 +1915,7 @@ "To continue learning and exploring more features of\n", "the EasyDiffraction library, you can visit the official tutorial page\n", "and select one of the many available tutorials:\n", - "https://easyscience.github.io/diffraction-lib/tutorials/" + "https://docs.easydiffraction.org/lib/tutorials/" ] } ], diff --git a/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.py b/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.py index 8ce98927..9e61e4bd 100644 --- a/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.py +++ b/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.py @@ -31,7 +31,7 @@ # This tutorial is self-contained and designed for hands-on learning. # However, if you're interested in exploring more advanced features or learning # about additional capabilities of the EasyDiffraction library, please refer to -# the official documentation: https://easyscience.github.io/diffraction-lib +# the official documentation: https://docs.easydiffraction.org/lib/tutorials/ # # Depending on your requirements, you may choose to import only specific # classes. However, for the sake of simplicity in this tutorial, we will import @@ -1121,4 +1121,4 @@ # To continue learning and exploring more features of # the EasyDiffraction library, you can visit the official tutorial page # and select one of the many available tutorials: -# https://easyscience.github.io/diffraction-lib/tutorials/ +# https://docs.easydiffraction.org/lib/tutorials/ From ed967ba9a3dc5544ca5b1aa0d70e818a5f5793a1 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 Aug 2025 15:40:39 +0200 Subject: [PATCH 6/9] Replaces sed pip uncomment command with Python script --- .github/workflows/build-docs.yml | 2 +- .github/workflows/test-tutorials-colab.yaml | 2 +- .github/workflows/test-tutorials.yaml | 2 +- tools/nb_uncomment_pip.py | 111 ++++++++++++++++++++ 4 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 tools/nb_uncomment_pip.py diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 8cb2c63a..f18f6e4c 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -113,7 +113,7 @@ jobs: cp -R ${{ env.NOTEBOOKS_DIR }}/data docs/${{ env.NOTEBOOKS_DIR }}/ jupytext ${{ env.NOTEBOOKS_DIR }}/*.py --from py:percent --to ipynb nbstripout ${{ env.NOTEBOOKS_DIR }}/*.ipynb - sed -i '' 's/# !pip/!pip/g' ${{ env.NOTEBOOKS_DIR }}/*.ipynb + python tools/nb_uncomment_pip.py ${{ env.NOTEBOOKS_DIR }}/ mv ${{ env.NOTEBOOKS_DIR }}/*.ipynb docs/${{ env.NOTEBOOKS_DIR }}/ # The following step is needed to avoid the following message during the build: diff --git a/.github/workflows/test-tutorials-colab.yaml b/.github/workflows/test-tutorials-colab.yaml index 02640df2..6cfa6d76 100644 --- a/.github/workflows/test-tutorials-colab.yaml +++ b/.github/workflows/test-tutorials-colab.yaml @@ -1,4 +1,4 @@ -name: Testing tutorials on Colab +name: Test tutorials on Colab on: # Trigger the workflow on push diff --git a/.github/workflows/test-tutorials.yaml b/.github/workflows/test-tutorials.yaml index df3acb2a..529aea24 100644 --- a/.github/workflows/test-tutorials.yaml +++ b/.github/workflows/test-tutorials.yaml @@ -151,7 +151,7 @@ jobs: run: | jupytext ${{ env.NOTEBOOKS_DIR }}/*.py --from py:percent --to ipynb nbstripout ${{ env.NOTEBOOKS_DIR }}/*.ipynb - sed -i '' 's/# !pip/!pip/g' ${{ env.NOTEBOOKS_DIR }}/*.ipynb + python tools/nb_uncomment_pip.py ${{ env.NOTEBOOKS_DIR }}/ - name: Run tutorials as Jupyter Notebooks (using src/ as the source dir) shell: bash diff --git a/tools/nb_uncomment_pip.py b/tools/nb_uncomment_pip.py new file mode 100644 index 00000000..206845d3 --- /dev/null +++ b/tools/nb_uncomment_pip.py @@ -0,0 +1,111 @@ +""" +Uncomment `# !pip ...` lines in Jupyter notebooks so they become `!pip ...`. + +- Operates only on code cells (does not touch outputs/metadata/markdown). +- Matches lines that start with optional whitespace, then `# !pip` (e.g., " # !pip install ..."). +- Rewrites to keep the original indentation and replace the leading "# !pip" with "!pip". +- Processes one or more paths (files or directories) given as CLI args, recursively for directories. +""" + +from __future__ import annotations + +import argparse +import sys +from pathlib import Path +import re + +import nbformat + +# Regex: beginning-of-line, capture leading whitespace, then "#", spaces, then "!pip" +_PATTERN = re.compile(r"^(\s*)#\s*!pip\b") + + +def fix_cell_source(src: str) -> tuple[str, int]: + """ + Replace lines starting with optional whitespace + '# !pip' with '!pip'. + Returns the updated source and number of replacements performed. + """ + changed = 0 + new_lines: list[str] = [] + for line in src.splitlines(keepends=False): + m = _PATTERN.match(line) + if m: + indent = m.group(1) + # Replace only the first '# !pip' at the beginning, preserve the rest of the line + # e.g., " # !pip install foo" -> " !pip install foo" + new_line = _PATTERN.sub(r"\1!pip", line, count=1) + if new_line != line: + changed += 1 + new_lines.append(new_line) + else: + new_lines.append(line) + return ("\n".join(new_lines), changed) + + +def process_notebook(path: Path) -> int: + """ + Process a single .ipynb file. Returns number of lines changed. + """ + nb = nbformat.read(path, as_version=4) + total_changes = 0 + for cell in nb.cells: + if cell.cell_type != "code": + continue + new_src, changes = fix_cell_source(cell.source or "") + if changes: + cell.source = new_src + total_changes += changes + if total_changes: + nbformat.write(nb, path) + return total_changes + + +def iter_notebooks(paths: list[Path]): + for p in paths: + if p.is_dir(): + yield from (q for q in p.rglob("*.ipynb") if q.is_file()) + elif p.is_file() and p.suffix == ".ipynb": + yield p + + +def main(argv: list[str]) -> int: + ap = argparse.ArgumentParser( + description="Uncomment '# !pip ...' to '!pip ...' in code cells of .ipynb notebooks." + ) + ap.add_argument("paths", nargs="+", help="Notebook files or directories to process") + ap.add_argument("--dry-run", action="store_true", help="Report changes without writing files") + args = ap.parse_args(argv) + + targets = list(iter_notebooks([Path(p) for p in args.paths])) + if not targets: + print("No .ipynb files found.", file=sys.stderr) + return 1 + + total_files = 0 + total_changes = 0 + for nb_path in targets: + changes = process_notebook(nb_path) if not args.dry_run else 0 + if args.dry_run: + # For dry-run, compute changes without writing + nb = nbformat.read(nb_path, as_version=4) + changes = 0 + for cell in nb.cells: + if cell.cell_type != "code": + continue + _, c = fix_cell_source(cell.source or "") + changes += c + if changes: + action = "UPDATED" if not args.dry_run else "WOULD UPDATE" + print(f"{action}: {nb_path} ({changes} line(s))") + total_files += 1 + total_changes += changes + + if total_files == 0: + print("No changes needed.") + else: + print(f"Done. Files changed: {total_files}, lines changed: {total_changes}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv[1:])) \ No newline at end of file From b8621b90b3e6e134828890fa49337d520af62463 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 Aug 2025 15:45:32 +0200 Subject: [PATCH 7/9] Sets Plotly as the plotting engine --- ...ool-2025_analysis-powder-diffraction.ipynb | 244 +++++++++--------- ...school-2025_analysis-powder-diffraction.py | 7 + 2 files changed, 136 insertions(+), 115 deletions(-) diff --git a/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.ipynb b/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.ipynb index 0ade4a5a..affa9299 100644 --- a/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.ipynb +++ b/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.ipynb @@ -231,7 +231,10 @@ "columns: TOF, intensity, and intensity error (if available).\n", "\n", "The `plot_meas` method of the project enables us to visualize the measured\n", - "diffraction pattern." + "diffraction pattern.\n", + "\n", + "Before plotting, we set the plotting engine to 'plotly', which provides\n", + "interactive visualizations." ] }, { @@ -240,13 +243,23 @@ "id": "16", "metadata": {}, "outputs": [], + "source": [ + "project_1.plotter.engine = 'plotly'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17", + "metadata": {}, + "outputs": [], "source": [ "project_1.plot_meas(expt_name='sim_si')" ] }, { "cell_type": "markdown", - "id": "17", + "id": "18", "metadata": {}, "source": [ "If you zoom in on the highest TOF peak (around 120,000 Ξs), you will notice\n", @@ -261,7 +274,7 @@ { "cell_type": "code", "execution_count": null, - "id": "18", + "id": "19", "metadata": {}, "outputs": [], "source": [ @@ -271,7 +284,7 @@ }, { "cell_type": "markdown", - "id": "19", + "id": "20", "metadata": {}, "source": [ "To visualize the effect of excluding the high TOF region, we can plot\n", @@ -282,7 +295,7 @@ { "cell_type": "code", "execution_count": null, - "id": "20", + "id": "21", "metadata": {}, "outputs": [], "source": [ @@ -291,7 +304,7 @@ }, { "cell_type": "markdown", - "id": "21", + "id": "22", "metadata": {}, "source": [ "#### Set Instrument Parameters\n", @@ -314,7 +327,7 @@ { "cell_type": "code", "execution_count": null, - "id": "22", + "id": "23", "metadata": {}, "outputs": [], "source": [ @@ -324,7 +337,7 @@ }, { "cell_type": "markdown", - "id": "23", + "id": "24", "metadata": {}, "source": [ "Every parameters is an object, which has different attributes, such as\n", @@ -337,7 +350,7 @@ { "cell_type": "code", "execution_count": null, - "id": "24", + "id": "25", "metadata": {}, "outputs": [], "source": [ @@ -346,7 +359,7 @@ }, { "cell_type": "markdown", - "id": "25", + "id": "26", "metadata": {}, "source": [ "The `value` attribute represents the current value of the parameter as a float.\n", @@ -360,7 +373,7 @@ { "cell_type": "code", "execution_count": null, - "id": "26", + "id": "27", "metadata": {}, "outputs": [], "source": [ @@ -369,7 +382,7 @@ }, { "cell_type": "markdown", - "id": "27", + "id": "28", "metadata": {}, "source": [ "Note that to set the value of the parameter, you can simply assign a new value\n", @@ -378,7 +391,7 @@ }, { "cell_type": "markdown", - "id": "28", + "id": "29", "metadata": {}, "source": [ "#### Set Peak Profile Parameters\n", @@ -402,7 +415,7 @@ { "cell_type": "code", "execution_count": null, - "id": "29", + "id": "30", "metadata": {}, "outputs": [], "source": [ @@ -418,7 +431,7 @@ }, { "cell_type": "markdown", - "id": "30", + "id": "31", "metadata": {}, "source": [ "#### Set Background\n", @@ -452,7 +465,7 @@ { "cell_type": "code", "execution_count": null, - "id": "31", + "id": "32", "metadata": {}, "outputs": [], "source": [ @@ -468,7 +481,7 @@ }, { "cell_type": "markdown", - "id": "32", + "id": "33", "metadata": {}, "source": [ "### ðŸ§Đ Create a Sample Model – Si\n", @@ -510,7 +523,7 @@ }, { "cell_type": "markdown", - "id": "33", + "id": "34", "metadata": {}, "source": [ "```\n", @@ -542,7 +555,7 @@ }, { "cell_type": "markdown", - "id": "34", + "id": "35", "metadata": {}, "source": [ "\n", @@ -556,7 +569,7 @@ { "cell_type": "code", "execution_count": null, - "id": "35", + "id": "36", "metadata": {}, "outputs": [], "source": [ @@ -565,7 +578,7 @@ }, { "cell_type": "markdown", - "id": "36", + "id": "37", "metadata": {}, "source": [ "#### Set Space Group" @@ -574,7 +587,7 @@ { "cell_type": "code", "execution_count": null, - "id": "37", + "id": "38", "metadata": {}, "outputs": [], "source": [ @@ -584,7 +597,7 @@ }, { "cell_type": "markdown", - "id": "38", + "id": "39", "metadata": {}, "source": [ "#### Set Lattice Parameters" @@ -593,7 +606,7 @@ { "cell_type": "code", "execution_count": null, - "id": "39", + "id": "40", "metadata": {}, "outputs": [], "source": [ @@ -602,7 +615,7 @@ }, { "cell_type": "markdown", - "id": "40", + "id": "41", "metadata": {}, "source": [ "#### Set Atom Sites" @@ -611,7 +624,7 @@ { "cell_type": "code", "execution_count": null, - "id": "41", + "id": "42", "metadata": {}, "outputs": [], "source": [ @@ -628,7 +641,7 @@ }, { "cell_type": "markdown", - "id": "42", + "id": "43", "metadata": {}, "source": [ "### 🔗 Assign Sample Model to Experiment\n", @@ -642,7 +655,7 @@ { "cell_type": "code", "execution_count": null, - "id": "43", + "id": "44", "metadata": {}, "outputs": [], "source": [ @@ -651,7 +664,7 @@ }, { "cell_type": "markdown", - "id": "44", + "id": "45", "metadata": {}, "source": [ "### 🚀 Analyze and Fit the Data\n", @@ -683,7 +696,7 @@ { "cell_type": "code", "execution_count": null, - "id": "45", + "id": "46", "metadata": {}, "outputs": [], "source": [ @@ -703,7 +716,7 @@ }, { "cell_type": "markdown", - "id": "46", + "id": "47", "metadata": {}, "source": [ "#### Show Free Parameters\n", @@ -715,7 +728,7 @@ { "cell_type": "code", "execution_count": null, - "id": "47", + "id": "48", "metadata": {}, "outputs": [], "source": [ @@ -724,7 +737,7 @@ }, { "cell_type": "markdown", - "id": "48", + "id": "49", "metadata": {}, "source": [ "#### Visualize Diffraction Patterns\n", @@ -740,7 +753,7 @@ { "cell_type": "code", "execution_count": null, - "id": "49", + "id": "50", "metadata": {}, "outputs": [], "source": [ @@ -749,7 +762,7 @@ }, { "cell_type": "markdown", - "id": "50", + "id": "51", "metadata": {}, "source": [ "#### Run Fitting\n", @@ -761,7 +774,7 @@ { "cell_type": "code", "execution_count": null, - "id": "51", + "id": "52", "metadata": {}, "outputs": [], "source": [ @@ -770,7 +783,7 @@ }, { "cell_type": "markdown", - "id": "52", + "id": "53", "metadata": {}, "source": [ "#### Check Fit Results\n", @@ -788,7 +801,7 @@ }, { "cell_type": "markdown", - "id": "53", + "id": "54", "metadata": {}, "source": [ "#### Visualize Fit Results\n", @@ -802,7 +815,7 @@ { "cell_type": "code", "execution_count": null, - "id": "54", + "id": "55", "metadata": {}, "outputs": [], "source": [ @@ -811,7 +824,7 @@ }, { "cell_type": "markdown", - "id": "55", + "id": "56", "metadata": {}, "source": [ "#### TOF vs d-spacing\n", @@ -830,7 +843,7 @@ { "cell_type": "code", "execution_count": null, - "id": "56", + "id": "57", "metadata": {}, "outputs": [], "source": [ @@ -839,7 +852,7 @@ }, { "cell_type": "markdown", - "id": "57", + "id": "58", "metadata": {}, "source": [ "As you can see, the calculated diffraction pattern now matches the measured\n", @@ -874,7 +887,7 @@ { "cell_type": "code", "execution_count": null, - "id": "58", + "id": "59", "metadata": {}, "outputs": [], "source": [ @@ -885,7 +898,7 @@ }, { "cell_type": "markdown", - "id": "59", + "id": "60", "metadata": {}, "source": [ "### 🔎 Exercise 2: Define an Experiment\n", @@ -904,7 +917,7 @@ { "cell_type": "code", "execution_count": null, - "id": "60", + "id": "61", "metadata": {}, "outputs": [], "source": [ @@ -914,7 +927,7 @@ { "cell_type": "code", "execution_count": null, - "id": "61", + "id": "62", "metadata": {}, "outputs": [], "source": [ @@ -924,7 +937,7 @@ { "cell_type": "code", "execution_count": null, - "id": "62", + "id": "63", "metadata": {}, "outputs": [], "source": [ @@ -939,7 +952,7 @@ }, { "cell_type": "markdown", - "id": "63", + "id": "64", "metadata": {}, "source": [ "#### Exercise 2.1: Inspect Measured Data\n", @@ -959,17 +972,18 @@ { "cell_type": "code", "execution_count": null, - "id": "64", + "id": "65", "metadata": {}, "outputs": [], "source": [ + "project_2.plotter.engine = 'plotly'\n", "project_2.plot_meas(expt_name='sim_lbco')" ] }, { "cell_type": "code", "execution_count": null, - "id": "65", + "id": "66", "metadata": {}, "outputs": [], "source": [ @@ -980,7 +994,7 @@ { "cell_type": "code", "execution_count": null, - "id": "66", + "id": "67", "metadata": {}, "outputs": [], "source": [ @@ -989,7 +1003,7 @@ }, { "cell_type": "markdown", - "id": "67", + "id": "68", "metadata": {}, "source": [ "#### Exercise 2.2: Set Instrument Parameters\n", @@ -1005,7 +1019,7 @@ { "cell_type": "code", "execution_count": null, - "id": "68", + "id": "69", "metadata": {}, "outputs": [], "source": [ @@ -1015,7 +1029,7 @@ }, { "cell_type": "markdown", - "id": "69", + "id": "70", "metadata": {}, "source": [ "#### Exercise 2.3: Set Peak Profile Parameters\n", @@ -1033,7 +1047,7 @@ { "cell_type": "code", "execution_count": null, - "id": "70", + "id": "71", "metadata": {}, "outputs": [], "source": [ @@ -1049,7 +1063,7 @@ }, { "cell_type": "markdown", - "id": "71", + "id": "72", "metadata": {}, "source": [ "#### Exercise 2.4: Set Background\n", @@ -1068,7 +1082,7 @@ { "cell_type": "code", "execution_count": null, - "id": "72", + "id": "73", "metadata": {}, "outputs": [], "source": [ @@ -1084,7 +1098,7 @@ }, { "cell_type": "markdown", - "id": "73", + "id": "74", "metadata": {}, "source": [ "### ðŸ§Đ Exercise 3: Define a Sample Model – LBCO\n", @@ -1100,7 +1114,7 @@ }, { "cell_type": "markdown", - "id": "74", + "id": "75", "metadata": {}, "source": [ "```\n", @@ -1135,7 +1149,7 @@ }, { "cell_type": "markdown", - "id": "75", + "id": "76", "metadata": {}, "source": [ "#### Exercise 3.1: Create Sample Model\n", @@ -1151,7 +1165,7 @@ { "cell_type": "code", "execution_count": null, - "id": "76", + "id": "77", "metadata": {}, "outputs": [], "source": [ @@ -1160,7 +1174,7 @@ }, { "cell_type": "markdown", - "id": "77", + "id": "78", "metadata": {}, "source": [ "#### Exercise 3.2: Set Space Group\n", @@ -1175,7 +1189,7 @@ { "cell_type": "code", "execution_count": null, - "id": "78", + "id": "79", "metadata": {}, "outputs": [], "source": [ @@ -1185,7 +1199,7 @@ }, { "cell_type": "markdown", - "id": "79", + "id": "80", "metadata": {}, "source": [ "#### Exercise 3.3: Set Lattice Parameters\n", @@ -1200,7 +1214,7 @@ { "cell_type": "code", "execution_count": null, - "id": "80", + "id": "81", "metadata": {}, "outputs": [], "source": [ @@ -1209,7 +1223,7 @@ }, { "cell_type": "markdown", - "id": "81", + "id": "82", "metadata": {}, "source": [ "#### Exercise 3.4: Set Atom Sites\n", @@ -1226,7 +1240,7 @@ { "cell_type": "code", "execution_count": null, - "id": "82", + "id": "83", "metadata": {}, "outputs": [], "source": [ @@ -1272,7 +1286,7 @@ }, { "cell_type": "markdown", - "id": "83", + "id": "84", "metadata": {}, "source": [ "### 🔗 Exercise 4: Assign Sample Model to Experiment\n", @@ -1287,7 +1301,7 @@ { "cell_type": "code", "execution_count": null, - "id": "84", + "id": "85", "metadata": {}, "outputs": [], "source": [ @@ -1296,7 +1310,7 @@ }, { "cell_type": "markdown", - "id": "85", + "id": "86", "metadata": {}, "source": [ "### 🚀 Exercise 5: Analyze and Fit the Data\n", @@ -1316,7 +1330,7 @@ { "cell_type": "code", "execution_count": null, - "id": "86", + "id": "87", "metadata": {}, "outputs": [], "source": [ @@ -1328,7 +1342,7 @@ }, { "cell_type": "markdown", - "id": "87", + "id": "88", "metadata": {}, "source": [ "#### Exercise 5.2: Run Fitting\n", @@ -1347,7 +1361,7 @@ { "cell_type": "code", "execution_count": null, - "id": "88", + "id": "89", "metadata": {}, "outputs": [], "source": [ @@ -1357,7 +1371,7 @@ { "cell_type": "code", "execution_count": null, - "id": "89", + "id": "90", "metadata": {}, "outputs": [], "source": [ @@ -1366,7 +1380,7 @@ }, { "cell_type": "markdown", - "id": "90", + "id": "91", "metadata": {}, "source": [ "#### Exercise 5.3: Find the Misfit in the Fit\n", @@ -1401,7 +1415,7 @@ { "cell_type": "code", "execution_count": null, - "id": "91", + "id": "92", "metadata": {}, "outputs": [], "source": [ @@ -1410,7 +1424,7 @@ }, { "cell_type": "markdown", - "id": "92", + "id": "93", "metadata": {}, "source": [ "#### Exercise 5.4: Refine the LBCO Lattice Parameter\n", @@ -1426,7 +1440,7 @@ { "cell_type": "code", "execution_count": null, - "id": "93", + "id": "94", "metadata": {}, "outputs": [], "source": [ @@ -1436,7 +1450,7 @@ { "cell_type": "code", "execution_count": null, - "id": "94", + "id": "95", "metadata": {}, "outputs": [], "source": [ @@ -1446,7 +1460,7 @@ { "cell_type": "code", "execution_count": null, - "id": "95", + "id": "96", "metadata": {}, "outputs": [], "source": [ @@ -1455,7 +1469,7 @@ }, { "cell_type": "markdown", - "id": "96", + "id": "97", "metadata": {}, "source": [ "One of the main goals of this study was to refine the lattice parameter of\n", @@ -1467,7 +1481,7 @@ }, { "cell_type": "markdown", - "id": "97", + "id": "98", "metadata": {}, "source": [ "#### Exercise 5.5: Visualize the Fit Results in d-spacing\n", @@ -1483,7 +1497,7 @@ { "cell_type": "code", "execution_count": null, - "id": "98", + "id": "99", "metadata": {}, "outputs": [], "source": [ @@ -1492,7 +1506,7 @@ }, { "cell_type": "markdown", - "id": "99", + "id": "100", "metadata": {}, "source": [ "#### Exercise 5.6: Refine the Peak Profile Parameters\n", @@ -1511,7 +1525,7 @@ { "cell_type": "code", "execution_count": null, - "id": "100", + "id": "101", "metadata": {}, "outputs": [], "source": [ @@ -1520,7 +1534,7 @@ }, { "cell_type": "markdown", - "id": "101", + "id": "102", "metadata": {}, "source": [ "The peak profile parameters are determined based on both the instrument\n", @@ -1540,7 +1554,7 @@ { "cell_type": "code", "execution_count": null, - "id": "102", + "id": "103", "metadata": {}, "outputs": [], "source": [ @@ -1556,7 +1570,7 @@ { "cell_type": "code", "execution_count": null, - "id": "103", + "id": "104", "metadata": {}, "outputs": [], "source": [ @@ -1566,7 +1580,7 @@ { "cell_type": "code", "execution_count": null, - "id": "104", + "id": "105", "metadata": {}, "outputs": [], "source": [ @@ -1575,7 +1589,7 @@ }, { "cell_type": "markdown", - "id": "105", + "id": "106", "metadata": {}, "source": [ "#### Exercise 5.7: Find Undefined Features\n", @@ -1596,7 +1610,7 @@ { "cell_type": "code", "execution_count": null, - "id": "106", + "id": "107", "metadata": {}, "outputs": [], "source": [ @@ -1605,7 +1619,7 @@ }, { "cell_type": "markdown", - "id": "107", + "id": "108", "metadata": {}, "source": [ "#### Exercise 5.8: Identify the Cause of the Unexplained Peaks\n", @@ -1631,7 +1645,7 @@ }, { "cell_type": "markdown", - "id": "108", + "id": "109", "metadata": {}, "source": [ "#### Exercise 5.9: Identify the impurity phase\n", @@ -1653,7 +1667,7 @@ { "cell_type": "code", "execution_count": null, - "id": "109", + "id": "110", "metadata": {}, "outputs": [], "source": [ @@ -1663,7 +1677,7 @@ }, { "cell_type": "markdown", - "id": "110", + "id": "111", "metadata": {}, "source": [ "#### Exercise 5.10: Create a Second Sample Model – Si as Impurity\n", @@ -1681,7 +1695,7 @@ }, { "cell_type": "markdown", - "id": "111", + "id": "112", "metadata": {}, "source": [ "**Set Space Group**" @@ -1690,7 +1704,7 @@ { "cell_type": "code", "execution_count": null, - "id": "112", + "id": "113", "metadata": {}, "outputs": [], "source": [ @@ -1700,7 +1714,7 @@ { "cell_type": "code", "execution_count": null, - "id": "113", + "id": "114", "metadata": {}, "outputs": [], "source": [ @@ -1710,7 +1724,7 @@ }, { "cell_type": "markdown", - "id": "114", + "id": "115", "metadata": {}, "source": [ "**Set Lattice Parameters**" @@ -1719,7 +1733,7 @@ { "cell_type": "code", "execution_count": null, - "id": "115", + "id": "116", "metadata": {}, "outputs": [], "source": [ @@ -1728,7 +1742,7 @@ }, { "cell_type": "markdown", - "id": "116", + "id": "117", "metadata": {}, "source": [ "**Set Atom Sites**" @@ -1737,7 +1751,7 @@ { "cell_type": "code", "execution_count": null, - "id": "117", + "id": "118", "metadata": {}, "outputs": [], "source": [ @@ -1754,7 +1768,7 @@ }, { "cell_type": "markdown", - "id": "118", + "id": "119", "metadata": {}, "source": [ "**🔗 Assign Sample Model to Experiment**" @@ -1763,7 +1777,7 @@ { "cell_type": "code", "execution_count": null, - "id": "119", + "id": "120", "metadata": {}, "outputs": [], "source": [ @@ -1772,7 +1786,7 @@ }, { "cell_type": "markdown", - "id": "120", + "id": "121", "metadata": {}, "source": [ "#### Exercise 5.11: Refine the Scale of the Si Phase\n", @@ -1798,7 +1812,7 @@ { "cell_type": "code", "execution_count": null, - "id": "121", + "id": "122", "metadata": {}, "outputs": [], "source": [ @@ -1807,7 +1821,7 @@ }, { "cell_type": "markdown", - "id": "122", + "id": "123", "metadata": {}, "source": [ "As you can see, the calculated pattern is now the sum of both phases,\n", @@ -1820,7 +1834,7 @@ { "cell_type": "code", "execution_count": null, - "id": "123", + "id": "124", "metadata": {}, "outputs": [], "source": [ @@ -1829,7 +1843,7 @@ }, { "cell_type": "markdown", - "id": "124", + "id": "125", "metadata": {}, "source": [ "**Run Fitting**\n", @@ -1840,7 +1854,7 @@ { "cell_type": "code", "execution_count": null, - "id": "125", + "id": "126", "metadata": {}, "outputs": [], "source": [ @@ -1849,7 +1863,7 @@ }, { "cell_type": "markdown", - "id": "126", + "id": "127", "metadata": {}, "source": [ "**Visualize Fit Results**\n", @@ -1863,7 +1877,7 @@ { "cell_type": "code", "execution_count": null, - "id": "127", + "id": "128", "metadata": {}, "outputs": [], "source": [ @@ -1873,7 +1887,7 @@ { "cell_type": "code", "execution_count": null, - "id": "128", + "id": "129", "metadata": {}, "outputs": [], "source": [ @@ -1882,7 +1896,7 @@ }, { "cell_type": "markdown", - "id": "129", + "id": "130", "metadata": {}, "source": [ "All previously unexplained peaks are now accounted for in the pattern, and the\n", @@ -1903,7 +1917,7 @@ }, { "cell_type": "markdown", - "id": "130", + "id": "131", "metadata": {}, "source": [ "## 🎁 Bonus\n", diff --git a/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.py b/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.py index 9e61e4bd..68dcadc1 100644 --- a/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.py +++ b/tutorials/dmsc-summer-school-2025_analysis-powder-diffraction.py @@ -129,6 +129,12 @@ # # The `plot_meas` method of the project enables us to visualize the measured # diffraction pattern. +# +# Before plotting, we set the plotting engine to 'plotly', which provides +# interactive visualizations. + +# %% +project_1.plotter.engine = 'plotly' # %% project_1.plot_meas(expt_name='sim_si') @@ -567,6 +573,7 @@ # **Solution:** # %% +project_2.plotter.engine = 'plotly' project_2.plot_meas(expt_name='sim_lbco') # %% From 3a3034510b2058137f376bff25b82731eb731587 Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 Aug 2025 15:51:06 +0200 Subject: [PATCH 8/9] Standardizes single quotes in Python script --- tools/nb_uncomment_pip.py | 43 ++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/tools/nb_uncomment_pip.py b/tools/nb_uncomment_pip.py index 206845d3..8d2a2ff4 100644 --- a/tools/nb_uncomment_pip.py +++ b/tools/nb_uncomment_pip.py @@ -10,14 +10,14 @@ from __future__ import annotations import argparse +import re import sys from pathlib import Path -import re import nbformat # Regex: beginning-of-line, capture leading whitespace, then "#", spaces, then "!pip" -_PATTERN = re.compile(r"^(\s*)#\s*!pip\b") +_PATTERN = re.compile(r'^(\s*)#\s*!pip\b') def fix_cell_source(src: str) -> tuple[str, int]: @@ -30,16 +30,15 @@ def fix_cell_source(src: str) -> tuple[str, int]: for line in src.splitlines(keepends=False): m = _PATTERN.match(line) if m: - indent = m.group(1) # Replace only the first '# !pip' at the beginning, preserve the rest of the line # e.g., " # !pip install foo" -> " !pip install foo" - new_line = _PATTERN.sub(r"\1!pip", line, count=1) + new_line = _PATTERN.sub(r'\1!pip', line, count=1) if new_line != line: changed += 1 new_lines.append(new_line) else: new_lines.append(line) - return ("\n".join(new_lines), changed) + return ('\n'.join(new_lines), changed) def process_notebook(path: Path) -> int: @@ -49,9 +48,9 @@ def process_notebook(path: Path) -> int: nb = nbformat.read(path, as_version=4) total_changes = 0 for cell in nb.cells: - if cell.cell_type != "code": + if cell.cell_type != 'code': continue - new_src, changes = fix_cell_source(cell.source or "") + new_src, changes = fix_cell_source(cell.source or '') if changes: cell.source = new_src total_changes += changes @@ -63,22 +62,20 @@ def process_notebook(path: Path) -> int: def iter_notebooks(paths: list[Path]): for p in paths: if p.is_dir(): - yield from (q for q in p.rglob("*.ipynb") if q.is_file()) - elif p.is_file() and p.suffix == ".ipynb": + yield from (q for q in p.rglob('*.ipynb') if q.is_file()) + elif p.is_file() and p.suffix == '.ipynb': yield p def main(argv: list[str]) -> int: - ap = argparse.ArgumentParser( - description="Uncomment '# !pip ...' to '!pip ...' in code cells of .ipynb notebooks." - ) - ap.add_argument("paths", nargs="+", help="Notebook files or directories to process") - ap.add_argument("--dry-run", action="store_true", help="Report changes without writing files") + ap = argparse.ArgumentParser(description="Uncomment '# !pip ...' to '!pip ...' in code cells of .ipynb notebooks.") + ap.add_argument('paths', nargs='+', help='Notebook files or directories to process') + ap.add_argument('--dry-run', action='store_true', help='Report changes without writing files') args = ap.parse_args(argv) targets = list(iter_notebooks([Path(p) for p in args.paths])) if not targets: - print("No .ipynb files found.", file=sys.stderr) + print('No .ipynb files found.', file=sys.stderr) return 1 total_files = 0 @@ -90,22 +87,22 @@ def main(argv: list[str]) -> int: nb = nbformat.read(nb_path, as_version=4) changes = 0 for cell in nb.cells: - if cell.cell_type != "code": + if cell.cell_type != 'code': continue - _, c = fix_cell_source(cell.source or "") + _, c = fix_cell_source(cell.source or '') changes += c if changes: - action = "UPDATED" if not args.dry_run else "WOULD UPDATE" - print(f"{action}: {nb_path} ({changes} line(s))") + action = 'UPDATED' if not args.dry_run else 'WOULD UPDATE' + print(f'{action}: {nb_path} ({changes} line(s))') total_files += 1 total_changes += changes if total_files == 0: - print("No changes needed.") + print('No changes needed.') else: - print(f"Done. Files changed: {total_files}, lines changed: {total_changes}") + print(f'Done. Files changed: {total_files}, lines changed: {total_changes}') return 0 -if __name__ == "__main__": - raise SystemExit(main(sys.argv[1:])) \ No newline at end of file +if __name__ == '__main__': + raise SystemExit(main(sys.argv[1:])) From f029bbafc51b784c64d484e2fc8cd0d42dac511f Mon Sep 17 00:00:00 2001 From: Andrew Sazonov Date: Mon, 11 Aug 2025 15:55:13 +0200 Subject: [PATCH 9/9] Removes dev dependencies installation step --- .github/workflows/publish-pypi.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index c4e702f7..76ee6261 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -29,9 +29,6 @@ jobs: - name: Upgrade package installer for Python run: pip install --upgrade pip - - name: Install Python dependencies - run: pip install '.[dev]' - - name: Create Python package run: python -m build