diff --git a/.github/workflows/ci_PR.yml b/.github/workflows/ci_PR.yml index 88374ad6f..dedc0989a 100644 --- a/.github/workflows/ci_PR.yml +++ b/.github/workflows/ci_PR.yml @@ -1,33 +1,41 @@ -name: DeerLab PR tests -on: - pull_request: - branches: - - "**" - -jobs: - tests: - name: python test - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - python-version: ['3.11','3.12'] - - steps: - - uses: actions/checkout@v3 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - cache: 'pip' - cache-dependency-path: setup.py - - run: | - python -m pip install --upgrade pip - pip install wheel - pip install . - - - name: Test with pytest - run: | - pytest +name: DeerLab PR tests + +on: + pull_request: + branches: + - "**" + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + tests: + name: python test + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + python-version: ['3.12', '3.13', '3.14'] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + cache-dependency-path: setup.py + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install . + + - name: Test with pytest + run: pytest diff --git a/.github/workflows/ci_scheduled.yml b/.github/workflows/ci_scheduled.yml index 655421332..c2feb593c 100644 --- a/.github/workflows/ci_scheduled.yml +++ b/.github/workflows/ci_scheduled.yml @@ -1,70 +1,37 @@ -name: Scheduled DeerLab tests -on: - workflow_dispatch: - schedule: - # Run once a week on Monday at 6:30 AM - - cron: '30 6 * * 1' - -jobs: - matrix_test: - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - python-version: [3.9, "3.10", "3.11", "3.12"] - steps: - - uses: actions/checkout@v3 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - cache: 'pip' - cache-dependency-path: setup.py - - run: | - python -m pip install --upgrade pip - pip install wheel - pip install . - -# - uses: actions/cache@v2 -# if: startsWith(runner.os, 'Windows') -# with: -# path: | -# ~\AppData\Local\pip\Cache -# key: ${{ runner.os }}-${{ hashFiles('**/setup.py') }} -# restore-keys: | -# {{ runner.os }}-pip- - -# - uses: actions/cache@v2 -# if: startsWith(runner.os, 'macOS') -# with: -# path: | -# ~/Library/Caches/pip -# key: ${{ runner.os }}-${{ hashFiles('**/setup.py') }} -# restore-keys: | -# {{ runner.os }}-pip- - -# - uses: actions/cache@v2 -# if: startsWith(runner.os, 'Linux') -# with: -# path: | -# ~/.cache/pip -# key: ${{ runner.os }}-${{ hashFiles('**/setup.py') }} -# restore-keys: | -# {{ runner.os }}-pip- - -# - name: Install dependencies -# if: steps.cache.outputs.cache-hit != 'false' -# run: | -# python -m pip install --upgrade pip -# pip install wheel -# pip install . - -# - name: Windows MKL linking -# if: matrix.os == 'windows-latest' -# run: | -# python upgrade_mkl.py - - - name: Test with pytest - run: pytest +name: Scheduled DeerLab tests + +on: + workflow_dispatch: + schedule: + # Run once a week on Monday at 6:30 AM UTC + - cron: '30 6 * * 1' + +permissions: + contents: read + +jobs: + matrix_test: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + python-version: ["3.10", "3.11", "3.12", "3.13"] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + cache-dependency-path: setup.py + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install . + + - name: Test with pytest + run: pytest diff --git a/.github/workflows/deploy_ghpages.yml b/.github/workflows/deploy_ghpages.yml index 195370c98..95984f87f 100644 --- a/.github/workflows/deploy_ghpages.yml +++ b/.github/workflows/deploy_ghpages.yml @@ -1,44 +1,53 @@ name: Docs Build & Deployment -on: +on: workflow_dispatch: release: types: [published] +permissions: + contents: read + pages: write + id-token: write + jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 + with: + python-version: '3.13' + cache: 'pip' + cache-dependency-path: setup.py + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install furo numpydoc sphinx-gallery sphinxcontrib-httpdomain sphinxcontrib-ghcontributors sphinx-issues sphinx-copybutton sphinx sphinx-design . + sudo apt-get update -y + sudo apt-get install -y latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended + + - name: Configure Pages + uses: actions/configure-pages@v5 + + - name: Build with Sphinx + run: sphinx-build -E -b html ./docsrc/source ./docs + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./docs deploy: + needs: build runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} steps: - - uses: actions/checkout@v3 - - - name: Set up Python 3.10 - uses: actions/setup-python@v4 - with: - python-version: '3.10' - cache: 'pip' - cache-dependency-path: setup.py - - name: Install dependencies - run: | - python -m pip install --upgrade pip - python -m pip install furo - python -m pip install numpydoc - python -m pip install sphinx-gallery - python -m pip install sphinxcontrib-httpdomain - python -m pip install sphinxcontrib-ghcontributors - python -m pip install sphinx-issues - python -m pip install sphinx-copybutton - python -m pip install sphinx - python -m pip install sphinx-design - python -m pip install . - sudo apt-get update -y - sudo apt-get install -y latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended - - name: Build with Sphinx - run: | - sphinx-build -E -b html ./docsrc/source ./docs - - name: Deploy to GH-Pages - if: always() - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./docs + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/docs_PR.yml b/.github/workflows/docs_PR.yml index cd4f9f670..7f01bdbe4 100644 --- a/.github/workflows/docs_PR.yml +++ b/.github/workflows/docs_PR.yml @@ -1,44 +1,41 @@ -name: Test documentation build PR - -on: - pull_request: - branches: - - "**" - paths: - - 'docsrc/**' - - '.github/workflows/deploy_ghpages.yml' - - '.github/workflows/docs_PR.yml' - - '.github/workflows/examples_PR.yml' -jobs: - - docsbuild: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Set up Python 3.10 - uses: actions/setup-python@v4 - with: - python-version: '3.10' - cache: 'pip' - cache-dependency-path: setup.py - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install furo - pip install numpydoc - pip install sphinx-gallery - pip install sphinxcontrib-httpdomain - pip install sphinxcontrib-ghcontributors - pip install sphinx-issues - pip install sphinx-copybutton - pip install sphinx - pip install sphinx-design - python -m pip install . - sudo apt-get update -y - sudo apt-get install -y latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended - - - - name: Build with Sphinx - run: | - sphinx-build -E -b html ./docsrc/source ./docs -D plot_gallery=0 +name: Test documentation build PR + +on: + pull_request: + branches: + - "**" + paths: + - 'docsrc/**' + - '.github/workflows/deploy_ghpages.yml' + - '.github/workflows/docs_PR.yml' + - '.github/workflows/examples_PR.yml' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + docsbuild: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 + with: + python-version: '3.13' + cache: 'pip' + cache-dependency-path: setup.py + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install furo numpydoc sphinx-gallery sphinxcontrib-httpdomain sphinxcontrib-ghcontributors sphinx-issues sphinx-copybutton sphinx sphinx-design . + sudo apt-get update -y + sudo apt-get install -y latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended + + - name: Build with Sphinx + run: sphinx-build -E -b html ./docsrc/source ./docs -D plot_gallery=0 diff --git a/.github/workflows/examples_PR.yml b/.github/workflows/examples_PR.yml index 94a5ddfcf..a89905065 100644 --- a/.github/workflows/examples_PR.yml +++ b/.github/workflows/examples_PR.yml @@ -1,43 +1,41 @@ -name: Test documentation examples build PR - -on: - pull_request: - branches: - - "**" - paths: - - 'examples/**' - - '.github/workflows/deploy_ghpages.yml' - - '.github/workflows/docs_PR.yml' - - '.github/workflows/examples_PR.yml' -jobs: - - deploy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Set up Python 3.10 - uses: actions/setup-python@v4 - with: - python-version: '3.10' - cache: 'pip' - cache-dependency-path: setup.py - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - python -m pip install furo - python -m pip install numpydoc - python -m pip install sphinx-gallery - python -m pip install sphinxcontrib-httpdomain - python -m pip install sphinxcontrib-ghcontributors - python -m pip install sphinx-issues - python -m pip install sphinx-copybutton - python -m pip install sphinx - python -m pip install sphinx-design - python -m pip install . - sudo apt-get update -y - sudo apt-get install -y latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended - - name: Build with Sphinx - run: | - sphinx-build -E -b html ./docsrc/source ./docs +name: Test documentation examples build PR + +on: + pull_request: + branches: + - "**" + paths: + - 'examples/**' + - '.github/workflows/deploy_ghpages.yml' + - '.github/workflows/docs_PR.yml' + - '.github/workflows/examples_PR.yml' + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + docsbuild: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 + with: + python-version: '3.13' + cache: 'pip' + cache-dependency-path: setup.py + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install furo numpydoc sphinx-gallery sphinxcontrib-httpdomain sphinxcontrib-ghcontributors sphinx-issues sphinx-copybutton sphinx sphinx-design . + sudo apt-get update -y + sudo apt-get install -y latexmk texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended + + - name: Build with Sphinx + run: sphinx-build -E -b html ./docsrc/source ./docs diff --git a/.github/workflows/package_upload.yml b/.github/workflows/package_upload.yml index 4a3b99777..1e2a73b07 100644 --- a/.github/workflows/package_upload.yml +++ b/.github/workflows/package_upload.yml @@ -1,28 +1,31 @@ -name: Build & Upload DeerLab to PyPI - -on: - release: - types: [published] - -jobs: - - pypi-build-n-publish: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v1 - - name: Set up Python 3.11 - uses: actions/setup-python@v1 - with: - python-version: "3.11" - - name: Install pypa/build - run: >- - python -m pip install build --user - - name: Build a binary wheel and a source tarball - run: >- - python -m build --sdist --wheel --outdir dist/ - - name: Publish distribution to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - user: __token__ - password: ${{ secrets.PYPI_API_TOKEN }} +name: Build & Upload DeerLab to PyPI + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + pypi-build-n-publish: + runs-on: ubuntu-latest + environment: pypi + permissions: + id-token: write + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python 3.13 + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Build package + run: | + python -m pip install build + python -m build --sdist --wheel --outdir dist/ + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.gitignore b/.gitignore index fa662345d..e06f9135a 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,9 @@ docsrc/source/_autosummary/**/* docsrc/source/auto_examples/**/* docsrc/plot_directive/ docsrc/source/_build/ + +examples/**/*.txt +examples/**/*.hdf5 +examples/**/*.npy +examples/**/*.npz +examples/**/*.csv diff --git a/README.md b/README.md index 133ed84bb..959dfdd73 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ The documentation can be found [here](https://jeschkelab.github.io/DeerLab/index The early versions of DeerLab (up to version 0.9.2) are written in MATLAB. The old MATLAB codebase is archived and can be found [here](https://github.com/JeschkeLab/DeerLab-Matlab). +A graphical user interface (GUI) for processing DEER data using DeerLab is now available as a separate package called [DeerAnalysis](https://github.com/JeschkeLab/DeerAnalysis). ## Requirements DeerLab is available for Windows, Mac and Linux systems and requires **Python 3.9** to **3.13** @@ -58,4 +59,4 @@ Here is the citation in bibtex format: DeerLab is licensed under the [MIT License](LICENSE). -Copyright © 2019-2024: Luis Fábregas Ibáñez, Stefan Stoll, Gunnar Jeschke, and [other contributors](https://github.com/JeschkeLab/DeerLab/contributors). +Copyright © 2019-2026: Luis Fábregas Ibáñez, Stefan Stoll, Hugo Karas, Gunnar Jeschke, and [other contributors](https://github.com/JeschkeLab/DeerLab/contributors). diff --git a/VERSION b/VERSION index 3e0c29c66..79127d85a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1.1.5 +v1.2.0 diff --git a/deerlab/dd_models.py b/deerlab/dd_models.py index cd6805612..23fbab4c5 100644 --- a/deerlab/dd_models.py +++ b/deerlab/dd_models.py @@ -51,16 +51,17 @@ def _dd_docstring(model,notes): string += '\n' string += '\n' table = [] - table.append(['Name','Lower','Upper','Type','Frozen','Unit','Description']) + table.append(['Name','Lower','Upper','par0','Type','Frozen','Unit','Description']) for n,paramname in enumerate(model._parameter_list(order='vector')): param_str = f'``{paramname}``' lb_str = f'{np.atleast_1d(getattr(model,paramname).lb)[0]:5.3g}' ub_str = f'{np.atleast_1d(getattr(model,paramname).ub)[0]:5.3g}' + par0_str = f'{np.atleast_1d(getattr(model,paramname).par0)[0]:5.3g}' linear_str = "linear" if np.all(getattr(model,paramname).linear) else "nonlin" frozen_str = "Yes" if np.all(getattr(model,paramname).frozen) else "No" unit_str = str(getattr(model,paramname).unit) desc_str = str(getattr(model,paramname).description) - table.append([param_str,lb_str,ub_str,linear_str,frozen_str,unit_str,desc_str]) + table.append([param_str,lb_str,ub_str,par0_str,linear_str,frozen_str,unit_str,desc_str]) string += formatted_table(table) string += f'\n{notes}' @@ -213,7 +214,7 @@ def _gauss2(r,mean1,std1,mean2,std2): #======================================================================================= # dd_gauss3 #======================================================================================= -ntoes = r""" +notes = r""" **Model** :math:`P(r) = a_1\frac{1}{\sigma_1\sqrt{2\pi}}\exp\left(-\frac{(r-\left)^2}{2\sigma_1^2}\right) + a_2\frac{1}{\sigma_2\sqrt{2\pi}}\exp\left(-\frac{(r-\left)^2}{2\sigma_2^2}\right) + a_3\frac{1}{\sigma_3\sqrt{2\pi}}\exp\left(-\frac{(r-\left)^2}{2\sigma_3^2}\right)` diff --git a/deerlab/fit.py b/deerlab/fit.py index c1c27da30..9b7a9fc52 100644 --- a/deerlab/fit.py +++ b/deerlab/fit.py @@ -501,13 +501,14 @@ def bootstrap_fcn(ysim): fitresults.param = fitresults.paramUncert.median # Get the uncertainty estimates for the model response - modellb = np.min(param_uq[1].samples,axis=0) - modelub = np.max(param_uq[1].samples,axis=0) + modellb = [np.min(param_uq[n].samples,axis=0) for n in range(1,len(param_uq))] + modelub = [np.max(param_uq[n].samples,axis=0) for n in range(1,len(param_uq))] fitresults.model = [param_uq[n].median for n in range(1,len(param_uq))] - fitresults.modelUncert = UQResult('bootstrap',data=param_uq[1].samples,lb=modellb,ub=modelub) + fitresults.modelUncert = [UQResult('bootstrap',data=param_uq[n].samples,lb=modellb[n-1],ub=modelub[n-1]) for n in range(1,len(param_uq))] if len(fitresults.model)==1: fitresults.model = fitresults.model[0] + fitresults.modelUncert = fitresults.modelUncert[0] # Get some basic information on the parameter vector keys = model._parameter_list(order='vector') diff --git a/deerlab/fitresult.py b/deerlab/fitresult.py index 86884c368..4d1ee66a6 100644 --- a/deerlab/fitresult.py +++ b/deerlab/fitresult.py @@ -369,7 +369,7 @@ def plot(self,axis=None,xlabel=None,gof=False,fontsize=13): bins = np.linspace(-4,4,300) N0 = dd_gauss(bins,0,1) axs[n].get_yaxis().set_visible(False) - axs[n].fill(bins,N0,'k',alpha=0.4, label='$\mathcal{N}(0,1)$') + axs[n].fill(bins,N0,'k',alpha=0.4, label=r'$\mathcal{N}(0,1)$') axs[n].set_xlabel('Normalized residuals',size=fontsize) axs[n].set_yticks([]) axs[n].spines.right.set_visible(False) diff --git a/docsrc/source/changelog.rst b/docsrc/source/changelog.rst index 08714a20b..3c8306feb 100644 --- a/docsrc/source/changelog.rst +++ b/docsrc/source/changelog.rst @@ -24,6 +24,22 @@ Release Notes - |fix| : Something which was not working as expected or leading to errors has been fixed. - |api| : This will require changes in your scripts or code. + +Release ``v1.2`` - June 2026 +------------------------------------------ +- |feature| : `modelUncert` is now returned in the `FitResult` object +- |feature| : Added new saving and loading options for `FitResult` and `UQResult` objects, using `save` and `load` functions. +- |feature| : Added new automatic calculation of background function with `dipolarbackgroundmodel` function. Added `FitResult.bg` and `FitResult.bgUncert` attributes to store the fitted background function and its uncertainty, when possible. +- |feature| : Added multi-core parallelization to the `profile_analysis` function via the `cores` argument. +- |feature| : Added a new `show_config` function to display deatils about how DeerLab is configured in the current system. +- |fix| : Fixes issues with bootrstrap uncertainties +- |api| : N bootstrap samples no longer produces N+1 samples +- |enhancement| : Support Python 3.13 and 3.14 +- |fix| : All gaussian models now normalise to 1 +- |fix| : Fixed bug in `ex_fitting_5pdeer_pathways` so scales are now correct on the pathways. +- |api| : Models are now deepcopied on import to avoid issues with users modifying the built-in models. +- |fix| : Fixes bug where some parameters frozen before the `dl.dipolarmodel` function were not frozen in the resulting model. + Release ``v1.1.4`` - September 2024 ------------------------------------------ - |enhancement| : Expanded sophgrid to allow for closed phi integral. (:pr:`482`) diff --git a/docsrc/source/deerlab1_2.rst b/docsrc/source/deerlab1_2.rst new file mode 100644 index 000000000..a0ae0b6e8 --- /dev/null +++ b/docsrc/source/deerlab1_2.rst @@ -0,0 +1,21 @@ +DeerLab Version 1.2 +======================== + +DeerLab version 1.2 is a major update which brings a number of new features and improvements to the library. The most significant changes include: +- **Background model support in fit results**: When fitting a dipolar signal model that includes a background component, the fit results now include the evaluated background signal and its uncertainty. This allows users to easily access and analyze the background contribution to their fitted models. +- **Saving and Loading of Fit Results**: The fit results can now be saved to and loaded from disk, allowing users to preserve their fitting outcomes and share them with others. + +The following sections provide more details on these new features and how to use them effectively in your analysis. + + +Background Model Support in Fit Results +--------------------------------------- + + + + + +Saving and Loading of Fit Results +---------------------------------- + + diff --git a/docsrc/source/reference.rst b/docsrc/source/reference.rst index 1cf06c352..d8b395890 100644 --- a/docsrc/source/reference.rst +++ b/docsrc/source/reference.rst @@ -87,7 +87,7 @@ Reference Index formatted_table store_pickle read_pickle - dump_jsons - load_jsons + json_dumps + json_loads show_config freedist diff --git a/examples/basic/ex_saving_loading.py b/examples/basic/ex_saving_loading.py index aa7d92b15..a3ac61613 100644 --- a/examples/basic/ex_saving_loading.py +++ b/examples/basic/ex_saving_loading.py @@ -64,7 +64,7 @@ # %% np.savetxt('fitted_signal.txt', np.column_stack((t, Vexp, results.model, results.bg)), header='Time (μs), Data, Fit, Background') -Pfit = results.evaluate(dl.dd_gauss2, r) -Puncert = results.propagate(dl.dd_gauss2, r).ci(95) +Pfit = results.P +Puncert = results.PUncert.ci(95) np.savetxt('distance_distribution.txt', np.column_stack((r, Pfit, Puncert[:,0], Puncert[:,1])), header='Distance (nm), P(r), P(r) 95% CI lower, P(r) 95% CI upper') # %% diff --git a/examples/intermediate/ex_plot_dipolar_spectrum.py b/examples/intermediate/ex_plot_dipolar_spectrum.py new file mode 100644 index 000000000..44a610160 --- /dev/null +++ b/examples/intermediate/ex_plot_dipolar_spectrum.py @@ -0,0 +1,85 @@ +# %% [markdown] +""" +Plotting the dipolar spectrum / Pake pattern +------------------------------------------------------------------------- + +The dipolar spectrum or Pake patern is the Fourier transform of the dipolar signal, and can be useful for visualising the dipolar frequencies present in the signal. We can also overlay the dipolar spectrum of the fitted model to see how well the fit captures the dipolar frequencies in the data. +""" + + +import numpy as np +import matplotlib.pyplot as plt +import deerlab as dl +# %% +# File location +path = '../data/' +file = 'example_4pdeer_1.DTA' + +# Experimental parameters +tau1 = 0.3 # First inter-pulse delay, μs +tau2 = 4.0 # Second inter-pulse delay, μs +tmin = 0.1 # Start time, μs + +# Load the experimental data +t,Vexp = dl.deerload(path + file) + +# Pre-processing +Vexp = dl.correctphase(Vexp) # Phase correction +Vexp = Vexp/np.max(Vexp) # Rescaling (aesthetic) +t = t - t[0] # Account for zerotime +t = t + tmin +# Distance vector +r = np.arange(2.5,5,0.01) # nm + +# Construct the model +experimentInfo = dl.ex_4pdeer(tau1,tau2, pathways=[1]) +Vmodel = dl.dipolarmodel(t,r, experiment = experimentInfo, Bmodel=dl.bg_hom3d) + +# Fit the model to the data +results = dl.fit(Vmodel,Vexp) + +# Print results summary +print(results) +results.plot() + +# %% [markdown] +""" +Fourier transform ++++++++++++++++++ +""" +import numpy.fft as fft + + +# Fourier transform of the data and model +# Before background division +Vexp_ft = fft.fftshift(fft.fft(Vexp)) +Vmodel_ft = fft.fftshift(fft.fft(results.model)) +ft_axis = fft.fftshift(fft.fftfreq(len(t), d=t[1]-t[0])) + +# After background division +Vexp_div = Vexp / results.bg -1 +Vmodel_div = results.model / results.bg - 1 +Vexp_div_ft = fft.fftshift(fft.fft(Vexp_div)) +Vmodel_div_ft = fft.fftshift(fft.fft(Vmodel_div)) + +# Plotting +violet = '#4550e6' +fig,axs = plt.subplots(1,2,figsize=[10,6],sharex=True) +axs[0].set_title('Before background division') +axs[0].plot(ft_axis, np.abs(Vexp_ft), '.', color='grey', label='Data') +axs[0].plot(ft_axis, np.abs(Vmodel_ft), linewidth=3, color=violet, label='Fit') +axs[0].legend() +axs[0].set_ylabel('Magnitude (arb.u.)') +axs[0].set_xlabel('Dipolar frequency (MHz)') +axs[0].set_xlim(-10, 10) # Limit x-axis to focus on relevant frequencies + + +axs[1].set_title('After background division') +axs[1].plot(ft_axis, np.abs(Vexp_div_ft), '.', color='grey', label='Data') +axs[1].plot(ft_axis, np.abs(Vmodel_div_ft), linewidth=3, color=violet, label='Fit') +axs[1].legend() +axs[1].set_xlabel('Dipolar frequency (MHz)') +axs[1].set_ylabel('Magnitude (arb.u.)') +axs[1].set_xlim(-10, 10) # Limit x-axis to + +# %% diff --git a/setup.py b/setup.py index 5a81d4407..46872106c 100644 --- a/setup.py +++ b/setup.py @@ -44,6 +44,8 @@ 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', 'Topic :: Scientific/Engineering :: Chemistry', ] )