commit d9b2077d2cf998a693e0c6c6bed9f4c69bd6016d Author: fjosw Date: Tue Oct 13 16:53:00 2020 +0200 Initial public release diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b35fbaaa --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +__pycache__ +*.pyc +.ipynb_* +examples/B1k2_pcac_plateau.p +examples/Untitled.* +core.* +*.swp diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..7f29e06c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,97 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [1.0.0] - 2020-10-13 +### Added +- Compatibility with the BDIO Native format outlined [here](https://ific.uv.es/~alramos/docs/ADerrors/tutorial/). Read and write function added to input.bdio +- new function `input.bdio.read_dSdm` which can read the bdio output of the + program `dSdm` by Tomasz Korzec +- Expected chisquare implemented for fits with xerrors +- New implementation of the covariance of two observables which employs the + arithmetic mean of the integrated autocorrelation times of the two + observables. This new procedure has proven to be less biased in simulated + data and is also much faster to compute as the computation time is of O(N) + whereas the evaluation of the full correlation function is of O(Nlog(N)). +- Added function `gen_correlated_data` to `misc` which generates a set of + observables with given covariance and autocorrelation. + +### Fixed +- Bias correction hep-lat/0306017 eq. (49) is no longer applied to the + exponential tail in the critical slowing down analysis, but only to the part + which is directly estimated from rho. This can lead to slightly smaller + errors when using the critical slowing down analysis. The values for the + integrated autocorrelation time tauint now include this bias correction (up + to now the bias correction was applied after estimating tauint). The errors + resulting from the automatic windowing procedure are unchanged. + +## [0.8.1] - 2020-06-09 +### Fixed +- Bug in fits.standard_fit fixed which occurred when attempting a fit with zero + degrees of freedom. + +## [0.8.0] - 2020-06-05 +### Added +- `merge_obs` function added which allows to merge Obs which describe different replica of the same observable and have been read in separately. Use with care as there is no safeguard implemented which prevent you from merging unrelated Obs. +- `standard fit` and `odr_fit` can now treat fits with several x-values via tuples. +- Fit functions have a new kwarg `dict_output` which allows to change the + output to a dictionary containing additional information. +- `S_dict` and `tau_exp_dict` added to Obs in which global values for individual ensembles can be stored. +- new function `read_pbp` added which reads dS/dm_q from pbp.dat files. +- new function `extract_t0` added which can extract the value of t0 from .ms.dat files of openQCD v 1.2 + +### Changed +- When creating an Obs object defined for multiple replica/ensembles, the given names are now sorted alphabetically before assigning the internal dictionaries. This makes sure that `my_Obs` has the same dictionaries as `my_Obs * 1` (`derived_observable` always sorted the names). WARNING: `Obs` created with previous versions of pyerrors may not be completely identical to new ones (The internal dictionaries may have different ordering). However, this should not affect the inner workings of the error analysis. + +### Fixed +- Bug in `covariance` fixed which appeared when different ensemble contents were used. + +## [0.7.0] - 2020-03-10 +### Added +- New fit funtions for fitting with and without x-errors added which use automatic differentiation and should be more reliable than the old ones. +- Fitting with Bayesian priors added. +- New functions for visualization of fits which can be activated via the kwargs resplot and qqplot. +- chisquare/expected_chisquared which takes into account correlations in the data and non-linearities in the fit function can now be activated with the kwarg expected_chisquare. +- Silent mode added to fit functions. +- Examples reworked. +- Changed default function to compute covariances. +- output of input.bdio.read_mesons is now a dictionary instead of a list. + +### Deprecated +- The function `fit_general` which is based on numerical differentiation will be removed in future versions as new fit functions based on automatic differentiation are now available. + +## [0.6.1] - 2020-01-14 +### Added +- mesons bdio functionality improved and accelerated, progress report added. +- added the possibility to manually supply a jacobian to derived_observable via the kwarg `man_grad`. This feature was not implemented for the user, but for internal optimization of most basic arithmetic operations which now do not require a call to the autograd package anymore. This results in a speed up of 2 to 3, especially relevant for the multiplication of large matrices. + +### Changed +- input.py and bdio.py moved into submodule input. This should not affect the user API. +- autograd.numpy was replaced by pure numpy wherever it was possible. This should result in a slight speed up. + +### Fixed +- fixed bias_correction which broke as a result of the vectorized derived_observable. +- linalg.eig does not give an error anymore if the eigenvalues are complex by just truncating the imaginary part. + +## [0.6.0] - 2020-01-06 +### Added +- Matrix pencil method for algebraic extraction of energy levels implemented according to [Y. Hua, T. K. Sarkar, IEEE Trans. Acoust. 38, 814-824 (1990)](https://ieeexplore.ieee.org/document/56027) in module `mpm.py`. +- Import API simplified. After `import pyerrors as pe`, some submodules can be accessed via `pe.fits` etc. +- `derived_observable` now supports functions which have single- or multi-dimensional numpy arrays as input and/or output (Works only with automatic differentiation). +- Matrix functions accelerated by using the new version of `derived_observable`. +- New matrix functions: Moore-Penrose Pseudoinverse, Singular Value Decomposition, eigenvalue determination of a general matrix (automatic differentiation included from autograd master). +- Obs can now be compared with < or >, a list of Obs can now be sorted. +- Numerical differentiation can now be controlled via the kwargs of numdifftools.step_generators.MaxStepGenerator. +- Tuned standard parameters for numerical derivative to `base_step=0.1` and `step_ratio=2.5`. + +### Changed +- Matrix functions moved to new module `linalg.py`. +- Kolmogorov-Smirnov test moved to new module `misc.py`. + +## [0.5.0] - 2019-12-19 +### Added +- Numerical differentiation is now based on the package numdifftools which should be more reliable. + +### Changed +- kwarg `h_num_grad` changed to `num_grad` which takes boolean values (default False). +- Speed up of rfft calculation of the autocorrelation by reducing the zero padding. diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..e4cb6bfc --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Fabian Joswig + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 00000000..eb288c4a --- /dev/null +++ b/README.md @@ -0,0 +1,56 @@ +# pyerrors +pyerrors is a python package for error computation and propagation of Markov Chain Monte Carlo data. +It is based on the gamma method [arXiv:hep-lat/0306017](https://arxiv.org/abs/hep-lat/0306017). Some of its features are: +* automatic differentiation as suggested in [arXiv:1809.01289](https://arxiv.org/abs/1809.01289) (partly based on the [autograd](https://github.com/HIPS/autograd) package) +* the treatment of slow modes in the simulation as suggested in [arXiv:1009.5228](https://arxiv.org/abs/1009.5228) +* multi ensemble analyses +* non-linear fits with y-errors and exact linear error propagation based on automatic differentiation as introduced in [arXiv:1809.01289] +* non-linear fits with x- and y-errors and exact linear error propagation based on automatic differentiation +* matrix valued operations and their error propagation based on automatic differentiation (cholesky decomposition, calculation of eigenvalues and eigenvectors, singular value decomposition...) +* implementation of the matrix-pencil-method [IEEE Trans. Acoust. 38, 814-824 (1990)](https://ieeexplore.ieee.org/document/56027) for the extraction of energy levels, especially suited for noisy data and excited states + +There exist similar implementations of gamma method error analysis suites in +- [Fortran](https://gitlab.ift.uam-csic.es/alberto/aderrors). +- [Julia](https://gitlab.ift.uam-csic.es/alberto/aderrors.jl) +- [Python 3](https://github.com/mbruno46/pyobs) + +## Installation +pyerrors requires python versions >= 3.5.0 + +Install the package for the local user: +```bash +pip install . --user +``` + +Run tests to verify the installation: +```bash +pytest . +``` + +## Usage +The basic objects of a pyerrors analysis are instances of the class `Obs`. They can be initialized with an array of Monte Carlo data (e.g. `samples1`) and a name for the given ensemble (e.g. `'ensemble1'`). The `gamma_method` can then be used to compute the statistical error, taking into account autocorrelations. The `print` method outputs a human readable result. +```python +import numpy as np +import pyerrors as pe + +observable1 = pe.Obs([samples1], ['ensemble1']) +observable1.gamma_method() +observable1.print() +``` +Often one is interested in secondary observables which can be arbitrary functions of primary observables. `pyerrors` overloads most basic math operations and numpy functions such that the user can work with `Obs` objects as if they were floats +```python +observable3 = 12.0 / observable1 ** 2 - np.exp(-1.0 / observable2) +observable3.gamma_method() +observable3.print() +``` + +More detailed examples can be found in the `/examples` folder: + +* [01_basic_example](examples/01_basic_example.ipynb) +* [02_pcac_example](examples/02_pcac_example.ipynb) +* [03_fit_example](examples/03_fit_example.ipynb) +* [04_matrix_operations](examples/04_matrix_operations.ipynb) + + +## License +[MIT](https://choosealicense.com/licenses/mit/) diff --git a/conftest.py b/conftest.py new file mode 100644 index 00000000..e69de29b diff --git a/examples/01_basic_example.ipynb b/examples/01_basic_example.ipynb new file mode 100644 index 00000000..794076eb --- /dev/null +++ b/examples/01_basic_example.ipynb @@ -0,0 +1,435 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Basic pyerrors example" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import pyerrors, as well as autograd wrapped numpy and matplotlib. The sys statement is not necessary if pyerrors was installed via pip." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.append('..')\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import pyerrors as pe" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We use numpy to generate some fake data" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "test_sample1 = np.random.normal(2.0, 0.5, 1000)\n", + "test_sample2 = np.random.normal(1.0, 0.1, 1000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "From this we can construct `Obs`, which are the basic object of `pyerrors`. For each sample we give to the obs, we also have to specify an ensemble/replica name. In this example we assume that both datasets originate from the same gauge field ensemble labeled 'ens1'." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "obs1 = pe.Obs([test_sample1], ['ens1'])\n", + "obs2 = pe.Obs([test_sample2], ['ens1'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now combine these two observables into a third one:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "obs3 = np.log(obs1 ** 2 / obs2 ** 4)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`pyerrors` overloads all basic math operations, the user can work with these `Obs` as if they were real numbers. The proper resampling is performed in the background via automatic differentiation." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we are now interested in the error of obs3, we can use the `gamma_method` to compute it and then print the object to the notebook" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Obs[1.415(20)]\n" + ] + } + ], + "source": [ + "obs3.gamma_method()\n", + "print(obs3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With print level 1 we can take a look at the integrated autocorrelation time estimated by the automatic windowing procedure." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Result\t 1.41522010e+00 +/- 2.03946273e-02 +/- 1.01973136e-03 (1.441%)\n", + " t_int\t 5.07378446e-01 +/- 4.51400871e-02 S = 2.00\n" + ] + } + ], + "source": [ + "obs3.print(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As expected the random data from numpy exhibits no autocorrelation ($\\tau_\\text{int}\\,\\approx0.5$). It can still be interesting to have a look at the window size dependence of the integrated autocorrelation time" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "obs3.plot_tauint()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This figure shows the windowsize dependence of the integrated autocorrelation time. The red vertical line signalizes the window chosen by the automatic windowing procedure with $S=2.0$.\n", + "Choosing a larger windowsize would not significantly alter $\\tau_\\text{int}$, so everything seems to be correct here." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Correlated data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now generate fake data with given covariance matrix and integrated autocorrelation times:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "cov = np.array([[0.5, -0.2], [-0.2, 0.3]]) # Covariance matrix\n", + "tau = [4, 8] # Autocorrelation times\n", + "c_obs1, c_obs2 = pe.misc.gen_correlated_data([2.8, 2.1], cov, 'ens1', tau)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "and once again combine the two `Obs` to a new one with arbitrary math operations" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Result\t 3.27194697e-01 +/- 1.96872835e+00 +/- 3.38140198e-01 (601.699%)\n", + " t_int\t 5.41336983e+00 +/- 1.59801329e+00 S = 2.00\n" + ] + } + ], + "source": [ + "c_obs3 = np.sin(c_obs1 / c_obs2 - 1)\n", + "c_obs3.gamma_method()\n", + "c_obs3.print()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This time we see a significant autocorrelation so it is worth to have a closer look at the normalized autocorrelation function (rho) and the integrated autocorrelation time" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "c_obs3.plot_rho()\n", + "c_obs3.plot_tauint()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now redo the error analysis and alter the value of S or attach a tail to the autocorrelation function to take into account long range autocorrelations" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Result\t 3.27194697e-01 +/- 2.14280114e+00 +/- 2.48970994e-01 (654.901%)\n", + " t_int\t 6.41297945e+00 +/- 2.18167829e+00 tau_exp = 20.00, N_sigma = 1\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "c_obs3.gamma_method(tau_exp=20)\n", + "c_obs3.print()\n", + "c_obs3.plot_tauint()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Jackknife" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For comparison and as a crosscheck, we can do a jackknife binning analysis. We compare the result for different binsizes with the result from the gamma method. Besides the more robust approach of the gamma method, it can also be shown that the systematic error of the error decreases faster with $N$ in comparison to the binning approach (see hep-lat/0306017)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Binning analysis:\n", + "Result:\t 3.27194697e-01 +/- 1.81819841e+00 +/- 3.98347312e-01 (555.693%)\n", + "Result:\t 3.27194697e-01 +/- 1.66475180e+00 +/- 5.21149746e-01 (508.795%)\n", + "Result:\t 3.27194697e-01 +/- 1.41273466e+00 +/- 6.28627238e-01 (431.772%)\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Result from the automatic windowing procedure for comparison:\n", + "Result\t 3.27194697e-01 +/- 2.02097394e+00 +/- 3.22723658e-01 (617.667%)\n", + " t_int\t 5.70449936e+00 +/- 1.53928442e+00 S = 1.50\n", + "Result\t 3.27194697e-01 +/- 1.96872835e+00 +/- 3.38140198e-01 (601.699%)\n", + " t_int\t 5.41336983e+00 +/- 1.59801329e+00 S = 2.00\n", + "Result\t 3.27194697e-01 +/- 1.89700786e+00 +/- 3.67353992e-01 (579.780%)\n", + " t_int\t 5.02613753e+00 +/- 1.69573607e+00 S = 3.00\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import pyerrors.jackknifing as jn\n", + "jack1 = jn.generate_jack(c_obs1, max_binsize=120)\n", + "jack2 = jn.generate_jack(c_obs2, max_binsize=120)\n", + "jack3 = jn.derived_jack(lambda x: np.sin(x[0] / x[1] - 1), [jack1, jack2])\n", + "\n", + "print('Binning analysis:')\n", + "jack3.print(binsize=25)\n", + "jack3.print(binsize=50)\n", + "jack3.print(binsize=100)\n", + "\n", + "jack3.plot_tauint()\n", + "\n", + "print('Result from the automatic windowing procedure for comparison:')\n", + "c_obs3.gamma_method(S=1.5)\n", + "c_obs3.print()\n", + "c_obs3.gamma_method(S=2)\n", + "c_obs3.print()\n", + "c_obs3.gamma_method(S=3)\n", + "c_obs3.print()\n", + "\n", + "c_obs3.gamma_method(S=2)\n", + "c_obs3.plot_tauint()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For this specific example the binned Jackknife procedure seems to underestimate the final error, the deduced intergrated autocorrelation time depends strongly on the chosen binsize. The automatic windowing procedure displayed for comparison gives more robust results for this example." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.11" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/02_pcac_example.ipynb b/examples/02_pcac_example.ipynb new file mode 100644 index 00000000..87a83585 --- /dev/null +++ b/examples/02_pcac_example.ipynb @@ -0,0 +1,623 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.append('..')\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import pyerrors as pe" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Primary observables" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can load data from preprocessed pickle files which contain a list of `pyerror` `Obs`:" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "p_obs_names = ['f_A', 'f_P']\n", + "\n", + "p_obs = {}\n", + "for i, item in enumerate(p_obs_names):\n", + " p_obs[item] = pe.load_object('./data/B1k2_' + item + '.p') " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now use the `pyerrors` function `plot_corrs` to have a quick look at the data we just read in " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAbAAAAEKCAYAAABzHwA5AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAAZRUlEQVR4nO3df3Bc5X3v8c93JRZsATYE+QfGqoFxbWyMTSznxw2TAMFc4yYQN7QDabi0Sep28suZZujQdjKUKbnphEkKSXvJuJgkdgIZajCQ1KXV8MNcpomLHGxsZIy4BJBlC4tQ2/gHCGm/94+zAklI2t2ze3bPo32/ZjSrPTpnz5f1zn54nvOc5zF3FwAAocnUugAAAOIgwAAAQSLAAABBIsAAAEEiwAAAQSLAAABBakziRc844wyfM2dOEi8NABPStm3bXnP35lrXEZJEAmzOnDlqb29P4qUBYEIys5drXUNo6EIEAASJAAMABIkAAwAEKZFrYACA2tm2bdu0xsbGOyWdr3AbKjlJu/r7+7+wdOnSA6PtEH6A5Qakzjap5xlpxgXS3OVSpqHWVQFAzTQ2Nt45Y8aM85qbm/87k8kEOWN7Lpez3t7eBT09PXdKunK0fcIOsNyAtGGV1N0u9R2TspOlWa3SdZsIMQD17PyQw0uSMpmMNzc3H+rp6Tl/rH3CDrDOtnx4HY2e9x2Nnne2SfNW1LY2AKidTLHh9Xe/6Dhz3ZO/mTly++cvOnv/Nz6xYF/lSyte/r9hzC7QsANs8w3vhtegvqPRdgIMAAr6xicW7PvGJxbsu+ofn5wnSQ9++aI9ta6pWKFe3IusvFXKNg3flm2KtgMAitKfy+nQ8bcbeg69mX1o+74p/blc2a95yy23TDvnnHMWXnnllWePtc9ll1127uLFi+fHPUfYATZ3eXTNK9skyaLHWa3RdgBAQf25nP7gB7+c+8rrxya9+sZb2b+8b8c5f/CDX84tN8TWrVvX3NbW9vxDDz30m9H+/tprrzXs2rWr6Y033mjo6OjIxjlH2AGWaYgGbHz6LumSv4keGcABAEXb/EzPlN37D5+cy18xe/PtXGb3/sMnb36mZ0rc1/zMZz7Tsnfv3hOvuOKKuTfffPO00fb5yU9+MvWyyy47uGrVqtfXr19/epzzhB1gUhRW81ZIH8tf9yK8AKBoO7sPTX7r7dywLHjr7Vxm175Dk+O+5t133/3KtGnT3t6yZcvzN91006j3cN17772nf/azn339+uuvf/3++++PFWDpGcTB/VwAUHWLZk05duIJmdybQ0LsxBMyufPPnHIsqXN2dXU1vvzyyyddfvnlRzKZjBobG/2pp546admyZW+W8jrpCLBa3c9FaAKocysvmHHoh//5myM7ug6emnPppBMyufNmnnpk5QUzDiV1zvXr159++PDhhtmzZy+SpCNHjjSsX7/+fcuWLesu5XXS0YU47H4uH34/V1IGQ/O+z0mP/e/occOqaDsA1InGTEb/8ucf7mw5ffLx6aee2PftTy9+8V/+/MOdjZnk4mHjxo2nb9q0qbO7u3tnd3f3zq1bt3Y88MADp5X6OgUrNLN5ZrZ9yM9hM/tarKrHMt79XEmpRWgCQAo1ZjKaMumEgRmnntR35ZIzDyUZXnv27Ml2d3dnL7300ne+9OfPn993yimnDDz66KNN4x07UsEuRHffI2mJJJlZg6RuSZtKK7mAlbdGLaChIZb0/VzcBA0A75mJY86N/7pUKn8mju7u7p2jbZ83b17fgQMHnhm5vaOjY3ep5yj1GtjHJf0/d6/syqGD93ONvAaW5P1ctQhNAEiZwZk4al1HHKUG2DWS7hntD2a2WtJqSWppaSntVQfv5+psk3p2SjMWJT+gohahCQB15Pbbb3/fHXfcMX3otmXLlh3ZsGHDK5V4fXMvbrJiM8tK2idpobu/Ot6+ra2t3t7eXoHyEvbOKMQqhSYAjMHMtrl7ayVea8eOHS8tXrz4tUq8Vq3t2LHjjMWLF88Z7W+ltMCukPTrQuEVlMGboLnmBQDBKWWoybUao/sQAIBqK6oFZmZNkpZL+rNkywEAVNXDf3WmfvV/3rMemD70xf1a8a1UD+4oKsDc/aik9yVcCwCg2lZ8a59WfGuf1l4yT5K0+jHWAwMABCLXLx0/2KDD+7LauXGKcv1lv+R464F973vfe99pp522eP78+QvOPffchd/5znfOiHMOAgwA6lmuX7prxVwdfGmSjvRk9eCXz9FdK+aWG2KF1gP75Cc/+d/PPfdcxxNPPLHnlltumdXV1VXy3LwEGADUs2cfmKKeXSfL8wtY9h/PqGfXyXr2gUTXAxs0a9as/paWlrdeeOGFkhe1TMds9ACA2ti/fbL63xzemOl/M6P9OyZr0dWxZqS/++67X9myZcuULVu2PD9z5sxxm3IdHR3Zrq6uExcsWPBWqechwACgns1cckyNJ+XUf/zdEGs8KaeZixNbD0ySfv7zn582f/78k7PZbO622257efr06SUvBUKAxcE6YgAmioWfOqStPzii7m2nynNS46ScZpx/RAs/ldh6YFJ0DWz9+vVlTSlFgJWqVotvAkASMo3S5x7u1PeXLVD/8QZdfssrWvipQ8qkPx4YxFEq1hEDMNFkGqVJUwd0ysw+Lbo6iPCSaIGVjnXEAEwkI2fi+NspSyWVPRPHWOuBSdJXv/rV30r6bdzXHkSAlYp1xABMJIMzcQSIACsV64gBQFGSXg+MACtVLRbfBIDS5HK5nGUymeIWfEzImjVrfrtmzZrYXYW5XM4k5cb6OwEWB+uIAUi3Xb29vQuam5sP1TrE4srlctbb2ztF0q6x9iHAAGCC6e/v/0JPT8+dPT095yvc0eY5Sbv6+/u/MNYOBBgATDBLly49IOnKWteRtFCTGQBQ54oKMDObamYbzew5M9ttZh9OujAAAMZTbBfi7ZIedverzSwraXKCNQEAUFDBADOzKZI+KumPJcnd+yT1JVsWAADjK6YL8WxJvZJ+aGZPm9mdZtY0ciczW21m7WbW3tvbW/FCAQAYqpgAa5T0fkl3uPuFko5KunHkTu6+1t1b3b21ubm5wmUCADBcMQG2V9Jed9+af75RUaABAFAzBQPM3XskdZnZvPymj0vqSLQqAAAKKHYU4lck/TQ/AvFFSX+SXEkAABRWVIC5+3ZJrcmWAgBA8ZhKqtpyA/mZ7J+RZlzATPYAEBMBVk25AWnDqveuJXbdJkIMAErEXIjV1NmWD6+jkjx67G6PtgMASkKAVdPmG/LhNUTf0Wg7AKAkBFg1rbxVyo6YxCTbFG0HAJSEAKumucuja17ZJkkWPc5qjbYDAErCII5qyjREAzY626SendKMRYxCBICYCLBqyzRI81ZEPwCA2OhCBAAEiQADAASJAAMABIkAAwAEiQADAASJAAMABIkAAwAEiQADAASpqBuZzewlSW9IGpDU7+4sbgkAqKlSZuK4xN1fS6wSAABKQBciACBIxQaYS/oPM9tmZqtH28HMVptZu5m19/b2Vq5CAABGUWyAXeTu75d0haQvmdlHR+7g7mvdvdXdW5ubmytaJAAAIxUVYO7enX88IGmTpA8kWRQAAIUUDDAzazKzUwZ/l3S5pF1JF4YRcgPSnoelLd+OHnMDta4IAGqqmFGI0yVtMrPB/e9294cTrQrD5QakDauk7nap75iUnRyt5HzdJhbDBFC3CgaYu78oaXEVasFYOtvy4XU0et53NHre2cbCmADqFsPoQ7D5hnfDa1Df0Wg7ANQpAiwEK2+Vsk3Dt2Wbou0AUKcIsBDMXR5d88o2SbLocVZrtB0A6lQpU0mhVjIN0YCNzjapZ6c0Y1EUXgzgAFDHCLBQZBqiARsM2gAASXQhAgACRYABAIJEgAEAgkSAAQCCRIABAIJEgAEAgkSAAQCCRIABAIJEgAEAgkSAAQCCRIABAIJUdICZWYOZPW1mv0iyIAAAilHKZL5rJO2WdGpCtSApuYH8TPbPSDMuYCZ7ABNCUQFmZmdJ+j1J35T0F4lWhMrKDUgbVknd7VLfMSk7OVpL7LpNhBiAoBXbhXibpL+UlBtrBzNbbWbtZtbe29tbidpQCZ1t+fA6Ksmjx+72aDsABKxggJnZJyQdcPdt4+3n7mvdvdXdW5ubmytWIMq0+YZ8eA3RdzTaDgABK6YF9hFJV5rZS5J+JulSM/tJolWhclbeKmWbhm/LNkXbASBgBQPM3f/K3c9y9zmSrpH0qLt/NvHKUBlzl0fXvLJNkix6nNUabQeAgJUyChEhyjREAzY626SendKMRYxCBDAhlBRg7v64pMcTqQTJyTRI81ZEPwAwQTATBwAgSAQYACBIBBgAIEgEGAAgSAQYACBIBBgAIEgEGAAgSAQYACBIBBgAIEgEGAAgSMyFiLGxkjOAFCPAMDpWcgaQcnQhYnSs5Awg5QgwjI6VnAGkHAGG0bGSM4CUI8AwOlZyBpByBQdxmNlJkp6QdGJ+/43uflPShaHGWMkZQMoVMwrxLUmXuvsRMztB0pNm9m/u/quEa0OtsZIzgBQrGGDu7pKO5J+ekP/xJIsCAKCQoq6BmVmDmW2XdEBSm7tvHWWf1WbWbmbtvb29FS4TAIDhigowdx9w9yWSzpL0ATM7f5R91rp7q7u3Njc3V7hMAACGK2kUorsflPSYJC6KAABqqmCAmVmzmU3N/z5J0nJJzyVcFwAA4ypmFOJMST82swZFgXevu/8i2bIAABhfMaMQn5F0YRVqAQCgaMxGj2SwFAuAhBFgqDyWYgFQBcyFiMpjKRYAVUCAofJYigVAFRBgqDyWYgFQBQQYKo+lWABUAYM4UHksxQKgCggwJIOlWAAkjC5EAECQCDAAQJAIMABAkAgwAECQCDAAQJAYhYh0YRJgAEUiwJAeTAIMoAR0ISI9mAQYQAkKBpiZzTazx8ysw8yeNbM11SgMdYhJgAGUoJgWWL+kr7v7AkkfkvQlM1uQbFmoS0wCDKAEBQPM3fe7+6/zv78habekWUkXhjrEJMAASlDSIA4zmyPpQklbR/nbakmrJamlpaUStaHeMAkwgBKYuxe3o9nJkrZI+qa73z/evq2trd7e3l6B8gCgPpjZNndvrXUdISlqFKKZnSDpPkk/LRReAABUQzGjEE3SOkm73f27yZcEAEBhxVwD+4ik6yTtNLPt+W1/7e6bE6sKiINZPIC6UjDA3P1JSVaFWoD4mMUDqDvMxIGJgVk8gLpDgGFiYBYPoO4QYJgYmMUDqDsEGCYGZvEA6g7LqWBiYBYPoO4QYJg4Mg3SvBXRD4AJjwADuH8MCBIBhvrG/WNAsBjEgfrG/WNAsAgw1DfuHwOCRYChvnH/GBAsAgz1jfvHgGAxiAP1jfvHgGARYEA5948xBB+oGQIMiIsh+EBNcQ0MiIsh+EBNFQwwM7vLzA6Y2a5qFAQEgyH4QE0V0wL7kSQmlwNGYgg+UFMFA8zdn5D0ehVqAcJSzhD83IC052Fpy7ejx9xA4uUCE03FBnGY2WpJqyWppaWlUi8LpFfcIfgM/gAqomKDONx9rbu3untrc3NzpV4WSLfBIfgfuyF6LCaAGPwBVASjEIFqY/AHUBEEGFBtDP4AKqKYYfT3SPqlpHlmttfMPp98WcAEVu78iwwAASQVMYjD3a+tRiFA3Shn/kUGgADvYCopoBbizr84bACIhg8AiTOXIxAwroEBISlnAAhdj5hgaIEBIVl5q3Tf54aHWDEDQOh6xARECwwISdwBINx7hgmIFhgQkrgDQMbreizm2hnrniGFCDAgNHEGgMTtepTofkRq0YUI1INy7j0rp/uRgSNIEC0woB6Uc+9Z3O5HWm5IGC0woF7EmXhYij/1VbkDR2i9oQBaYADGN9j9OLIlVaj7sZyBI7TeUAQCDMD44nY/ljNwpJwZRxgxWTcIMACFxRn5GLflJtXuuhvhFxQCDEAyyhk4Erf1Vm7LjW7LoDCIA0By4g4ciTvsv5y5IrldIDi0wACkTy2uu3G7QHBogQFIpzitt3Ju2K7V7QKIragWmJmtkHS7pAZJd7r73ydaFQDEUc51t1rcLoCymLuPv4NZg6TnJS2XtFfSU5KudfeOsY5pbW319vb2StYJAMl7ZxRiCeG35+HRuy0/fVdJAWZm29y9NWbldamYFtgHJL3g7i9Kkpn9TNJVksYMMAAIUrVvF0BZigmwWZK6hjzfK+mDI3cys9WSVktSS0tLRYoDUDkDOdfjew7o2X2HtfDMU3XxvGlqyFiix9bFOTMNGvij+7Vzy0Ydf+VpTWq5UIs+drUaGMCRuIqNQnT3tZLWSlEXYqVeF0haPXzJDuRc163bqu1dB3W8b0CTsg1aMnuqNnz+g4kdW1fn/GG7tndN1fG+j2rSbxq05MX2os6J8hQTYN2SZg95flZ+G5AqfLGPfezjew5oe9dBHeuL7k861jeg7V0H9fieA/r4edPHPWfcYzln4XOiPMUMo39K0lwzO9vMspKukfRQsmUhdAM51yO7X9X3HunUI7tf1UCuuEZ5Ocddt26rvnLP0/qHtuf1lXue1nXrthY8fuiXj2v4l08hcY+txTlvevDZd75gBx3rG9BNDz5b8Jxxj+Wchc+J8hQMMHfvl/RlSf8uabeke9294v8ycb+4kJxqh0nc4yS+2Asde/NVCzU5O/yazORsg26+amHBc8Y9lnMWPifKU9SNzO6+2d1/193PdfdvVrqIcr64UFicIKpFmJTTMuGLffxjL543TUtmT9XkbIMsf8yS2VN18bxpBc8Z91jOWficKE/B+8DiKPU+sEd2v6qv3PP0sC+gydkGff/aC+lDzitnsECcaybl/Jtc9PePau/B4+/ZftbUSXryxksrflw59dbLNbDBYx/fc0Ad+w5rQcyBI6UeyzmLx31gpUtFgJXzxRWaag80iPvFXoswKSc0+WJntFvoCLDSpSLAyv3iijscOa56aA3VIkzKCaHB4/liR6gIsNKlYjb6wT7kkV9chfqQK/WFV63WUNzhtuNd3ykUJjdftXDUICr2mkmp/yaS1JAxbfj8B0sOk7jHDT3+4+dNp9sZqBOpaIFJ8f7vuRathHppDQ0eS4sGqA5aYKVLTYDFUYvrNKENNBg8niAC0o0AK10quhDjits9JsXvlivnnHG75ehaA4D3CjrAyrlOE9K1ocFjCSEAeFfQXYhSecOYuTYEIC3oQixd8AFWDoIIQFoQYKULuguxXHTLAUC4ipoLEQCAtCHAAABBIsAAAEEiwAAAQSLAAABBSmQYvZn1Sno55uFnSHqtguVMNLw/hfEejY/3p7BavEe/4+7NVT5n0BIJsHKYWTv3QoyN96cw3qPx8f4UxnsUBroQAQBBIsAAAEFKY4CtrXUBKcf7Uxjv0fh4fwrjPQpA6q6BAQBQjDS2wAAAKIgAAwAEKTUBZmYrzGyPmb1gZjfWup40MrOXzGynmW03s/SvV1MFZnaXmR0ws11Dtp1uZm1m1pl/PK2WNdbSGO/P35pZd/5ztN3MVtayxloys9lm9piZdZjZs2a2Jr+dz1AAUhFgZtYg6Z8kXSFpgaRrzWxBbatKrUvcfQn3qLzjR5JWjNh2o6RH3H2upEfyz+vVj/Te90eS/iH/OVri7purXFOa9Ev6ursvkPQhSV/Kf/fwGQpAKgJM0gckveDuL7p7n6SfSbqqxjUhAO7+hKTXR2y+StKP87//WNKnqllTmozx/iDP3fe7+6/zv78habekWeIzFIS0BNgsSV1Dnu/Nb8NwLuk/zGybma2udTEpNt3d9+d/75HEiqXv9WUzeybfxUj3mCQzmyPpQklbxWcoCGkJMBTnInd/v6Ku1i+Z2UdrXVDaeXSfCPeKDHeHpHMlLZG0X9J3alpNCpjZyZLuk/Q1dz889G98htIrLQHWLWn2kOdn5bdhCHfvzj8ekLRJUdcr3utVM5spSfnHAzWuJ1Xc/VV3H3D3nKR/Vp1/jszsBEXh9VN3vz+/mc9QANISYE9JmmtmZ5tZVtI1kh6qcU2pYmZNZnbK4O+SLpe0a/yj6tZDkq7P/369pAdrWEvqDH4x561SHX+OzMwkrZO0292/O+RPfIYCkJqZOPJDeW+T1CDpLnf/Zm0rShczO0dRq0uSGiXdzXskmdk9ki5WtPzFq5JukvSApHsltSha1ucP3b0uBzKM8f5crKj70CW9JOnPhlzvqStmdpGk/ytpp6RcfvNfK7oOxmco5VITYAAAlCItXYgAAJSEAAMABIkAAwAEiQADAASJAAMABIkAAwAEiQBDXTKzH5jZR2pdB4D4uA8MdcnMtkta6u4Dta4FQDy0wDBh5BcmXJ7//RYz+/4Y+50n6fnB8DKzq83sV2a2w8yeNLPmKpYNICYCDBPJTZL+xsz+SNGyGF8bY78rJD085Plj7v4hd18sqU3SHyZaJYCKIMAwYeQXbzRJfyHpGncfyE+C/GMz++d8sEnS/9TwAPtjM/svM9sh6YuS3qxu5QDiIMAwYZjZIkkzJfXlV9eVpN+XtNHd/1TSlWY2WdJUd9+XP+Z/KVpO5NJ8C2yPpGerXz2AUhFgmBDyS4T8VNFS8EfMbEX+T2fp3dW+ByRdIumxIYcukvSf7n7EzD4t6X8ompkcQMoRYAhevlV1v6Svu/tuSX+n6HqYJO1VFGJS9Hkfef3rR5K+aGb/pei62YvufrQadQMoD8PoMaHlF//8R0XXtZ6U9HVJH3T3t2taGICyEWAAgCDRhQgACBIBBgAIEgEGAAgSAQYACBIBBgAIEgEGAAgSAQYACBIBBgAIEgEGAAjS/wdLowDMJTn02wAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "pe.plot_corrs([p_obs['f_A'], p_obs['f_P']], label=p_obs_names)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Secondary observables" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One way of generating secondary observables is to write the desired math operations as for standard floats. `pyerrors` currently supports the basic arithmetic operations as well as numpy's basic trigonometric functions.\n", + "\n", + "We start by looking at the unimproved pcac mass $am=\\tilde{\\partial}_0 f_\\mathrm{A}/2 f_\\mathrm{P}$" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "uimpr_mass = []\n", + "for i in range(1, len(p_obs['f_A']) - 1):\n", + " uimpr_mass.append((p_obs['f_A'][i + 1] - p_obs['f_A'][i - 1]) / 2 / (2 * p_obs['f_P'][i]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For more complicated secondary obsevables or secondary obsevables we use over and over again it is often useful to define a dedicated function for it. Here is an example for the improved pcac mass" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def pcac_mass(data, **kwargs):\n", + " if 'ca' in kwargs:\n", + " ca = kwargs.get('ca')\n", + " else:\n", + " ca = 0\n", + " return ((data[1] - data[0]) / 2. + ca * (data[2] - 2 * data[3] + data[4])) / 2. / data[3]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can construct the derived observable `pcac_mass` from the primary ones. Note the additional key word argument `ca` with which we can provide a value for the $\\mathrm{O}(a)$ improvement coefficient of the axial vector current." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "impr_mass = []\n", + "for i in range(1, len(p_obs['f_A']) - 1):\n", + " impr_mass.append(pcac_mass([p_obs['f_A'][i - 1], p_obs['f_A'][i + 1], p_obs['f_P'][i - 1],\n", + " p_obs['f_P'][i], p_obs['f_P'][i + 1]], ca=-0.03888694628624465))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To calculate the error of an observable we use the `gamma_method`. Let us have a look at the docstring" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\u001b[0;31mSignature:\u001b[0m \u001b[0mpe\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mObs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgamma_method\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mDocstring:\u001b[0m\n", + "Calculate the error and related properties of the Obs.\n", + "\n", + "Keyword arguments\n", + "-----------------\n", + "S -- specifies a custom value for the parameter S (default 2.0), can be\n", + " a float or an array of floats for different ensembles\n", + "tau_exp -- positive value triggers the critical slowing down analysis\n", + " (default 0.0), can be a float or an array of floats for\n", + " different ensembles\n", + "N_sigma -- number of standard deviations from zero until the tail is\n", + " attached to the autocorrelation function (default 1)\n", + "e_tag -- number of characters which label the ensemble. The remaining\n", + " ones label replica (default 0)\n", + "fft -- boolean, which determines whether the fft algorithm is used for\n", + " the computation of the autocorrelation function (default True)\n", + "\u001b[0;31mFile:\u001b[0m ~/.local/lib/python3.6/site-packages/pyerrors/pyerrors.py\n", + "\u001b[0;31mType:\u001b[0m function\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "?pe.Obs.gamma_method" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can apply the `gamma_method` to the pcac mass on every time slice for both the unimproved and the improved mass." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "masses = [uimpr_mass, impr_mass]\n", + "for i, item in enumerate(masses):\n", + " [o.gamma_method() for o in item]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now have a look at the result by plotting the two lists of `Obs`" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjMAAAEKCAYAAADnz9Q6AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAA5tElEQVR4nO3deXxU9b3/8ddnJiQQkLBvAQxKEkhYpKS4VFsQqVAXRPRKsVxaodat7lfB+7i9VOtVf6316q1t9YqK1ita1Ba1xVpFbYuKEUQIuwv7KhDAREImn98fM7EhBiXJIbPk/Xw85pE53znnzGcWOJ/5rubuiIiIiCSrULwDEBEREWkMJTMiIiKS1JTMiIiISFJTMiMiIiJJTcmMiIiIJDUlMyIiIpLU0uIdQJA6derkOTk58Q5DRCSpvPvuuzvdvXO84xBpqJRKZnJyciguLo53GCIiScXM1sU7BpHGUDOTiIiIJDUlMyIiIpLUlMyIiIhIUkupPjMiIhI/7777bpe0tLSHgAHox7IEqwpYVllZOXXo0KHbaz+oZEZERAKRlpb2ULdu3fp37tx5dygU0irGEpiqqirbsWNHwdatWx8Czq39uDJnEREJyoDOnTvvVSIjQQuFQt65c+dSorV+X6CaGRERCUroSBOZ215Y3mPm3z/qXrt8yql9tvzH2QWbgw9Nkl3su1VnJYySGRERaXL/cXbB5v84u2Dz2F/9PR/gj1eduiqI82ZmZg4pKytbHMS5mkJ2dvbA4uLiFd27d6+MdyzJTM1MIiISF5VVVZSWHwxvLf0sfe57m7Mqq6riHVKdDh48GO8Q5CsomRERkSZXWVXFhb99M3f9rrJW2/YdSL/pmSXHXfjbN3ODSmheeOGFY77+9a/njxw58viePXsOvOKKK7J/85vfdBg4cGD/vLy8gpKSkgyA8ePH50ycOLH3gAED+ufk5Ax48sknswDuu+++jqeffnrfk046Ke+UU07J37ZtW/iMM844Pi8vr2Dw4MH93n777VaRSITs7OyBO3fuDFc/77HHHjtgw4YNaZs3b04788wzjx8wYED/AQMG9P/LX/7SGmDr1q3hb3zjG7l9+/YtvOiii451r7tVLjMzc8iUKVN69e3bt/Dkk0/O27x5cxrAsmXLMk455ZS8/Pz8goKCgv4lJSUZpaWloZNPPjmvoKCgf15eXsHvfve7dtXn+dWvftUxLy+vID8/v+C8887rU/t5rr/++h7nn39+ztChQ/N79OgxcNasWe0uu+yynnl5eQWnnXZa7oEDBwzgxhtv7D5gwID+ubm5hd/97nePrYp9Tj/72c+6HH/88YV5eXkFZ5999nEAL774Ypt+/foV9OvXr6B///4Fu3fvPuq5hpIZERFpcn96f2vWii1721TFruWfHawKrdiyt82f3t+aFdRzrFy5stXDDz+8fs2aNcvmzJnTcfXq1S2XLl26YtKkSTvvvvvuLtX7bdiwIWPJkiUrnn/++TXXXnvtsWVlZQZQUlKS+cc//vGDd955Z9VNN93UY/DgwWWrV69eftttt22aPHlyn3A4zLe//e09TzzxRDuAV199tXV2dnZFr169Kn/0ox/1uv7667ctW7ZsxXPPPffBZZddlgMwbdq0HieffPL+tWvXlowbN27Pli1b0uuKvby8PFRUVPTp2rVrS77xjW/smzZtWg+AiRMn9rnsssu2r1q1anlxcfHK3r17H8zMzKx68cUX1y5fvnzF66+/vvqWW27pWVVVRXFxcctf/OIX3V9//fXVq1atWv7AAw+sr+u51q1bl7FgwYLVzzzzzNrLLrusz+mnn7539erVy1u2bFn19NNPZwH827/92/Zly5atWLNmTUl5eXlo9uzZ1Ulft2XLli1fvXr18kcffXQdwN13393tvvvuW7dy5crlb7311so2bdoc9So3JTMiItLklm4qzTxwsOqQa9CBg1WhZZtLM4N6joEDB3567LHHHmzVqpX37t37wJgxY0oBBg8eXL5+/frPk4jx48fvCofDDBw48ECvXr0OvPfeey0BTjvttL1du3aNACxcuPCYKVOmfAJw7rnn7tuzZ0/arl27QhMnTtw1Z86cDgBPPPFEh/Hjx+8C+Mc//tH2mmuu6d2vX7+Cc845p+/+/fvDpaWlobfeeuuYSy655BOACRMmlLZt2zZSV+yhUIipU6fuArjkkks+WbhwYZvdu3eHtm3blv6v//qvewAyMzP9mGOOqaqqqrJrr722Z15eXsGIESPytm/fnr5x48a0l156qe0555yzu7o/TvVrqe2MM84ozcjI8GHDhpVHIhG74IIL9gIUFhaWf/TRR+kAf/7zn48ZNGhQv7y8vIIFCxYcs2zZslYA+fn55ePGjevz61//ukOLFi0c4KSTTtp/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bUFBQf/8/PyCk08+OQ9g/vz5mSeccEK//v37FwwZMqTfkiVLMgAqKyu59NJLe+bm5hbm5eUV3H777V94vmHDhuVPmTKl14ABA/ofd9xxha+//nrmt7/97eOPPfbYAVdffXWP6v3OOOOM4wsLC/v37du38Be/+EWn6vOPHz8+p/r8P/3pT7sA/OxnP+ty/PHHF+bl5RWcffbZx9Xnsw0iBd4E1Kye6xkrq2ufjWaWBmQBn3zJsRuBje7+dqx8DodJZqQZCLLmorppqGJ/tGkod1T9a1IAtr4PFbV+yFWUwdalkD+64fGlGtU6yeGU/CGLrcvafP6DoLI8xNZlbSj5QxYDj97095WVlbZ06dIVTz31VNatt97aY/To0atr77Nu3bqMBQsWrF60aFHL008/vd+sWbM++O1vf7tx1KhRxz/99NNZkyZN2gOQlZVVuXr16uW/+tWvOv74xz/uNX/+/LUAW7ZsSV+0aNHKtLQ08vLyCu655571Z5111v5rr722x80339zj4Ycf3nDw4EFbuXJler9+/Soee+yxDuedd97uAwcO2NVXX937xRdfXNujR4/K//3f/21/4403Zv/+97//eMqUKTn33nvv+jFjxuz/0Y9+1PNwr2/p0qWtFy9evCwvL6/im9/8Zu5jjz3W/swzz9x31VVX5bz22msr+/XrV1G9RtPgwYM/e+edd1a2aNGCP/zhD8fcdNNNPV966aUP7r777s7r169PX758eUmLFi0Ou6ZTenp61bJly1bcdtttXS688MK+77zzzoouXbpU5uTkDLzlllu2devWLfLEE0983LVr18j+/fttyJAhBd/73vd2r1mzJmPLli0t1qxZUwKwc+fOMMB9993Xbd26dUtbtWrl1WVHKoiamXeAXDPrE+uoOwGYW2ufucDk2P0LgFc9OlvfXGBCbLRTHyAXWOjuW4ENZpYfO2YksByRxqjZNFS6Pto09Pi4hvV16TYI0mv1SU/PhG4Dg4lVvki1PKlly3uZVH526DWo8rMQW5Y0eLDH4VaWrll+4YUX7gY45ZRTPt24cWN6XfufccYZpRkZGT5s2LDySCRiF1xwwV6AwsLC8o8++ujzYyZPnrwL4Ic//OGuxYsXt6kuP//883enpaXxySefhPft2xc+66yz9sf2++Stt95qA3DeeefteuyxxzoAPPfcc+0nTZq06/33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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "pe.plot_corrs([impr_mass, uimpr_mass], xrange=[0.5, 18.5], label=['Improved pcac mass', 'Unimproved pcac mass'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tertiary observables" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now construct a plateau as (tertiary) derived observable from the masses. At this point the distinction between primary and secondary observables becomes blurred. We can again and again resample objects into new observables which allows us to modulize the analysis. Note that `np.mean` and similar functions can be applied to the `Obs` as if they were real numbers." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Result\t 4.79208242e-03 +/- 2.09091228e-04 +/- 1.90500140e-05 (4.363%)\n", + " t_int\t 1.09826949e+00 +/- 1.84087104e-01 S = 2.00\n" + ] + } + ], + "source": [ + "pcac_plateau = np.mean(impr_mass[6:15])\n", + "pcac_plateau.gamma_method()\n", + "pcac_plateau.print()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also use a weighted average with given `plateau_range` (passed to the function as kwarg)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def weighted_plateau(data, **kwargs):\n", + " if 'plateau_range' in kwargs:\n", + " plateau_range = kwargs.get('plateau_range')\n", + " else:\n", + " raise Exception('No range given.')\n", + " \n", + " num = 0\n", + " den = 0\n", + " for i in range(plateau_range[0], plateau_range[1]):\n", + " if data[i].dvalue == 0.0:\n", + " raise Exception('Run gamma_method for input first')\n", + " num += 1 / data[i].dvalue * data[i]\n", + " den += 1 / data[i].dvalue\n", + " return num / den" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Result\t 4.78698515e-03 +/- 2.04149923e-04 +/- 1.85998184e-05 (4.265%)\n", + " t_int\t 1.06605715e+00 +/- 1.79069383e-01 S = 2.00\n" + ] + } + ], + "source": [ + "w_pcac_plateau = weighted_plateau(impr_mass, plateau_range=[6, 15])\n", + "w_pcac_plateau.gamma_method()\n", + "w_pcac_plateau.print()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this case the two variants of the plateau are almost identical\n", + "\n", + "We can now plot the data with the two plateaus" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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opKA/9WV2xO+OzAxP8bX8LpylpaW0qxZs0iHISfR8L410ng0sA6WM2JeYFPzyV+5zYh5IaJxeaYhjopqqPReRVxZMMilf30/efP+wha7Copjf/7Cqt6X/vX95LJg0JPzv/baa62++c1vpo4cOfKMbt26DbjuuuuS/vKXv7QbMGBAv5SUlLTs7Ow4gEmTJvWcPHny6f379+/Xs2fP/s8880wCwCOPPNJ+xIgRfc4666yUs88+O3XXrl3+UaNGnZGSkpKWkZHRd8WKFS0CgQBJSUkD9u7de6x6sEePHv23bNkSs3379pgLLrjgjP79+/fr379/v3/84x+nAezcudP/rW99K7lPnz7pl112WQ/nql6mKT4+ftDUqVO79+nTJ33YsGEp27dvjwFYs2ZN3Nlnn52SmpqalpaW1i87OzsuPz/fN2zYsJS0tLR+KSkpaU8//XSb8vP87//+b/uUlJS01NTUtIsuuqhX5ee55ZZbul588cU9Bw8enNq1a9cBTz75ZJvp06d3S0lJSTv33HOTi4uLDeC2227r0r9//37JycnpP/jBD3oEw5/T7373u05nnHFGekpKStq4ceN6AyxatKhl37590/r27ZvWr1+/tAMHDpzyXEPJjHyVF0lIQ5wTJDzC6rIui7msy+K6jbBqiBrqpIANkd6riHv9050J63YcahkMX8uPlgZ963Ycavn6pzsTvHqO9evXt3jiiSc2b9iwYc2CBQva5+bmNl+9evW6K6+8cu9DDz3UqXy/LVu2xK1atWrdwoULN9x88809CgsLDSA7Ozv+lVde+ezDDz/M+fnPf941IyOjMDc3d+1vf/vbbVOmTOnl9/s5//zzD86fP78NwJIlS05LSkoq6d69e9m1117b/ZZbbtm1Zs2adS+99NJn06dP7wlw5513dh02bNjhvLy87IkTJx7csWNHbFWxFxUV+TIzM4/k5eVlf+tb3yq48847uwJMnjy51/Tp03fn5OSszcrKWn/66aeXxsfHBxctWpS3du3adcuWLcv9xS9+0S0YDJKVldX8wQcf7LJs2bLcnJyctbNmzdpc1XN98cUXce+9917uCy+8kDd9+vReI0aMOJSbm7u2efPmweeffz4B4Pbbb9+9Zs2adRs2bMguKiryPfvss+VJX+KaNWvW5ubmrp07d+4XAA899FDiI4888sX69evXLl++fH3Lli29yVBPQslMI/DHt3LpeecieuZcF7rduYiedy7ij2/VYgZtr5IQzQlSfeVz8nzx79CtLnPyNMRJARsqvVcRtXpbfnxxafC4a1BxadC3Znt+/ImOqakBAwYc6dGjR2mLFi3c6aefXjx27Nh8gIyMjKLNmzcfSyImTZq03+/3M2DAgOLu3bsXr1y5sjnAueeee6hz584BgA8++KDV1KlT9wFceOGFBQcPHozZv3+/b/LkyfsXLFjQDmD+/PntJk2atB/gP//5T+ubbrrp9L59+6aNHz++z+HDh/35+fm+5cuXt7r66qv3AVx++eX5rVu3rvKPq8/nY9q0afsBrr766n0ffPBBywMHDvh27doV+6Mf/eggQHx8vGvVqlUwGAzazTff3C0lJSVt+PDhKbt3747dunVrzJtvvtl6/PjxB8r745S/lspGjRqVHxcX54YMGVIUCATskksuOQSQnp5etHHjxliAN954o9XAgQP7pqSkpL333nut1qxZ0wIgNTW1aOLEib0effTRds2aNXMAZ5111uHbbrut++9+97tOe/fu9ddHE536zDQC5f03sn9/DgDpv/h37U/m1SgPdbCsvgY4Msqz/kVeDmH3eji8RNSApITCuGa+4NEKCU1cM1+wf9eEwpMdVxNxcXHH2nB8Ph/Nmzd35fcDgYCVP2Zmxx1Xvh0fH/+1NQojR448MnXq1Ljt27fHLF68uM199923HcA5x8cff7wuPj6+6nakGqocY0WzZs1qt2/fvpjVq1evi4uLc0lJSQOKioqqXVlR/j75/X5iYmKcL9xvyefzUVZWZoWFhXbrrbf2WLFixdo+ffqU3nLLLV2PHj3qA1i6dOmGN954o9Urr7yS8OCDD3bJycnJ/v3vf7/zoosuyn/llVcSzj333L6LFi3aMGjQoKN1ewdOTjUzjUUwQMvgIToGdtWtf4pXE5M1xCn6G6hjNWuVbrWqWfOIZ/2LyidPrHyrTfLh5bkk4r47MDG/X5fWh33ha3TzZr5gvy6tD393YGJ+fcfy4osvtg0EAmRnZ8dt2bIlLiMj4ysX3qFDhxbMmTOnPYT647Rt27asXbt2QZ/Px9ixYw9ed9113fv06VOUmJgYADjnnHMO3X///ceast57770WAGeddVbB3Llz2wM8//zzrQ8dOlRllWAwGGTOnDltAebOndt+yJAhBW3btg0m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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "pe.plot_corrs([impr_mass, uimpr_mass], plateau=[pcac_plateau, w_pcac_plateau], xrange=[0.5, 18.5],\n", + " label=['Improved pcac mass', 'Unimproved pcac mass'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Refined error analysis" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are two way of adjusting the value of S. One can either change the class variable `Obs.S_global`. The set value is then used for all following applications of the `gamma_method`." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Result\t 4.79208242e-03 +/- 2.02509166e-04 +/- 2.05063968e-05 (4.226%)\n", + " t_int\t 1.03021214e+00 +/- 1.94552148e-01 S = 3.00\n" + ] + } + ], + "source": [ + "pe.Obs.S_global = 3.0\n", + "pcac_plateau.gamma_method()\n", + "pcac_plateau.print()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Alternatively one can call the gamma_method with the keyword argument S. This value overwrites the global value only for the current application of the `gamma_method`." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Result\t 4.79208242e-03 +/- 2.04669865e-04 +/- 1.97135904e-05 (4.271%)\n", + " t_int\t 1.05231340e+00 +/- 1.88061498e-01 S = 2.50\n" + ] + } + ], + "source": [ + "pcac_plateau.gamma_method(S=2.5)\n", + "pcac_plateau.print()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can have a look at the respective normalized autocorrelation function (rho) and the integrated autocorrelation time" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "pcac_plateau.plot_rho()\n", + "pcac_plateau.plot_tauint()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Critical slowing down" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`pyerrors` also supports the critical slowing down analysis of arXiv:1009.5228" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Result\t 4.79208242e-03 +/- 2.28649024e-04 +/- 1.67571716e-05 (4.771%)\n", + " t_int\t 1.31333644e+00 +/- 5.19554793e-01 tau_exp = 10.00, N_sigma = 1\n" + ] + } + ], + "source": [ + "pcac_plateau.gamma_method(tau_exp=10, N_sigma=1)\n", + "pcac_plateau.print()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The attached tail, which takes into account long range autocorrelations, is shown in the plots for rho and tauint" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "pcac_plateau.plot_rho()\n", + "pcac_plateau.plot_tauint()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Additional information on the ensembles and replicas can be printed with print level 2 (In this case there is only one ensemble with one replicum.)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Result\t 4.79208242e-03 +/- 2.28649024e-04 +/- 1.67571716e-05 (4.771%)\n", + " t_int\t 1.31333644e+00 +/- 5.19554793e-01 tau_exp = 10.00, N_sigma = 1\n", + "1024 samples in 1 ensembles:\n", + " : ['B1k2r2']\n" + ] + } + ], + "source": [ + "pcac_plateau.print(2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The Monte Carlo history of the observable can be accessed with `plot_history` to identify possible outliers or have a look at the shape of the distribution" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "pcac_plateau.plot_history()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If everything is satisfactory, dump the `Obs` in a pickle file for future use. The `Obs` `pcac_plateau` conatains all relevant information for any follow up analyses." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "pcac_plateau.dump('B1k2_pcac_plateau')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.11" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/03_fit_example.ipynb b/examples/03_fit_example.ipynb new file mode 100644 index 00000000..e0de4040 --- /dev/null +++ b/examples/03_fit_example.ipynb @@ -0,0 +1,774 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.append('..')\n", + "import pyerrors as pe\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read data from the pcac example" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "p_obs = {}\n", + "p_obs['f_P'] = pe.load_object('./data/B1k2_f_P.p')\n", + "\n", + "# f_A can be accesed via p_obs['f_A']\n", + "\n", + "[o.gamma_method() for o in p_obs['f_P']];" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now define a custom fit function, in this case a single exponential. __Here we need to use the autograd wrapped version of numpy__ (imported as anp) to use automatic differentiation." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as anp\n", + "def func_exp(a, x):\n", + " y = a[1] * anp.exp(-a[0] * x)\n", + " return y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Fit single exponential to f_P. The kwarg `resplot` generates a figure which visualizes the fit with residuals." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fit with 2 parameters\n", + "Method: Levenberg-Marquardt\n", + "`xtol` termination condition is satisfied.\n", + "chisquare/d.o.f.: 0.00287692704517733\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mass, Matrix element:\n", + "[Obs[0.2102(63)], Obs[14.24(66)]]\n" + ] + } + ], + "source": [ + "# Specify fit range for single exponential fit\n", + "start_se = 8\n", + "stop_se = 19\n", + "\n", + "a = pe.fits.standard_fit(np.arange(start_se, stop_se), p_obs['f_P'][start_se:stop_se], func_exp, resplot=True)\n", + "[o.gamma_method() for o in a]\n", + "print('Mass, Matrix element:')\n", + "print(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The covariance of the two fit parameters can be computed in the following way" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Covariance: 0.003465486601483565\n", + "Normalized covariance: 0.8360758153764549\n" + ] + } + ], + "source": [ + "cov_01 = pe.fits.covariance(a[0], a[1])\n", + "print('Covariance: ', cov_01)\n", + "print('Normalized covariance: ', cov_01 / a[0].dvalue / a[1].dvalue)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Effective mass" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the effective mass for comparison" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "m_eff_f_P = []\n", + "for i in range(len(p_obs['f_P']) - 1):\n", + " m_eff_f_P.append(np.log(p_obs['f_P'][i] / p_obs['f_P'][i+1]))\n", + " m_eff_f_P[i].gamma_method()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Calculate the corresponding plateau and compare the two results" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Effective mass:\n", + "Obs[0.2114(52)]\n", + "Fitted mass:\n", + "Obs[0.2102(63)]\n" + ] + } + ], + "source": [ + "m_eff_plateau = np.mean(m_eff_f_P[start_se: stop_se]) # Plateau from 8 to 16\n", + "m_eff_plateau.gamma_method()\n", + "print('Effective mass:')\n", + "m_eff_plateau.print(0)\n", + "print('Fitted mass:')\n", + "a[0].print(0)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAfoAAAEKCAYAAAD6h5dQAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAAsiUlEQVR4nO3de3xU5Z0G8OeXCYFEkgCSQG4akExu3BNAqpaUi0AlUAXLRd3axRKlWg2pldbqUls/UjVL1brdRFmwCqi1LpKCF4pGt1SQBAKYAIEimpBAIpCbCQmZefePmcEQcpkkM7wzJ8/38+FD5syZk2cSmGfOe86cV5RSICIiImPy0R2AiIiI3IdFT0REZGAseiIiIgNj0RMRERkYi56IiMjAWPREREQG5qs7QGuDBw9W0dHRumMQEXmV/Pz8r5VSIbpzkOfxuKKPjo5GXl6e7hiGUVZWhvDwcN0xiMjNRORL3RnIM3Ho3uCys7N1RyAiIo1Y9ERERAbGoiciIjIwjztGT66VkpKiOwIReZn8/PxQX1/flwGMBHcIPZ0VwOfNzc33JCUlVbS1Aove4Fj0RNRVvr6+Lw8dOjQ+JCTknI+PD2c+82BWq1UqKysTTp069TKAuW2tw3dqBpeZmak7AhF5n5EhISE1LHnP5+Pjo0JCQqphG31pe50rmIc0qK2t1R2BiLyPD0vee9h/V+32OYueiIg8jslkSoqLi0uIiYlJnD179vDa2lofAAgICBjX0eO+/vpr0+rVq91y4aB33323f0JCQryvr2/SunXrBrrje7gDi97gwsLCdEcgIuqyvn37Wg8fPlx09OjRwj59+qjMzEynyvvMmTOmtWvXhroj0/Dhw5vWrVt3IjU19Yw7tu8uLHqDS0tL0x2BiKhHbrzxxrpjx471bbmsurraZ/LkyeaEhIR4s9mc8Nprrw0AgIyMjMiSkpK+cXFxCWlpaZEA8Nhjjw0ZOXJkvNlsTkhPT794qdDp06dfl5iYGD9ixIjEZ599drBjectRg3Xr1g2cP39+NADExsY2TZo0qcHHx7uqk2fdG1xOTg5SU1N1xyAiL/WzTfuudcd2n188zqlL9l64cAHvv/9+0M0331zTcnlAQIB169atxwYNGmQtLy/3nTRpUtySJUuqMjMzS+fMmeN/+PDhIgB4++23g44dO9bvwIEDh5RSmD59+oh33323/+zZs+s2bNhwYsiQIZa6ujoZN25cwp133nlu6NChFnc8X51Y9AaXn5/Poicir9PY2OgTFxeXAACTJk2qffDBB79ueb/VapWHHnoocteuXf19fHxQUVHhV1paelmnvffee0GffPJJUEJCQgIA1NfX+xw+fLjf7Nmz637/+98P2bp16wAAOHXqVJ/CwsJ+Q4cO/eYKPL0ryqmiF5FZAJ4DYALwslJqdav7VwC4B0AzgEoA/66U+rLF/UEAigBsVkrd76LsRETkZs7uebua4xh9e/dnZWUNOnPmjO/BgwcP9e3bV0VERIxqaGi4bExdKYWHHnqo/OGHH77kjcLf/va3wI8//jgwLy/vcGBgoHXixImxjseLyMX1GhoaBF6u0wMNImIC8CKA2QASACwWkYRWq+0DkKyUGg3gLQBPt7r/twA+6XlcIiIioLq62jR48OALffv2VTk5OYFlZWV+ABAcHGz55ptvLnbb7Nmza1599dXB1dXVPgDwxRdf9Dl58qRvVVWVKTg42BIYGGjdt29fv/3791/leMzVV199Ye/evf0sFgveeecdrzm7vj3OnFEwEcAxpdRxpVQTgNcBzGu5glLqI6VUvf3mLgCRjvtEJAnAEAAfuCYydUVGRobuCERELnfPPfec3b9//1VmsznhlVdeuXrYsGHnAWDo0KGWpKSkupiYmMS0tLTI2267reb2228/O2HChDiz2Zxw6623XldVVWWaP39+dXNzswwfPjzx4YcfjhgzZszFIfvf/OY3J+fNmzdi/PjxcUOGDLngWP7xxx8HDBkyZPS2bdsGpqenXztixIhEHc+9q0Spjq+JICILAMxSSt1jv30XgEntDcGLyB8BnFJK/U5EfAB8COBOANNh2+u/7HEisgzAMgC45pprkr78ktMqu8qRI0cQGxurOwYRuZmI5Culkl2xrf37958YM2bM152vSZ5i//79g8eMGRPd1n0uPRlPRO4EkAxgin3RcgDblFKlLY95tKaUygaQDQDJycm8GpMLbdq0CatWrdIdg4i6YM32Yjy34+hlyx+cFoP0GWYNicibOVP0JwFEtbgdaV92CRGZDuBRAFOUUo32xZMB3CQiywH0B+AnInVKqZU9i01EZFzpM8xIn2HGwqxPAQBvpE3WnIi8mTNFvwdAjIgMg63gFwFY0nIFERkHIAu2If6L0+Qppe5osc7d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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "pe.plot_corrs([m_eff_f_P], plateau=[a[0], m_eff_plateau], xrange=[3.5, 19.5], prange=[start_se, stop_se], label=['Effective mass'])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fitting two exponentials" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also fit the data with two exponentials where the second term describes the cutoff effects imposed by the boundary." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "def func_2exp(a, x):\n", + " y = a[1] * anp.exp(-a[0] * x) + a[3] * anp.exp(-a[2] * x)\n", + " return y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can trigger the computation of $\\chi^2/\\chi^2_\\text{exp}$ with the kwarg `expected_chisquare` which takes into account correlations in the data and non-linearities in the fit function and should give a more reliable measure for goodness of fit than $\\chi^2/\\text{d.o.f.}$." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fit with 4 parameters\n", + "Method: Levenberg-Marquardt\n", + "`xtol` termination condition is satisfied.\n", + "chisquare/d.o.f.: 0.05399877210985092\n", + "chisquare/expected_chisquare: 0.7915235152326285\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fit result:\n", + "[Obs[0.2146(65)], Obs[15.15(88)], Obs[0.623(60)], Obs[-9.64(74)]]\n" + ] + } + ], + "source": [ + "# Specify fit range for double exponential fit\n", + "start_de = 2\n", + "stop_de = 21\n", + "\n", + "a = pe.fits.standard_fit(np.arange(start_de, stop_de), p_obs['f_P'][start_de:stop_de], func_2exp, initial_guess=[0.21, 14.0, 0.6, -10], resplot=True, expected_chisquare=True)\n", + "[o.gamma_method() for o in a]\n", + "print('Fit result:')\n", + "print(a)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fitting with x-errors" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We first generate pseudo data" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(Obs[0.16(35)], Obs[0.15(25)])\n", + "(Obs[2.21(35)], Obs[0.88(25)])\n", + "(Obs[3.72(35)], Obs[-1.70(25)])\n", + "(Obs[6.10(35)], Obs[-1.58(25)])\n", + "(Obs[7.55(35)], Obs[-0.18(25)])\n" + ] + } + ], + "source": [ + "ox = []\n", + "oy = []\n", + "for i in range(0,10,2):\n", + " ox.append(pe.pseudo_Obs(i + 0.35 * np.random.normal(), 0.35, str(i)))\n", + " oy.append(pe.pseudo_Obs(np.sin(i) + 0.25 * np.random.normal() - 0.2 * i + 0.17, 0.25, str(i)))\n", + "\n", + "[o.gamma_method() for o in ox + oy]\n", + "[print(o) for o in zip(ox, oy)];" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And choose a function to fit" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def func(a, x):\n", + " y = a[0] + a[1] * x + a[2] * anp.sin(x)\n", + " return y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can then fit this function to the data and get the fit parameter as Obs with the function `odr_fit` which uses orthogonal distance regression." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fit with 3 parameters\n", + "Method: ODR\n", + "Sum of squares convergence\n", + "Residual variance: 0.03576834451052203\n", + "Parameter 1 : Obs[0.02(40)]\n", + "Parameter 2 : Obs[-0.225(75)]\n", + "Parameter 3 : Obs[1.59(39)]\n" + ] + } + ], + "source": [ + "beta = pe.fits.odr_fit(ox, oy, func)\n", + "\n", + "pe.Obs.e_tag_global = 1 # Makes sure that the different samples with name length 1 are treated as ensembles and not as replica\n", + "\n", + "for i, item in enumerate(beta):\n", + " item.gamma_method()\n", + " print('Parameter', i + 1, ':', item)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For the visulization we determine the value of the fit function in a range of x values" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "x_t = np.arange(min(ox).value - 1, max(ox).value + 1, 0.01)\n", + "y_t = func([o.value for o in beta], x_t)\n", + "\n", + "plt.errorbar([e.value for e in ox], [e.value for e in oy], xerr=[e.dvalue for e in ox], yerr=[e.dvalue for e in oy], marker='D', lw=1, ls='none', zorder=10)\n", + "plt.plot(x_t, y_t, '--')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also take a look at how much the inidividual ensembles contribute to the uncetainty of the fit parameters" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Parameter 0\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Parameter 1\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAV0AAADsCAYAAADXaXXTAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAAg7UlEQVR4nO3deXyU1aH/8c+ZJQkQCAQUZXMAFwZZXECRqiDaFbF2sa2t1mrtr2mx1fbaOu3trWOt1dafXrcUEPdWq63V1jrW9mpcquwIksAEZF9lERgIBLLMuX9M7EUByUxm5szyfb9e86qBzPN8yyv55uQ85zmPsdYiIiLZ4XEdQESkmKh0RUSySKUrIpJFKl0RkSxS6YqIZJFKV0Qki1S6IiJZpNIVEckila6ISBapdEVEskilKyKSRSpdEZEsUumKiGSRSldEJItUuiIiWeRzHUCkPQKhiA/oAngB78Q9foY2+yzQCrQADZOnTtDm0JLzjDYxF5cCochRwMC21yAgAPQGugM92l7dga4Hvu8bu0rfPCru+dgBfxQHYsAOYHvb/+4AtgCrgBVtr5WTp07Ym6n/P+lkjPkBcDVggVrgSmvtPreppKNUupIVgVCkC3AqcFrbayRwPFCeyvEOUbrJeJdEAS8C5rW9Fk+eOqE1xeOlnTGmL/AGMNRa22iM+SPwgrX2EbfJpKM0vSAZEQhFBgIXAOcCo4ATyZ1rCMe0vQ4s7b3VVTULSRTwTODlyVMnbHWQ7UA+oJMxphnoDGx0nEfSQCNdSYtAKNILmECiaC8gMV2QMR0c6baHBRYA/wD+Cbw5eeqE5gye7yDGmGuBW4BG4J/W2q9l8/ySGSpdSVkgFOkDfBG4hMSo0WTr3Fko3Q9rAGqAp4G/TJ46YXcmT2aM6QH8GfgysBP4E/C0tfb3mTyvZJ5KV5LismgP5KB0D9QIPA/8AXhh8tQJ+9N9AmPMJcCnrLXfbPv468AYa+13030uyS7N6coRBUIRL3AhUAV8gtyZm3WlE4kfOpcAseqqmmeAByZPnTAjjedYC4wxxnQmUfLnk5hvljynka4cVtuo9uq2V3/HcT7A8Uj3cOYD9wJPpmP0a4y5icT0QguJ+eWrrbVpH1VLdql05SCBUOQM4MfAZ8nR34ZytHTftxWYDkyZPHXCetdhJLeodOXfAqHIucB/kVh9kNNyvHTf1wI8Afxi8tQJK1yHkdyg0hUCocgngJ8B57jO0l55UrrvawEeA26ePHXCasdZxDGVbhELhCJnA7cDY1xnSVaele77moGHgV9Onjphnesw4oZKtwgFQpHjgd8An3OdJVV5WrrvawLuJjHyzeh6X8k9Kt0iEghFupKYs70WKHEcp0PyvHTftxn4CfCIdkgrHsW+3rJoBEKRLwPLgB+R54VbQHoDDwFvVFfVjHAdRrJDI90CFwhFjgGmABc7jpJWBTLSPVAriSmHn02eOqHRdRjJHI10C1ggFLkCWEKBFW6B8gI/BOZXV9WMch1GMkcj3QIUCEX6AfcDn3adJVMKcKR7oBbgZuBXk6dOaHEdRtJLI90CEwhFJgJvU8CFWwR8wE3Am9VVNSe6DiPppdItEIFQxBcIRX4D/A2odJ1H0uIMYEF1Vc03XAeR9NH0QgFom054kg8+CaGgFfj0wqH8Frgu2xupS/pppJvn2m7hXUARFW6R+i5QU11Vc4zrINIxKt08FghFvgO8APRynUWy4mwSqxvOch1EUqfSzUOBUMQTCEXuJPErp9d1HsmqPsCr1VU1V7gOIqlR6eaZQCjSmcSzs37gOos4UwI8Ul1Vc4PrIJI8XUjLI4FQpDeJ1QmjXWdxrQgvpB3OncD12rshf2ikmycCoUhf4HVUuPJBPwQera6qycknfMjBVLp5IBCKDABeA7RQXg7lcuC56qqazq6DyJGpdHNcIBQJkCjcwY6jSG77NPDX6qqaUtdB5KOpdHNYIBQZTKJwA46jSH64AHi6uqrG7zqIHJ5KN0e1TSm8CgxwHEXyy4XAE9VVNVpKmKNUujkoEIpUAv8A+rnOInnpi8DD1VU1xnUQOZhKN8cEQpFOwPPAENdZJK9dTuLmGckxKt0cEghFvMBTgG7zlHSoqq6qud51CPkglW5umQpMch1CCsqvq6tq9DWVQ1S6OSIQivwHcLXrHFJwPCQurI10HUQSVLo5IBCKnAf82nUOKVjlJG6e6O06iKh0nWvbgPwptFuYZNYAEjdPlLgOUuxUuikwxnzKGLPUGLPcGBNK9TiBUKSUxI5hR6UvnchhnYl+o3JOpZskY4wXqCZx2+VQ4FJjzNAUD3cPiedgiWTLddVVNRNdhyhmKt3knQEst9autNY2kXg22WeTPUggFPkS8P/SHU6kHR6prqrp4zpEsVLpJq8vsO6Aj9e3/Vm7BUKRY4Ep6QwlkoRewO+rq2r0/e+A/tHdeBA9Jl3cOg/4iesQxUilm7wNQP8DPu7X9mftEghFvk1iPljEtXB1Vc0I1yGKjUo3eXOBE4wxA40xJcBXgOfa88a2rRrvyGQ4kST4gOmaZsgu/WMnyVrbAlxDYhewKPBHa+3idr79QaBLprKJpOAMEl/PkiV6MGWWBEKRK4BHXOcoFHowZVo1AEMnT52w7oifKR2mkW4WBEKRHsDtrnOIHEY5ibXnkgUq3ey4Gd11JrltUnVVzeddhygGKt0MC4Qiw4Aq1zlE2uF27c2QeSrdzLsLbWYj+WEQ8D3XIQqdSjeDAqHIBcD5rnOItFfJ/tjF0SHBHq5zFDKf6wAF7mbXAUTaw9Pa9M5Jy57ceezm2WcDPwJ+6jpTodKSsQwJhCITSTxgUjJAS8bSxLZuGrj6xRWBNX8fa7Dv/+a7BxgcrI9udhmtUGmkmwGBUMQAv3CdQ+SwrI0d++7MBSe+89QYb7zl7A/9bRcS+zJcl/1ghU9zuplxMXCa6xAiB7F2f4/t0dfOefOGeHDp4+O98Zayw3xmVXRIsP9h/k46QCPdzLjRdQCRD7A23mXPppkj6qYd12nftnHteEcp8H0S87uSRprTTbO2h0zWuM5R6DSn234l+3fOG143vWvF7tUnJfnW7UC/YH20MRO5ipVGuul3resAIgDeln3RYP1j+47e9vaoFA9RSWIXvYfTGKvoqXTTKBCKDAQmuc4hxc3EW9YOXvmX9f3Xv3KWAdPBw01GpZtWKt30ugZdnBRXbHxbvw2vLT5+xTNjPTY+IE1HPT06JHhmsD46O03HK3oq3TQJhCLlwDdd55AiZO3eXtvenjO0/rHTfa3723ORLFnXACrdNNGoLH0uBSpch5AiYm1Lt12r/zV25s92j1g8fbyvdX/XDJ3pkuiQoHbJSxONdNPnctcBpHiUNW6bNaJuWu/yPRvPycLpSoGrgVuzcK6CpyVjaRAIRQYAq+n4RQtpp2JdMuZr3rvo5CUPmZ47osOzfOq1wKBgfbQ1y+ctOBrppsfXUOFKBnnizStOfOeP2/psmnGmowgDgHFoDXqHqXTT4zLXAaRA2fi7gTX/eGfg6shYgx3sOM1FqHQ7TKXbQYFQ5BRgqOscUmCs3dV785y3hix78gxvvCkb87btMQltgtNhKt2O+5LrAFJArG3qvnPZzGFLHhxe0rxnvOs4HzIoOiQ4LFgfrXMdJJ+pdDtuousAUgCstZ33vjtjRN20AZ0bt2ZirW26XASodDtApdsBgVCkLzDCdQ7Jb/6mXW8Nr5veqfuulfmwGuMi4FeuQ+QzlW7HfNp1AMlfntb9S4P1v9/Te+tb+bT38hnRIcHeeqpE6lS6HaPSlaSZeOv6QaueWzNg3Utj07AhTbYZ4ELgQddB8pVKN0WBUMQPXOA6h+QRa7f33fiv2hOW/3mMx7b0cx2nAy5CpZsylW7qzgS6uQ4hecDaxp7b62YPXfLoqf7Wxly+SNZeF0SHBEuC9dEm10HykUo3dWNdB5AcZ21r14Z1M4bX3X982f4d413HSaPOwDDgLddB8pFKN3WubseUPFC6b/ucEXXTenZtWJ8rNzak2+modFOi0k3dGNcBJPd4WxrrTl7ycGuv7YvPcJ0lw/JpxUVOUemmIBCK9Af6uM4hucPEW1adsPzpzf02/qtYfhif7jpAvlLppqZYvrHkSGx8y4B1L9cPWvXcWI+ND3QdJ4uGR4cEfcH6aIvrIPlGpZuaQv/VUY7E2t1Hb5k/P7j08dHeeNO5ruM4UAacDLztOki+UemmJug6gDhibXNFbMWMYYsfGFravHu86ziOnY5KN2kq3dSc5DqAZJm1tlPj1lkj6qb26bJ3cyGstU2H04CHXIfINyrdJAVCkRKgmObuip6/qWHhsMUPlPSIvXOW6yw5JumLacaY7sADJNb5WuAqa+3MNOfKaSrd5A0GvK5DSOZ5WpveGbLsidgxm+eOcp0lRw1L4T13Ay9aa79ojCkhcaNFUVHpJu9E1wEkw2zrxoGrX1gZWPOPsQbrcR0nh5VHhwR7BOujO9rzycaYCuBc4BsA1tomoOhuJVbpJk/zuYXK2p19Ns14+4TlfzzTG2/ROuz26Qe0q3RJTMttBR42xowE5gPXWmv3ZCpcLtJP8eTl8+5QcijW7qvcvuTVc978MUOWPTHOG28pcx0pjyTz/eAjcfFtirX2VGAPEMpIqhymkW7yjnYdQNLE2nj5ng0zh9dNG9hp3/bxruPkqf5JfO56YL21dnbbx0+j0pV2UOkWgNL9O+cOr5vWvdvutfnwiJxcdmx7P9Fa+64xZp0x5iRr7VLgfGBJ5qLlJpVu8lS6eczbsm/J0OijTUe9t2i06ywFoleSn/894PG2lQsrgSvTHym3qXST19t1AEmeibesOX7Fsxv7bXh1TB4+IieXJVW61tqFQFEvwVPpJiEQiniBStc5JAk2vrX/+lejg1c+e5bHxo9zHacAJTvSLXoq3eR0Qys+8oO1e47atnBusP53p/ta9xfjhjTZotJNkko3OZ1cB5AjsLal265VM4cvfuCk0qbYeNdxikC56wD5RqWbHJVuDuvUuHXW8Nppvcv3birUR+TkIus6QL5R6SanxHUAOZivec/bwxY/6K3cuVSby2df3HWAfKPSTY42uskhntam5Se+89SOPu/O0vIvd1S6SVLpJkelmwP6sG3T2S3Pbzl65uJKf4tV4bql6YUkqXSTo/WdDnWjIXaX/7cLzvMsPNP04XN7LzF7XtrX9aXd9V1ah6ww/To1MVRrcLNOI90kqXST0+g6QDEqoXl/2PforK94a0Z4DOPf//PO1na5qHTXBa0jd7X+4ZzyOc/abjPGLDSt5yy2XbvtZbjR13c2qHSTpC/K5BTVFnSuGeLxa7x/mXmt75mAz8QP+4gcL3gv29Vw1mU08Nqwsrf/a3xl0579ntgnFxCdsDBe2nM3IwyUZjN7EVHpJkmlmxyVbpZ8wfP63Fv8D3YvM81JbUgzrnHfyHHrNrLU71954+hK+/THSkaUNdN83tv2rU++FefY7Qwz0DVTuYuQSjdJKt3kqHQzbKynbnG1/57mHqahQxfITmpuHvTkxs2Dtno9W3/Zs3Lxi6M6jfz7aF8PX4vd/7Eldu5n5sX3H7eZoR7d1t1RupCWJGOt/s2SEQhFmtEPq7Q70axbNd1/x+bjPFsysta20Zi99/aomPeHbl0DLcYMAPDEbevpy23thXPiu05czwle2/5tCuXfXgvWR8e7DpFPVLpJCoQiO4DurnMUit5s3zK15K6lp5jlZxmT+R9mcYg/1bV8zt2V3bvu8XhO/vdfWGtPXmuXTJpttw1fZY/zxwlkOkuBeDxYH73MdYh8ohFb8rah0u2wcvbuusM/ZcEnPPNHGUPWbtv1gOfS3Q1jLt3dwOudyhb9slflvk1e72iMMYuPMycvbtuHbNAmu3zS7PiG05fbY8qa9Vy8j7DBdYB8o5FukgKhyCvwf8uWJDl+Wpr+0/f7WV/3/s/JHmN7us4DsMzvX3Vjr8r1daUlozHmoOejHbPdrps0O75ybNRWdt7PMK0F/oDvB+uj97oOkU9UukkKhCK/B77mOkf+sfbb3udnXu/7Y3+/aU3muVpZs83r2XpLz8olL3fuNNwac8gLbJW77OZPz4svG1dnO1fsYaTWAvP5YH30Wdch8olKN0mBUOQ24AbXOfLJJM+M+b/2Ty/vbPbnxa/pjcbsre5RMe/xbl2PazHmsBuflzfanR9fYBefvzDuPyrGcFOcu9CdEayPznUdIp+odJMUCEWuAfTrVDuMNvXRKSV3NfYyu05znSUVcYj/qWv5nLsqu5c3eDzDPupzS5vsnnG1tvZT8+Pxvu9xsoGKbOV0rG+wPrrRdYh8otJNUiAU+RzwjOscuWyQ2bhmuv+OjYPMpjHGFMb85xudympv7lm5d6PPOxpjPvLpIb5W2zQmahdNnBtvHPguQU/hPl2hBSgN1kd1g0QSVLpJCoQiI4GFrnPkop7Etk0puWvxaLN0rDH4XefJhBV+3+qf9+q5dlHiotsRpxOMtfFTl9vaC+fYWHCdHey19M1GzixZF6yPDnAdIt+odJMUCEVKSdyZpm0e23ShseHX/unzJ3pmnWZMcdxi+57Hs+1XvSoX/0/nTsOsMe1ehRFca6OTZse3jFxl+/tbGZTJjFkwK1gfPct1iHyj0k1BIBSJAkNc53DNR0vzDb4nZ17l/XvQa+xRrvO4sM+YxindK+b9rqJr/2ZjAsm897jNduWk2fF1o5fZ3p2a8/Lr6aFgffSbrkPkG5VuCgKhyJ+AL7rO4Y61V3pfnPUT3xN9SkyrHmtO4qLb013L597Vo3vn3V7P8GTf33uHXX/hnPiKsUts9/J9DDf58dTpqmB9dJrrEPlGpZuCQCjyc+Am1zlc+IRn7oI7/VNKy82+oa6z5KoZZWW1N/fqsWe9z3fGkS66HUpFg936mXnx+vGLbOfuexhhyNn58dOC9dEFrkPkG5VuCopxBcNIs3zZ/SV37uptdo5ynSVfrPT71vy8V881b7fzotuhdN5nYxcstHUfXxD3Hr2TEQY6pztnihqBbsH6aIvrIPlGpZuCQCgyCFjhOkc2DDCb10/337HmRLP+LGPy4lfenLPd43nv1p49av/RpfMwa0zKy8dKmm3juXV20afmxVv6b2OY47XAM4L10aT2OpYElW6KAqHIRijcrQB7sGv7ff57a8d6Fo8xRk9dSIf9hn1TulfMfayiW79mYwZ25FjeVtt85lK7aOLc+N7BmxjisWT7QuZ/B+ujP8zyOQuCSjdFgVDkKeBLrnOkWyf2773F/+Dcz3neOMWYormrKqss2GfKu8y9s7J72S6vd0RHj2esjY9caRdPmm23B9fZwb44/dKR8wguDdZHn8zCeQqOSjdFgVBkMnCf6xzp4iHe+h++P82o8j53gtfYY1znKRazykrrftGrsmFdihfdDuXE9XbppNnxd09dYfuVtDI4Hcc8hMHB+ujKDB27oKl0UxQIRUYAb7vOkQ5f9b4060bfY0eXmpZ8X6yft1b5fWtu7FW5ZkFp6SiMSdvFsv5b7KqLZsfXnrHMHtWpiXStONkWrI8W5brsdFDppigQihjgPaCH6yypGu9ZuOge/32mm9mb9LpSyYwdHs/2W3v2qH2xS+eh1pi0FttRO+3GiXPjy89ebCu6NjLMpH5X5QvB+ujEdGYrJirdDgiEIn8BPus6R7JONquWTy+5c0cf816HHv4ombPfsG9a94q5j1Z069tkTNp/A6nYY7d9cn48et4iW1a5m5EGSpJ4uzYu7wCVbgcEQpFvAfe7ztFefdm66f6SO1cMNWvOMkZ7R+QDC/Yv5V3m3lHZvSyWhotuh9Jpn911/tu27uML4p5jdjDcQJcjvGVgsD66OhNZioFKtwMCoUhvYCM5fstmNxpi9/jvWzjOs+hMYzjocTSSH+aUlS6+qVflrrWJi24Z+aHpb7H7zl5sF316Xrz5uC0MNQdPn9UF66OajuoAlW4HBUKRGUBO7rRUStO+m3yPzv6S95WRHqOHaRaKNT7fuht7Va6cX1Y6CmOONCpNmSduW85YZmsnzonvPmEjJ3ksvYFbg/XRn2bqnMWg2J/vlA5/JcdK1xCPf8/77Izv+54d5DPxca7zSHod19LS/5F3t/Tf6fHsuK1nj3l/79I5GDfm6HSfJ+4xvllDzKmzhnjAWjt8ta07t84+E0z3iYqMRrodFAhFTgLqXed43yXeV+fe7Hu4e5lpPsF1FsmOJtg/vXvF3Icquh3b5DGZWpcLsB4YUHtFrUqjA1S6aZAL++t+zFNXd5//ntYepmGkyxzijgX71/Iu8+6o7F6y0+vNxNfB3bVX1F6XgeMWFU0vpMfvgFtcnPgks3bVdP8dWwZ4tp7p4vySOwyYixv2jL64YQ/zykqX3NSzMrban9aLbn9I03GKmka6aRAIRfoCa8jiI3yOYfvmqSX/vWykWXGWMfrhKYe21udbf2OvypXzykpPw5jyDhyqvvaKWk3npkFOL3XKF6tvm7gB+Gc2zlXO3l3T/Xe8NrP0mq6neFaco8KVjzKgpaXfw+9uOfeNtRtaLtrd8JrH2s0pHurRZD7ZGOM1xiwwxjyf4vkKlko3fR7K5MH9tDTd7HvotUWl32r+uHf+OGNyZjNryQMV8Xj3W7ZtHzd39boe392x842SuE1mP+gWkixd4FogmuR7ioJKN32eA7al/7DWVnmfm7Gk9Motl/teGucxtt1PnhX5sBIo+c7OXWfPW7Nu0K+2bpvXo7V1YTve9nztFbWb2nsOY0w/YCLwQKo5C5lKN01W3zaxicQFtbS5yPPm/CWlVy0L+Z8c6zet2dgjVYqEATOpYe+o19duOOWRjZujgabmGVh7uEfvJHur+13Aj4F4h0IWKM0Hpte9wPfp4AW1M0x0yZSSu/b3NLtPT08skcM7ff/+4N82bGKdz7c+3KtyxZyy0tMPuOhWD7zY3mMZYy4Etlhr5xtjxmcgbt7T6oU0C4QiTwJfTuW9g8zGNQ/4///GgebdMcZg0hxNpF1iHhO7vbLHwr+VdzkpbsxNtVfUTm3ve40xtwKXk5gHLgO6Ac9Yay/LUNy8o9JNs0AochowP5n39GLn1ikld0VHmWVnGZOzj9uWItMEG0JH9zr+zu+u2JfK+9tGutdbay9Ma7A8pzndNFt928S3gJfb87ldaGyo9t/92tzS73Ya7Vl2rgpXckkJTEu1cOXwNKebGbcD5x/uL320NId8f5h5lffFoMdYbUgjuaiBDj4D0Fr7KvBqOsIUEk0vZEggFJkPnPbBP7X2Ku+LM3/ie6Kv37Qe5ySYSPv8hnDsBtchCpFGupnzX0Dk/Q8+6Zmz4A7/1NJys2+sw0wi7bEDuM11iEKlkW4GBUKRf51q3jlqWsmdDUebmJZ/Sb74MeHY7a5DFCqNdDPoPv/d10/0zJ5hjC5YSt5YR2K9uWSIRrqZFq74M/B51zFE2ulKwrFHXIcoZBqBZd4NQLPrECLtUAs85jpEoVPpZlo4thy423UMkXa4nnBM+yVkmEo3O8LAascZRD7KE4RjWdkTutipdLMhHNsDfMd1DJHDeA+4znWIYqHSzZZw7EX0jCnJTdcTjm11HaJYqHSz6zpgu+sQIgeo0WqF7FLpZlM4tgX4kesYIm32Ad92HaLYqHSzLRx7CPib6xgiQKhtdY1kkUrXjSuBDa5DSFF7jnBMSxkdUOm6EI69B3wVaHUdRYrSehI/+MUBla4r4djrwC9dx5Ci0wpcSjimC7qOqHTduhl4zXUIKSo3EY694TpEMVPpuhSOtQJfA7a4jiJF4WXgFtchip1K17VwbAPwWRLLd0QyZSlwifZWcE+lmwvCsVkkLmxon03JhPeACwnHdrgOIird3BGOPUliYxyRdGoCPqf1uLlDm5jnmnDF74DLXMeQgnEF4Zj2yM0hGunmnqsBXV2WdLhFhZt7NNLNReGKCuAlYJTrKJK3qgnHrnEdQg6mkW4uCsdiwCeAhY6TSH66H/ie6xByaBrp5rJwRS/gFWCY6yiSNx4BriIc0zd2jlLp5rpwxdHAq0DQcRLJfY8DX9da3Nym6YVcl9iD93wSi9tFDucpEisVVLg5TqWbD8KxTcDHgFmuo0hOug/4attt5ZLjNL2QT8IVnYEngUmuo0hOsMBPCcducx1E2k+lm2/CFV5gCvAt11HEqWbgm4Rjv3MdRJKj0s1X4Yob0W3DxaoB+ALh2D9dB5HkqXTzWbjicmAa0Ml1FMmaVcDnCccWug4iqVHp5rtwxQjgz8DxrqNIxj0PXE44ttN1EEmdVi/ku3BsEYnbhZ9zHUUyJg78DLhIhZv/NNItFOEKA9xA4rlrXsdpJH22kXim2Uuug0h6qHQLTbjiPBK3gg5wnEQ67nXgMsKxda6DSPpoeqHQhGOvAMOBB1xHkZTtB64HzlPhFh6NdAtZuOJTwHSgn+so0m5zgCsJx5a4DiKZoZFuIQvHXiSxQ9lDrqPIETWSGN2OVeEWNo10i0W44uPAvcBJrqPIQf4G/FDPMSsOKt1iEq7wA9cCPwe6Ok4jUAf8QCsTiotKtxiFK3oDN5F4HpuWl2XfNhI/+O7XzmDFR6VbzMIVJwO3ol3LsqWRxGZFN+smh+Kl0hUIV5wC/CfweXRxNRMaSJTtHYRjm12HEbdUuvJ/whVB4KfApWjaIR12AvcAdxOObXecRXKESlcOFq4YDPwIuAzo4jhNPloPVAO/JRzb5TqM5BaVrhxeuKIr8DXg28ApbsPkvDjwAonHn7+gC2RyOCpdaZ9wxWgS5fsVNPo90AbgQeAB3bIr7aHSleSEK7oBFwFfAD5JcW6gvgX4K4l9jF/SqFaSodKV1IUrugCfIVHAn6Gwb7hYBzxLomjf0KPOJVUqXUmPcEUpMAEY3/Y6DfA5TNRRDcAbwGvAy8A8wjF9s0iHqXQlM8IV5cDZwDgSJXwqUOoy0hHsBGaQKNlXgbcIx1pcBpLCpNKV7AhX+IATSOz1e+BrIGCymKQJiAK1ba86oFYXwSRbVLriVmJeuD/Q9xCvY0islOh0wKszUHbAEZpJFOleElMCDSRGrRsOeG084L/XaQQrLql0Jf8kngfnIxxrdh1FJFkqXRGRLNLmJiIiWaTSFRHJIpWuiEgWqXSlYBhj+htjXjHGLDHGLDbGXOs6k8iH6UKaFAxjzLHAsdbat4wxXYH5wMXWWj1dV3KGRrpSMKy1m6y1b7X9924SN0H0dZtK5INUulKQjDEBErcez3YcReQDVLpScIwx5SR2A7vOWqsnN0hOUelKQTHG+EkU7uPW2mdc5xH5MF1Ik4JhjDHAo8B2a+11juOIHJJKVwqGMeZs4F8kdg97f5Pxn1prX3CXSuSDVLoiIlmkOV0RkSxS6YqIZJFKV0Qki1S6IiJZpNIVEckila6ISBapdEVEskilKyKSRf8LI+xRzJoJNcoAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Parameter 2\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "for i, item in enumerate(beta):\n", + " print('Parameter', i)\n", + " item.plot_piechart()\n", + " print()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fitting with priors" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When extracting energy levels and matrix elements from correlation functions one is interested in using as much data is possible in order to decrease the final error estimate and also have better control over systematic effects from higher states. This can in principle be achieved by fitting a tower of exponentials to the data. However, in practice it can be very difficult to fit a function with 6 or more parameters to noisy data. One way around this is to cnostrain the fit parameters with Bayesian priors. The principle idea is that any parameter which is determined by the data is almost independent of the priors while the additional parameters which would let a standard fit collapse are essentially constrained by the priors." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We first generate fake data as a tower of three exponentials with noise which increases with temporal separation." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "m1 = 0.18\n", + "m2 = 0.5\n", + "m3 = 0.8\n", + "\n", + "A1 = 180\n", + "A2 = 300\n", + "A3 = 500\n", + "\n", + "px = []\n", + "py = []\n", + "for i in range(40):\n", + " px.append(i)\n", + " val = (A1 * np.exp(-m1 * i) + A2 * np.exp(-m2 * i) + A3 * np.exp(-m3 * i))\n", + " err = 0.03 * np.sqrt(i + 1)\n", + " tmp = pe.pseudo_Obs(val * (1 + err * np.random.normal()), val * err, 'e1')\n", + " py.append(tmp)\n", + " \n", + "[o.gamma_method() for o in py];\n", + "\n", + "pe.plot_corrs([py], logscale=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As fit function we choose the sum of three exponentials" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "def func_3exp(a, x):\n", + " y = a[1] * anp.exp(-a[0] * x) + a[3] * anp.exp(-a[2] * x) + a[5] * anp.exp(-a[4] * x)\n", + " return y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can specify the priors in a string format or alternatively input `Obs` from a previous analysis. It is important to choose the priors wide enough, otherwise they can influence the final result." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "priors = ['0.2(4)', '200(500)', \n", + " '0.6(1.2)', '300(550)',\n", + " '0.9(1.8)', '400(700)']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It is important to chose a sufficiently large value of `Obs.e_tag_global`, as every prior is given an ensemble id." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "pe.Obs.e_tag_global = 5" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The fit can then be performed by calling `prior_fit` which in comparison to the standard fit requires the priors as additional input." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fit with 6 parameters\n", + "Method: migrad\n", + "chisquare/d.o.f.: 1.0925587749193326\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[Obs[0.1861(27)], Obs[210(12)], Obs[0.701(60)], Obs[321(433)], Obs[0.711(51)], Obs[435(433)]]\n" + ] + } + ], + "source": [ + "beta_p = pe.fits.prior_fit(px, py, func_3exp, priors, resplot=True)\n", + "[o.gamma_method() for o in beta_p]\n", + "print(beta_p)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now observe how far the individual fit parameters are constrained by the data or the priors" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAV0AAADsCAYAAADXaXXTAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAAhnklEQVR4nO3deZwU5b3v8c8zwwz7oigKuLQi2pW4Ytgx7snNHa4nOTHBaEzMYuLJOSceJUc70RONR3RER4254BqXiBqMJuZKn6AsMsCwi7JWIyjDvsvqLN3T/dw/qjFkYJburq6nqvv3fr3mJUJP1Vcy880z1VW/R2mtEUII4Y0S0wGEEKKYSOkKIYSHpHSFEMJDUrpCCOEhKV0hhPCQlK4QQnhISlcUNKXUi0qp9UqpD9MfF5rOJIpbB9MBhPDAf2qt3zAdQgiQla4oEEqpkFIqppR6RSllK6XeUEp1MZ1LiOakdEUhOQeYqLW2gAPAz9K/P04ptVwp9ZhSqqO5eEJI6YrCsklrXZP+9SRgFPBLIAwMBo4H7jSUTQhASlcUluaDRLTWept2NAIvAEMM5BLic1K6opCcppQanv719cBcpVRfAKWUAr4OrDSUTQgAlEwZE4VAKRUCpgJLgIuB1cCNwBTgREABHwK3aK0PmUkphJSuKBDp0p2itT7XdBYhWiOXF4TwAaXUE0opWYEXAXk4QhQErXUtEMhVrlLqS8BxpnMIb8hKVwgPtPTwhlKqFHgYuMN0RuENuaYrhAfS15zXA6O01jVKqedx3uxLACVa68eUUoe01t1M5hT5J5cXhPBO84c3IkAX4DJjiYTnpHSFb4Qi0eOBM4ATgN44T5D1PuKjJ1AOlAKls+meKEGV4qwWG/fHd6+fuuX3nYB9R3xsAz4GPhk7ecpnXv73HEPzHysHA43AOuc2YroopdZprc/yPJnwjFxeEJ4KRaLlwBdw5iScDQw84p/HZ3KsOXRvUKhOh//9UGLfgujmp4e18inbcQr4yI+1wPKxk6c0ZHLuTB1xeWGE1nq+Uuo5wNZaVx3xGrm8UARkpSvyKhSJ9geGpz+GAYOATq1+UpaadCLZxktOTn+MbPb78aoxoz8AaoB5QM3YyVO25yHiGuBfj7ie+2QeziF8Tla6wlWhSPQkYDTwFWAEcEq+ztV8pbu7YcvsGdsmfdmlw6/HKeB5wLSxk6eszeVg8vCGOExWuiJnoUj0QuD/4JTtYJxHbj2XSDW6uYI4I/1xA0DVmNErgTeBP4+dPGW5i+cRRUZWuiIroUh0KM5sg2uAU01kaL7S3XBo9awFu96+zINTrwX+jFPAizw4nyggUrqi3dKXDr4H3ITzZphRzUt37YGl1Uv3TLvU4xibgNeBZ8ZOnvKRx+cWASSlK1oVikTLgArgh8DX8NElqealu3rfvDkr9s65xGCk94CncVbACYM5hI/55htI+EsoEu0O/AS4DehvOE67xJMNpYYjXJ7+2F41ZvRE4Mmxk6fsNpxJ+IysdMU/CEWifYBbcfYX62U2Teuar3QX7oouqj200k87QzTgPHn26NjJU2zTYYQ/SOkKAEKR6JnAL4AfkKf7aN3WvHTn7Hhz2da6dReYzNSCFPAy8Ouxk6dsNB1GmCWlW+TSK9vfAD8mYJebmpfuzK2v2LsaN1smM7WhEXgKGDd28pRdpsMIM6R0i1QoEu0E3I6zO24Pw3Gy0rx0p25+fv3+xK4zTGZqp4PAo0DV2MlTDpoOI7wlpVtkQpGowrnh/wEM3V/rlual+/bGidvqkgf7msyUoV3AOGCi3O1QPGSIeREJRaJDgEU41xcDXbjHktDxrqYzZOhE4HFgadWY0YMNZxEekZVuEQhFol1xVrb/RgH9H23zle7r68cnNdr0bWPZSuIU8H+NnTyl3nAWkUcF8w0oji0UiV4NrAJ+TgH/7621bghw4YIzI3gssLxqzGivn6oTHpKVboEKRaLdcPbeusV0lnw5cqWrtd79eu34E0xncokGngHuGDt5ygHTYYS7CnblU8xCkegwYDkFXLjNaVKF9CO5An4KrKoaM/pqz06q1O+VUsuUUsvTG2fKQPU8kNItMKFI9OfAbJyxhEUjpVN53fnBkFOAqVVjRt9dNWa0F+Myb9NaX6C1Ph/YiPMegHCZlG6BCEWi3UOR6GTgt0CZ6TxeS+lko+kMeVIC/DfwVtWY0T3dOGBL28FrrQ+k/1wBnTl6TzfhAindAhCKRL8ILAa+bTqLKUndVKile9g1wOKqMaPd2nniHGCi1toCDuDM2kAp9QLOXnJh4HcunUscQUo34EKR6PXAQpxvoqKV1IlieLhgILCwaszo77hwrObbwY8C0Fr/AOgH2MAYF84jmpHSDbBQJHoP8AoQtIcCXNeOTSkLRRfg1aoxox+vGjM6l1kZzS8dfP7vWusk8EfgmzkcX7RASjeAQpFoaSgSfQa413QWv0ik4sVSuofdCrxdNWZ0lyw//zSl1PD0r68H5iqlzoLPr+leA8Ryjymak9INmFAk2gV4C7jZcBRfSaQaU6YzGPC/gJlVY0b3zuJzD28HbwPH4WwH/5JSagWwAugL3OdaUvG5QI3yK3ahSPREYArgp0HdvpBINRjZgdgHhgJzH/3O9Vff/tqrmzP4vCat9Xeb/d5IF3OJFshKNyBCkehpQA1SuMcUTzUWa+mC6lxX3uOmmRNumXmW6SiibVK6ARCKRPvjbHo40HQWv4onG4rza1mVr+zY80dnK9VhIDBnwi0zw219ita6Vmvt1q1nIkPF+YUaIKFI9GRgJnCm6Sx+Fk/VB3nYTZY6rO3Y40enKFV++HHdk4H3Jtwys6hvH/Q7KV0fC0WiJwDTgbNNZ/G7eKqhyN6fKNnQsecPe6qSzr2a/cHJwMwJt8wcYCCUaAcpXZ8KRaLH4xTuF01nCYJ4sr7cdAbvqG3lPW4qVSXd+rTwgn7A9Am3zOzvZSrRPlK6PhSKRLsD7wB+3NnWl+Kpxo6mM3hkT3n379aXlPY6pdVXaX1qqPZvj9lhq5c3sUR7Sen6TCgSLQFeA75kOkuQJFINxVC6B8q7j9lZ0uHE1q/va9149trJi8+snfIt4C07bBXD301gSOn6zyNAhekQQRNPNXY2nSHP6su6fX19SYf+rW8xr/XB81Y9s/qUrXOGpX/nUuAlO2wV7y11PlNkbz74WygSvRm4zXSOIGpKNRby/IlEWZevrSotO7P1n350ategDx7b3evAJxc1+5MxwBac7YCEYbLS9YlQJHo5MMF0jqAK4E7A7ZXq0PmyJaUdrVYLV6WSm4Yuvr+u14FPWloJ326HrevzkE9kSErXB0KR6EDgDYpw+LgbtNb1FOjXcmmnoTUdOg0a3tprSpLxtcMX/Lq8a92O09s43NN22JLbDw0ryC/UIAlFop1xBtgcbzhKgOlDphPkQ2n5edVlnUde0tprOiQ+Wz5y/q/6dIrvO6kdh+wGvG6HrU5tvlLkjZSueY8BXzAdIsg0upA2pQSgpGxAdVnXq1vdir1jw6eLRs6/a2BZU30m2/hcADyeUziREyldg0KR6Ddwdn0VOSi0TSlVh/7V5d3+qdXC7XZo89zhC+8ZVJpKZHPXxk/tsHVdlvFEjqR0DQlFoqcCvzedoxAU0qaUqqR3TXm3b3+5tdcc/+nq6sFLHhxZolO53H30jB22ZICSAVK6BqQfgJiEMzxa5KhQNqVUJT0Wlve4cVh654Zj6ru1pvrC5RMuVZDrfbfdca7vyoMTHpPSNeMuoNXVjGi/Jp1oMp0hZ6rz0vIeN12oVMmxp6VpnTxj/ZS51kevtnrZIUMXAlUuHk+0g5Sux0KR6LnAr03nKCTJVMA3pfz7TNxjrzq1rg+vmfT+GRv+NioPZ/+ZHbaG5uG4ogVSuh4KRaIKeAp5EtBVCd0Y4NI9aibuP9J6//krnvyo3/YF+doxRAET7bBVhPOIzZDS9daPkH2oXBfcTSlbnInr0KkdX1r68I4TPl2V72lzg4B/yfM5RJqUrkfSA8kfMp2jEAVzf7TWZ+KqVNOGYYvui/c4uMGrJ8jut8NWex6wEDmS0vXOI8hTZ3mRSAZuJ+BWZ+KWJBtjI+bf3aVL/a5TPczUE3jYw/MVLSldD4Qi0UuB75vOUajiqUBtStnqTNyy+KEPR837Vb+OiYMneh0MuNEOW3JXTZ4F6Ys1kNJvnj1mOkchawzOppStzsTtVL97wcj5d1kdkg09vA52hAl22JI3evNISjf/rgWazzcVLoqnGoIwne3wTNxjvinW/cCGOcMX3ju4RDeZfljhXOBWwxkKmpRuC5RS45RSm5RSWU+wCkWipcB9LsYSxxBPNvh9U8pWZ+KesHt59eCl4y9RaL+s2H9ph61CnU9snJRuy94Gcr038kYg7EIW0YpEyt+l2+JMXK11/82zqs9f+bSbT5m5oTdwi+kQhUpKF1BKfVcptUgp9aFS6mmlVKnWeoHWelu2xwxFouXAPS7GFC2Ipxp8Ox+2xZm4WicGfPLWvHPW/clvhXvYWJnLkB9FX7pKKQtnD6mRWusLgSRwgwuHvhkIuXAc0YZEqrGL6QzH0uJMXK3rvmC/uOz0TdP9/KBMX+AHpkMUoqIvXeBK4GJgsVLqw/S/t77FdRvSq9y7co8m2iORivuudFuciav13guX/e6Tk3cuaX2TSX+4U+5kcJ/8hTrPnr+ktf6li8e8AWelIPJMa62btL9Kt8WZuDq5bfD74+u6H9p8roFY2QgB1wN/MJyjoMhKF2YA1yql+gAopY5XSrW1wV9bZBt179Tho6/jlmbiqlRi/fCFv0l1P7R5gKlsWYrYYStoT/z5mm++WE3RWq8G7gbeVUotB6YBfZVS45VSm4EuSqnNSql723O8UCR6FXBe3gKLZnSd6QSfa2EmbmlTw+qR8+/u0blhT39T0XJgAf9sOkQhkcsLgNZ6MjC52W8vAO7I4nD/nnsi0V6+2ZSyhZm45fED7w9beO85HZKNxx7dGAx3Am+aDlEoin6l66ZQJHo6MNp0jmLij00pjz0Tt3Pdjnkj5t99XsALF2CwHbZkx2qXSOm66xbk79RTKd1kuHSPPRO35/6PZw9b9N/DSnTS1w9uZOB7pgMUCikIl6Q3m5RJYh5L6qa4ubMfeyZun53vV1/8waNfVuhC+v66wQ5bhfTfY4z8JbrnUuQ2Mc816SZTm1IePRNX69RpG6fNPnf18359yiwXpwCXmQ5RCKR03fMd0wGKUVMqbqJ0j56Jq3V84Lo3Fp71yVuFPI9WLjG4QErXBaFItAz4pukcxSiRinu9KeXRM3G1PnTu6t+vPHXLrKOH2hSWb9phy1cPogSRlK47vopsxWNEQnv6PtrRM3F1as9FHz6+sc+uDwZ5GcSQbsA3TIcIOildd8ilBUMSyUavTnXUTFyVSm4esuTBA8ftX1dMt1PdaDpA0Enp5igUiXYG/sl0jmIVT3mzKWXzmbglyfi64QvvKe322dYzvDi/j1xlhy0T+7cVDCnd3F0KyJR9Q7zYlLL5TNwOiboVI+ffdUKnxr3FeLdKKXC56RBBJqWbu6tNByhm8VR9Xh9lbz4Tt2PjvsUj5981oKyprlc+z+tzV5oOEGQyeyF3V5kOUMziyYa8fQ03n4nb9bOtNYOXPDi0RKeK/fvmCtMBgkxWujkIRaInIRPFjIrnaX+05jNxe+1dUz1k8bgRUrgAnGWHrVNNhwgqKd3cXIkzBF0YEk81uL6PV/OZuCdvX1A9aNkTlyr53/pIstrNkpRubuR6rmHxVGNnVw945ExcrZOh2v+Z84XYy4X4WG+u5LpuluRHpdzIF55hCTdL98iZuFo3nPPRa8v6b6s5eidfAXIHQ9ZkpZul9PVcua5lWJNrOwEfMRNX6wPnrXw61n9bzVB3jl2QTrHD1tmmQwSRlG72LjIdoOhpUk064ULpHjETV6d2XfxB1bYT96y4MPfjFjxZ7WZBLi9kT0rXvDogx9L9+0xclWraOGTxA7pr/Y5zXElX+C5o+yWiOSnd7BXDgBNfS+W+P9rhmbhnliQb1wxf+JvjOsb392n700Ra2HSAIJLSzZ6sdA3TOpVL6R6eiWt1SHy2bPiCe0JlyfqeroUrDlK6WZBrulkIRaI9gDPbfKHIqyRZjxj7fCZux4ZPF42c/6tzpHCz0tcOWz1MhwgaKd3snI/cKG9cUmdVup/PxO12cNPcEQt+fXFpqqmT6+GKh6x2MySlm50BpgMISKYSiQw/5fOZuMfvWVU95P3KUQpdmpdwxcNq+yXiSHJNNzunmw4goEknMtofrbTT0JoOHS8a1W/r3OrwR6/JU2bukJVuhqR0s3Oa6QACmlLxVHtfW1p+XnVZpxEjz1z/dk1o4ztSuO6R0s2QlG52pHR9IJ5qbNemlCVlA6rLulw1xFozaWnf7QtG5TtXkZHSzZCUbnakdH0gkWp7U0rVoX91eddrLrhg+YS1vffaQzyIVWxCpgMEjbyRlh2ZueAD8VRjq3eQqJLeNeVdrz37S0vH7+q91z7fq1xFppMdtvIy07hQSelmKBSJ9ibnR0+FGxKtbEqpSnos7NjtupOHL74v2ePgxoFe5ipCco9zBuTyQuaOMx1AOBqT9cdeNKjOSzt3GdN5xIJ7epYnDp7gcaxi1APYZTpEUEjpZk52/vWJeKq+7KjfVOUru3f6Znz4gnsGdkg2djcQqxjJSjcDUrqZk9L1iXiqoVnpdlh7XOnXdg9dOG54iW5yfRsf0SIp3QxI6Waum+kAwvGPm1KWbDgpNax20PuPXanQ8l6Ft6R0MyClmzlZ6fpEIlmfLl217bS6gWvOXfvSV8wmKlpSuhmQ0s2crHR9IuFs1bNn4Ke9Vg3c9D9SuOZI6WZASjdzstL1iYRONJ27Nbn6tF1LrjKdpcjJeMcMSOmKQOrYFK87/+Mtu08+sE926zVPxpxmQEo3c9kOzhYu6Zqo3//iuw9s6Jaol8d6/SFuOkCQSOlmru0H/kXe9Go4uPuFaQ/u7pSMy2O9/iGlmwEp3czJSteQPnWfbnt2+kP15amkTLbyFyndDEjpZk5K14BTDu7Y8OTMqpIOOiV70/mPfE9kQEo3c/IF5rGz9m366LeznuhZgj7JdBZxTAdNBwgSKd3MSel66Nzd61Y9NPepviVwvOksokX7TQcIEindzO01HaBYDNm+8oN7F7w4QMl9oH53wHSAIJHSzdw20wGKwRUbFy/8xdLJ5yvobDqLaJOsdDMgg0EyVFtZsQe5xJBX13w8u+YXSycPksINDPnpLwNSutmR1W6e3BD72+xbVvy/YQqOnpUr/KgB+X7IiJRuduSLLA/+Zfkb7303NuMSBaWms4h2W2/FbG06RJDINd3sbDUdoNDcueSlmZdtXnGF6RwiY+tMBwgaKd3sSOm6R98/78lZF+/8WAo3mKR0MySlm531pgMUAqWTyUdnPzE3vHfL5aaziKxJ6WZISjc7tukAQVeSaoo/NfORRace2n2p6SwiJ1K6GZLSzY6Ubg7KkvG656ZXruhTf2CU6SwiZ1K6GZLSzc5G4BCydU/GOjXVH3hh2oPrejXWDTWdReQsAWwwHSJo5JaxLNRWVmhghekcQdMtfmjPpKn3b+jVWDfIdBbhig1WzE6aDhE0UrrZ+9B0gCA5rmHvtpffuX9X16bG80xnEa5ZZjpAEMnlhex9aDpAUJz02c4Nz86oSpbJ8PFCM9t0gCCS0s3eItMBguC0g1vWTZz5eKdSrU83nUW4bo7pAEEklxeytxwZ9NGqgfvWr3pyxuM9SrU+xXQW4br9yOWFrEjpZqm2siKF/HjVovN3r/7gt7Mm9CtB9zGdReRFjRWzU6ZDBJGUbm5mmQ7gR8O3L11YOff5sxQcZzqLyBtZcGRJrunm5j3TAfzmqk01Nbe//xeZhVv45HpulqR0c7Mc+BTZvwuAb3w8rfrmFe+MkFm4Ba8eWGw6RFDJ5YUcpB+SqDadww++b/91xs0r3rlECrcoLLBidsJ0iKCS0s3dO6YDmPbvy1+Zdt2aOVco+XoqFjNNBwgy+SbJ3V+AYn0UUt+1+Nnp//uTD64GlOkwwjOTTQcIMindHNVWVuykKN/J1akH5/1u5qgta64ynUR46n0rZq81HSLIpHTd8SfTAbykdFPiiepHZl+4c8OVprMIz71mOkDQSem6489AUdwoXpKK1z8746GFA/fuuMx0FuE5jVxayJmUrgtqKyt2UAT3LZYnGw6+NO2BZf0P7ZXh48VpjhWzN5sOEXRSuu4p6EsMnZs+2/OHd+5fe0L9oWGmswhj5NKCC6R03fNHoMF0iHzonti/fdLU+7f2jDfI8PHi1QS8YTpEIZDSdUltZcUeCnC1e1zj7o0vT31gf5emhAwfL27TrJi923SIQiCl666JpgO46eT6beteemd8smMyeY7pLMK4l00HKBRSui6qraxYACw1ncMNpx/cYD/37qOdy1KpM0xnEcZtpAB/ijNFStd9T5oOkKtz9q1ZNnHG73qXat3fdBbhC49bMbvJdIhCIaXrvleBfaZDZOui3csWPzbr2dNLQIaPC3C+lp81HaKQSOm6rLayog54wXSObIzavrBm3NyXLQW9TGcRvvGkFbMPmQ5RSKR08+MRAnb72Fc3vVf9qwV/ulhBN9NZhG80Ar81HaLQSOnmQW1lxVYC9CPZtz6eMuPW96MjFHQynUX4yh+smL3DdIhCI6WbPw8SgNXuj+zX3/3BilmXy/Bx0UwK5yc24TIp3TyprazYBjxjOkdr/mPZi+9eu2bRV2T4uDiGv1ox+yPTIQqRfLPlVyW+XO2mUr9ePHHaV9ev/IrpJMKXUsB9pkMUKindPEqvdp82neMfpZrG1zw+c/iWT642nUT41rNWzP7QdIhCJaWbf/cDe02HAFA60fB/qx+ac96urbLbg2jJXuAu0yEKmZRuntVWVuwG/st0jlLdeOi5GQ8uHrB3z+Wmswhfu8eK2XtMhyhkUrreeAr40NTJy1OfffrSu+NW9Tt04BJTGUQgrKTAhjb5kZSuB2orK5LAv+Jsd+Kpzk0Hd7w89YENvevrhnp9bhE4t1oxu1h3tvaMlK5Haisr5uHxeLzuiU83T5o6bmePeONFXp5XBNKbVsyeaTpEMZDS9dYdwH4vTtS7cdsnL099qK5LU5MMHxdtqQfGmg5RLKR0PZTewPI/832efvWbYi+882hJx2Ty7HyfSxSEcVbM3mA6RLGQ0vVYbWXFs8Db+Tr+mQfXLn/m3Sd6lKV0KF/nEAVlDs5DPMIjUrpm/BjY6fZBv7hvxeLfzXi6b6nW/dw+tihIe4Eb5M0zb0npGlBbWbETp3hdM3j3onkPz3ppYAmc6OZxRUG72YrZm0yHKDZSuobUVla8jUvjHy/bPqv6N3NfP1+Gj4sMPGvF7DdNhyhGUrpm3Qasy+UAFZv+NuOOBVOGyvBxkQEb+A/TIYqV0trz+/XFEUKR6AXAPKBLpp973Sdvvvu95fOvUNDB/WSiQDUCQ62Yvcx0kGIlK13DaisrlgE3Zfp5P7EnTf3e8vlXSeGKDN0phWuWrHR9IhSJjgN+1fYrdeoXy55558r1a7+W91Ci0Ey2YvZ1pkMUO1np+sfdtHn/bqrpN4ufmC6FK7JQDXzfdAghK11fCUWiPYAFgHXUH+pEY9W8x2Z/YddOGT4uMrUaGGnF7H2mgwgpXd8JRaIDgflA78O/p2j8bMKshxedsW+fzMIVmdoKDLdi9kbTQYRDSteHQpHoEGAG0K1U1+99bkblqpMPfTbKdC4ROAeBS+SNM3+R0vWpUCR6dcfUgReenzZ+8/H1DTILV2QqAVRYMXua6SDiH0np+tjMIYMq+h6ofwu5LUxk7vtWzP6D6RDiaFK6PmeHreuASUCp6SwiMO6wYvbDpkOIY5NbxnzOitl/BH4IpExnEb6ncbbckcL1MSldDyml7lFKNSiltFLqL0qp8vZ8XvrHxJuR4hUtSwE/tWL2E6aDiNZJ6XprJM7OERtwtu35UXs/0YrZzwP/DNTlJ5oIsCaca7iuTK0T+SWlmwdKqVFKqUal1Pr0PzcrpU4ABgFPpl/2R+DrmRzXitl/BS4nDwPQRWDVAV+3YvYk00FE+0jp5k858JDWuiPON8YLwD6tdVP6z7cC/TM9qBWzFwHDgJhbQUVg7QGusGJ21HQQ0X5SuvmT1Fo/lf71U8Bgtw5sxez1wAhgtlvHFIFTi/No70LTQURmpHS9kwJ6KaUO33PbD9iS7cGsmL0XuBp41YVsIlim48zEXZPrgZRSryil1iilViqlnldKlbmQT7RCSjd/SpVSN6d//RNgCfAecG36964D/prLCayYHQe+CzyQy3FEYKSA+4CvWjHbrev6rwBh4DygMy7v3SeOJg9H5IFSahTO7IQtONdtdwPnAz8HfgmUAQ3Aa1rrH7pxTjtsXQs8AxznxvGE7+zG2bn33Ww+WSkVAqYC7+O8obsK+J7Wuu6I19wGnKC1viv3uKIlUrp5kC7d6VrrTl6e1w5bpwAvA5d5eV6RdzXAdVbM3pztAdKlux4YpbWuUUo9D6zWWj+S/vMyYCFwq9Z6jguZRQvk8kIBSX9TXgnciTPwRARfFXBZLoV7hE1a65r0rycBR06umwjMlsLNPxmkkgda67mAp6vcw6yYnQLG22FrOs6bbOeYyCFytg/4gRWz33LxmM1/rNXgPCkJnAj81MVziRbISrdAWTF7Kc61u6dNZxEZ+yNguVy4AKcppYanf309MFcp9WPgq8B3tNbymLkH5JpuEbDD1jU4T8L1M51FtGot8DMrZk93+8BHvJG2BLgYZwufG4EDOI+lH0y/9M9a6/vcPr/4OyndImGHra5ABPgFhi59iBY1ApXAg1bMbszHCdKlO0VrfW4+ji/aT0q3yNhh63RgPPBt01kE4Dzo8DMrZq/N50mkdP1DSrdI2WFrFPA4zo+awnvbgdutmP2a6SDCW/JGWpGyYvZcnHkQPwS2GY5TTLYBtwMDpHCLk6x0BXbY6gbcBvwb0MdwnEK1GXgIeM6K2Q2mwwhzpHTF5+yw1QnnHe3bcZ7HF7mrBR4EXkzPyhBFTkpXHMUOWwqoAMYijxRnax3OIKKXrZjd1NaLRfGQ0hWtssPWxTjl+y3kCca2xIEo8CIQtWJ20mwc4UdSuqJd7LB1GnATzq1mXzSbxneW4hTtq1bM3mM4i/A5KV2RMTtsfREYk/4423AcU3bgzKJ90YrZK0yHEcEhpStyYoetC3DK99vAAMNx8m0TMA34CzBVrtWKbEjpCtekr/9W4Gw1PxzobjZRzvbj7PYxDZhuxeyPDOcRBUBKV+SFHbZKcXbLGIkzt3UUWex+7LFGYAHOo7nTgCXyZphwm5Su8IwdtkI4JTwUOAs4EwgBHT2O0giswZm0tSr9z9XAOrlkIPJNSlcYlb4nuB9OAZ8JnHHEr/vgXKLoBnQFVBuHqwP2NvvYl/7nDsDGKdePZQUrTJHSFYGQLueuOKviDumPMqAUZxbsPnniSwSBlK4QQnhIpowJIYSHpHSFEMJDUrpCCOEhKV0hhPCQlK4QQnhISlcIITwkpSuEEB6S0hVCCA9J6QohhIekdIUQwkNSukII4SEpXSGE8JCUrhBCeEhKVwghPCSlK4QQHpLSFUIID/1/RmV009uglasAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAV0AAADsCAYAAADXaXXTAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAAYxklEQVR4nO3de7RcdX338fcvN4GonCCXJo4IBQoqRYoCchlIRwk8tVZdtV7w0oeiMHWepz4qPh20Xb15mbpa8fIMjlUUW2ltxdYL2GpgN2FIQEBAQJJgJGAGCJcAOefk5Fxm5vv8sSfhGBJyZmbP/u09+/Naa9aZczKz57OyzvnMb3577992ZoaIiMRjnu8AIiJZotIVEYmRSldEJEYqXRGRGKl0RURipNIVEYmRSlcSzTn3qHPOOrcHnHMH+M4k0g+VriTdU8CfAQa0ga/4jSPSH5WuJIJz7i2d0Wyr87XpnHspcDDwt52HrQRO9ZdSpH8qXUmKZZ2vl5mZA1rAWuBpM2t2/i0POB/hRKKi0pWkOKHz9XXOuTuBCeCwWf/ugNs7PxdJLZWuJIUDMLMTzexE4F+AGWDEOfdXncdcBTzkJ55INFS6khR3ATjnPtf5/p3AL4EHgLcT7kh7G/BdH+FEouK0ypgkgXPuLcC3CI9QmEdYsm8EvrfbQ7eY2dKY44lEZoHvACKzmJnN3+1n2nEmQ0XTCyIiMdL0gohIjDTSFRGJkUpXRCRGKl0RkRjp6AVJjGoxGAGOBI7ofH0pMAIsmn2bpPXka0cWcTDzDiM8XbgJjANPAFs7t9n3HwE25yp57cAQ77QjTWJTLQaLgGP51WI9Ytb9A+eynSbtdeeNLGovxr2ii5ffAWwENnRu93W+rs9V8tu62I5IX1S6MjCdkj0F+G1gOXAasH+/223SXn/eyKJWl6W7NwasJ1xcZw2wNlfJb4hguyJ7pNKVyFSLwULgZJ4p2dOByBcdb9LecN7IomZEpbsnTwA3ATcC1+Yq+Z8N6HUkg1S60pdqMTgZeB1hyZ4BLB70azZp33feyKKZAZbu7n5BuObDd4E1uUq+FdPryhBS6UrXqsXgMOA9wB8Bx8X9+h5Kd7atwLXAfwA/yFXy0x4ySIqpdGVOqsVgPvA7hEX7u3g88qVF++fnjiya9lS6sz0O/BPw5Vwlv95zFkkJla48p2oxOIawaP8QSMTqXi3aG88dWTSVgNKdbQ3h9dv+LVfJa6F12SuVrjxLtRgcALwFuBA4y3OcZ0lo6e60jXD0+3e5Sv5B32EkeVS6sku1GBwIfBD4AOFJCYnUov2Lc0cWTSa0dHdqEl7p4lM6BE1mU+kK1WLwAsKi/RCwxHOcfWph9587snBHwkt3pzbwbeATuUr+p77DiH8q3QzrTCP8CXAJ8CLPceYsZaU727XAn+Uq+Tt9BxF/VLoZVC0G8wgP+fo48GLPcbrWwjadO7JwIoWlC+HI96vAx3KV/GO+w0j8VLoZUy0GBeDvgRM9R+lZG3tgxcjC7Skt3Z1Ggb8BPper5Gd8h5H4qHQzoloMjgY+A7zBd5Z+tbEHV4wsHE956e50H/DhXCV/je8gEg+VbgZUi8HFhKPbgZ+iG4e22YMrlgxN6e70A+DiXCXf8B1EBkulO8SqxeBQ4ArCM8iGRhvbvGJk4eiQlS6EUw6X5Cr5L/sOIoOj0h1S1WLwBsIzpA71nSVqQ1y6O/0IuCBXyT/sO4hET6U7ZKrFYDHh3O1FvrMMShtrrBhZuG2ISxfgSaCYq+S/5TuIREulO0SqxeAU4BvAMb6zDFLb7KEVSxY+PeSlu9PXgT/OVfI7fAeRaKh0h0BnBbCPAX9OBq571zZ7eMWShU9lpHQB7gDerLUchoOuBpxy1WKQA+rAX5GBwu1wvgPE7LeA2xrl+mt9B5H+qXRTrFoMXk54ba/TfGeJU9Yat+Ng4IeNcv3DvoNIfzS9kFLVYnAG8H1SsEBN1MxsyzlLFm7N0PTC7v4FeK/W7U0njXRTqFoM3ghcRwYLtyOjg91d3gEEjXL9IN9BpHsq3ZSpFoOLCJcK3M93Fo+yXroApwI3NMr1Zb6DSHdUuilSLQZ/AXwJmO87i2cq3dArgDWNcv1o30Fk7jSnmwKdpRgvBy72nSUJzOzxc5YsfCzDc7q7exQ4V4ukp4NGuglXLQb7AVejwp1Nv7e/6jBgVaNcP8N3ENk3/fImWOeU3h8Bb/adJWE0vfBsI4SHlL3GdxB5birdhOqcZfZNIO87SwKpdPdsMXBto1w/3ncQ2TuVbnJ9niFbkjFCKt29Owj4UaNcP9J3ENkzlW4CVYvBJcD7feeQ1FoKrGyU67/mO4g8m0o3YarF4A+AT/vOkXAa6e7bUYQj3hHfQeRXqXQTpFoMTgf+EZXKvuj/Z25+E/h+o1xf5DuIPEOlmxDVYnAM8D2yfabZXKl05+5Mwv0DkhAq3QSoFoODgf8EXuQ7S0qodLtzcaNcf5/vEBJS6XrWOfnhe4RzcDI3Kt3u/T8dw5sMKl3/vk7G1sONgEq3e4uAbzfK9aW+g2SdStejajF4H/BW3zlSSKXbm2XA1Y1yfaHvIFmm0vWks+PsMt85Ukql27vTgU/6DpFlKl0PqsVgAXAV4Wmb0iWn39t+fahRrp/pO0RW6ZfXj78ETvYdIsU00u3PPODKRrmuN30PVLox65wAcanvHCmn0u3fUcDf+Q6RRSrdGFWLwfOAK9D/e79UutEoNsr1Fb5DZI3++OP158BxvkMMAYcueBKVr2p9hnipdGNSLQavBP6v7xxDwqHWjcqLgb/1HSJLVLox6CxIfgWg4yOj4JzT/EKk3tso10/0HSIrVLrx+N/Aq3yHENmLeWhRnNiodAesWgyeD3zMdw6Rfcg3yvW3+Q6RBSrdwfsT4GDfIUTm4NONcn1/3yGGnUp3gKrF4EDgEt85RObocLSzd+BUuoP1QWCJ7xAiXfjTRrm+zHeIYabSHZBqMTiIsHRF0mR/4CO+Qwwzle7gXAK80HeIYaUDdQfqoka5fojvEMNKpTsA1WJwCOEONJE0OoCIP6U55650zm1yzt3ZuZ0Y5fbTRKU7GGW0bKOkW2kApwd/xMxO7NzujHjbqaHSjVi1GCwF/th3DpE+vZAePq05545wzq13zl3lnFvnnLvaOXfAAPKllko3eh8l3BkhknYfaJTrz+/heccCl5vZy4BR4P2dn3/COXeXc+4y59zzIkuZMirdCHWOy32v7xwiETkI+KMenrfZzNZ07n8DOJNwDenjCBfvPwj400gSppBKN1pvBfbzHSILtOBNbC7u4Tm7H1liZvaIhaaArwGn9B8tnVS60XqP7wAiEXt5o1w/q8vnHO6cO61z/3zgRufcUti1QNybgHuii5guKt2IVIvBrwNn+M4hMgDFLh+/ASg559YRnpH5ReAq59zdwN2Ea5F8PNqI6bHAd4Ah8m70qVeG05sb5fpIrpJ/eo6Pb5rZu3b7WSHiTKmlkW503u07QLbo/S1G+wHv8B1iWKh0I1AtBmcQXl1VZFhdMJcHmdkDZnb8oMOkmUo3GtqBJsPu5Ea5/uu+QwwDlW6fOpdVf6vvHCIxeKPvAMNApdu/3wNGfIcQiYFKNwIq3f5pasED7Ubz4sxGuf4i3yHSTqXbh2oxeAFwnu8cIjGZD7zed4i0U+n25zR0rLNki6YY+qTS7c+ZvgOIxOzcRrmu9UX6oNLtj0pXsmYxcLrvEGmm0u1RtRgsAE71nUPEA60x0geVbu9OIryWlEjWaKTbB5Vu7zS1IFl1WqNc11F7PVLp9i7vO0CW6S/eqwOBV/gOkVYq3d5pXkuyTL//PVLp9qBaDI4FDvGdQ8QjlW6PVLq90XyuZN2rfQdIK5Vub/QuL1l3VKNcn+87RBqpdHujRZol6xYBR/oOkUYq3d5oMWcR+A3fAdJIpdulzspiWt5OBI71HSCNVLrd00cqkZBKtwcq3e5pakEkpNLtgUq3exrpioSO9h0gjVS63VvmO4DoNOCEONh3gDRS6XbvMN8BRBJiv0a5vth3iLRR6XZPpSvyDI12u6TS7Z5KV+QZOnyySyrd7h3qO4AAmtZNCo10u6TS7UK1GDi0upjIbBrpdkml2x2HLrkuMptKt0sq3S6UaoU2YL5ziCTIIt8B0kal272W7wAikl4q3e6pdEWkZyrd7ql0E2C6zZjvDCK9UOl2T6WbAKvHmy9rmt3nO4fo0L1uqXS71/QdQGDGOPC60eaSttmDvrOIdEOl2z2NdBNiyjgkGGvOb5s94juLyFypdLun0k2Q7W1yN4w3J8zsSd9ZMmrSd4C0Uel2T9MLCbOtxVFrxltbzEw71+K31XeAtFHpdk8j3QTa2rKX3zLR2mhmU76zZIw+YXRJpdu9Gd8BZM+2zNhv/XRH604z0xtjfDTS7ZJKt3vaaZNgD07bqesn2zeZmU7XjodKt0sq3e79wncAeW73TbXP3DTdvsF3joxQ6XZJpdu9+30HkH27e0f77Ien26t95xhyM7lKXjsvu6TS7Z5Guilx60Tr7CeaKt4Besx3gDRS6XZPI90UWTPeOmu0ZTf6zjGkNvoOkEYq3e5ppJsubtVY8zUTbbvFd5AhpLUveqDS7VKpVngMGPedQ+bOYMH1o80Tptp2p+8sQ2aD7wBppNLtjaYYUqYN+1032jyqabbOd5YhopFuD1S6vVHpplATXrBytHloy0xTRNFQ6fZApdsb/dGm1LTxoutHmwe0zRq+s6RcEw0+eqLS7Y1+2VJsh7F01VizaWaP+86SYptylbxOie+BSrc32oGQcmNtjqiPt540s22+s6TUbb4DpJVKtzc3o4VvUu+plh178/bWg2Y24TtLCukQvB6pdHtQqhW2Az/2nUP691jTTrh9onWvmelNtDv6/e+RSrd31/sOINFozNir75ls32pmbd9ZUmIKuMN3iLRS6fZOpTtE7p9qn75xqq3Thefm1lwlr8v09Eil27ubge2+Q0h07p1sn/XL6fYq3zlSoO47QJqpdHtUqhVmAI2MhswdE63lj86oePdBaxX3QaXbH00xDKGbt7eWP9VsazS3ZztQ6fZFpdsfle6QumG8dcZ4y27ynSOBVuYqeR1i1weVbn/uRFdDHVbzgrHmqybb9hPfQRLmu74DpJ1Ktw+lWqENrPKdQwbDYNF1o83jZszu9p0lIdrANb5DpJ1Kt3+aYhhiLVi8crT5kqaZVtSCm3KVvC7R0yeVbv++TzgCkCE1Y4xcP9ocaZs96DuLZ9/zHWAYqHT7VKoVNgP/7TuHDNakcWgw1pxnZlt8Z/FI87kRUOlG40rfAWTwtrd5yerx5riZPeU7iwc/yVXyWl0vAirdaPw7MOY7hAzethZHr93eetjMsnadvC/7DjAsVLoRKNUKE8DVvnNIPJ5o2itunWjdZ2ZTvrPEZDvwz75DDAuV7m6cc1c4537qnLvLOXe1c+75c3zqlYPMJcnyyIyddNeO9h1m1vKdJQbfylXy+iQXEZXus33QzF5pZicAvwT+11yeVKoVbgDuHWgySZQHptuvWT/ZXmtm5jvLgH3Fd4BhktnSdc4d4Zxb75y7yjm3rjOqPcDMRjv/7oD9gW7+oKoDCSuJdd9UO//AdHu17xwDtC5Xya/xHWKYZLZ0O44FLjezlwGjwPsBnHNfA7YAxwFf6GJ7/9jZjmTIXTvayx8e3uLVKDdiWS/dzWa28138G8CZAGZ2AbAMWAe8ba4bK9UK44TFKxlz60Tr7K3NoSvep1HpRi7rpbv71MGu7zs7SL4J/H6X29QUQ0bdON46a7Rlw/RR/Au5Sl6f3CKW9dI93Dl3Wuf++cCNzrmjYdec7u8B67vZYKlWWE94arBkj1s11jx1R9uG4Uq524HP+Q4xjLJeuhuAknNuHbAE+CLwdefc3cDdwFLgr3vY7qVAFg4lkt0YLLhutHnCdNvu9J2lT7VcJb/Vd4hh5Ib/aJc9c84dAVxjZscPYvvVYvAV4MJBbFuSbwGMnnvggocWOPcy31l6MAUcmavkH/EdZBhlfaQ7SH9BeGkTyaAmvHDlaPOQltn9vrP04Gsq3MHJbOma2QODGuUClGqFh4DPDmr7knzTxsHXjzX3a5s95DtLFyaBiu8QwyyzpRuTCvCE7xDiz442y1aNNafN7HHfWeboM7lKPuvrBg+USneASrXCKPBx3znEr7E2R9bHW1vNbJvvLPvwMPAp3yGGnUp38L4IbPIdQvx6qmXH/Xh76wEzS/I8/6W5Sj5rS1bGTqU7YKVaYRr4mO8c4t+jTXvl7ROte8xsxneWPbgF+CffIbJApRuPbwK3+Q4h/jVm7OSfTbZvMbMkXVfPgA/kKvlsHj8aM5VuDEq1ggEf8Z1DkuEXU+0zNk61b/SdY5arcpX8zb5DZIVKNyalWmEVWpdBOu6dbJ+1ebq9yncO4FHg//gOkSUq3XhdAvzMdwhJhtsnWssfm/FevO/T6b7xUunGqFQrTALvIDzNUoSbtreWP920uqeX/3quktfiTDFT6casVCvcDZR955DkWD3ePH17y+KeU90MfCDm1xRUur58Dvih7xCSGPOvH2ueNNm2n8T0egZcmKvkk36yxlBS6XrQOZrhfwJpOTVUBsxg0XWjzeNmzO6J4eW+mKvkV8bwOrIHKl1PSrXCFuAC3zkkOVqweOVo88Uts/sG+DK3Ah8a4PZlH1S6HpVqhWuBy33nkOSYMZZcN9o8sG02iEVnHgd+P1fJa0euRypd/y4B7vUdQpJj0jgsGGs6M9sS4WabwFtzlfzmCLcpPVDpelaqFXYQXnFYFwCUXba3OXz1eHPMzJ6KaJMfyVXyqyLalvRBpZsApVrhHsKLYOpjn+yyrcUxa7e3HjKz7X1u6qpcJf/ZKDJJ/1S6CVGqFVYDb0cXtJRZnmja8bdNtDaYWa9vyD8BLooyk/RHpZsgpVrhO8DFvnNIsjw8Yyf9dKJ1u5l1+4a8AfgfuUp+YhC5pDcq3YQp1QpXAB/1nUOS5cEZO23DZHst4YkNc7EZOCdXyetY8IRR6SZQqVb4FHCZ7xySLBum2vlNU63Vc3joE8AKHamQTCrd5Pow8A3fISRZ7trRXv7Icy8JOUY4pbA+pkjSJZVuQnVOFb4A+IHvLJIst0y0lm9ttvc04p0C3pSr5HWVkgRT6SZYqVZoAn8ArPWdRZLlxvFWfqxla2b9aAJ4Q66SD3xlkrlxZrosUtJVi8EIcA1whucokiAOmue8cMEd+89zxwKvz1XySboEkOyFRropUKoVngZeB/yH5yiSIAYLrh9tLt3Rtt9W4aaHSjclOledeAtaIEeesakFrz3m02fd7juIzJ2mF1KoWgw+CnzCdw7x6g7gdzpLhEqKaKSbQqVa4ZPAO4FJ31nEi5XA2VEVrnPu88658Si2Jfum0k2pUq3wz8BZwMO+s0is/gF4falWGItiY865VwNLotiWzI2mF1KuWgyWAt8BTvEcRQbraeCiUq3wrW6f6Jw7AvgvwsVvTgJ+BryH8Lje64DzgZ+b2fOjCit7p9IdAtVisB/hCOjdvrPIQKwFzi/VCj1dTaJTupuAM81sjXPuq4QL588A88zsMufcuEo3HirdIVItBu8hvNLwiOcoEo028EngL0u1Qs9LfnZK9wYzO7zzfQEoAwcAy82sqdKNj0p3yFSLwTKgBrzBdxbpSwN4V2ed5b50Sne1mb20830B+Dbh9MLOnbGHA/eb2dH9vp48N5XukKoWg3cBn0c7SdLoO8CFpVrhySg2Nmt64XQzu8k59xVgnZn9/azHaKQbE5XuEKsWg18DvkR4KSBJvkngw6VaIdITYGbtSLsNeBXhfO67zWxi1mNUujFR6WZAtRi8k3DUe5DvLLJXa4GLO9fLi1SndK8xs+Oj3rZ0T6WbEdVicBjhXO+bPEeRX7URKJdqhW8P6gVUusmi0s2YajF4O/Bp4CW+s2TcVuBvgMtLtcKM7zASH5VuBlWLwSLgQuBSVL5xmwK+AHyis3qcZIxKN8M65ftewvLNeY6TBf8KXFqqFTb5DiL+qHSFajF4HmH5llH5DsKNwCWlWuHHvoOIfypd2WVW+V4KvNhznLRrA/9JOGer69zJLipdeZZO+b6PcOSr8u3OFuAK4Mu9rpUgw02lK3tVLQYLgHMI1+59E7DYa6DkMiAgPCTvuzoaQZ6LSlfmpFoMFgNvJizgc4D5fhMlwhPAlcCXSrXCRs9ZJCVUutK1zokWbwfeBbzac5y4NYE64RTC1aVaYcpzHkkZla70pVoMfoOwfM8HjvIcZ1AeI9wp9gPgRzq+Vvqh0pXIVIvBUcBy4OzO7XCvgXq3A7gJWAX8ELi1VCvoD0UiodKVgakWgyMIy/cUwmmIVwLP85lpL54EbgdWExbtLaVaYdprIhlaKl2JTbUYLAR+EzgZOJHwRIxlnduhDPZCqU8SLi7z885t5/2NUa1bKzIXKl1JhGoxmA8cxjMlvAxYOuv+QYQ7saYJr+218za9l/vbULFKAql0RURiNMiPcyIishuVrohIjFS6IiIxUumKiMRIpSsiEiOVrohIjFS6IiIxUumKiMRIpSsiEiOVrohIjFS6IiIxUumKiMRIpSsiEiOVrohIjFS6IiIxUumKiMRIpSsiEqP/D+1Okj6noJylAAAAAElFTkSuQmCC\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "[o.plot_piechart() for o in beta_p];" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.11" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/04_matrix_operations.ipynb b/examples/04_matrix_operations.ipynb new file mode 100644 index 00000000..c68a1358 --- /dev/null +++ b/examples/04_matrix_operations.ipynb @@ -0,0 +1,475 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.append('..')\n", + "import pyerrors as pe\n", + "import numpy as np\n", + "import scipy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As an example we look at a symmetric 2x2 matrix which positive semidefinte and has an error on all entries" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[Obs[4.10(20)] Obs[-1.00(10)]]\n", + " [Obs[-1.00(10)] Obs[1.000(10)]]]\n" + ] + } + ], + "source": [ + "obs11 = pe.pseudo_Obs(4.1, 0.2, 'e1')\n", + "obs22 = pe.pseudo_Obs(1, 0.01, 'e1')\n", + "obs12 = pe.pseudo_Obs(-1, 0.1, 'e1')\n", + "matrix = np.asarray([[obs11, obs12], [obs12, obs22]])\n", + "print(matrix)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We require to use `np.asarray` here as it makes sure that we end up with a numpy array of `Obs`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The standard matrix product can be performed with @" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[Obs[17.81] Obs[-5.1]]\n", + " [Obs[-5.1] Obs[2.0]]]\n" + ] + } + ], + "source": [ + "print(matrix @ matrix)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Multiplication with unit matrix leaves the matrix unchanged" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[Obs[4.1] Obs[-1.0]]\n", + " [Obs[-1.0] Obs[1.0]]]\n" + ] + } + ], + "source": [ + "print(matrix @ np.identity(2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Mathematical functions work elementwise" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[Obs[30.161857460980094] Obs[-1.1752011936438014]]\n", + " [Obs[-1.1752011936438014] Obs[1.1752011936438014]]]\n" + ] + } + ], + "source": [ + "print(np.sinh(matrix))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For a vector of `Obs`, we again use np.asarray to end up with the correct object" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[Obs[2.00(40)] Obs[1.00(10)]]\n" + ] + } + ], + "source": [ + "vec1 = pe.pseudo_Obs(2, 0.4, 'e1')\n", + "vec2 = pe.pseudo_Obs(1, 0.1, 'e1')\n", + "vector = np.asarray([vec1, vec2])\n", + "for (i), entry in np.ndenumerate(vector):\n", + " entry.gamma_method()\n", + "print(vector)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The matrix times vector product can then be computed via" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[Obs[7.2(1.7)] Obs[-1.00(47)]]\n" + ] + } + ], + "source": [ + "product = matrix @ vector\n", + "for (i), entry in np.ndenumerate(product):\n", + " entry.gamma_method()\n", + "print(product)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Matrix to scalar operations\n", + "If we want to apply a numpy matrix function with a scalar return value we can use `scalar_mat_op`. __Here we need to use the autograd wrapped version of numpy__ (imported as anp) to use automatic differentiation." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "det \t Obs[3.10(28)]\n", + "trace \t Obs[5.10(20)]\n", + "norm \t Obs[4.45(19)]\n" + ] + } + ], + "source": [ + "import autograd.numpy as anp # Thinly-wrapped numpy\n", + "funcs = [anp.linalg.det, anp.trace, anp.linalg.norm]\n", + "\n", + "for i, func in enumerate(funcs):\n", + " res = pe.linalg.scalar_mat_op(func, matrix)\n", + " res.gamma_method()\n", + " print(func.__name__, '\\t', res)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For matrix operations which are not supported by autograd we can use numerical differentiation" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cond \t Obs[6.23(59)]\n", + "expm_cond \t Obs[4.45(19)]\n" + ] + } + ], + "source": [ + "funcs = [np.linalg.cond, scipy.linalg.expm_cond]\n", + "\n", + "for i, func in enumerate(funcs):\n", + " res = pe.linalg.scalar_mat_op(func, matrix, num_grad=True)\n", + " res.gamma_method()\n", + " print(func.__name__, ' \\t', res)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Matrix to matrix operations\n", + "For matrix operations with a matrix as return value we can use another wrapper `mat_mat_op`. Take as an example the cholesky decompostion. __Here we need to use the autograd wrapped version of numpy__ (imported as anp) to use automatic differentiation." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[Obs[2.025(49)] Obs[0.0]]\n", + " [Obs[-0.494(50)] Obs[0.870(29)]]]\n" + ] + } + ], + "source": [ + "cholesky = pe.linalg.mat_mat_op(anp.linalg.cholesky, matrix)\n", + "for (i, j), entry in np.ndenumerate(cholesky):\n", + " entry.gamma_method()\n", + "print(cholesky)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now check if the decomposition was succesfull" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[Obs[-8.881784197001252e-16] Obs[0.0]]\n", + " [Obs[0.0] Obs[0.0]]]\n" + ] + } + ], + "source": [ + "check = cholesky @ cholesky.T\n", + "print(check - matrix)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now further compute the inverse of the cholesky decomposed matrix and check that the product with its inverse gives the unit matrix with zero error." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[Obs[0.494(12)] Obs[0.0]]\n", + " [Obs[0.280(40)] Obs[1.150(39)]]]\n", + "Check:\n", + "[[Obs[1.0] Obs[0.0]]\n", + " [Obs[0.0] Obs[1.0]]]\n" + ] + } + ], + "source": [ + "inv = pe.linalg.mat_mat_op(anp.linalg.inv, cholesky)\n", + "for (i, j), entry in np.ndenumerate(inv):\n", + " entry.gamma_method()\n", + "print(inv)\n", + "print('Check:')\n", + "check_inv = cholesky @ inv\n", + "print(check_inv)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Matrix to matrix operations which are not supported by autograd can also be computed with numeric differentiation" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "orth\n", + "[[Obs[-0.9592(75)] Obs[0.283(25)]]\n", + " [Obs[0.283(25)] Obs[0.9592(75)]]]\n", + "expm\n", + "[[Obs[75(15)] Obs[-21.4(4.2)]]\n", + " [Obs[-21.4(4.2)] Obs[8.3(1.4)]]]\n", + "logm\n", + "[[Obs[1.334(57)] Obs[-0.496(61)]]\n", + " [Obs[-0.496(61)] Obs[-0.203(50)]]]\n", + "sinhm\n", + "[[Obs[37.3(7.4)] Obs[-10.8(2.1)]]\n", + " [Obs[-10.8(2.1)] Obs[3.94(69)]]]\n", + "sqrtm\n", + "[[Obs[1.996(51)] Obs[-0.341(37)]]\n", + " [Obs[-0.341(37)] Obs[0.940(15)]]]\n" + ] + } + ], + "source": [ + "funcs = [scipy.linalg.orth, scipy.linalg.expm, scipy.linalg.logm, scipy.linalg.sinhm, scipy.linalg.sqrtm]\n", + "\n", + "for i,func in enumerate(funcs):\n", + " res = pe.linalg.mat_mat_op(func, matrix, num_grad=True)\n", + " for (i, j), entry in np.ndenumerate(res):\n", + " entry.gamma_method()\n", + " print(func.__name__)\n", + " print(res)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Eigenvalues and eigenvectors\n", + "We can also compute eigenvalues and eigenvectors of symmetric matrices with a special wrapper `eigh`" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Eigenvalues:\n", + "[Obs[0.705(57)] Obs[4.39(19)]]\n", + "Eigenvectors:\n", + "[[Obs[-0.283(25)] Obs[-0.9592(75)]]\n", + " [Obs[-0.9592(75)] Obs[0.283(25)]]]\n" + ] + } + ], + "source": [ + "e, v = pe.linalg.eigh(matrix)\n", + "for (i), entry in np.ndenumerate(e):\n", + " entry.gamma_method()\n", + "print('Eigenvalues:')\n", + "print(e)\n", + "for (i, j), entry in np.ndenumerate(v):\n", + " entry.gamma_method()\n", + "print('Eigenvectors:')\n", + "print(v)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can check that we got the correct result" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Check eigenvector 1\n", + "[Obs[-5.551115123125783e-17] Obs[0.0]]\n", + "Check eigenvector 2\n", + "[Obs[0.0] Obs[-2.220446049250313e-16]]\n" + ] + } + ], + "source": [ + "for i in range(2):\n", + " print('Check eigenvector', i + 1)\n", + " print(matrix @ v[:, i] - v[:, i] * e[i])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.11" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/data/B1k2_f_A.p b/examples/data/B1k2_f_A.p new file mode 100644 index 00000000..48c52af6 Binary files /dev/null and b/examples/data/B1k2_f_A.p differ diff --git a/examples/data/B1k2_f_P.p b/examples/data/B1k2_f_P.p new file mode 100644 index 00000000..748b6b30 Binary files /dev/null and b/examples/data/B1k2_f_P.p differ diff --git a/pyerrors/__init__.py b/pyerrors/__init__.py new file mode 100644 index 00000000..7397bc5e --- /dev/null +++ b/pyerrors/__init__.py @@ -0,0 +1,5 @@ +from .pyerrors import * +from . import fits +from . import linalg +from . import misc +from . import mpm \ No newline at end of file diff --git a/pyerrors/fits.py b/pyerrors/fits.py new file mode 100644 index 00000000..c0f394ca --- /dev/null +++ b/pyerrors/fits.py @@ -0,0 +1,730 @@ +#!/usr/bin/env python +# coding: utf-8 + +import numpy as np +import autograd.numpy as anp +import scipy.optimize +import scipy.stats +import matplotlib.pyplot as plt +from matplotlib import gridspec +from scipy.odr import ODR, Model, RealData +import iminuit +from autograd import jacobian +from autograd import elementwise_grad as egrad +from .pyerrors import Obs, derived_observable, covariance, pseudo_Obs + + +def standard_fit(x, y, func, silent=False, **kwargs): + """Performs a non-linear fit to y = func(x) and returns a list of Obs corresponding to the fit parameters. + + x has to be a list of floats. + y has to be a list of Obs, the dvalues of the Obs are used as yerror for the fit. + + func has to be of the form + + def func(a, x): + return a[0] + a[1] * x + a[2] * anp.sinh(x) + + For multiple x values func can be of the form + + def func(a, x): + (x1, x2) = x + return a[0] * x1 ** 2 + a[1] * x2 + + It is important that all numpy functions refer to autograd.numpy, otherwise the differentiation + will not work + + Keyword arguments + ----------------- + dict_output -- If true, the output is a dictionary containing all relevant + data instead of just a list of the fit parameters. + silent -- If true all output to the console is omitted (default False). + initial_guess -- can provide an initial guess for the input parameters. Relevant for + non-linear fits with many parameters. + method -- can be used to choose an alternative method for the minimization of chisquare. + The possible methods are the ones which can be used for scipy.optimize.minimize and + migrad of iminuit. If no method is specified, Levenberg-Marquard is used. + Reliable alternatives are migrad, Powell and Nelder-Mead. + resplot -- If true, a plot which displays fit, data and residuals is generated (default False). + qqplot -- If true, a quantile-quantile plot of the fit result is generated (default False). + expected_chisquare -- If true prints the expected chisquare which is + corrected by effects caused by correlated input data. + This can take a while as the full correlation matrix + has to be calculated (default False). + """ + + result_dict = {} + + result_dict['fit_function'] = func + + x = np.asarray(x) + + if x.shape[-1] != len(y): + raise Exception('x and y input have to have the same length') + + if len(x.shape) > 2: + raise Exception('Unkown format for x values') + + if not callable(func): + raise TypeError('func has to be a function.') + + for i in range(25): + try: + func(np.arange(i), x.T[0]) + except: + pass + else: + break + + n_parms = i + if not silent: + print('Fit with', n_parms, 'parameters') + + y_f = [o.value for o in y] + dy_f = [o.dvalue for o in y] + + if np.any(np.asarray(dy_f) <= 0.0): + raise Exception('No y errors available, run the gamma method first.') + + if 'initial_guess' in kwargs: + x0 = kwargs.get('initial_guess') + if len(x0) != n_parms: + raise Exception('Initial guess does not have the correct length.') + else: + x0 = [0.1] * n_parms + + def chisqfunc(p): + model = func(p, x) + chisq = anp.sum(((y_f - model) / dy_f) ** 2) + return chisq + + if 'method' in kwargs: + result_dict['method'] = kwargs.get('method') + if not silent: + print('Method:', kwargs.get('method')) + if kwargs.get('method') == 'migrad': + fit_result = iminuit.minimize(chisqfunc, x0) + fit_result = iminuit.minimize(chisqfunc, fit_result.x) + else: + fit_result = scipy.optimize.minimize(chisqfunc, x0, method=kwargs.get('method')) + fit_result = scipy.optimize.minimize(chisqfunc, fit_result.x, method=kwargs.get('method'), tol=1e-12) + + chisquare = fit_result.fun + else: + result_dict['method'] = 'Levenberg-Marquardt' + if not silent: + print('Method: Levenberg-Marquardt') + + def chisqfunc_residuals(p): + model = func(p, x) + chisq = ((y_f - model) / dy_f) + return chisq + + fit_result = scipy.optimize.least_squares(chisqfunc_residuals, x0, method='lm', ftol=1e-15, gtol=1e-15, xtol=1e-15) + + chisquare = np.sum(fit_result.fun ** 2) + + if not fit_result.success: + raise Exception('The minimization procedure did not converge.') + + if x.shape[-1] - n_parms > 0: + result_dict['chisquare/d.o.f.'] = chisquare / (x.shape[-1] - n_parms) + else: + result_dict['chisquare/d.o.f.'] = float('nan') + + if not silent: + print(fit_result.message) + print('chisquare/d.o.f.:', result_dict['chisquare/d.o.f.']) + + if kwargs.get('expected_chisquare') is True: + W = np.diag(1 / np.asarray(dy_f)) + cov = covariance_matrix(y) + A = W @ jacobian(func)(fit_result.x, x) + P_phi = A @ np.linalg.inv(A.T @ A) @ A.T + expected_chisquare = np.trace((np.identity(x.shape[-1]) - P_phi) @ W @ cov @ W) + result_dict['chisquare/expected_chisquare'] = chisquare / expected_chisquare + if not silent: + print('chisquare/expected_chisquare:', + result_dict['chisquare/expected_chisquare']) + + hess_inv = np.linalg.pinv(jacobian(jacobian(chisqfunc))(fit_result.x)) + + def chisqfunc_compact(d): + model = func(d[:n_parms], x) + chisq = anp.sum(((d[n_parms:] - model) / dy_f) ** 2) + return chisq + + jac_jac = jacobian(jacobian(chisqfunc_compact))(np.concatenate((fit_result.x, y_f))) + + deriv = -hess_inv @ jac_jac[:n_parms, n_parms:] + + result = [] + for i in range(n_parms): + result.append(derived_observable(lambda x, **kwargs: x[0], [pseudo_Obs(fit_result.x[i], 0.0, y[0].names[0], y[0].shape[y[0].names[0]])] + list(y), man_grad=[0] + list(deriv[i]))) + + result_dict['fit_parameters'] = result + + result_dict['chisquare'] = chisqfunc(fit_result.x) + result_dict['d.o.f.'] = x.shape[-1] - n_parms + + if kwargs.get('resplot') is True: + residual_plot(x, y, func, result) + + if kwargs.get('qqplot') is True: + qqplot(x, y, func, result) + + return result_dict if kwargs.get('dict_output') else result + + +def odr_fit(x, y, func, silent=False, **kwargs): + """Performs a non-linear fit to y = func(x) and returns a list of Obs corresponding to the fit parameters. + + x has to be a list of Obs, or a tuple of lists of Obs + y has to be a list of Obs + the dvalues of the Obs are used as x- and yerror for the fit. + + func has to be of the form + + def func(a, x): + y = a[0] + a[1] * x + a[2] * anp.sinh(x) + return y + + For multiple x values func can be of the form + + def func(a, x): + (x1, x2) = x + return a[0] * x1 ** 2 + a[1] * x2 + + It is important that all numpy functions refer to autograd.numpy, otherwise the differentiation + will not work. + Based on the orthogonal distance regression module of scipy + + Keyword arguments + ----------------- + dict_output -- If true, the output is a dictionary containing all relevant + data instead of just a list of the fit parameters. + silent -- If true all output to the console is omitted (default False). + initial_guess -- can provide an initial guess for the input parameters. Relevant for non-linear + fits with many parameters. + expected_chisquare -- If true prints the expected chisquare which is + corrected by effects caused by correlated input data. + This can take a while as the full correlation matrix + has to be calculated (default False). + """ + + result_dict = {} + + result_dict['fit_function'] = func + + x = np.array(x) + + x_shape = x.shape + + if not callable(func): + raise TypeError('func has to be a function.') + + for i in range(25): + try: + func(np.arange(i), x.T[0]) + except: + pass + else: + break + + n_parms = i + if not silent: + print('Fit with', n_parms, 'parameters') + + x_f = np.vectorize(lambda o: o.value)(x) + dx_f = np.vectorize(lambda o: o.dvalue)(x) + y_f = np.array([o.value for o in y]) + dy_f = np.array([o.dvalue for o in y]) + + if np.any(np.asarray(dx_f) <= 0.0): + raise Exception('No x errors available, run the gamma method first.') + + if np.any(np.asarray(dy_f) <= 0.0): + raise Exception('No y errors available, run the gamma method first.') + + if 'initial_guess' in kwargs: + x0 = kwargs.get('initial_guess') + if len(x0) != n_parms: + raise Exception('Initial guess does not have the correct length.') + else: + x0 = [1] * n_parms + + data = RealData(x_f, y_f, sx=dx_f, sy=dy_f) + model = Model(func) + odr = ODR(data, model, x0, partol=np.finfo(np.float).eps) + odr.set_job(fit_type=0, deriv=1) + output = odr.run() + + result_dict['residual_variance'] = output.res_var + + result_dict['method'] = 'ODR' + + result_dict['xplus'] = output.xplus + + if not silent: + print('Method: ODR') + print(*output.stopreason) + print('Residual variance:', result_dict['residual_variance']) + + if output.info > 3: + raise Exception('The minimization procedure did not converge.') + + m = x_f.size + + def odr_chisquare(p): + model = func(p[:n_parms], p[n_parms:].reshape(x_shape)) + chisq = anp.sum(((y_f - model) / dy_f) ** 2) + anp.sum(((x_f - p[n_parms:].reshape(x_shape)) / dx_f) ** 2) + return chisq + + if kwargs.get('expected_chisquare') is True: + W = np.diag(1 / np.asarray(np.concatenate((dy_f.ravel(), dx_f.ravel())))) + + if kwargs.get('covariance') is not None: + cov = kwargs.get('covariance') + else: + cov = covariance_matrix(np.concatenate((y, x.ravel()))) + + number_of_x_parameters = int(m / x_f.shape[-1]) + + old_jac = jacobian(func)(output.beta, output.xplus) + fused_row1 = np.concatenate((old_jac, np.concatenate((number_of_x_parameters * [np.zeros(old_jac.shape)]), axis=0))) + fused_row2 = np.concatenate((jacobian(lambda x, y : func(y, x))(output.xplus, output.beta).reshape(x_f.shape[-1], x_f.shape[-1] * number_of_x_parameters), np.identity(number_of_x_parameters * old_jac.shape[0]))) + new_jac = np.concatenate((fused_row1, fused_row2), axis=1) + + A = W @ new_jac + P_phi = A @ np.linalg.inv(A.T @ A) @ A.T + expected_chisquare = np.trace((np.identity(P_phi.shape[0]) - P_phi) @ W @ cov @ W) + if expected_chisquare <= 0.0: + print('Warning, negative expected_chisquare.') + expected_chisquare = np.abs(expected_chisquare) + result_dict['chisquare/expected_chisquare'] = odr_chisquare(np.concatenate((output.beta, output.xplus.ravel()))) / expected_chisquare + if not silent: + print('chisquare/expected_chisquare:', + result_dict['chisquare/expected_chisquare']) + + hess_inv = np.linalg.pinv(jacobian(jacobian(odr_chisquare))(np.concatenate((output.beta, output.xplus.ravel())))) + + def odr_chisquare_compact_x(d): + model = func(d[:n_parms], d[n_parms:n_parms + m].reshape(x_shape)) + chisq = anp.sum(((y_f - model) / dy_f) ** 2) + anp.sum(((d[n_parms + m:].reshape(x_shape) - d[n_parms:n_parms + m].reshape(x_shape)) / dx_f) ** 2) + return chisq + + jac_jac_x = jacobian(jacobian(odr_chisquare_compact_x))(np.concatenate((output.beta, output.xplus.ravel(), x_f.ravel()))) + + deriv_x = -hess_inv @ jac_jac_x[:n_parms + m, n_parms + m:] + + def odr_chisquare_compact_y(d): + model = func(d[:n_parms], d[n_parms:n_parms + m].reshape(x_shape)) + chisq = anp.sum(((d[n_parms + m:] - model) / dy_f) ** 2) + anp.sum(((x_f - d[n_parms:n_parms + m].reshape(x_shape)) / dx_f) ** 2) + return chisq + + jac_jac_y = jacobian(jacobian(odr_chisquare_compact_y))(np.concatenate((output.beta, output.xplus.ravel(), y_f))) + + deriv_y = -hess_inv @ jac_jac_y[:n_parms + m, n_parms + m:] + + result = [] + for i in range(n_parms): + result.append(derived_observable(lambda x, **kwargs: x[0], [pseudo_Obs(output.beta[i], 0.0, y[0].names[0], y[0].shape[y[0].names[0]])] + list(x.ravel()) + list(y), man_grad=[0] + list(deriv_x[i]) + list(deriv_y[i]))) + + result_dict['fit_parameters'] = result + + result_dict['odr_chisquare'] = odr_chisquare(np.concatenate((output.beta, output.xplus.ravel()))) + result_dict['d.o.f.'] = x.shape[-1] - n_parms + + return result_dict if kwargs.get('dict_output') else result + + +def prior_fit(x, y, func, priors, silent=False, **kwargs): + """Performs a non-linear fit to y = func(x) with given priors and returns a list of Obs corresponding to the fit parameters. + + x has to be a list of floats. + y has to be a list of Obs, the dvalues of the Obs are used as yerror for the fit. + + func has to be of the form + + def func(a, x): + y = a[0] + a[1] * x + a[2] * anp.sinh(x) + return y + + It is important that all numpy functions refer to autograd.numpy, otherwise the differentiation + will not work + + priors has to be a list with an entry for every parameter in the fit. The entries can either be + Obs (e.g. results from a previous fit) or strings containing a value and an error formatted like + 0.548(23), 500(40) or 0.5(0.4) + + It is important for the subsequent error estimation that the e_tag for the gamma method is large + enough. + + Keyword arguments + ----------------- + dict_output -- If true, the output is a dictionary containing all relevant + data instead of just a list of the fit parameters. + silent -- If true all output to the console is omitted (default False). + initial_guess -- can provide an initial guess for the input parameters. + If no guess is provided, the prior values are used. + resplot -- if true, a plot which displays fit, data and residuals is generated (default False) + qqplot -- if true, a quantile-quantile plot of the fit result is generated (default False) + tol -- Specify the tolerance of the migrad solver (default 1e-4) + """ + + result_dict = {} + + result_dict['fit_function'] = func + + if Obs.e_tag_global < 4: + print('WARNING: e_tag_global is smaller than 4, this can cause problems when calculating errors from fits with priors') + + x = np.asarray(x) + + if not callable(func): + raise TypeError('func has to be a function.') + + for i in range(100): + try: + func(np.arange(i), 0) + except: + pass + else: + break + + n_parms = i + + if n_parms != len(priors): + raise Exception('Priors does not have the correct length.') + + def extract_val_and_dval(string): + split_string = string.split('(') + if '.' in split_string[0] and '.' not in split_string[1][:-1]: + factor = 10 ** -len(split_string[0].partition('.')[2]) + else: + factor = 1 + return float(split_string[0]), float(split_string[1][:-1]) * factor + + loc_priors = [] + for i_n, i_prior in enumerate(priors): + if isinstance(i_prior, Obs): + loc_priors.append(i_prior) + else: + loc_val, loc_dval = extract_val_and_dval(i_prior) + loc_priors.append(pseudo_Obs(loc_val, loc_dval, 'p' + str(i_n))) + + result_dict['priors'] = loc_priors + + if not silent: + print('Fit with', n_parms, 'parameters') + + y_f = [o.value for o in y] + dy_f = [o.dvalue for o in y] + + if np.any(np.asarray(dy_f) <= 0.0): + raise Exception('No y errors available, run the gamma method first.') + + p_f = [o.value for o in loc_priors] + dp_f = [o.dvalue for o in loc_priors] + + if np.any(np.asarray(dp_f) <= 0.0): + raise Exception('No prior errors available, run the gamma method first.') + + if 'initial_guess' in kwargs: + x0 = kwargs.get('initial_guess') + if len(x0) != n_parms: + raise Exception('Initial guess does not have the correct length.') + else: + x0 = p_f + + def chisqfunc(p): + model = func(p, x) + chisq = anp.sum(((y_f - model) / dy_f) ** 2) + anp.sum(((p_f - p) / dp_f) ** 2) + return chisq + + if not silent: + print('Method: migrad') + + m = iminuit.Minuit.from_array_func(chisqfunc, x0, error=np.asarray(x0) * 0.01, errordef=1, print_level=0) + if 'tol' in kwargs: + m.tol = kwargs.get('tol') + else: + m.tol = 1e-4 + m.migrad() + params = np.asarray(m.values.values()) + + result_dict['chisquare/d.o.f.'] = m.fval / len(x) + + result_dict['method'] = 'migrad' + + if not silent: + print('chisquare/d.o.f.:', result_dict['chisquare/d.o.f.']) + + if not m.get_fmin().is_valid: + raise Exception('The minimization procedure did not converge.') + + hess_inv = np.linalg.pinv(jacobian(jacobian(chisqfunc))(params)) + + def chisqfunc_compact(d): + model = func(d[:n_parms], x) + chisq = anp.sum(((d[n_parms: n_parms + len(x)] - model) / dy_f) ** 2) + anp.sum(((d[n_parms + len(x):] - d[:n_parms]) / dp_f) ** 2) + return chisq + + jac_jac = jacobian(jacobian(chisqfunc_compact))(np.concatenate((params, y_f, p_f))) + + deriv = -hess_inv @ jac_jac[:n_parms, n_parms:] + + result = [] + for i in range(n_parms): + result.append(derived_observable(lambda x, **kwargs: x[0], [pseudo_Obs(params[i], 0.0, y[0].names[0], y[0].shape[y[0].names[0]])] + list(y) + list(loc_priors), man_grad=[0] + list(deriv[i]))) + + result_dict['fit_parameters'] = result + result_dict['chisquare'] = chisqfunc(np.asarray(params)) + + if kwargs.get('resplot') is True: + residual_plot(x, y, func, result) + + if kwargs.get('qqplot') is True: + qqplot(x, y, func, result) + + return result_dict if kwargs.get('dict_output') else result + + +def fit_lin(x, y, **kwargs): + """Performs a linear fit to y = n + m * x and returns two Obs n, m. + + y has to be a list of Obs, the dvalues of the Obs are used as yerror for the fit. + x can either be a list of floats in which case no xerror is assumed, or + a list of Obs, where the dvalues of the Obs are used as xerror for the fit. + """ + + def f(a, x): + y = a[0] + a[1] * x + return y + + if all(isinstance(n, Obs) for n in x): + return odr_fit(x, y, f, **kwargs) + elif all(isinstance(n, float) or isinstance(n, int) for n in x) or isinstance(x, np.ndarray): + return standard_fit(x, y, f, **kwargs) + else: + raise Exception('Unsupported types for x') + + +def fit_exp(data, **kwargs): + """Fit a single exponential to a discrete time series of Obs without errors. + + Keyword arguments + ----------------- + shift -- specifies the absolute timeslice value of the first entry of data (default 0.0) + only important if one is interested in the matrix element, for the mass this is irrelevant. + """ + if 'shift' in kwargs: + shift = kwargs.get("shift") + else: + shift = 0 + length = len(data) + xsum = 0 + xsum2 = 0 + ysum = 0 + xysum = 0 + for i in range(shift, length + shift): + xsum += i + xsum2 += i ** 2 + tmp_log = np.log(np.abs(data[i - shift])) + ysum += tmp_log + xysum += i * tmp_log + res0 = -(length * xysum - xsum * ysum) / (length * xsum2 - xsum * xsum) # mass + res1 = np.exp((xsum2 * ysum - xsum * xysum) / (length * xsum2 - xsum * xsum)) # matrix element + return [res0, res1] + + +def qqplot(x, o_y, func, p): + """ Generates a quantile-quantile plot of the fit result which can be used to + check if the residuals of the fit are gaussian distributed. + """ + + residuals = [] + for i_x, i_y in zip(x, o_y): + residuals.append((i_y - func(p, i_x)) / i_y.dvalue) + residuals = sorted(residuals) + my_y = [o.value for o in residuals] + probplot = scipy.stats.probplot(my_y) + my_x = probplot[0][0] + fig = plt.figure(figsize=(8, 8 / 1.618)) + plt.errorbar(my_x, my_y, fmt='o') + fit_start = my_x[0] + fit_stop = my_x[-1] + samples = np.arange(fit_start, fit_stop, 0.01) + plt.plot(samples, samples, 'k--', zorder=11, label='Standard normal distribution') + plt.plot(samples, probplot[1][0] * samples + probplot[1][1], zorder=10, label='Least squares fit, r=' + str(np.around(probplot[1][2], 3))) + + plt.xlabel('Theoretical quantiles') + plt.ylabel('Ordered Values') + plt.legend() + plt.show() + + +def residual_plot(x, y, func, fit_res): + """ Generates a plot which compares the fit to the data and displays the corresponding residuals""" + xstart = x[0] - 0.5 + xstop = x[-1] + 0.5 + x_samples = np.arange(xstart, xstop, 0.01) + + plt.figure(figsize=(8, 8 / 1.618)) + gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1], wspace=0.0, hspace=0.0) + ax0 = plt.subplot(gs[0]) + ax0.errorbar(x, [o.value for o in y], yerr=[o.dvalue for o in y], ls='none', fmt='o', capsize=3, markersize=5, label='Data') + ax0.plot(x_samples, func([o.value for o in fit_res], x_samples), label='Fit', zorder=10) + ax0.set_xticklabels([]) + ax0.set_xlim([xstart, xstop]) + ax0.set_xticklabels([]) + ax0.legend() + + residuals = (np.asarray([o.value for o in y]) - func([o.value for o in fit_res], x)) / np.asarray([o.dvalue for o in y]) + ax1 = plt.subplot(gs[1]) + ax1.plot(x, residuals, 'ko', ls='none', markersize=5) + ax1.tick_params(direction='out') + ax1.tick_params(axis="x", bottom=True, top=True, labelbottom=True) + ax1.axhline(y=0.0, ls='--', color='k') + ax1.fill_between(x_samples, -1.0, 1.0, alpha=0.1, facecolor='k') + ax1.set_xlim([xstart, xstop]) + ax1.set_ylabel('Residuals') + plt.subplots_adjust(wspace=None, hspace=None) + plt.show() + + +def covariance_matrix(y): + """Returns the covariance matrix of y.""" + length = len(y) + cov = np.zeros((length, length)) + for i, item in enumerate(y): + for j, jtem in enumerate(y[:i + 1]): + if i == j: + cov[i, j] = item.dvalue ** 2 + else: + cov[i, j] = covariance(item, jtem) + return cov + cov.T - np.diag(np.diag(cov)) + + +def error_band(x, func, beta): + """Returns the error band for an array of sample values x, for given fit function func with optimized parameters beta.""" + cov = covariance_matrix(beta) + if np.any(np.abs(cov - cov.T) > 1000 * np.finfo(np.float).eps): + print('Warning, Covariance matrix is not symmetric within floating point precision') + print('cov - cov.T:') + print(cov - cov.T) + + deriv = [] + for i, item in enumerate(x): + deriv.append(np.array(egrad(func)([o.value for o in beta], item))) + + err = [] + for i, item in enumerate(x): + err.append(np.sqrt(deriv[i] @ cov @ deriv[i])) + err = np.array(err) + + return err + + +def fit_general(x, y, func, silent=False, **kwargs): + """Performs a non-linear fit to y = func(x) and returns a list of Obs corresponding to the fit parameters. + + WARNING: In the current version the fits are performed with numerical derivatives. + Plausibility of the results should be checked. To control the numerical differentiation + the kwargs of numdifftools.step_generators.MaxStepGenerator can be used. + + func has to be of the form + + def func(a, x): + y = a[0] + a[1] * x + a[2] * np.sinh(x) + return y + + y has to be a list of Obs, the dvalues of the Obs are used as yerror for the fit. + x can either be a list of floats in which case no xerror is assumed, or + a list of Obs, where the dvalues of the Obs are used as xerror for the fit. + + Keyword arguments + ----------------- + silent -- If true all output to the console is omitted (default False). + initial_guess -- can provide an initial guess for the input parameters. Relevant for non-linear fits + with many parameters. + """ + + if not silent: + print('WARNING: This function is deprecated and will be removed in future versions.') + print('New fit functions with exact error propagation are now available as alternative.') + + if not callable(func): + raise TypeError('func has to be a function.') + + for i in range(10): + try: + func(np.arange(i), 0) + except: + pass + else: + break + n_parms = i + if not silent: + print('Fit with', n_parms, 'parameters') + + global print_output, beta0 + print_output = 1 + if 'initial_guess' in kwargs: + beta0 = kwargs.get('initial_guess') + if len(beta0) != n_parms: + raise Exception('Initial guess does not have the correct length.') + else: + beta0 = np.arange(n_parms) + + if len(x) != len(y): + raise Exception('x and y have to have the same length') + + if all(isinstance(n, Obs) for n in x): + obs = x + y + x_constants = None + xerr = [o.dvalue for o in x] + yerr = [o.dvalue for o in y] + elif all(isinstance(n, float) or isinstance(n, int) for n in x) or isinstance(x, np.ndarray): + obs = y + x_constants = x + xerr = None + yerr = [o.dvalue for o in y] + else: + raise Exception('Unsupported types for x') + + def do_the_fit(obs, **kwargs): + + global print_output, beta0 + + func = kwargs.get('function') + yerr = kwargs.get('yerr') + length = len(yerr) + + xerr = kwargs.get('xerr') + + if length == len(obs): + assert 'x_constants' in kwargs + data = RealData(kwargs.get('x_constants'), obs, sy=yerr) + fit_type = 2 + elif length == len(obs) // 2: + data = RealData(obs[:length], obs[length:], sx=xerr, sy=yerr) + fit_type = 0 + else: + raise Exception('x and y do not fit together.') + + model = Model(func) + + odr = ODR(data, model, beta0, partol=np.finfo(np.float).eps) + odr.set_job(fit_type=fit_type, deriv=1) + output = odr.run() + if print_output and not silent: + print(*output.stopreason) + print('chisquare/d.o.f.:', output.res_var) + print_output = 0 + beta0 = output.beta + return output.beta[kwargs.get('n')] + res = [] + for n in range(n_parms): + res.append(derived_observable(do_the_fit, obs, function=func, xerr=xerr, yerr=yerr, x_constants=x_constants, num_grad=True, n=n, **kwargs)) + return res diff --git a/pyerrors/input/__init__.py b/pyerrors/input/__init__.py new file mode 100644 index 00000000..7a835029 --- /dev/null +++ b/pyerrors/input/__init__.py @@ -0,0 +1,2 @@ +from .input import * +from . import bdio diff --git a/pyerrors/input/bdio.py b/pyerrors/input/bdio.py new file mode 100644 index 00000000..8c0878df --- /dev/null +++ b/pyerrors/input/bdio.py @@ -0,0 +1,628 @@ +#!/usr/bin/env python +# coding: utf-8 + +import ctypes +import hashlib +import autograd.numpy as np # Thinly-wrapped numpy +from ..pyerrors import Obs + + +def read_ADerrors(file_path, bdio_path='./libbdio.so', **kwargs): + """ Extract generic MCMC data from a bdio file + + read_ADerrors requires bdio to be compiled into a shared library. This can be achieved by + adding the flag -fPIC to CC and changing the all target to + + all: bdio.o $(LIBDIR) + gcc -shared -Wl,-soname,libbdio.so -o $(BUILDDIR)/libbdio.so $(BUILDDIR)/bdio.o + cp $(BUILDDIR)/libbdio.so $(LIBDIR)/ + + Parameters + ---------- + file_path -- path to the bdio file + bdio_path -- path to the shared bdio library libbdio.so (default ./libbdio.so) + """ + bdio = ctypes.cdll.LoadLibrary(bdio_path) + + bdio_open = bdio.bdio_open + bdio_open.restype = ctypes.c_void_p + + bdio_close = bdio.bdio_close + bdio_close.restype = ctypes.c_int + bdio_close.argtypes = [ctypes.c_void_p] + + bdio_seek_record = bdio.bdio_seek_record + bdio_seek_record.restype = ctypes.c_int + bdio_seek_record.argtypes = [ctypes.c_void_p] + + bdio_get_rlen = bdio.bdio_get_rlen + bdio_get_rlen.restype = ctypes.c_int + bdio_get_rlen.argtypes = [ctypes.c_void_p] + + bdio_get_ruinfo = bdio.bdio_get_ruinfo + bdio_get_ruinfo.restype = ctypes.c_int + bdio_get_ruinfo.argtypes = [ctypes.c_void_p] + + bdio_read = bdio.bdio_read + bdio_read.restype = ctypes.c_size_t + bdio_read.argtypes = [ctypes.c_char_p, ctypes.c_size_t, ctypes.c_void_p] + + bdio_read_f64 = bdio.bdio_read_f64 + bdio_read_f64.restype = ctypes.c_size_t + bdio_read_f64.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_void_p] + + bdio_read_int32 = bdio.bdio_read_int32 + bdio_read_int32.restype = ctypes.c_size_t + bdio_read_int32.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_void_p] + + b_path = file_path.encode('utf-8') + read = 'r' + b_read = read.encode('utf-8') + + fbdio = bdio_open(ctypes.c_char_p(b_path), ctypes.c_char_p(b_read), None) + + return_list = [] + + print('Reading of bdio file started') + while 1 > 0: + record = bdio_seek_record(fbdio) + ruinfo = bdio_get_ruinfo(fbdio) + + if ruinfo == 7: + print('MD5sum found') # For now we just ignore these entries and do not perform any checks on them + continue + + if ruinfo < 0: + # EOF reached + break + rlen = bdio_get_rlen(fbdio) + + def read_c_double(): + d_buf = ctypes.c_double + pd_buf = d_buf() + ppd_buf = ctypes.c_void_p(ctypes.addressof(pd_buf)) + iread = bdio_read_f64(ppd_buf, ctypes.c_size_t(8), ctypes.c_void_p(fbdio)) + return pd_buf.value + + mean = read_c_double() + print('mean', mean) + + def read_c_size_t(): + d_buf = ctypes.c_size_t + pd_buf = d_buf() + ppd_buf = ctypes.c_void_p(ctypes.addressof(pd_buf)) + iread = bdio_read_int32(ppd_buf, ctypes.c_size_t(4), ctypes.c_void_p(fbdio)) + return pd_buf.value + + neid = read_c_size_t() + print('neid', neid) + + ndata = [] + for index in range(neid): + ndata.append(read_c_size_t()) + print('ndata', ndata) + + nrep = [] + for index in range(neid): + nrep.append(read_c_size_t()) + print('nrep', nrep) + + vrep = [] + for index in range(neid): + vrep.append([]) + for jndex in range(nrep[index]): + vrep[-1].append(read_c_size_t()) + print('vrep', vrep) + + ids = [] + for index in range(neid): + ids.append(read_c_size_t()) + print('ids', ids) + + nt = [] + for index in range(neid): + nt.append(read_c_size_t()) + print('nt', nt) + + zero = [] + for index in range(neid): + zero.append(read_c_double()) + print('zero', zero) + + four = [] + for index in range(neid): + four.append(read_c_double()) + print('four', four) + + d_buf = ctypes.c_double * np.sum(ndata) + pd_buf = d_buf() + ppd_buf = ctypes.c_void_p(ctypes.addressof(pd_buf)) + iread = bdio_read_f64(ppd_buf, ctypes.c_size_t(8 * np.sum(ndata)), ctypes.c_void_p(fbdio)) + delta = pd_buf[:] + + samples = np.split(np.asarray(delta) + mean, np.cumsum([a for su in vrep for a in su])[:-1]) + no_reps = [len(o) for o in vrep] + assert len(ids) == len(no_reps) + tmp_names = [] + ens_length = max([len(str(o)) for o in ids]) + for loc_id, reps in zip(ids, no_reps): + for index in range(reps): + missing_chars = ens_length - len(str(loc_id)) + tmp_names.append(str(loc_id) + ' ' * missing_chars + 'r' + '{0:03d}'.format(index)) + + return_list.append(Obs(samples, tmp_names)) + + bdio_close(fbdio) + print() + print(len(return_list), 'observable(s) extracted.') + return return_list + + +def write_ADerrors(obs_list, file_path, bdio_path='./libbdio.so', **kwargs): + """ Write Obs to a bdio file according to ADerrors conventions + + read_mesons requires bdio to be compiled into a shared library. This can be achieved by + adding the flag -fPIC to CC and changing the all target to + + all: bdio.o $(LIBDIR) + gcc -shared -Wl,-soname,libbdio.so -o $(BUILDDIR)/libbdio.so $(BUILDDIR)/bdio.o + cp $(BUILDDIR)/libbdio.so $(LIBDIR)/ + + Parameters + ---------- + file_path -- path to the bdio file + bdio_path -- path to the shared bdio library libbdio.so (default ./libbdio.so) + """ + + for obs in obs_list: + if not obs.e_names: + raise Exception('Run the gamma method first for all obs.') + + bdio = ctypes.cdll.LoadLibrary(bdio_path) + + bdio_open = bdio.bdio_open + bdio_open.restype = ctypes.c_void_p + + bdio_close = bdio.bdio_close + bdio_close.restype = ctypes.c_int + bdio_close.argtypes = [ctypes.c_void_p] + + bdio_start_record = bdio.bdio_start_record + bdio_start_record.restype = ctypes.c_int + bdio_start_record.argtypes = [ctypes.c_size_t, ctypes.c_size_t, ctypes.c_void_p] + + bdio_flush_record = bdio.bdio_flush_record + bdio_flush_record.restype = ctypes.c_int + bdio_flush_record.argytpes = [ctypes.c_void_p] + + bdio_write_f64 = bdio.bdio_write_f64 + bdio_write_f64.restype = ctypes.c_size_t + bdio_write_f64.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_void_p] + + bdio_write_int32 = bdio.bdio_write_int32 + bdio_write_int32.restype = ctypes.c_size_t + bdio_write_int32.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_void_p] + + b_path = file_path.encode('utf-8') + write = 'w' + b_write = write.encode('utf-8') + form = 'pyerrors ADerror export' + b_form = form.encode('utf-8') + + fbdio = bdio_open(ctypes.c_char_p(b_path), ctypes.c_char_p(b_write), b_form) + + for obs in obs_list: + + mean = obs.value + neid = len(obs.e_names) + vrep = [[obs.shape[o] for o in sl] for sl in list(obs.e_content.values())] + vrep_write = [item for sublist in vrep for item in sublist] + ndata = [np.sum(o) for o in vrep] + nrep = [len(o) for o in vrep] + print('ndata', ndata) + print('nrep', nrep) + print('vrep', vrep) + keys = list(obs.e_content.keys()) + ids = [] + for key in keys: + try: # Try to convert key to integer + ids.append(int(key)) + except: # If not possible construct a hash + ids.append(int(hashlib.sha256(key.encode('utf-8')).hexdigest(), 16) % 10 ** 8) + print('ids', ids) + nt = [] + for e, e_name in enumerate(obs.e_names): + + r_length = [] + for r_name in obs.e_content[e_name]: + r_length.append(len(obs.deltas[r_name])) + + #e_N = np.sum(r_length) + nt.append(max(r_length) // 2) + print('nt', nt) + zero = neid * [0.0] + four = neid * [4.0] + print('zero', zero) + print('four', four) + delta = np.concatenate([item for sublist in [[obs.deltas[o] for o in sl] for sl in list(obs.e_content.values())] for item in sublist]) + + bdio_start_record(0x00, 8, fbdio) + + def write_c_double(double): + pd_buf = ctypes.c_double(double) + ppd_buf = ctypes.c_void_p(ctypes.addressof(pd_buf)) + iwrite = bdio_write_f64(ppd_buf, ctypes.c_size_t(8), ctypes.c_void_p(fbdio)) + + def write_c_size_t(int32): + pd_buf = ctypes.c_size_t(int32) + ppd_buf = ctypes.c_void_p(ctypes.addressof(pd_buf)) + iwrite = bdio_write_int32(ppd_buf, ctypes.c_size_t(4), ctypes.c_void_p(fbdio)) + + write_c_double(obs.value) + write_c_size_t(neid) + + for element in ndata: + write_c_size_t(element) + for element in nrep: + write_c_size_t(element) + for element in vrep_write: + write_c_size_t(element) + for element in ids: + write_c_size_t(element) + for element in nt: + write_c_size_t(element) + + for element in zero: + write_c_double(element) + for element in four: + write_c_double(element) + + for element in delta: + write_c_double(element) + + bdio_close(fbdio) + return 0 + + +def _get_kwd(string, key): + return (string.split(key, 1)[1]).split(" ", 1)[0] + + +def _get_corr_name(string, key): + return (string.split(key, 1)[1]).split(' NDIM=', 1)[0] + + +def read_mesons(file_path, bdio_path='./libbdio.so', **kwargs): + """ Extract mesons data from a bdio file and return it as a dictionary + + The dictionary can be accessed with a tuple consisting of (type, source_position, kappa1, kappa2) + + read_mesons requires bdio to be compiled into a shared library. This can be achieved by + adding the flag -fPIC to CC and changing the all target to + + all: bdio.o $(LIBDIR) + gcc -shared -Wl,-soname,libbdio.so -o $(BUILDDIR)/libbdio.so $(BUILDDIR)/bdio.o + cp $(BUILDDIR)/libbdio.so $(LIBDIR)/ + + Parameters + ---------- + file_path -- path to the bdio file + bdio_path -- path to the shared bdio library libbdio.so (default ./libbdio.so) + stop -- stops reading at given configuration number (default None) + alternative_ensemble_name -- Manually overwrite ensemble name + """ + bdio = ctypes.cdll.LoadLibrary(bdio_path) + + bdio_open = bdio.bdio_open + bdio_open.restype = ctypes.c_void_p + + bdio_close = bdio.bdio_close + bdio_close.restype = ctypes.c_int + bdio_close.argtypes = [ctypes.c_void_p] + + bdio_seek_record = bdio.bdio_seek_record + bdio_seek_record.restype = ctypes.c_int + bdio_seek_record.argtypes = [ctypes.c_void_p] + + bdio_get_rlen = bdio.bdio_get_rlen + bdio_get_rlen.restype = ctypes.c_int + bdio_get_rlen.argtypes = [ctypes.c_void_p] + + bdio_get_ruinfo = bdio.bdio_get_ruinfo + bdio_get_ruinfo.restype = ctypes.c_int + bdio_get_ruinfo.argtypes = [ctypes.c_void_p] + + bdio_read = bdio.bdio_read + bdio_read.restype = ctypes.c_size_t + bdio_read.argtypes = [ctypes.c_char_p, ctypes.c_size_t, ctypes.c_void_p] + + bdio_read_f64 = bdio.bdio_read_f64 + bdio_read_f64.restype = ctypes.c_size_t + bdio_read_f64.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_void_p] + + b_path = file_path.encode('utf-8') + read = 'r' + b_read = read.encode('utf-8') + form = 'Generic Correlator Format 1.0' + b_form = form.encode('utf-8') + + ensemble_name = '' + volume = [] # lattice volume + boundary_conditions = [] + corr_name = [] # Contains correlator names + corr_type = [] # Contains correlator data type (important for reading out numerical data) + corr_props = [] # Contanis propagator types (Component of corr_kappa) + d0 = 0 # tvals + d1 = 0 # nnoise + prop_kappa = [] # Contains propagator kappas (Component of corr_kappa) + prop_source = [] # Contains propagator source positions + # Check noise type for multiple replica? + cnfg_no = -1 + corr_no = -1 + data = [] + + fbdio = bdio_open(ctypes.c_char_p(b_path), ctypes.c_char_p(b_read), ctypes.c_char_p(b_form)) + + print('Reading of bdio file started') + while 1 > 0: + record = bdio_seek_record(fbdio) + ruinfo = bdio_get_ruinfo(fbdio) + if ruinfo < 0: + # EOF reached + break + rlen = bdio_get_rlen(fbdio) + if ruinfo == 5: + d_buf = ctypes.c_double * (2 + d0 * d1 * 2) + pd_buf = d_buf() + ppd_buf = ctypes.c_void_p(ctypes.addressof(pd_buf)) + iread = bdio_read_f64(ppd_buf, ctypes.c_size_t(rlen), ctypes.c_void_p(fbdio)) + if corr_type[corr_no] == 'complex': + tmp_mean = np.mean(np.asarray(np.split(np.asarray(pd_buf[2 + 2 * d1:-2 * d1:2]), d0 - 2)), axis=1) + else: + tmp_mean = np.mean(np.asarray(np.split(np.asarray(pd_buf[2 + d1:-d0 * d1 - d1]), d0 - 2)), axis=1) + + data[corr_no].append(tmp_mean) + corr_no += 1 + else: + alt_buf = ctypes.create_string_buffer(1024) + palt_buf = ctypes.c_char_p(ctypes.addressof(alt_buf)) + iread = bdio_read(palt_buf, ctypes.c_size_t(rlen), ctypes.c_void_p(fbdio)) + if rlen != iread: + print('Error') + for i, item in enumerate(alt_buf): + if item == b'\x00': + alt_buf[i] = b' ' + tmp_string = (alt_buf[:].decode("utf-8")).rstrip() + if ruinfo == 0: + ensemble_name = _get_kwd(tmp_string, 'ENSEMBLE=') + volume.append(int(_get_kwd(tmp_string, 'L0='))) + volume.append(int(_get_kwd(tmp_string, 'L1='))) + volume.append(int(_get_kwd(tmp_string, 'L2='))) + volume.append(int(_get_kwd(tmp_string, 'L3='))) + boundary_conditions.append(_get_kwd(tmp_string, 'BC0=')) + boundary_conditions.append(_get_kwd(tmp_string, 'BC1=')) + boundary_conditions.append(_get_kwd(tmp_string, 'BC2=')) + boundary_conditions.append(_get_kwd(tmp_string, 'BC3=')) + + if ruinfo == 1: + corr_name.append(_get_corr_name(tmp_string, 'CORR_NAME=')) + corr_type.append(_get_kwd(tmp_string, 'DATATYPE=')) + corr_props.append([_get_kwd(tmp_string, 'PROP0='), _get_kwd(tmp_string, 'PROP1=')]) + if d0 == 0: + d0 = int(_get_kwd(tmp_string, 'D0=')) + else: + if d0 != int(_get_kwd(tmp_string, 'D0=')): + print('Error: Varying number of time values') + if d1 == 0: + d1 = int(_get_kwd(tmp_string, 'D1=')) + else: + if d1 != int(_get_kwd(tmp_string, 'D1=')): + print('Error: Varying number of random sources') + if ruinfo == 2: + prop_kappa.append(_get_kwd(tmp_string, 'KAPPA=')) + prop_source.append(_get_kwd(tmp_string, 'x0=')) + if ruinfo == 4: + if 'stop' in kwargs: + if cnfg_no >= kwargs.get('stop') - 1: + break + cnfg_no += 1 + print('\r%s %i' % ('Reading configuration', cnfg_no + 1), end='\r') + if cnfg_no == 0: + no_corrs = len(corr_name) + data = [] + for c in range(no_corrs): + data.append([]) + + corr_no = 0 + bdio_close(fbdio) + + print('\nEnsemble: ', ensemble_name) + if 'alternative_ensemble_name' in kwargs: + ensemble_name = kwargs.get('alternative_ensemble_name') + print('Ensemble name overwritten to', ensemble_name) + print('Lattice volume: ', volume) + print('Boundary conditions: ', boundary_conditions) + print('Number of time values: ', d0) + print('Number of random sources: ', d1) + print('Number of corrs: ', len(corr_name)) + print('Number of configurations: ', cnfg_no + 1) + + corr_kappa = [] # Contains kappa values for both propagators of given correlation function + corr_source = [] + for item in corr_props: + corr_kappa.append([float(prop_kappa[int(item[0])]), float(prop_kappa[int(item[1])])]) + if prop_source[int(item[0])] != prop_source[int(item[1])]: + raise Exception('Source position do not match for correlator' + str(item)) + else: + corr_source.append(int(prop_source[int(item[0])])) + + result = {} + for c in range(no_corrs): + tmp_corr = [] + for t in range(d0 - 2): + tmp_corr.append(Obs([np.asarray(data[c])[:, t]], [ensemble_name])) + result[(corr_name[c], corr_source[c]) + tuple(sorted(corr_kappa[c]))] = tmp_corr + + # Check that all data entries have the same number of configurations + if len(set([o[0].N for o in list(result.values())])) != 1: + raise Exception('Error: Not all correlators have the same number of configurations. bdio file is possibly corrupted.') + + return result + + +def read_dSdm(file_path, bdio_path='./libbdio.so', **kwargs): + """ Extract dSdm data from a bdio file and return it as a dictionary + + The dictionary can be accessed with a tuple consisting of (type, kappa) + + read_dSdm requires bdio to be compiled into a shared library. This can be achieved by + adding the flag -fPIC to CC and changing the all target to + + all: bdio.o $(LIBDIR) + gcc -shared -Wl,-soname,libbdio.so -o $(BUILDDIR)/libbdio.so $(BUILDDIR)/bdio.o + cp $(BUILDDIR)/libbdio.so $(LIBDIR)/ + + Parameters + ---------- + file_path -- path to the bdio file + bdio_path -- path to the shared bdio library libbdio.so (default ./libbdio.so) + stop -- stops reading at given configuration number (default None) + """ + bdio = ctypes.cdll.LoadLibrary(bdio_path) + + bdio_open = bdio.bdio_open + bdio_open.restype = ctypes.c_void_p + + bdio_close = bdio.bdio_close + bdio_close.restype = ctypes.c_int + bdio_close.argtypes = [ctypes.c_void_p] + + bdio_seek_record = bdio.bdio_seek_record + bdio_seek_record.restype = ctypes.c_int + bdio_seek_record.argtypes = [ctypes.c_void_p] + + bdio_get_rlen = bdio.bdio_get_rlen + bdio_get_rlen.restype = ctypes.c_int + bdio_get_rlen.argtypes = [ctypes.c_void_p] + + bdio_get_ruinfo = bdio.bdio_get_ruinfo + bdio_get_ruinfo.restype = ctypes.c_int + bdio_get_ruinfo.argtypes = [ctypes.c_void_p] + + bdio_read = bdio.bdio_read + bdio_read.restype = ctypes.c_size_t + bdio_read.argtypes = [ctypes.c_char_p, ctypes.c_size_t, ctypes.c_void_p] + + bdio_read_f64 = bdio.bdio_read_f64 + bdio_read_f64.restype = ctypes.c_size_t + bdio_read_f64.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_void_p] + + b_path = file_path.encode('utf-8') + read = 'r' + b_read = read.encode('utf-8') + form = 'Generic Correlator Format 1.0' + b_form = form.encode('utf-8') + + ensemble_name = '' + volume = [] # lattice volume + boundary_conditions = [] + corr_name = [] # Contains correlator names + corr_type = [] # Contains correlator data type (important for reading out numerical data) + corr_props = [] # Contains propagator types (Component of corr_kappa) + d0 = 0 # tvals + d1 = 0 # nnoise + prop_kappa = [] # Contains propagator kappas (Component of corr_kappa) + # Check noise type for multiple replica? + cnfg_no = -1 + corr_no = -1 + data = [] + + fbdio = bdio_open(ctypes.c_char_p(b_path), ctypes.c_char_p(b_read), ctypes.c_char_p(b_form)) + + print('Reading of bdio file started') + while 1 > 0: + record = bdio_seek_record(fbdio) + ruinfo = bdio_get_ruinfo(fbdio) + if ruinfo < 0: + # EOF reached + break + rlen = bdio_get_rlen(fbdio) + if ruinfo == 5: + d_buf = ctypes.c_double * (2 + d0) + pd_buf = d_buf() + ppd_buf = ctypes.c_void_p(ctypes.addressof(pd_buf)) + iread = bdio_read_f64(ppd_buf, ctypes.c_size_t(rlen), ctypes.c_void_p(fbdio)) + tmp_mean = np.mean(np.asarray(pd_buf[2:])) + + data[corr_no].append(tmp_mean) + corr_no += 1 + else: + alt_buf = ctypes.create_string_buffer(1024) + palt_buf = ctypes.c_char_p(ctypes.addressof(alt_buf)) + iread = bdio_read(palt_buf, ctypes.c_size_t(rlen), ctypes.c_void_p(fbdio)) + if rlen != iread: + print('Error') + for i, item in enumerate(alt_buf): + if item == b'\x00': + alt_buf[i] = b' ' + tmp_string = (alt_buf[:].decode("utf-8")).rstrip() + if ruinfo == 0: + creator = _get_kwd(tmp_string, 'CREATOR=') + ensemble_name = _get_kwd(tmp_string, 'ENSEMBLE=') + volume.append(int(_get_kwd(tmp_string, 'L0='))) + volume.append(int(_get_kwd(tmp_string, 'L1='))) + volume.append(int(_get_kwd(tmp_string, 'L2='))) + volume.append(int(_get_kwd(tmp_string, 'L3='))) + boundary_conditions.append(_get_kwd(tmp_string, 'BC0=')) + boundary_conditions.append(_get_kwd(tmp_string, 'BC1=')) + boundary_conditions.append(_get_kwd(tmp_string, 'BC2=')) + boundary_conditions.append(_get_kwd(tmp_string, 'BC3=')) + + if ruinfo == 1: + corr_name.append(_get_corr_name(tmp_string, 'CORR_NAME=')) + corr_type.append(_get_kwd(tmp_string, 'DATATYPE=')) + corr_props.append(_get_kwd(tmp_string, 'PROP0=')) + if d0 == 0: + d0 = int(_get_kwd(tmp_string, 'D0=')) + else: + if d0 != int(_get_kwd(tmp_string, 'D0=')): + print('Error: Varying number of time values') + if ruinfo == 2: + prop_kappa.append(_get_kwd(tmp_string, 'KAPPA=')) + if ruinfo == 4: + if 'stop' in kwargs: + if cnfg_no >= kwargs.get('stop') - 1: + break + cnfg_no += 1 + print('\r%s %i' % ('Reading configuration', cnfg_no + 1), end='\r') + if cnfg_no == 0: + no_corrs = len(corr_name) + data = [] + for c in range(no_corrs): + data.append([]) + + corr_no = 0 + bdio_close(fbdio) + + print('\nCreator: ', creator) + print('Ensemble: ', ensemble_name) + print('Lattice volume: ', volume) + print('Boundary conditions: ', boundary_conditions) + print('Number of random sources: ', d0) + print('Number of corrs: ', len(corr_name)) + print('Number of configurations: ', cnfg_no + 1) + + corr_kappa = [] # Contains kappa values for both propagators of given correlation function + corr_source = [] + for item in corr_props: + corr_kappa.append(float(prop_kappa[int(item)])) + + result = {} + for c in range(no_corrs): + result[(corr_name[c], str(corr_kappa[c]))] = Obs([np.asarray(data[c])], [ensemble_name]) + + # Check that all data entries have the same number of configurations + if len(set([o.N for o in list(result.values())])) != 1: + raise Exception('Error: Not all correlators have the same number of configurations. bdio file is possibly corrupted.') + + return result diff --git a/pyerrors/input/input.py b/pyerrors/input/input.py new file mode 100644 index 00000000..124cc80b --- /dev/null +++ b/pyerrors/input/input.py @@ -0,0 +1,660 @@ +#!/usr/bin/env python +# coding: utf-8 + +import sys +import os +import fnmatch +import re +import struct +import autograd.numpy as np # Thinly-wrapped numpy +from ..pyerrors import Obs +from ..fits import fit_lin + + +def read_sfcf(path, prefix, name, **kwargs): + """Read sfcf C format from given folder structure. + + Keyword arguments + ----------------- + im -- if True, read imaginary instead of real part of the correlation function. + single -- if True, read a boundary-to-boundary correlation function with a single value + b2b -- if True, read a time-dependent boundary-to-boundary correlation function + names -- Alternative labeling for replicas/ensembles. Has to have the appropriate length + """ + if kwargs.get('im'): + im = 1 + part = 'imaginary' + else: + im = 0 + part = 'real' + + if kwargs.get('single'): + b2b = 1 + single = 1 + else: + b2b = 0 + single = 0 + + if kwargs.get('b2b'): + b2b = 1 + + read = 0 + T = 0 + start = 0 + ls = [] + for (dirpath, dirnames, filenames) in os.walk(path): + ls.extend(dirnames) + break + if not ls: + print('Error, directory not found') + sys.exit() + for exc in ls: + if fnmatch.fnmatch(exc, prefix + '*'): + ls = list(set(ls) - set(exc)) + if len(ls) > 1: + ls.sort(key=lambda x: int(re.findall(r'\d+', x[len(prefix):])[0])) + replica = len(ls) + print('Read', part, 'part of', name, 'from', prefix, ',', replica, 'replica') + if 'names' in kwargs: + new_names = kwargs.get('names') + if len(new_names) != replica: + raise Exception('Names does not have the required length', replica) + else: + new_names = ls + print(replica, 'replica') + for i, item in enumerate(ls): + print(item) + sub_ls = [] + for (dirpath, dirnames, filenames) in os.walk(path+'/'+item): + sub_ls.extend(dirnames) + break + for exc in sub_ls: + if fnmatch.fnmatch(exc, 'cfg*'): + sub_ls = list(set(sub_ls) - set(exc)) + sub_ls.sort(key=lambda x: int(x[3:])) + no_cfg = len(sub_ls) + print(no_cfg, 'configurations') + + if i == 0: + with open(path + '/' + item + '/' + sub_ls[0] + '/' + name) as fp: + for k, line in enumerate(fp): + if read == 1 and not line.strip() and k > start + 1: + break + if read == 1 and k >= start: + T += 1 + if '[correlator]' in line: + read = 1 + start = k + 7 + b2b + T -= b2b + + deltas = [] + for j in range(T): + deltas.append([]) + + sublength = len(sub_ls) + for j in range(T): + deltas[j].append(np.zeros(sublength)) + + for cnfg, subitem in enumerate(sub_ls): + with open(path + '/' + item + '/' + subitem + '/'+name) as fp: + for k, line in enumerate(fp): + if(k >= start and k < start + T): + floats = list(map(float, line.split())) + deltas[k-start][i][cnfg] = floats[1 + im - single] + + result = [] + for t in range(T): + result.append(Obs(deltas[t], new_names)) + + return result + + +def read_sfcf_c(path, prefix, name, **kwargs): + """Read sfcf c format from given folder structure. + + Keyword arguments + ----------------- + im -- if True, read imaginary instead of real part of the correlation function. + single -- if True, read a boundary-to-boundary correlation function with a single value + b2b -- if True, read a time-dependent boundary-to-boundary correlation function + names -- Alternative labeling for replicas/ensembles. Has to have the appropriate length + """ + if kwargs.get('im'): + im = 1 + part = 'imaginary' + else: + im = 0 + part = 'real' + + if kwargs.get('single'): + b2b = 1 + single = 1 + else: + b2b = 0 + single = 0 + + if kwargs.get('b2b'): + b2b = 1 + + read = 0 + T = 0 + start = 0 + ls = [] + for (dirpath, dirnames, filenames) in os.walk(path): + ls.extend(dirnames) + break + if not ls: + print('Error, directory not found') + sys.exit() + # Exclude folders with different names + for exc in ls: + if not fnmatch.fnmatch(exc, prefix+'*'): + ls = list(set(ls) - set([exc])) + if len(ls) > 1: + ls.sort(key=lambda x: int(re.findall(r'\d+', x[len(prefix):])[0])) # New version, to cope with ids, etc. + replica = len(ls) + if 'names' in kwargs: + new_names = kwargs.get('names') + if len(new_names) != replica: + raise Exception('Names does not have the required length', replica) + else: + new_names = ls + print('Read', part, 'part of', name, 'from', prefix[:-1], ',', replica, 'replica') + for i, item in enumerate(ls): + sub_ls = [] + for (dirpath, dirnames, filenames) in os.walk(path+'/'+item): + sub_ls.extend(filenames) + break + for exc in sub_ls: + if not fnmatch.fnmatch(exc, prefix+'*'): + sub_ls = list(set(sub_ls) - set([exc])) + sub_ls.sort(key=lambda x: int(re.findall(r'\d+', x)[-1])) + + first_cfg = int(re.findall(r'\d+', sub_ls[0])[-1]) + + last_cfg = len(sub_ls) + first_cfg - 1 + + for cfg in range(1, len(sub_ls)): + if int(re.findall(r'\d+', sub_ls[cfg])[-1]) != first_cfg + cfg: + last_cfg = cfg + first_cfg - 1 + break + + no_cfg = last_cfg - first_cfg + 1 + print(item, ':', no_cfg, 'evenly spaced configurations (', first_cfg, '-', last_cfg, ') ,', len(sub_ls) - no_cfg, 'configs omitted\n') + + if i == 0: + read = 0 + found = 0 + with open(path+'/'+item+'/'+sub_ls[0]) as fp: + for k, line in enumerate(fp): + if 'quarks' in kwargs: + if found == 0 and read == 1: + if line.strip() == 'quarks ' + kwargs.get('quarks'): + found = 1 + print('found', kwargs.get('quarks')) + else: + read = 0 + if read == 1 and not line.strip(): + break + if read == 1 and k >= start_read: + T += 1 + if line.strip() == 'name '+name: + read = 1 + start_read = k + 5 + b2b + print('T =', T, ', starting to read in line', start_read) + + #TODO what to do if start_read was not found + if 'quarks' in kwargs: + if found == 0: + raise Exception(kwargs.get('quarks') + ' not found') + + deltas = [] + for j in range(T): + deltas.append([]) + + sublength = no_cfg + for j in range(T): + deltas[j].append(np.zeros(sublength)) + + for cfg in range(no_cfg): + with open(path+'/'+item+'/'+sub_ls[cfg]) as fp: + for k, line in enumerate(fp): + if k == start_read - 5 - b2b: + if line.strip() != 'name ' + name: + raise Exception('Wrong format', sub_ls[cfg]) + if(k >= start_read and k < start_read + T): + floats = list(map(float, line.split())) + deltas[k-start_read][i][cfg] = floats[1 + im - single] + + result = [] + for t in range(T): + result.append(Obs(deltas[t], new_names)) + + return result + + +def read_qtop(path, prefix, **kwargs): + """Read qtop format from given folder structure. + + Keyword arguments + ----------------- + target -- specifies the topological sector to be reweighted to (default 0) + full -- if true read the charge instead of the reweighting factor. + """ + + if 'target' in kwargs: + target = kwargs.get('target') + else: + target = 0 + + if kwargs.get('full'): + full = 1 + else: + full = 0 + + ls = [] + for (dirpath, dirnames, filenames) in os.walk(path): + ls.extend(filenames) + break + + if not ls: + print('Error, directory not found') + sys.exit() + + # Exclude files with different names + for exc in ls: + if not fnmatch.fnmatch(exc, prefix+'*'): + ls = list(set(ls) - set([exc])) + if len(ls) > 1: + ls.sort(key=lambda x: int(re.findall(r'\d+', x[len(prefix):])[0])) # New version, to cope with ids, etc. + replica = len(ls) + print('Read Q_top from', prefix[:-1], ',', replica, 'replica') + + deltas = [] + + for rep in range(replica): + tmp = [] + with open(path+'/'+ls[rep]) as fp: + for k, line in enumerate(fp): + floats = list(map(float, line.split())) + if full == 1: + tmp.append(floats[1]) + else: + if int(floats[1]) == target: + tmp.append(1.0) + else: + tmp.append(0.0) + + deltas.append(np.array(tmp)) + + result = Obs(deltas, [(w.split('.'))[0] for w in ls]) + + return result + + +def read_rwms(path, prefix, **kwargs): + """Read rwms format from given folder structure. Returns a list of length nrw + + Keyword arguments + ----------------- + new_format -- if True, the array of the associated numbers of Hasenbusch factors is extracted (v>=openQCD1.6) + r_start -- list which contains the first config to be read for each replicum + r_stop -- list which contains the last config to be read for each replicum + + """ + + if kwargs.get('new_format'): + extract_nfct = 1 + else: + extract_nfct = 0 + + ls = [] + for (dirpath, dirnames, filenames) in os.walk(path): + ls.extend(filenames) + break + + if not ls: + print('Error, directory not found') + sys.exit() + + # Exclude files with different names + for exc in ls: + if not fnmatch.fnmatch(exc, prefix + '*.dat'): + ls = list(set(ls) - set([exc])) + if len(ls) > 1: + ls.sort(key=lambda x: int(re.findall(r'\d+', x[len(prefix):])[0])) + replica = len(ls) + + if 'r_start' in kwargs: + r_start = kwargs.get('r_start') + if len(r_start) != replica: + raise Exception('r_start does not match number of replicas') + # Adjust Configuration numbering to python index + r_start = [o - 1 if o else None for o in r_start] + else: + r_start = [None] * replica + + if 'r_stop' in kwargs: + r_stop = kwargs.get('r_stop') + if len(r_stop) != replica: + raise Exception('r_stop does not match number of replicas') + else: + r_stop = [None] * replica + + print('Read reweighting factors from', prefix[:-1], ',', replica, 'replica', end='') + + print_err = 0 + if 'print_err' in kwargs: + print_err = 1 + print() + + deltas = [] + + for rep in range(replica): + tmp_array = [] + with open(path+ '/' + ls[rep], 'rb') as fp: + + #header + t = fp.read(4) # number of reweighting factors + if rep == 0: + nrw = struct.unpack('i', t)[0] + for k in range(nrw): + deltas.append([]) + else: + if nrw != struct.unpack('i', t)[0]: + print('Error: different number of reweighting factors for replicum', rep) + sys.exit() + + for k in range(nrw): + tmp_array.append([]) + + # This block is necessary for openQCD1.6 ms1 files + nfct = [] + if extract_nfct == 1: + for i in range(nrw): + t = fp.read(4) + nfct.append(struct.unpack('i', t)[0]) + print('nfct: ', nfct) # Hasenbusch factor, 1 for rat reweighting + else: + for i in range(nrw): + nfct.append(1) + + nsrc = [] + for i in range(nrw): + t = fp.read(4) + nsrc.append(struct.unpack('i', t)[0]) + + #body + while 0 < 1: + t = fp.read(4) + if len(t) < 4: + break + if print_err: + config_no = struct.unpack('i', t) + for i in range(nrw): + tmp_nfct = 1.0 + for j in range(nfct[i]): + t = fp.read(8 * nsrc[i]) + t = fp.read(8 * nsrc[i]) + tmp_rw = struct.unpack('d' * nsrc[i], t) + tmp_nfct *= np.mean(np.exp(-np.asarray(tmp_rw))) + if print_err: + print(config_no, i, j, np.mean(np.exp(-np.asarray(tmp_rw))), np.std(np.exp(-np.asarray(tmp_rw)))) + print('Sources:', np.exp(-np.asarray(tmp_rw))) + print('Partial factor:', tmp_nfct) + tmp_array[i].append(tmp_nfct) + + for k in range(nrw): + deltas[k].append(tmp_array[k][r_start[rep]:r_stop[rep]]) + + print(',', nrw, 'reweighting factors with', nsrc, 'sources') + result = [] + for t in range(nrw): + result.append(Obs(deltas[t], [(w.split('.'))[0] for w in ls])) + + return result + + +def read_pbp(path, prefix, **kwargs): + """Read pbp format from given folder structure. Returns a list of length nrw + + Keyword arguments + ----------------- + r_start -- list which contains the first config to be read for each replicum + r_stop -- list which contains the last config to be read for each replicum + + """ + + extract_nfct = 1 + + ls = [] + for (dirpath, dirnames, filenames) in os.walk(path): + ls.extend(filenames) + break + + if not ls: + print('Error, directory not found') + sys.exit() + + # Exclude files with different names + for exc in ls: + if not fnmatch.fnmatch(exc, prefix + '*.dat'): + ls = list(set(ls) - set([exc])) + if len(ls) > 1: + ls.sort(key=lambda x: int(re.findall(r'\d+', x[len(prefix):])[0])) + replica = len(ls) + + if 'r_start' in kwargs: + r_start = kwargs.get('r_start') + if len(r_start) != replica: + raise Exception('r_start does not match number of replicas') + # Adjust Configuration numbering to python index + r_start = [o - 1 if o else None for o in r_start] + else: + r_start = [None] * replica + + if 'r_stop' in kwargs: + r_stop = kwargs.get('r_stop') + if len(r_stop) != replica: + raise Exception('r_stop does not match number of replicas') + else: + r_stop = [None] * replica + + print('Read from', prefix[:-1], ',', replica, 'replica', end='') + + print_err = 0 + if 'print_err' in kwargs: + print_err = 1 + print() + + deltas = [] + + for rep in range(replica): + tmp_array = [] + with open(path+ '/' + ls[rep], 'rb') as fp: + + #header + t = fp.read(4) # number of reweighting factors + if rep == 0: + nrw = struct.unpack('i', t)[0] + for k in range(nrw): + deltas.append([]) + else: + if nrw != struct.unpack('i', t)[0]: + print('Error: different number of reweighting factors for replicum', rep) + sys.exit() + + for k in range(nrw): + tmp_array.append([]) + + # This block is necessary for openQCD1.6 ms1 files + nfct = [] + if extract_nfct == 1: + for i in range(nrw): + t = fp.read(4) + nfct.append(struct.unpack('i', t)[0]) + print('nfct: ', nfct) # Hasenbusch factor, 1 for rat reweighting + else: + for i in range(nrw): + nfct.append(1) + + nsrc = [] + for i in range(nrw): + t = fp.read(4) + nsrc.append(struct.unpack('i', t)[0]) + + #body + while 0 < 1: + t = fp.read(4) + if len(t) < 4: + break + if print_err: + config_no = struct.unpack('i', t) + for i in range(nrw): + tmp_nfct = 1.0 + for j in range(nfct[i]): + t = fp.read(8 * nsrc[i]) + t = fp.read(8 * nsrc[i]) + tmp_rw = struct.unpack('d' * nsrc[i], t) + tmp_nfct *= np.mean(np.asarray(tmp_rw)) + if print_err: + print(config_no, i, j, np.mean(np.asarray(tmp_rw)), np.std(np.asarray(tmp_rw))) + print('Sources:', np.asarray(tmp_rw)) + print('Partial factor:', tmp_nfct) + tmp_array[i].append(tmp_nfct) + + for k in range(nrw): + deltas[k].append(tmp_array[k][r_start[rep]:r_stop[rep]]) + + print(',', nrw, ' with', nsrc, 'sources') + result = [] + for t in range(nrw): + result.append(Obs(deltas[t], [(w.split('.'))[0] for w in ls])) + + return result + + +def extract_t0(path, prefix, dtr_read, xmin, spatial_extent, fit_range=5, **kwargs): + """Extract t0 from given .ms.dat files. Returns t0 as Obs. + + It is assumed that all boundary effects have sufficiently decayed at x0=xmin. + The data around the zero crossing of t^2 - 0.3 is fitted with a linear function + from which the exact root is extracted. + Only works with openQCD v 1.2. + + Parameters + ---------- + path -- Path to .ms.dat files + prefix -- Ensemble prefix + dtr_read -- Determines how many trajectories should be skipped when reading the ms.dat files. + Corresponds to dtr_cnfg / dtr_ms in the openQCD input file. + xmin -- First timeslice where the boundary effects have sufficiently decayed. + spatial_extent -- spatial extent of the lattice, required for normalization. + fit_range -- Number of data points left and right of the zero crossing to be included in the linear fit. (Default: 5) + + Keyword arguments + ----------------- + r_start -- list which contains the first config to be read for each replicum. + r_stop -- list which contains the last config to be read for each replicum. + plaquette -- If true extract the plaquette estimate of t0 instead. + """ + + ls = [] + for (dirpath, dirnames, filenames) in os.walk(path): + ls.extend(filenames) + break + + if not ls: + print('Error, directory not found') + sys.exit() + + # Exclude files with different names + for exc in ls: + if not fnmatch.fnmatch(exc, prefix + '*.ms.dat'): + ls = list(set(ls) - set([exc])) + if len(ls) > 1: + ls.sort(key=lambda x: int(re.findall(r'\d+', x[len(prefix):])[0])) + replica = len(ls) + + if 'r_start' in kwargs: + r_start = kwargs.get('r_start') + if len(r_start) != replica: + raise Exception('r_start does not match number of replicas') + # Adjust Configuration numbering to python index + r_start = [o - 1 if o else None for o in r_start] + else: + r_start = [None] * replica + + if 'r_stop' in kwargs: + r_stop = kwargs.get('r_stop') + if len(r_stop) != replica: + raise Exception('r_stop does not match number of replicas') + else: + r_stop = [None] * replica + + print('Extract t0 from', prefix, ',', replica, 'replica') + + Ysum = [] + + for rep in range(replica): + + with open(path + '/' + ls[rep], 'rb') as fp: + # Read header + t = fp.read(12) + header = struct.unpack('iii', t) + if rep == 0: + dn = header[0] + nn = header[1] + tmax = header[2] + elif dn != header[0] or nn != header[1] or tmax != header[2]: + raise Exception('Replica parameters do not match.') + + t = fp.read(8) + if rep == 0: + eps = struct.unpack('d', t)[0] + print('Step size:', eps, ', Maximal t value:', dn * (nn) * eps) + elif eps != struct.unpack('d', t)[0]: + raise Exception('Values for eps do not match among replica.') + + Ysl = [] + + # Read body + while 0 < 1: + t = fp.read(4) + if(len(t) < 4): + break + nc = struct.unpack('i', t)[0] + + t = fp.read(8 * tmax * (nn + 1)) + if kwargs.get('plaquette'): + if nc % dtr_read == 0: + Ysl.append(struct.unpack('d' * tmax * (nn + 1), t)) + t = fp.read(8 * tmax * (nn + 1)) + if not kwargs.get('plaquette'): + if nc % dtr_read == 0: + Ysl.append(struct.unpack('d' * tmax * (nn + 1), t)) + t = fp.read(8 * tmax * (nn + 1)) + + Ysum.append([]) + for i, item in enumerate(Ysl): + Ysum[-1].append([np.mean(item[current + xmin:current + tmax - xmin]) for current in range(0, len(item), tmax)]) + + t2E_dict = {} + for n in range(nn + 1): + samples = [] + for nrep, rep in enumerate(Ysum): + samples.append([]) + for cnfg in rep: + samples[-1].append(cnfg[n]) + samples[-1] = samples[-1][r_start[nrep]:r_stop[nrep]] + new_obs = Obs(samples, [(w.split('.'))[0] for w in ls]) + t2E_dict[n * dn * eps] = (n * dn * eps) ** 2 * new_obs / (spatial_extent ** 3) - 0.3 + + zero_crossing = np.argmax(np.array([o.value for o in t2E_dict.values()]) > 0.0) + + x = list(t2E_dict.keys())[zero_crossing - fit_range: zero_crossing + fit_range] + y = list(t2E_dict.values())[zero_crossing - fit_range: zero_crossing + fit_range] + [o.gamma_method() for o in y] + + fit_result = fit_lin(x, y) + return -fit_result[0] / fit_result[1] diff --git a/pyerrors/jackknifing.py b/pyerrors/jackknifing.py new file mode 100644 index 00000000..d574ff2c --- /dev/null +++ b/pyerrors/jackknifing.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python +# coding: utf-8 + +import pickle +import matplotlib.pyplot as plt +import numpy as np + + +def _jack_error(jack): + n = jack.size + mean = np.mean(jack) + error = 0 + for i in range(n): + error += (jack[i] - mean) ** 2 + + return np.sqrt((n - 1) / n * error) + + +class Jack: + + def __init__(self, value, jacks): + self.jacks = jacks + self.N = list(map(np.size, self.jacks)) + self.max_binsize = len(self.N) + self.value = value #list(map(np.mean, self.jacks)) + self.dvalue = list(map(_jack_error, self.jacks)) + + + def print(self, **kwargs): + """Print basic properties of the Jack.""" + + if 'binsize' in kwargs: + b = kwargs.get('binsize') - 1 + if b == -1: + b = 0 + if not isinstance(b, int): + raise TypeError('binsize has to be integer') + if b + 1 > self.max_binsize: + raise Exception('Chosen binsize not calculated') + else: + b = 0 + + print('Result:\t %3.8e +/- %3.8e +/- %3.8e (%3.3f%%)' % (self.value, self.dvalue[b], self.dvalue[b] * np.sqrt(2 * b / self.N[0]), np.abs(self.dvalue[b] / self.value * 100))) + + + def plot_tauint(self): + plt.xlabel('binsize') + plt.ylabel('tauint') + length = self.max_binsize + x = np.arange(length) + 1 + plt.errorbar(x[:], (self.dvalue[:] / self.dvalue[0]) ** 2 / 2, yerr=np.sqrt(((2 * (self.dvalue[:] / self.dvalue[0]) ** 2 * np.sqrt(2 * x[:] / self.N[0])) / 2) ** 2 + + ((2 * (self.dvalue[:] / self.dvalue[0]) ** 2 * np.sqrt(2 / self.N[0])) / 2) ** 2), linewidth=1, capsize=2) + plt.xlim(0.5, length + 0.5) + plt.title('Tauint') + plt.show() + + + def plot_history(self): + N = self.N + x = np.arange(N) + tmp = [] + for i in range(self.replicas): + tmp.append(self.deltas[i] + self.r_values[i]) + y = np.concatenate(tmp, axis=0) # Think about including kwarg to look only at some replica + plt.errorbar(x, y, fmt='.', markersize=3) + plt.xlim(-0.5, N - 0.5) + plt.show() + + def dump(self, name, **kwargs): + """Dump the Jack to a pickle file 'name'. + + Keyword arguments: + path -- specifies a custom path for the file (default '.') + """ + if 'path' in kwargs: + file_name = kwargs.get('path') + '/' + name + '.p' + else: + file_name = name + '.p' + with open(file_name, 'wb') as fb: + pickle.dump(self, fb) + + +def generate_jack(obs, **kwargs): + full_data = [] + for r, name in enumerate(obs.names): + if r == 0: + full_data = obs.deltas[name] + obs.r_values[name] + else: + full_data = np.append(full_data, obs.deltas[name] + obs.r_values[name]) + + jacks = [] + if 'max_binsize' in kwargs: + max_b = kwargs.get('max_binsize') + if not isinstance(max_b, int): + raise TypeError('max_binsize has to be integer') + else: + max_b = 1 + + for b in range(max_b): + #binning if necessary + if b > 0: + n = full_data.size // (b + 1) + binned_data = np.zeros(n) + for i in range(n): + for j in range(b + 1): + binned_data[i] += full_data[i * (b + 1) + j] + binned_data[i] /= (b + 1) + else: + binned_data = full_data + n = binned_data.size + #generate jacks from data + mean = np.mean(binned_data) + tmp_jacks = np.zeros(n) + #print(binned_data) + for i in range(n): + tmp_jacks[i] = (n * mean - binned_data[i]) / (n - 1) + jacks.append(tmp_jacks) + + # Value is not correctly reproduced here + return Jack(obs.value, jacks) + + +def derived_jack(func, data, **kwargs): + """Construct a derived Jack according to func(data, **kwargs). + + Parameters + ---------- + func -- arbitrary function of the form func(data, **kwargs). For the automatic differentiation to work, + all numpy functions have to have the autograd wrapper (use 'import autograd.numpy as np'). + data -- list of Jacks, e.g. [jack1, jack2, jack3]. + + Notes + ----- + For simple mathematical operations it can be practical to use anonymous functions. + For the ratio of two jacks one can e.g. use + + new_jack = derived_jack(lambda x : x[0] / x[1], [jack1, jack2]) + + """ + + # Check shapes of data + if not all(x.N == data[0].N for x in data): + raise Exception('Error: Shape of data does not fit') + + values = np.zeros(len(data)) + for j, item in enumerate(data): + values[j] = item.value + new_value = func(values, **kwargs) + + jacks = [] + for b in range(data[0].max_binsize): + tmp_jacks = np.zeros(data[0].N[b]) + for i in range(data[0].N[b]): + values = np.zeros(len(data)) + for j, item in enumerate(data): + values[j] = item.jacks[b][i] + tmp_jacks[i] = func(values, **kwargs) + jacks.append(tmp_jacks) + + return Jack(new_value, jacks) diff --git a/pyerrors/linalg.py b/pyerrors/linalg.py new file mode 100644 index 00000000..6e3a99e2 --- /dev/null +++ b/pyerrors/linalg.py @@ -0,0 +1,347 @@ +#!/usr/bin/env python +# coding: utf-8 + +import numpy as np +import autograd.numpy as anp # Thinly-wrapped numpy +from .pyerrors import derived_observable + + +### This code block is directly taken from the current master branch of autograd and remains +# only until the new version is released on PyPi +from functools import partial +from autograd.extend import defvjp + +_dot = partial(anp.einsum, '...ij,...jk->...ik') +# batched diag +_diag = lambda a: anp.eye(a.shape[-1])*a +# batched diagonal, similar to matrix_diag in tensorflow +def _matrix_diag(a): + reps = anp.array(a.shape) + reps[:-1] = 1 + reps[-1] = a.shape[-1] + newshape = list(a.shape) + [a.shape[-1]] + return _diag(anp.tile(a, reps).reshape(newshape)) + +# https://arxiv.org/pdf/1701.00392.pdf Eq(4.77) +# Note the formula from Sec3.1 in https://people.maths.ox.ac.uk/gilesm/files/NA-08-01.pdf is incomplete +def grad_eig(ans, x): + """Gradient of a general square (complex valued) matrix""" + e, u = ans # eigenvalues as 1d array, eigenvectors in columns + n = e.shape[-1] + def vjp(g): + ge, gu = g + ge = _matrix_diag(ge) + f = 1/(e[..., anp.newaxis, :] - e[..., :, anp.newaxis] + 1.e-20) + f -= _diag(f) + ut = anp.swapaxes(u, -1, -2) + r1 = f * _dot(ut, gu) + r2 = -f * (_dot(_dot(ut, anp.conj(u)), anp.real(_dot(ut, gu)) * anp.eye(n))) + r = _dot(_dot(anp.linalg.inv(ut), ge + r1 + r2), ut) + if not anp.iscomplexobj(x): + r = anp.real(r) + # the derivative is still complex for real input (imaginary delta is allowed), real output + # but the derivative should be real in real input case when imaginary delta is forbidden + return r + return vjp +defvjp(anp.linalg.eig, grad_eig) +### End of the code block from autograd.master + + +def scalar_mat_op(op, obs, **kwargs): + """Computes the matrix to scalar operation op to a given matrix of Obs.""" + def _mat(x, **kwargs): + dim = int(np.sqrt(len(x))) + if np.sqrt(len(x)) != dim: + raise Exception('Input has to have dim**2 entries') + + mat = [] + for i in range(dim): + row = [] + for j in range(dim): + row.append(x[j + dim * i]) + mat.append(row) + + return op(anp.array(mat)) + + if isinstance(obs, np.ndarray): + raveled_obs = (1 * (obs.ravel())).tolist() + elif isinstance(obs, list): + raveled_obs = obs + else: + raise TypeError('Unproper type of input.') + return derived_observable(_mat, raveled_obs, **kwargs) + + +def mat_mat_op(op, obs, **kwargs): + """Computes the matrix to matrix operation op to a given matrix of Obs.""" + if kwargs.get('num_grad') is True: + return _num_diff_mat_mat_op(op, obs, **kwargs) + return derived_observable(lambda x, **kwargs: op(x), obs) + + +def eigh(obs, **kwargs): + """Computes the eigenvalues and eigenvectors of a given hermitian matrix of Obs according to np.linalg.eigh.""" + if kwargs.get('num_grad') is True: + return _num_diff_eigh(obs, **kwargs) + w = derived_observable(lambda x, **kwargs: anp.linalg.eigh(x)[0], obs) + v = derived_observable(lambda x, **kwargs: anp.linalg.eigh(x)[1], obs) + return w, v + + +def eig(obs, **kwargs): + """Computes the eigenvalues of a given matrix of Obs according to np.linalg.eig.""" + if kwargs.get('num_grad') is True: + return _num_diff_eig(obs, **kwargs) + # Note: Automatic differentiation of eig is implemented in the git of autograd + # but not yet released to PyPi (1.3) + w = derived_observable(lambda x, **kwargs: anp.real(anp.linalg.eig(x)[0]), obs) + return w + + +def pinv(obs, **kwargs): + """Computes the Moore-Penrose pseudoinverse of a matrix of Obs.""" + if kwargs.get('num_grad') is True: + return _num_diff_pinv(obs, **kwargs) + return derived_observable(lambda x, **kwargs: anp.linalg.pinv(x), obs) + + +def svd(obs, **kwargs): + """Computes the singular value decomposition of a matrix of Obs.""" + if kwargs.get('num_grad') is True: + return _num_diff_svd(obs, **kwargs) + u = derived_observable(lambda x, **kwargs: anp.linalg.svd(x, full_matrices=False)[0], obs) + s = derived_observable(lambda x, **kwargs: anp.linalg.svd(x, full_matrices=False)[1], obs) + vh = derived_observable(lambda x, **kwargs: anp.linalg.svd(x, full_matrices=False)[2], obs) + return (u, s, vh) + + +def slog_det(obs, **kwargs): + """Computes the determinant of a matrix of Obs via np.linalg.slogdet.""" + def _mat(x): + dim = int(np.sqrt(len(x))) + if np.sqrt(len(x)) != dim: + raise Exception('Input has to have dim**2 entries') + + mat = [] + for i in range(dim): + row = [] + for j in range(dim): + row.append(x[j + dim * i]) + mat.append(row) + + (sign, logdet) = anp.linalg.slogdet(np.array(mat)) + return sign * anp.exp(logdet) + + if isinstance(obs, np.ndarray): + return derived_observable(_mat, (1 * (obs.ravel())).tolist(), **kwargs) + elif isinstance(obs, list): + return derived_observable(_mat, obs, **kwargs) + else: + raise TypeError('Unproper type of input.') + + +# Variants for numerical differentiation + +def _num_diff_mat_mat_op(op, obs, **kwargs): + """Computes the matrix to matrix operation op to a given matrix of Obs elementwise + which is suitable for numerical differentiation.""" + def _mat(x, **kwargs): + dim = int(np.sqrt(len(x))) + if np.sqrt(len(x)) != dim: + raise Exception('Input has to have dim**2 entries') + + mat = [] + for i in range(dim): + row = [] + for j in range(dim): + row.append(x[j + dim * i]) + mat.append(row) + + return op(np.array(mat))[kwargs.get('i')][kwargs.get('j')] + + if isinstance(obs, np.ndarray): + raveled_obs = (1 * (obs.ravel())).tolist() + elif isinstance(obs, list): + raveled_obs = obs + else: + raise TypeError('Unproper type of input.') + + dim = int(np.sqrt(len(raveled_obs))) + + res_mat = [] + for i in range(dim): + row = [] + for j in range(dim): + row.append(derived_observable(_mat, raveled_obs, i=i, j=j, **kwargs)) + res_mat.append(row) + + return np.array(res_mat) @ np.identity(dim) + + +def _num_diff_eigh(obs, **kwargs): + """Computes the eigenvalues and eigenvectors of a given hermitian matrix of Obs according to np.linalg.eigh + elementwise which is suitable for numerical differentiation.""" + def _mat(x, **kwargs): + dim = int(np.sqrt(len(x))) + if np.sqrt(len(x)) != dim: + raise Exception('Input has to have dim**2 entries') + + mat = [] + for i in range(dim): + row = [] + for j in range(dim): + row.append(x[j + dim * i]) + mat.append(row) + + n = kwargs.get('n') + res = np.linalg.eigh(np.array(mat))[n] + + if n == 0: + return res[kwargs.get('i')] + else: + return res[kwargs.get('i')][kwargs.get('j')] + + if isinstance(obs, np.ndarray): + raveled_obs = (1 * (obs.ravel())).tolist() + elif isinstance(obs, list): + raveled_obs = obs + else: + raise TypeError('Unproper type of input.') + + dim = int(np.sqrt(len(raveled_obs))) + + res_vec = [] + for i in range(dim): + res_vec.append(derived_observable(_mat, raveled_obs, n=0, i=i, **kwargs)) + + + res_mat = [] + for i in range(dim): + row = [] + for j in range(dim): + row.append(derived_observable(_mat, raveled_obs, n=1, i=i, j=j, **kwargs)) + res_mat.append(row) + + return (np.array(res_vec) @ np.identity(dim), np.array(res_mat) @ np.identity(dim)) + + +def _num_diff_eig(obs, **kwargs): + """Computes the eigenvalues of a given matrix of Obs according to np.linalg.eig + elementwise which is suitable for numerical differentiation.""" + def _mat(x, **kwargs): + dim = int(np.sqrt(len(x))) + if np.sqrt(len(x)) != dim: + raise Exception('Input has to have dim**2 entries') + + mat = [] + for i in range(dim): + row = [] + for j in range(dim): + row.append(x[j + dim * i]) + mat.append(row) + + n = kwargs.get('n') + res = np.linalg.eig(np.array(mat))[n] + + if n == 0: + # Discard imaginary part of eigenvalue here + return np.real(res[kwargs.get('i')]) + else: + return res[kwargs.get('i')][kwargs.get('j')] + + if isinstance(obs, np.ndarray): + raveled_obs = (1 * (obs.ravel())).tolist() + elif isinstance(obs, list): + raveled_obs = obs + else: + raise TypeError('Unproper type of input.') + + dim = int(np.sqrt(len(raveled_obs))) + + res_vec = [] + for i in range(dim): + # Note: Automatic differentiation of eig is implemented in the git of autograd + # but not yet released to PyPi (1.3) + res_vec.append(derived_observable(_mat, raveled_obs, n=0, i=i, **kwargs)) + + return np.array(res_vec) @ np.identity(dim) + + +def _num_diff_pinv(obs, **kwargs): + """Computes the Moore-Penrose pseudoinverse of a matrix of Obs elementwise which is suitable + for numerical differentiation.""" + def _mat(x, **kwargs): + shape = kwargs.get('shape') + + mat = [] + for i in range(shape[0]): + row = [] + for j in range(shape[1]): + row.append(x[j + shape[1] * i]) + mat.append(row) + + return np.linalg.pinv(np.array(mat))[kwargs.get('i')][kwargs.get('j')] + + if isinstance(obs, np.ndarray): + shape = obs.shape + raveled_obs = (1 * (obs.ravel())).tolist() + else: + raise TypeError('Unproper type of input.') + + res_mat = [] + for i in range(shape[1]): + row = [] + for j in range(shape[0]): + row.append(derived_observable(_mat, raveled_obs, shape=shape, i=i, j=j, **kwargs)) + res_mat.append(row) + + return np.array(res_mat) @ np.identity(shape[0]) + + +def _num_diff_svd(obs, **kwargs): + """Computes the singular value decomposition of a matrix of Obs elementwise which + is suitable for numerical differentiation.""" + def _mat(x, **kwargs): + shape = kwargs.get('shape') + + mat = [] + for i in range(shape[0]): + row = [] + for j in range(shape[1]): + row.append(x[j + shape[1] * i]) + mat.append(row) + + res = np.linalg.svd(np.array(mat), full_matrices=False) + + if kwargs.get('n') == 1: + return res[1][kwargs.get('i')] + else: + return res[kwargs.get('n')][kwargs.get('i')][kwargs.get('j')] + + if isinstance(obs, np.ndarray): + shape = obs.shape + raveled_obs = (1 * (obs.ravel())).tolist() + else: + raise TypeError('Unproper type of input.') + + mid_index = min(shape[0], shape[1]) + + res_mat0 = [] + for i in range(shape[0]): + row = [] + for j in range(mid_index): + row.append(derived_observable(_mat, raveled_obs, shape=shape, n=0, i=i, j=j, **kwargs)) + res_mat0.append(row) + + res_mat1 = [] + for i in range(mid_index): + res_mat1.append(derived_observable(_mat, raveled_obs, shape=shape, n=1, i=i, **kwargs)) + + res_mat2 = [] + for i in range(mid_index): + row = [] + for j in range(shape[1]): + row.append(derived_observable(_mat, raveled_obs, shape=shape, n=2, i=i, j=j, **kwargs)) + res_mat2.append(row) + + return (np.array(res_mat0) @ np.identity(mid_index), np.array(res_mat1) @ np.identity(mid_index), np.array(res_mat2) @ np.identity(shape[1])) diff --git a/pyerrors/misc.py b/pyerrors/misc.py new file mode 100644 index 00000000..f059d543 --- /dev/null +++ b/pyerrors/misc.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# coding: utf-8 + +import gc +import numpy as np +import scipy.stats +import matplotlib.pyplot as plt +from .pyerrors import Obs + + +def gen_correlated_data(means, cov, name, tau=0.5, samples=1000): + """ Generate observables with given covariance and autocorrelation times. + + Arguments + ----------------- + means -- list containing the mean value of each observable. + cov -- covariance matrix for the data to be geneated. + name -- ensemble name for the data to be geneated. + tau -- can either be a real number or a list with an entry for + every dataset. + samples -- number of samples to be generated for each observable. + """ + + assert len(means) == cov.shape[-1] + tau = np.asarray(tau) + if np.min(tau) < 0.5: + raise Exception('All integrated autocorrelations have to be >= 0.5.') + + a = (2 * tau - 1) / (2 * tau + 1) + rand = np.random.multivariate_normal(np.zeros_like(means), cov * samples, samples) + + # Normalize samples such that sample variance matches input + norm = np.array([np.var(o, ddof=1) / samples for o in rand.T]) + rand = rand @ np.diag(np.sqrt(np.diag(cov))) @ np.diag(1 / np.sqrt(norm)) + + data = [rand[0]] + for i in range(1, samples): + data.append(np.sqrt(1 - a ** 2) * rand[i] + a * data[-1]) + corr_data = np.array(data) - np.mean(data, axis=0) + means + return [Obs([dat], [name]) for dat in corr_data.T] + + +def ks_test(obs=None): + """Performs a Kolmogorov–Smirnov test for the Q-values of a list of Obs. + + If no list is given all Obs in memory are used. + + Disclaimer: The determination of the individual Q-values as well as this function have not been tested yet. + """ + + if obs is None: + obs_list = [] + for obj in gc.get_objects(): + if isinstance(obj, Obs): + obs_list.append(obj) + else: + obs_list = obs + + Qs = [] + for obs_i in obs_list: + for ens in obs_i.e_names: + if obs_i.e_Q[ens] is not None: + Qs.append(obs_i.e_Q[ens]) + + bins = len(Qs) + x = np.arange(0, 1.001, 0.001) + plt.plot(x, x, 'k', zorder=1) + plt.xlim(0, 1) + plt.ylim(0, 1) + plt.xlabel('Q value') + plt.ylabel('Cumulative probability') + plt.title(str(bins) + ' Q values') + + n = np.arange(1, bins + 1) / np.float(bins) + Xs = np.sort(Qs) + plt.step(Xs, n) + diffs = n - Xs + loc_max_diff = np.argmax(np.abs(diffs)) + loc = Xs[loc_max_diff] + plt.annotate(s='', xy=(loc, loc), xytext=(loc, loc + diffs[loc_max_diff]), arrowprops=dict(arrowstyle='<->', shrinkA=0, shrinkB=0)) + plt.show() + + print(scipy.stats.kstest(Qs, 'uniform')) + diff --git a/pyerrors/mpm.py b/pyerrors/mpm.py new file mode 100644 index 00000000..3ea99f1a --- /dev/null +++ b/pyerrors/mpm.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# coding: utf-8 + +import numpy as np +import scipy.linalg +from .pyerrors import Obs +from .linalg import svd, eig, pinv + + +def matrix_pencil_method(corrs, k=1, p=None, **kwargs): + """ Matrix pencil method to extract k energy levels from data + + Implementation of the matrix pencil method based on + eq. (2.17) of Y. Hua, T. K. Sarkar, IEEE Trans. Acoust. 38, 814-824 (1990) + + Parameters + ---------- + data -- can be a list of Obs for the analysis of a single correlator, or a list of lists + of Obs if several correlators are to analyzed at once. + k -- Number of states to extract (default 1). + p -- matrix pencil parameter which filters noise. The optimal value is expected between + len(data)/3 and 2*len(data)/3. The computation is more expensive the closer p is + to len(data)/2 but could possibly suppress more noise (default len(data)//2). + """ + if isinstance(corrs[0], Obs): + data = [corrs] + else: + data = corrs + + lengths = [len(d) for d in data] + if lengths.count(lengths[0]) != len(lengths): + raise Exception('All datasets have to have the same length.') + + data_sets = len(data) + n_data = len(data[0]) + + if p is None: + p = max(n_data // 2, k) + if n_data <= p: + raise Exception('The pencil p has to be smaller than the number of data samples.') + if p < k or n_data - p < k: + raise Exception('Cannot extract', k, 'energy levels with p=', p, 'and N-p=', n_data - p) + + # Construct the hankel matrices + matrix = [] + for n in range(data_sets): + matrix.append(scipy.linalg.hankel(data[n][:n_data-p], data[n][n_data-p-1:])) + matrix = np.array(matrix) + # Construct y1 and y2 + y1 = np.concatenate(matrix[:, :, :p]) + y2 = np.concatenate(matrix[:, :, 1:]) + # Apply SVD to y2 + u, s, vh = svd(y2, **kwargs) + # Construct z from y1 and SVD of y2, setting all singular values beyond the kth to zero + z = np.diag(1. / s[:k]) @ u[:, :k].T @ y1 @ vh.T[:, :k] + # Return the sorted logarithms of the real eigenvalues as Obs + energy_levels = np.log(np.abs(eig(z, **kwargs))) + return sorted(energy_levels, key=lambda x: abs(x.value)) + + +def matrix_pencil_method_old(data, p, noise_level=None, verbose=1, **kwargs): + """ Older impleentation of the matrix pencil method with pencil p on given data to + extract energy levels. + + Parameters + ---------- + data -- lists of Obs, where the nth entry is considered to be the correlation function + at x0=n+offset. + p -- matrix pencil parameter which corresponds to the number of energy levels to extract. + higher values for p can help decreasing noise. + noise_level -- If this argument is not None an additional prefiltering via singular + value decomposition is performed in which all singular values below 10^(-noise_level) + times the largest singular value are discarded. This increases the computation time. + verbose -- if larger than zero details about the noise filtering are printed to stdout + (default 1) + + """ + n_data = len(data) + if n_data <= p: + raise Exception('The pencil p has to be smaller than the number of data samples.') + + matrix = scipy.linalg.hankel(data[:n_data-p], data[n_data-p-1:]) @ np.identity(p + 1) + + if noise_level is not None: + u, s, vh = svd(matrix) + + s_values = np.vectorize(lambda x: x.value)(s) + if verbose > 0: + print('Singular values: ', s_values) + digit = np.argwhere(s_values / s_values[0] < 10.0**(-noise_level)) + if digit.size == 0: + digit = len(s_values) + else: + digit = int(digit[0]) + if verbose > 0: + print('Consider only', digit, 'out of', len(s), 'singular values') + + new_matrix = u[:, :digit] * s[:digit] @ vh[:digit, :] + y1 = new_matrix[:, :-1] + y2 = new_matrix[:, 1:] + else: + y1 = matrix[:, :-1] + y2 = matrix[:, 1:] + + # Moore–Penrose pseudoinverse + pinv_y1 = pinv(y1) + + # Note: Automatic differentiation of eig is implemented in the git of autograd + # but not yet released to PyPi (1.3). The code is currently part of pyerrors + e = eig((pinv_y1 @ y2), **kwargs) + energy_levels = -np.log(np.abs(e)) + return sorted(energy_levels, key=lambda x: abs(x.value)) diff --git a/pyerrors/pyerrors.py b/pyerrors/pyerrors.py new file mode 100644 index 00000000..22632754 --- /dev/null +++ b/pyerrors/pyerrors.py @@ -0,0 +1,1222 @@ +#!/usr/bin/env python +# coding: utf-8 + +import pickle +import numpy as np +import autograd.numpy as anp # Thinly-wrapped numpy +from autograd import jacobian +import matplotlib.pyplot as plt +import numdifftools as nd +import scipy.special + + +class Obs: + """Class for a general observable. + + Instances of Obs are the basic objects of a pyerrors error analysis. + They are initialized with a list which contains arrays of samples for + different ensembles/replica and another list of same length which contains + the names of the ensembles/replica. Mathematical operations can be + performed on instances. The result is another instance of Obs. The error of + an instance can be computed with the gamma_method. Also contains additional + methods for output and visualization of the error calculation. + + Attributes + ---------- + e_tag_global -- Integer which determines which part of the name belongs + to the ensemble and which to the replicum. + S_global -- Standard value for S (default 2.0) + S_dict -- Dictionary for S values. If an entry for a given ensemble + exists this overwrites the standard value for that ensemble. + tau_exp_global -- Standard value for tau_exp (default 0.0) + tau_exp_dict -- Dictionary for tau_exp values. If an entry for a given + ensemble exists this overwrites the standard value for that + ensemble. + N_sigma_global -- Standard value for N_sigma (default 1.0) + """ + + e_tag_global = 0 + S_global = 2.0 + S_dict = {} + tau_exp_global = 0.0 + tau_exp_dict = {} + N_sigma_global = 1.0 + + def __init__(self, samples, names): + + if len(samples) != len(names): + raise Exception('Length of samples and names incompatible.') + if len(names) != len(set(names)): + raise Exception('Names are not unique.') + if not all(isinstance(x, str) for x in names): + raise TypeError('All names have to be strings.') + if min(len(x) for x in samples) <= 4: + raise Exception('Samples have to have at least 4 entries.') + + self.names = sorted(names) + self.shape = {} + self.r_values = {} + self.deltas = {} + for name, sample in sorted(zip(names, samples)): + self.shape[name] = np.size(sample) + self.r_values[name] = np.mean(sample) + self.deltas[name] = sample - self.r_values[name] + + self.N = sum(map(np.size, list(self.deltas.values()))) + + self.value = 0 + for name in self.names: + self.value += self.shape[name] * self.r_values[name] + self.value /= self.N + + self.dvalue = 0.0 + self.ddvalue = 0.0 + self.reweighted = 0 + + self.S = {} + self.tau_exp = {} + self.N_sigma = 0 + + self.e_names = {} + self.e_content = {} + + self.e_dvalue = {} + self.e_ddvalue = {} + self.e_tauint = {} + self.e_dtauint = {} + self.e_windowsize = {} + self.e_Q = {} + self.e_rho = {} + self.e_drho = {} + self.e_n_tauint = {} + self.e_n_dtauint = {} + + + def gamma_method(self, **kwargs): + """Calculate the error and related properties of the Obs. + + Keyword arguments + ----------------- + S -- specifies a custom value for the parameter S (default 2.0), can be + a float or an array of floats for different ensembles + tau_exp -- positive value triggers the critical slowing down analysis + (default 0.0), can be a float or an array of floats for + different ensembles + N_sigma -- number of standard deviations from zero until the tail is + attached to the autocorrelation function (default 1) + e_tag -- number of characters which label the ensemble. The remaining + ones label replica (default 0) + fft -- boolean, which determines whether the fft algorithm is used for + the computation of the autocorrelation function (default True) + """ + + if 'e_tag' in kwargs: + e_tag_local = kwargs.get('e_tag') + if not isinstance(e_tag_local, int): + raise TypeError('Error: e_tag is not integer') + else: + e_tag_local = Obs.e_tag_global + + self.e_names = sorted(set([o[:e_tag_local] for o in self.names])) + self.e_content = {} + self.e_dvalue = {} + self.e_ddvalue = {} + self.e_tauint = {} + self.e_dtauint = {} + self.e_windowsize = {} + self.e_n_tauint = {} + self.e_n_dtauint = {} + e_gamma = {} + self.e_rho = {} + self.e_drho = {} + self.dvalue = 0 + self.ddvalue = 0 + + self.S = {} + self.tau_exp = {} + + if kwargs.get('fft') is False: + fft = False + else: + fft = True + + if 'S' in kwargs: + tmp = kwargs.get('S') + if isinstance(tmp, list): + if len(tmp) != len(self.e_names): + raise Exception('Length of S array does not match ensembles.') + for e, e_name in enumerate(self.e_names): + if tmp[e] <= 0: + raise Exception('S has to be larger than 0.') + self.S[e_name] = tmp[e] + else: + if isinstance(tmp, (int, float)): + if tmp <= 0: + raise Exception('S has to be larger than 0.') + for e, e_name in enumerate(self.e_names): + self.S[e_name] = tmp + else: + raise TypeError('S is not in proper format.') + else: + for e, e_name in enumerate(self.e_names): + if e_name in Obs.S_dict: + self.S[e_name] = Obs.S_dict[e_name] + else: + self.S[e_name] = Obs.S_global + + if 'tau_exp' in kwargs: + tmp = kwargs.get('tau_exp') + if isinstance(tmp, list): + if len(tmp) != len(self.e_names): + raise Exception('Length of tau_exp array does not match ensembles.') + for e, e_name in enumerate(self.e_names): + if tmp[e] < 0: + raise Exception('tau_exp smaller than 0.') + self.tau_exp[e_name] = tmp[e] + else: + if isinstance(tmp, (int, float)): + if tmp < 0: + raise Exception('tau_exp smaller than 0.') + for e, e_name in enumerate(self.e_names): + self.tau_exp[e_name] = tmp + else: + raise TypeError('tau_exp is not in proper format.') + else: + for e, e_name in enumerate(self.e_names): + if e_name in Obs.tau_exp_dict: + self.tau_exp[e_name] = Obs.tau_exp_dict[e_name] + else: + self.tau_exp[e_name] = Obs.tau_exp_global + + if 'N_sigma' in kwargs: + self.N_sigma = kwargs.get('N_sigma') + if not isinstance(self.N_sigma, (int, float)): + raise TypeError('N_sigma is not a number.') + else: + self.N_sigma = Obs.N_sigma_global + + if max([len(x) for x in self.names]) <= e_tag_local: + for e, e_name in enumerate(self.e_names): + self.e_content[e_name] = [e_name] + else: + for e, e_name in enumerate(self.e_names): + if len(e_name) < e_tag_local: + self.e_content[e_name] = [e_name] + else: + self.e_content[e_name] = sorted(filter(lambda x: x.startswith(e_name), self.names)) + + for e, e_name in enumerate(self.e_names): + + r_length = [] + for r_name in self.e_content[e_name]: + r_length.append(len(self.deltas[r_name])) + + e_N = np.sum(r_length) + w_max = max(r_length) // 2 + e_gamma[e_name] = np.zeros(w_max) + self.e_rho[e_name] = np.zeros(w_max) + self.e_drho[e_name] = np.zeros(w_max) + + if fft: + for r_name in self.e_content[e_name]: + max_gamma = min(self.shape[r_name], w_max) + # The padding for the fft has to be even + padding = self.shape[r_name] + max_gamma + (self.shape[r_name] + max_gamma) % 2 + e_gamma[e_name][:max_gamma] += np.fft.irfft(np.abs(np.fft.rfft(self.deltas[r_name], padding)) ** 2)[:max_gamma] + else: + for n in range(w_max): + for r_name in self.e_content[e_name]: + if self.shape[r_name] - n >= 0: + e_gamma[e_name][n] += self.deltas[r_name][0:self.shape[r_name] - n].dot(self.deltas[r_name][n:self.shape[r_name]]) + + e_shapes = [] + for r_name in self.e_content[e_name]: + e_shapes.append(self.shape[r_name]) + + div = np.array([]) + mul = np.array([]) + sorted_shapes = sorted(e_shapes) + for i, item in enumerate(sorted_shapes): + if len(div) > w_max: + break + if i == 0: + samples = item + else: + samples = item - sorted_shapes[i - 1] + div = np.append(div, np.repeat(np.sum(sorted_shapes[i:]), samples)) + mul = np.append(mul, np.repeat(len(sorted_shapes) - i, samples)) + div = div - np.arange(len(div)) * mul + + e_gamma[e_name] /= div[:w_max] + + if np.abs(e_gamma[e_name][0]) < 10 * np.finfo(float).tiny: # Prevent division by zero + self.e_tauint[e_name] = 0.5 + self.e_dtauint[e_name] = 0.0 + self.e_dvalue[e_name] = 0.0 + self.e_ddvalue[e_name] = 0.0 + self.e_windowsize[e_name] = 0 + continue + + self.e_rho[e_name] = e_gamma[e_name][:w_max] / e_gamma[e_name][0] + self.e_n_tauint[e_name] = np.cumsum(np.concatenate(([0.5], self.e_rho[e_name][1:]))) + # Make sure no entry of tauint is smaller than 0.5 + self.e_n_tauint[e_name][self.e_n_tauint[e_name] < 0.5] = 0.500000000001 + # hep-lat/0306017 eq. (42) + self.e_n_dtauint[e_name] = self.e_n_tauint[e_name] * 2 * np.sqrt(np.abs(np.arange(w_max) + + 0.5 - self.e_n_tauint[e_name]) / e_N) + self.e_n_dtauint[e_name][0] = 0.0 + + + def _compute_drho(i): + tmp = self.e_rho[e_name][i+1:w_max] + np.concatenate([self.e_rho[e_name][i-1::-1], self.e_rho[e_name][1:w_max - 2 * i]]) - 2 * self.e_rho[e_name][i] * self.e_rho[e_name][1:w_max - i] + self.e_drho[e_name][i] = np.sqrt(np.sum(tmp ** 2) / e_N) + + + _compute_drho(1) + if self.tau_exp[e_name] > 0: + # Critical slowing down analysis + for n in range(1, w_max // 2): + _compute_drho(n + 1) + if (self.e_rho[e_name][n] - self.N_sigma * self.e_drho[e_name][n]) < 0 or n >= w_max // 2 - 2: + # Bias correction hep-lat/0306017 eq. (49) included + self.e_tauint[e_name] = self.e_n_tauint[e_name][n] * (1 + (2 * n + 1) / e_N) / (1 + 1 / e_N) + self.tau_exp[e_name] * np.abs(self.e_rho[e_name][n + 1]) + # The absolute makes sure, that the tail contribution is always positive + self.e_dtauint[e_name] = np.sqrt(self.e_n_dtauint[e_name][n] ** 2 + self.tau_exp[e_name] ** 2 * self.e_drho[e_name][n + 1] ** 2) + # Error of tau_exp neglected so far, missing term: self.e_rho[e_name][n + 1] ** 2 * d_tau_exp ** 2 + self.e_dvalue[e_name] = np.sqrt(2 * self.e_tauint[e_name] * e_gamma[e_name][0] * (1 + 1 / e_N) / e_N) + self.e_ddvalue[e_name] = self.e_dvalue[e_name] * np.sqrt((n + 0.5) / e_N) + self.e_windowsize[e_name] = n + break + else: + # Standard automatic windowing procedure + g_w = self.S[e_name] / np.log((2 * self.e_n_tauint[e_name][1:] + 1) / (2 * self.e_n_tauint[e_name][1:] - 1)) + g_w = np.exp(- np.arange(1, w_max) / g_w) - g_w / np.sqrt(np.arange(1, w_max) * e_N) + for n in range(1, w_max): + if n < w_max // 2 - 2: + _compute_drho(n + 1) + if g_w[n - 1] < 0 or n >= w_max - 1: + self.e_tauint[e_name] = self.e_n_tauint[e_name][n] * (1 + (2 * n + 1) / e_N) / (1 + 1 / e_N) # Bias correction hep-lat/0306017 eq. (49) + self.e_dtauint[e_name] = self.e_n_dtauint[e_name][n] + self.e_dvalue[e_name] = np.sqrt(2 * self.e_tauint[e_name] * e_gamma[e_name][0] * (1 + 1 / e_N) / e_N) + self.e_ddvalue[e_name] = self.e_dvalue[e_name] * np.sqrt((n + 0.5) / e_N) + self.e_windowsize[e_name] = n + break + + if len(self.e_content[e_name]) > 1 and self.e_dvalue[e_name] > np.finfo(np.float).eps: + e_mean = 0 + for r_name in self.e_content[e_name]: + e_mean += self.shape[r_name] * self.r_values[r_name] + e_mean /= e_N + xi2 = 0 + for r_name in self.e_content[e_name]: + xi2 += self.shape[r_name] * (self.r_values[r_name] - e_mean) ** 2 + xi2 /= self.e_dvalue[e_name] ** 2 * e_N + self.e_Q[e_name] = 1 - scipy.special.gammainc((len(self.e_content[e_name]) - 1.0) / 2.0, xi2 / 2.0) + else: + self.e_Q[e_name] = None + + self.dvalue += self.e_dvalue[e_name] ** 2 + self.ddvalue += (self.e_dvalue[e_name] * self.e_ddvalue[e_name]) ** 2 + + self.dvalue = np.sqrt(self.dvalue) + if self.dvalue == 0.0: + self.ddvalue = 0.0 + else: + self.ddvalue = np.sqrt(self.ddvalue) / self.dvalue + return 0 + + + def print(self, level=1): + """Print basic properties of the Obs.""" + if level == 0: + print(self) + else: + print('Result\t %3.8e +/- %3.8e +/- %3.8e (%3.3f%%)' % (self.value, self.dvalue, self.ddvalue, np.abs(self.dvalue / self.value) * 100)) + if len(self.e_names) > 1: + print(' Ensemble errors:') + for e_name in self.e_names: + if len(self.e_names) > 1: + print('', e_name, '\t %3.8e +/- %3.8e' % (self.e_dvalue[e_name], self.e_ddvalue[e_name])) + if self.tau_exp[e_name] > 0: + print(' t_int\t %3.8e +/- %3.8e tau_exp = %3.2f, N_sigma = %1.0i' % (self.e_tauint[e_name], self.e_dtauint[e_name], self.tau_exp[e_name], self.N_sigma)) + else: + print(' t_int\t %3.8e +/- %3.8e S = %3.2f' % (self.e_tauint[e_name], self.e_dtauint[e_name], self.S[e_name])) + if level > 1: + print(self.N, 'samples in', len(self.e_names), 'ensembles:') + for e_name in self.e_names: + print(e_name, ':', self.e_content[e_name]) + + + def plot_tauint(self): + """Plot integrated autocorrelation time for each ensemble.""" + if not self.e_names: + raise Exception('Run the gamma method first.') + for e, e_name in enumerate(self.e_names): + plt.xlabel('W') + plt.ylabel('tauint') + length = int(len(self.e_n_tauint[e_name])) + plt.errorbar(np.arange(length), self.e_n_tauint[e_name][:], yerr=self.e_n_dtauint[e_name][:], linewidth=1, capsize=2) + plt.axvline(x=self.e_windowsize[e_name], color='r', alpha=0.25) + if self.tau_exp[e_name] > 0: + base = self.e_n_tauint[e_name][self.e_windowsize[e_name]] + x_help = np.arange(2 * self.tau_exp[e_name]) + y_help = (x_help + 1) * np.abs(self.e_rho[e_name][self.e_windowsize[e_name]+1]) * (1 - x_help / (2 * (2 * self.tau_exp[e_name] - 1))) + base + x_arr = np.arange(self.e_windowsize[e_name] + 1, self.e_windowsize[e_name] + 1 + 2 * self.tau_exp[e_name]) + plt.plot(x_arr, y_help, 'k', linewidth=1) + plt.errorbar([self.e_windowsize[e_name] + 2 * self.tau_exp[e_name]], [self.e_tauint[e_name]], + yerr=[self.e_dtauint[e_name]], fmt='k', linewidth=1, capsize=2) + xmax = self.e_windowsize[e_name] + 2 * self.tau_exp[e_name] + 1.5 + plt.title('Tauint ' + e_name + ', tau_exp='+str(np.around(self.tau_exp[e_name], decimals=2))) + else: + xmax = max(10.5, 2 * self.e_windowsize[e_name] - 0.5) + plt.title('Tauint ' + e_name + ', S='+str(np.around(self.S[e_name], decimals=2))) + plt.xlim(-0.5, xmax) + plt.show() + + + def plot_rho(self): + """Plot normalized autocorrelation function time for each ensemble.""" + if not self.e_names: + raise Exception('Run the gamma method first.') + for e, e_name in enumerate(self.e_names): + plt.xlabel('W') + plt.ylabel('rho') + length = int(len(self.e_drho[e_name])) + plt.errorbar(np.arange(length), self.e_rho[e_name][:length], yerr=self.e_drho[e_name][:], linewidth=1, capsize=2) + plt.axvline(x=self.e_windowsize[e_name], color='r', alpha=0.25) + if self.tau_exp[e_name] > 0: + plt.plot([self.e_windowsize[e_name] + 1, self.e_windowsize[e_name] + 1 + 2 * self.tau_exp[e_name]], + [self.e_rho[e_name][self.e_windowsize[e_name] + 1], 0], 'k-', lw=1) + xmax = self.e_windowsize[e_name] + 2 * self.tau_exp[e_name] + 1.5 + plt.title('Rho ' + e_name + ', tau_exp='+str(np.around(self.tau_exp[e_name], decimals=2))) + else: + xmax = max(10.5, 2 * self.e_windowsize[e_name] - 0.5) + plt.title('Rho ' + e_name + ', S=' + str(np.around(self.S[e_name], decimals=2))) + plt.plot([-0.5, xmax], [0, 0], 'k--', lw=1) + plt.xlim(-0.5, xmax) + plt.show() + + + def plot_rep_dist(self): + """Plot replica distribution for each ensemble with more than one replicum.""" + if not self.e_names: + raise Exception('Run the gamma method first.') + for e, e_name in enumerate(self.e_names): + if len(self.e_content[e_name]) == 1: + print('No replica distribution for a single replicum (', e_name, ')') + continue + r_length = [] + sub_r_mean = 0 + for r, r_name in enumerate(self.e_content[e_name]): + r_length.append(len(self.deltas[r_name])) + sub_r_mean += self.shape[r_name] * self.r_values[r_name] + e_N = np.sum(r_length) + sub_r_mean /= e_N + arr = np.zeros(len(self.e_content[e_name])) + for r, r_name in enumerate(self.e_content[e_name]): + arr[r] = (self.r_values[r_name] - sub_r_mean) / (self.e_dvalue[e_name] * np.sqrt(e_N / self.shape[r_name] - 1)) + plt.hist(arr, rwidth=0.8, bins=len(self.e_content[e_name])) + plt.title('Replica distribution' + e_name + ' (mean=0, var=1), Q='+str(np.around(self.e_Q[e_name], decimals=2))) + plt.show() + + + def plot_history(self): + """Plot derived Monte Carlo history for each ensemble.""" + if not self.e_names: + raise Exception('Run the gamma method first.') + + for e, e_name in enumerate(self.e_names): + f = plt.figure() + r_length = [] + sub_r_mean = 0 + for r, r_name in enumerate(self.e_content[e_name]): + r_length.append(len(self.deltas[r_name])) + e_N = np.sum(r_length) + x = np.arange(e_N) + tmp = [] + for r, r_name in enumerate(self.e_content[e_name]): + tmp.append(self.deltas[r_name]+self.r_values[r_name]) + y = np.concatenate(tmp, axis=0) + plt.errorbar(x, y, fmt='.', markersize=3) + plt.xlim(-0.5, e_N - 0.5) + plt.title(e_name) + plt.show() + + + def plot_piechart(self): + """Plot piechart which shows the fractional contribution of each + ensemble to the error and returns a dictionary containing the fractions.""" + if not self.e_names: + raise Exception('Run the gamma method first.') + if self.dvalue == 0.0: + raise Exception('Error is 0.0') + labels = self.e_names + sizes = [i ** 2 for i in list(self.e_dvalue.values())] / self.dvalue ** 2 + fig1, ax1 = plt.subplots() + ax1.pie(sizes, labels=labels, startangle=90, normalize=True) + ax1.axis('equal') + plt.show() + + return dict(zip(self.e_names, sizes)) + + def dump(self, name, **kwargs): + """Dump the Obs to a pickle file 'name'. + + Keyword arguments + ----------------- + path -- specifies a custom path for the file (default '.') + """ + if 'path' in kwargs: + file_name = kwargs.get('path') + '/' + name + '.p' + else: + file_name = name + '.p' + with open(file_name, 'wb') as fb: + pickle.dump(self, fb) + + + def __repr__(self): + if self.dvalue == 0.0: + return 'Obs['+str(self.value)+']' + fexp = np.floor(np.log10(self.dvalue)) + if fexp < 0.0: + return 'Obs[{:{form}}({:2.0f})]'.format(self.value, self.dvalue * 10 ** (-fexp + 1), form='.'+str(-int(fexp) + 1) + 'f') + elif fexp == 0.0: + return 'Obs[{:.1f}({:1.1f})]'.format(self.value, self.dvalue) + else: + return 'Obs[{:.0f}({:2.0f})]'.format(self.value, self.dvalue) + + + # Overload comparisons + def __lt__(self, other): + return self.value < other + + def __gt__(self, other): + return self.value > other + + + # Overload math operations + def __add__(self, y): + if isinstance(y, Obs): + return derived_observable(lambda x, **kwargs: x[0] + x[1], [self, y], man_grad=[1, 1]) + else: + if isinstance(y, np.ndarray): + return np.array([self + o for o in y]) + else: + return derived_observable(lambda x, **kwargs: x[0] + y, [self], man_grad=[1]) + + + def __radd__(self, y): + return self + y + + + def __mul__(self, y): + if isinstance(y, Obs): + return derived_observable(lambda x, **kwargs: x[0] * x[1], [self, y], man_grad=[y.value, self.value]) + else: + if isinstance(y, np.ndarray): + return np.array([self * o for o in y]) + else: + return derived_observable(lambda x, **kwargs: x[0] * y, [self], man_grad=[y]) + + + def __rmul__(self, y): + return self * y + + + def __sub__(self, y): + if isinstance(y, Obs): + return derived_observable(lambda x, **kwargs: x[0] - x[1], [self, y], man_grad=[1, -1]) + else: + if isinstance(y, np.ndarray): + return np.array([self - o for o in y]) + else: + return derived_observable(lambda x, **kwargs: x[0] - y, [self], man_grad=[1]) + + + def __rsub__(self, y): + return -1 * (self - y) + + + def __neg__(self): + return -1 * self + + + def __truediv__(self, y): + if isinstance(y, Obs): + return derived_observable(lambda x, **kwargs: x[0] / x[1], [self, y], man_grad=[1 / y.value, - self.value / y.value ** 2]) + else: + if isinstance(y, np.ndarray): + return np.array([self / o for o in y]) + else: + return derived_observable(lambda x, **kwargs: x[0] / y, [self], man_grad=[1 / y]) + + + def __rtruediv__(self, y): + if isinstance(y, Obs): + return derived_observable(lambda x, **kwargs: x[0] / x[1], [y, self], man_grad=[1 / self.value, - y.value / self.value ** 2]) + else: + if isinstance(y, np.ndarray): + return np.array([o / self for o in y]) + else: + return derived_observable(lambda x, **kwargs: y / x[0], [self], man_grad=[-y / self.value ** 2]) + + + def __pow__(self, y): + if isinstance(y, Obs): + return derived_observable(lambda x: x[0] ** x[1], [self, y]) + else: + return derived_observable(lambda x: x[0] ** y, [self]) + + + def __rpow__(self, y): + if isinstance(y, Obs): + return derived_observable(lambda x: x[0] ** x[1], [y, self]) + else: + return derived_observable(lambda x: y ** x[0], [self]) + + + def __abs__(self): + return derived_observable(lambda x: anp.abs(x[0]), [self]) + + + # Overload numpy functions + def sqrt(self): + return derived_observable(lambda x, **kwargs: np.sqrt(x[0]), [self], man_grad=[1 / 2 / np.sqrt(self.value)]) + + + def log(self): + return derived_observable(lambda x, **kwargs: np.log(x[0]), [self], man_grad=[1 / self.value]) + + + def exp(self): + return derived_observable(lambda x, **kwargs: np.exp(x[0]), [self], man_grad=[np.exp(self.value)]) + + + def sin(self): + return derived_observable(lambda x, **kwargs: np.sin(x[0]), [self], man_grad=[np.cos(self.value)]) + + + def cos(self): + return derived_observable(lambda x, **kwargs: np.cos(x[0]), [self], man_grad=[-np.sin(self.value)]) + + + def tan(self): + return derived_observable(lambda x, **kwargs: np.tan(x[0]), [self], man_grad=[1 / np.cos(self.value) ** 2]) + + + def arcsin(self): + return derived_observable(lambda x: anp.arcsin(x[0]), [self]) + + + def arccos(self): + return derived_observable(lambda x: anp.arccos(x[0]), [self]) + + + def arctan(self): + return derived_observable(lambda x: anp.arctan(x[0]), [self]) + + + def sinh(self): + return derived_observable(lambda x, **kwargs: np.sinh(x[0]), [self], man_grad=[np.cosh(self.value)]) + + + def cosh(self): + return derived_observable(lambda x, **kwargs: np.cosh(x[0]), [self], man_grad=[np.sinh(self.value)]) + + + def tanh(self): + return derived_observable(lambda x, **kwargs: np.tanh(x[0]), [self], man_grad=[1 / np.cosh(self.value) ** 2]) + + + def arcsinh(self): + return derived_observable(lambda x: anp.arcsinh(x[0]), [self]) + + + def arccosh(self): + return derived_observable(lambda x: anp.arccosh(x[0]), [self]) + + + def arctanh(self): + return derived_observable(lambda x: anp.arctanh(x[0]), [self]) + + + def sinc(self): + return derived_observable(lambda x: anp.sinc(x[0]), [self]) + + +def derived_observable(func, data, **kwargs): + """Construct a derived Obs according to func(data, **kwargs) using automatic differentiation. + + Parameters + ---------- + func -- arbitrary function of the form func(data, **kwargs). For the + automatic differentiation to work, all numpy functions have to have + the autograd wrapper (use 'import autograd.numpy as anp'). + data -- list of Obs, e.g. [obs1, obs2, obs3]. + + Keyword arguments + ----------------- + num_grad -- if True, numerical derivatives are used instead of autograd + (default False). To control the numerical differentiation the + kwargs of numdifftools.step_generators.MaxStepGenerator + can be used. + man_grad -- manually supply a list or an array which contains the jacobian + of func. Use cautiously, supplying the wrong derivative will + not be intercepted. + bias_correction -- if True, the bias correction specified in + hep-lat/0306017 eq. (19) is performed, not recommended. + (Only applicable for more than 1 replicum) + + Notes + ----- + For simple mathematical operations it can be practical to use anonymous + functions. For the ratio of two observables one can e.g. use + + new_obs = derived_observable(lambda x: x[0] / x[1], [obs1, obs2]) + """ + + data = np.asarray(data) + raveled_data = data.ravel() + + n_obs = len(raveled_data) + new_names = sorted(set([y for x in [o.names for o in raveled_data] for y in x])) + replicas = len(new_names) + + new_shape = {} + for i_data in raveled_data: + for name in new_names: + tmp = i_data.shape.get(name) + if tmp is not None: + if new_shape.get(name) is None: + new_shape[name] = tmp + else: + if new_shape[name] != tmp: + raise Exception('Shapes of ensemble', name, 'do not match.') + + values = np.vectorize(lambda x: x.value)(data) + + new_values = func(values, **kwargs) + + multi = 0 + if isinstance(new_values, np.ndarray): + multi = 1 + + new_r_values = {} + for name in new_names: + tmp_values = np.zeros(n_obs) + for i, item in enumerate(raveled_data): + tmp = item.r_values.get(name) + if tmp is None: + tmp = item.value + tmp_values[i] = tmp + if multi > 0: + tmp_values = np.array(tmp_values).reshape(data.shape) + new_r_values[name] = func(tmp_values, **kwargs) + + if 'man_grad' in kwargs: + deriv = np.asarray(kwargs.get('man_grad')) + if new_values.shape + data.shape != deriv.shape: + raise Exception('Manual derivative does not have correct shape.') + elif kwargs.get('num_grad') is True: + if multi > 0: + raise Exception('Multi mode currently not supported for numerical derivative') + options = { + 'base_step': 0.1, + 'step_ratio': 2.5, + 'num_steps': None, + 'step_nom': None, + 'offset': None, + 'num_extrap': None, + 'use_exact_steps': None, + 'check_num_steps': None, + 'scale': None} + for key in options.keys(): + kwarg = kwargs.get(key) + if kwarg is not None: + options[key] = kwarg + tmp_df = nd.Gradient(func, order=4, **{k:v for k, v in options.items() if v is not None})(values, **kwargs) + if tmp_df.size == 1: + deriv = np.array([tmp_df.real]) + else: + deriv = tmp_df.real + else: + deriv = jacobian(func)(values, **kwargs) + + final_result = np.zeros(new_values.shape, dtype=object) + + for i_val, new_val in np.ndenumerate(new_values): + new_deltas = {} + for j_obs, obs in np.ndenumerate(data): + for name in obs.names: + new_deltas[name] = new_deltas.get(name, 0) + deriv[i_val + j_obs] * obs.deltas[name] + + new_samples = [] + for name in new_names: + new_samples.append(new_deltas[name] + new_r_values[name][i_val]) + + final_result[i_val] = Obs(new_samples, new_names) + + # Bias correction + if replicas > 1 and kwargs.get('bias_correction'): + final_result[i_val].value = (replicas * new_val - final_result[i_val].value) / (replicas - 1) + else: + final_result[i_val].value = new_val + + if multi == 0: + final_result = final_result.item() + + return final_result + + +def reweight(weight, obs, **kwargs): + """Reweight a list of observables.""" + result = [] + for i in range(len(obs)): + if sorted(weight.names) != sorted(obs[i].names): + raise Exception('Error: Ensembles do not fit') + for name in weight.names: + if weight.shape[name] != obs[i].shape[name]: + raise Exception('Error: Shapes of ensemble', name, 'do not fit') + new_samples = [] + for name in sorted(weight.names): + new_samples.append((weight.deltas[name] + weight.r_values[name]) * (obs[i].deltas[name] + obs[i].r_values[name])) + tmp_obs = Obs(new_samples, sorted(weight.names)) + + result.append(derived_observable(lambda x, **kwargs: x[0] / x[1], [tmp_obs, weight], **kwargs)) + result[-1].reweighted = 1 + + return result + + +def correlate(obs_a, obs_b): + """Correlate two observables. + + Keep in mind to only correlate primary observables which have not been reweighted + yet. The reweighting has to be applied after correlating the observables. + Currently only works if ensembles are identical. This is not really necessary. + """ + + if sorted(obs_a.names) != sorted(obs_b.names): + raise Exception('Ensembles do not fit') + for name in obs_a.names: + if obs_a.shape[name] != obs_b.shape[name]: + raise Exception('Shapes of ensemble', name, 'do not fit') + + if obs_a.reweighted == 1: + print('Warning: The first observable is already reweighted.') + if obs_b.reweighted == 1: + print('Warning: The second observable is already reweighted.') + + new_samples = [] + for name in sorted(obs_a.names): + new_samples.append((obs_a.deltas[name] + obs_a.r_values[name]) * (obs_b.deltas[name] + obs_b.r_values[name])) + + return Obs(new_samples, sorted(obs_a.names)) + + +def covariance(obs1, obs2, correlation=False, **kwargs): + """Calculates the covariance of two observables. + + covariance(obs, obs) is equal to obs.dvalue ** 2 + The gamma method has to be applied first to both observables. + + If abs(covariance(obs1, obs2)) > obs1.dvalue * obs2.dvalue, the covariance + is constrained to the maximum value in order to make sure that covariance + matrices are positive semidefinite. + + Keyword arguments + ----------------- + correlation -- if true the correlation instead of the covariance is + returned (default False) + """ + + for name in sorted(set(obs1.names + obs2.names)): + if (obs1.shape.get(name) != obs2.shape.get(name)) and (obs1.shape.get(name) is not None) and (obs2.shape.get(name) is not None): + raise Exception('Shapes of ensemble', name, 'do not fit') + + if obs1.e_names == {} or obs2.e_names == {}: + raise Exception('The gamma method has to be applied to both Obs first.') + + dvalue = 0 + + for e_name in obs1.e_names: + + if e_name not in obs2.e_names: + continue + + gamma = 0 + r_length = [] + for r_name in obs1.e_content[e_name]: + if r_name not in obs2.e_content[e_name]: + continue + + r_length.append(len(obs1.deltas[r_name])) + + gamma += np.sum(obs1.deltas[r_name] * obs2.deltas[r_name]) / len(obs1.deltas[r_name]) + + e_N = np.sum(r_length) + + tau_combined = (obs1.e_tauint[e_name] + obs2.e_tauint[e_name]) / 2 + dvalue += gamma * (1 + 1 / e_N) / e_N * 2 * tau_combined + + if np.abs(dvalue / obs1.dvalue / obs2.dvalue) > 1.0: + dvalue = np.sign(dvalue) * obs1.dvalue * obs2.dvalue + + if correlation: + dvalue = dvalue / obs1.dvalue / obs2.dvalue + + return dvalue + + +def covariance2(obs1, obs2, correlation=False, **kwargs): + """Alternative implementation of the covariance of two observables. + + covariance(obs, obs) is equal to obs.dvalue ** 2 + The gamma method has to be applied first to both observables. + + If abs(covariance(obs1, obs2)) > obs1.dvalue * obs2.dvalue, the covariance + is constrained to the maximum value in order to make sure that covariance + matrices are positive semidefinite. + + Keyword arguments + ----------------- + correlation -- if true the correlation instead of the covariance is + returned (default False) + """ + + for name in sorted(set(obs1.names + obs2.names)): + if (obs1.shape.get(name) != obs2.shape.get(name)) and (obs1.shape.get(name) is not None) and (obs2.shape.get(name) is not None): + raise Exception('Shapes of ensemble', name, 'do not fit') + + if obs1.e_names == {} or obs2.e_names == {}: + raise Exception('The gamma method has to be applied to both Obs first.') + + dvalue = 0 + e_gamma = {} + e_dvalue = {} + e_n_tauint = {} + e_rho = {} + + for e_name in obs1.e_names: + + if e_name not in obs2.e_names: + continue + + r_length = [] + for r_name in obs1.e_content[e_name]: + r_length.append(len(obs1.deltas[r_name])) + + e_N = np.sum(r_length) + w_max = max(r_length) // 2 + e_gamma[e_name] = np.zeros(w_max) + + for r_name in obs1.e_content[e_name]: + if r_name not in obs2.e_content[e_name]: + continue + max_gamma = min(obs1.shape[r_name], w_max) + # The padding for the fft has to be even + padding = obs1.shape[r_name] + max_gamma + (obs1.shape[r_name] + max_gamma) % 2 + e_gamma[e_name][:max_gamma] += (np.fft.irfft(np.fft.rfft(obs1.deltas[r_name], padding) * np.conjugate(np.fft.rfft(obs2.deltas[r_name], padding)))[:max_gamma] + + np.fft.irfft(np.fft.rfft(obs2.deltas[r_name], padding) * np.conjugate(np.fft.rfft(obs1.deltas[r_name], padding)))[:max_gamma]) / 2.0 + + if np.all(e_gamma[e_name]) == 0.0: + continue + + e_shapes = [] + for r_name in obs1.e_content[e_name]: + e_shapes.append(obs1.shape[r_name]) + + div = np.array([]) + mul = np.array([]) + sorted_shapes = sorted(e_shapes) + for i, item in enumerate(sorted_shapes): + if len(div) > w_max: + break + if i == 0: + samples = item + else: + samples = item - sorted_shapes[i - 1] + div = np.append(div, np.repeat(np.sum(sorted_shapes[i:]), samples)) + mul = np.append(mul, np.repeat(len(sorted_shapes) - i, samples)) + div = div - np.arange(len(div)) * mul + + e_gamma[e_name] /= div[:w_max] + + e_rho[e_name] = e_gamma[e_name][:w_max] / e_gamma[e_name][0] + e_n_tauint[e_name] = np.cumsum(np.concatenate(([0.5], e_rho[e_name][1:]))) + # Make sure no entry of tauint is smaller than 0.5 + e_n_tauint[e_name][e_n_tauint[e_name] < 0.5] = 0.500000000001 + + + window = max(obs1.e_windowsize[e_name], obs2.e_windowsize[e_name]) + # Bias correction hep-lat/0306017 eq. (49) + e_dvalue[e_name] = 2 * (e_n_tauint[e_name][window] + obs1.tau_exp[e_name] * np.abs(e_rho[e_name][window + 1])) * (1 + (2 * window + 1) / e_N) * e_gamma[e_name][0] / e_N + + dvalue += e_dvalue[e_name] + + if np.abs(dvalue / obs1.dvalue / obs2.dvalue) > 1.0: + dvalue = np.sign(dvalue) * obs1.dvalue * obs2.dvalue + + if correlation: + dvalue = dvalue / obs1.dvalue / obs2.dvalue + + return dvalue + + +def covariance3(obs1, obs2, correlation=False, **kwargs): + """Another alternative implementation of the covariance of two observables. + + covariance2(obs, obs) is equal to obs.dvalue ** 2 + Currently only works if ensembles are identical. + The gamma method has to be applied first to both observables. + + If abs(covariance2(obs1, obs2)) > obs1.dvalue * obs2.dvalue, the covariance + is constrained to the maximum value in order to make sure that covariance + matrices are positive semidefinite. + + Keyword arguments + ----------------- + correlation -- if true the correlation instead of the covariance is + returned (default False) + plot -- if true, the integrated autocorrelation time for each ensemble is + plotted. + """ + + for name in sorted(set(obs1.names + obs2.names)): + if (obs1.shape.get(name) != obs2.shape.get(name)) and (obs1.shape.get(name) is not None) and (obs2.shape.get(name) is not None): + raise Exception('Shapes of ensemble', name, 'do not fit') + + if obs1.e_names == {} or obs2.e_names == {}: + raise Exception('The gamma method has to be applied to both Obs first.') + + tau_exp = [] + S = [] + for e_name in sorted(set(obs1.e_names + obs2.e_names)): + t_1 = obs1.tau_exp.get(e_name) + t_2 = obs2.tau_exp.get(e_name) + if t_1 is None: + t_1 = 0 + if t_2 is None: + t_2 = 0 + tau_exp.append(max(t_1, t_2)) + S_1 = obs1.S.get(e_name) + S_2 = obs2.S.get(e_name) + if S_1 is None: + S_1 = Obs.S_global + if S_2 is None: + S_2 = Obs.S_global + S.append(max(S_1, S_2)) + + check_obs = obs1 + obs2 + check_obs.gamma_method(tau_exp=tau_exp, S=S) + + if kwargs.get('plot'): + check_obs.plot_tauint() + check_obs.plot_rho() + + cov = (check_obs.dvalue ** 2 - obs1.dvalue ** 2 - obs2.dvalue ** 2) / 2 + + if np.abs(cov / obs1.dvalue / obs2.dvalue) > 1.0: + cov = np.sign(cov) * obs1.dvalue * obs2.dvalue + + if correlation: + cov = cov / obs1.dvalue / obs2.dvalue + + return cov + + +def use_time_reversal_symmetry(data1, data2, **kwargs): + """Combine two correlation functions (lists of Obs) according to time reversal symmetry + + Keyword arguments + ----------------- + minus -- if True, multiply the second correlation function by a minus sign. + """ + if kwargs.get('minus'): + sign = -1 + else: + sign = 1 + + result = [] + T = int(len(data1)) + for i in range(T): + result.append(derived_observable(lambda x, **kwargs: (x[0] + sign * x[1]) / 2, [data1[i], data2[T - i - 1]], **kwargs)) + + return result + + +def pseudo_Obs(value, dvalue, name, samples=1000): + """Generate a pseudo Obs with given value, dvalue and name + + The standard number of samples is a 1000. This can be adjusted. + """ + if dvalue <= 0.0: + return Obs([np.zeros(samples) + value], [name]) + else: + for _ in range(100): + deltas = [np.random.normal(0.0, dvalue * np.sqrt(samples), samples)] + deltas -= np.mean(deltas) + deltas *= dvalue / np.sqrt((np.var(deltas) / samples)) / np.sqrt(1 + 3 / samples) + deltas += value + res = Obs(deltas, [name]) + res.gamma_method(S=2, tau_exp=0) + if abs(res.dvalue - dvalue) < 1e-10 * dvalue: + break + + res.value = float(value) + + return res + + +def dump_object(obj, name, **kwargs): + """Dump object into pickle file. + + Keyword arguments + ----------------- + path -- specifies a custom path for the file (default '.') + """ + if 'path' in kwargs: + file_name = kwargs.get('path') + '/' + name + '.p' + else: + file_name = name + '.p' + with open(file_name, 'wb') as fb: + pickle.dump(obj, fb) + + +def load_object(path): + """Load object from pickle file. """ + with open(path, 'rb') as file: + return pickle.load(file) + + +def plot_corrs(observables, **kwargs): + """Plot lists of Obs. + + Parameters + ---------- + observables -- list of lists of Obs, where the nth entry is considered to be the + correlation function + at x0=n e.g. [[f_A_0,f_A_1],[f_P_0,f_P_1]] or [f_A,f_P], where f_A and f_P are lists of Obs. + + Keyword arguments + ----------------- + xrange -- list of two values, determining the range of the x-axis e.g. [4, 8] + yrange -- list of two values, determining the range of the y-axis e.g. [0.2, 1.1] + prange -- list of two values, visualizing the width of the plateau e.g. [10, 15] + reference -- float valued variable which is shown as horizontal line for reference + plateau -- Obs which is shown as horizontal line with errorbar for reference + shift -- shift x by given value + label -- list of labels, has to have the same length as observables + exp -- plot exponential from fitting routine + """ + + if 'shift' in kwargs: + shift = kwargs.get('shift') + else: + shift = 0 + + if 'label' in kwargs: + label = kwargs.get('label') + if len(label) != len(observables): + raise Exception('label has to be a list with exactly one entry per entry of observables.') + else: + label = [] + for j in range(len(observables)): + label.append(str(j + 1)) + + + f = plt.figure() + for j in range(len(observables)): + T = len(observables[j]) + + x = np.arange(T) + shift + y = np.zeros(T) + y_err = np.zeros(T) + + for i in range(T): + y[i] = observables[j][i].value + y_err[i] = observables[j][i].dvalue + + plt.errorbar(x, y, yerr=y_err, ls='none', fmt='o', capsize=3, markersize=5, label=label[j]) + + if kwargs.get('logscale'): + plt.yscale('log') + + if 'xrange' in kwargs: + xrange = kwargs.get('xrange') + plt.xlim(xrange[0], xrange[1]) + visible_y = y[int(xrange[0] + 0.5):int(xrange[1] + 0.5)] + visible_y_err = y_err[int(xrange[0] + 0.5):int(xrange[1] + 0.5)] + y_start = np.min(visible_y - visible_y_err) + y_stop = np.max(visible_y + visible_y_err) + span = y_stop - y_start + if np.isfinite(y_start) and np.isfinite(y_stop): + plt.ylim(y_start - 0.1 * span, y_stop + 0.1 * span) + + if 'yrange' in kwargs: + yrange = kwargs.get('yrange') + plt.ylim(yrange[0], yrange[1]) + + if 'reference' in kwargs: + y_value = kwargs.get('reference') + plt.axhline(y=y_value, linewidth=2, color='k', alpha=0.25) + + if 'prange' in kwargs: + prange = kwargs.get('prange') + plt.axvline(x=prange[0] - 0.5, ls='--', c='k', lw=1, alpha=0.5) + plt.axvline(x=prange[1] + 0.5, ls='--', c='k', lw=1, alpha=0.5) + + if 'plateau' in kwargs: + plateau = kwargs.get('plateau') + if isinstance(plateau, Obs): + plt.axhline(y=plateau.value, linewidth=2, color='k', alpha=0.6, label='Plateau') + plt.axhspan(plateau.value - plateau.dvalue, plateau.value + plateau.dvalue, alpha=0.25, color='k') + elif isinstance(plateau, list): + for i in range(len(plateau)): + plt.axhline(y=plateau[i].value, linewidth=2, color='C' + str(i), alpha=0.6, label='Plateau' + str(i + 1)) + plt.axhspan(plateau[i].value - plateau[i].dvalue, plateau[i].value + plateau[i].dvalue, + color='C' + str(i), alpha=0.25) + else: + raise Exception('Improper input for plateau.') + + if kwargs.get('exp'): + fit_result = kwargs.get('exp') + y_fit = fit_result[1].value * np.exp(-fit_result[0].value * x) + plt.plot(x, y_fit, color='k') + if not (fit_result[0].e_names == {} and fit_result[1].e_names == {}): + y_fit_err = np.sqrt((y_fit * fit_result[0].dvalue) ** 2 + 2 * covariance(fit_result[0], fit_result[1])* y_fit * + np.exp(-fit_result[0].value * x) + (np.exp(-fit_result[0].value * x) * fit_result[1].dvalue) ** 2) + plt.fill_between(x, y_fit + y_fit_err, y_fit - y_fit_err, color='k', alpha=0.1) + + plt.xlabel('$x_0/a$') + + if 'ylabel' in kwargs: + plt.ylabel(kwargs.get('ylabel')) + + if 'save' in kwargs: + lgd = plt.legend(loc=0) + else: + lgd = plt.legend(bbox_to_anchor=(1.04, 1), loc='upper left') + plt.show() + + if 'save' in kwargs: + save = kwargs.get('save') + if not isinstance(save, str): + raise Exception('save has to be a string.') + f.savefig(save + '.pdf', bbox_extra_artists=(lgd,), bbox_inches='tight') + + +def merge_obs(list_of_obs): + """Combine all observables in list_of_obs into one new observable + + It is not possible to combine obs which are based on the same replicum + """ + replist = [item for obs in list_of_obs for item in obs.names] + if (len(replist) == len(set(replist))) is False: + raise Exception('list_of_obs contains duplicate replica: %s' %(str(replist))) + new_dict = {} + for o in list_of_obs: + new_dict.update({key: o.deltas.get(key, 0) + o.r_values.get(key, 0) + for key in set(o.deltas) | set(o.r_values)}) + + return Obs(list(new_dict.values()), list(new_dict.keys())) diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..96153227 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,4 @@ +[pytest] +filterwarnings = + ignore::RuntimeWarning:autograd.*: + ignore::RuntimeWarning:numdifftools.*: diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..237db485 --- /dev/null +++ b/setup.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python + +from setuptools import setup, find_packages + +setup(name='pyerrors', + version='1.0.0', + description='Error analysis for lattice QCD', + author='Fabian Joswig', + author_email='fabian.joswig@wwu.de', + packages=find_packages(), + python_requires='>=3.5.0', + install_requires=['numpy>=1.16', 'autograd>=1.2', 'numdifftools', 'matplotlib', 'scipy', 'iminuit'] + ) diff --git a/tests/test_pyerrors.py b/tests/test_pyerrors.py new file mode 100644 index 00000000..caf36760 --- /dev/null +++ b/tests/test_pyerrors.py @@ -0,0 +1,339 @@ +import sys +sys.path.append('..') +import autograd.numpy as np +import os +import random +import math +import string +import copy +import scipy.optimize +from scipy.odr import ODR, Model, Data, RealData +import pyerrors as pe +import pytest + +test_iterations = 100 + +def test_dump(): + value = np.random.normal(5, 10) + dvalue = np.abs(np.random.normal(0, 1)) + test_obs = pe.pseudo_Obs(value, dvalue, 't') + test_obs.dump('test_dump') + new_obs = pe.load_object('test_dump.p') + os.remove('test_dump.p') + assert test_obs.deltas['t'].all() == new_obs.deltas['t'].all() + + +def test_comparison(): + value1 = np.random.normal(0, 100) + test_obs1 = pe.pseudo_Obs(value1, 0.1, 't') + value2 = np.random.normal(0, 100) + test_obs2 = pe.pseudo_Obs(value2, 0.1, 't') + assert (value1 > value2) == (test_obs1 > test_obs2) + assert (value1 < value2) == (test_obs1 < test_obs2) + + +def test_man_grad(): + a = pe.pseudo_Obs(17,2.9,'e1') + b = pe.pseudo_Obs(4,0.8,'e1') + + fs = [lambda x: x[0] + x[1], lambda x: x[1] + x[0], lambda x: x[0] - x[1], lambda x: x[1] - x[0], + lambda x: x[0] * x[1], lambda x: x[1] * x[0], lambda x: x[0] / x[1], lambda x: x[1] / x[0], + lambda x: np.exp(x[0]), lambda x: np.sin(x[0]), lambda x: np.cos(x[0]), lambda x: np.tan(x[0]), + lambda x: np.log(x[0]), lambda x: np.sqrt(x[0]), + lambda x: np.sinh(x[0]), lambda x: np.cosh(x[0]), lambda x: np.tanh(x[0])] + + for i, f in enumerate(fs): + t1 = f([a,b]) + t2 = pe.derived_observable(f, [a,b]) + c = t2 - t1 + assert c.value == 0.0, str(i) + assert np.all(np.abs(c.deltas['e1']) < 1e-14), str(i) + + +def test_overloading_vectorization(): + a = np.array([5, 4, 8]) + b = pe.pseudo_Obs(4,0.8,'e1') + + assert [o.value for o in a * b] == [o.value for o in b * a] + assert [o.value for o in a + b] == [o.value for o in b + a] + assert [o.value for o in a - b] == [-1 * o.value for o in b - a] + assert [o.value for o in a / b] == [o.value for o in [p / b for p in a]] + assert [o.value for o in b / a] == [o.value for o in [b / p for p in a]] + + +@pytest.mark.parametrize("n", np.arange(test_iterations // 10)) +def test_covariance_is_variance(n): + value = np.random.normal(5, 10) + dvalue = np.abs(np.random.normal(0, 1)) + test_obs = pe.pseudo_Obs(value, dvalue, 't') + test_obs.gamma_method() + assert np.abs(test_obs.dvalue ** 2 - pe.covariance(test_obs, test_obs)) <= 10 * np.finfo(np.float).eps + test_obs = test_obs + pe.pseudo_Obs(value, dvalue, 'q', 200) + test_obs.gamma_method(e_tag=0) + assert np.abs(test_obs.dvalue ** 2 - pe.covariance(test_obs, test_obs)) <= 10 * np.finfo(np.float).eps + + +@pytest.mark.parametrize("n", np.arange(test_iterations // 10)) +def test_fft(n): + value = np.random.normal(5, 100) + dvalue = np.abs(np.random.normal(0, 5)) + test_obs1 = pe.pseudo_Obs(value, dvalue, 't', int(500 + 1000 * np.random.rand())) + test_obs2 = copy.deepcopy(test_obs1) + test_obs1.gamma_method() + test_obs2.gamma_method(fft=False) + assert max(np.abs(test_obs1.e_rho[''] - test_obs2.e_rho[''])) <= 10 * np.finfo(np.float).eps + assert np.abs(test_obs1.dvalue - test_obs2.dvalue) <= 10 * max(test_obs1.dvalue, test_obs2.dvalue) * np.finfo(np.float).eps + + +@pytest.mark.parametrize('n', np.arange(test_iterations // 10)) +def test_standard_fit(n): + dim = 10 + int(30 * np.random.rand()) + x = np.arange(dim) + y = 2 * np.exp(-0.06 * x) + np.random.normal(0.0, 0.15, dim) + yerr = 0.1 + 0.1 * np.random.rand(dim) + + oy = [] + for i, item in enumerate(x): + oy.append(pe.pseudo_Obs(y[i], yerr[i], str(i))) + + def f(x, a, b): + return a * np.exp(-b * x) + + popt, pcov = scipy.optimize.curve_fit(f, x, y, sigma=[o.dvalue for o in oy], absolute_sigma=True) + + def func(a, x): + y = a[0] * np.exp(-a[1] * x) + return y + + beta = pe.fits.standard_fit(x, oy, func) + + pe.Obs.e_tag_global = 5 + for i in range(2): + beta[i].gamma_method(e_tag=5, S=1.0) + assert math.isclose(beta[i].value, popt[i], abs_tol=1e-5) + assert math.isclose(pcov[i, i], beta[i].dvalue ** 2, abs_tol=1e-3) + assert math.isclose(pe.covariance(beta[0], beta[1]), pcov[0, 1], abs_tol=1e-3) + pe.Obs.e_tag_global = 0 + + chi2_pyerrors = np.sum(((f(x, *[o.value for o in beta]) - y) / yerr) ** 2) / (len(x) - 2) + chi2_scipy = np.sum(((f(x, *popt) - y) / yerr) ** 2) / (len(x) - 2) + assert math.isclose(chi2_pyerrors, chi2_scipy, abs_tol=1e-10) + + +@pytest.mark.parametrize('n', np.arange(test_iterations // 10)) +def test_odr_fit(n): + dim = 10 + int(30 * np.random.rand()) + x = np.arange(dim) + np.random.normal(0.0, 0.15, dim) + xerr = 0.1 + 0.1 * np.random.rand(dim) + y = 2 * np.exp(-0.06 * x) + np.random.normal(0.0, 0.15, dim) + yerr = 0.1 + 0.1 * np.random.rand(dim) + + ox = [] + for i, item in enumerate(x): + ox.append(pe.pseudo_Obs(x[i], xerr[i], str(i))) + + oy = [] + for i, item in enumerate(x): + oy.append(pe.pseudo_Obs(y[i], yerr[i], str(i))) + + def f(x, a, b): + return a * np.exp(-b * x) + + def func(a, x): + y = a[0] * np.exp(-a[1] * x) + return y + + data = RealData([o.value for o in ox], [o.value for o in oy], sx=[o.dvalue for o in ox], sy=[o.dvalue for o in oy]) + model = Model(func) + odr = ODR(data, model, [0,0], partol=np.finfo(np.float).eps) + odr.set_job(fit_type=0, deriv=1) + output = odr.run() + + beta = pe.fits.odr_fit(ox, oy, func) + + pe.Obs.e_tag_global = 5 + for i in range(2): + beta[i].gamma_method(e_tag=5, S=1.0) + assert math.isclose(beta[i].value, output.beta[i], rel_tol=1e-5) + assert math.isclose(output.cov_beta[i,i], beta[i].dvalue**2, rel_tol=2.5e-1), str(output.cov_beta[i,i]) + ' ' + str(beta[i].dvalue**2) + assert math.isclose(pe.covariance(beta[0], beta[1]), output.cov_beta[0,1], rel_tol=2.5e-1) + pe.Obs.e_tag_global = 0 + + +@pytest.mark.parametrize('n', np.arange(test_iterations // 10)) +def test_odr_derivatives(n): + x = [] + y = [] + x_err = 0.01 + y_err = 0.01 + + for n in np.arange(1, 9, 2): + loc_xvalue = n + np.random.normal(0.0, x_err) + x.append(pe.pseudo_Obs(loc_xvalue, x_err, str(n))) + y.append(pe.pseudo_Obs((lambda x: x ** 2 - 1)(loc_xvalue) + + np.random.normal(0.0, y_err), y_err, str(n))) + + def func(a, x): + return a[0] + a[1] * x ** 2 + + fit1 = pe.fits.odr_fit(x, y, func) + + tfit = pe.fits.fit_general(x, y, func, base_step=0.1, step_ratio=1.1, num_steps=20) + assert np.abs(np.max(np.array(list(fit1[1].deltas.values())) + - np.array(list(tfit[1].deltas.values())))) < 10e-8 + + +@pytest.mark.parametrize('n', np.arange(test_iterations)) +def test_covariance_symmetry(n): + value1 = np.random.normal(5, 10) + dvalue1 = np.abs(np.random.normal(0, 1)) + test_obs1 = pe.pseudo_Obs(value1, dvalue1, 't') + test_obs1.gamma_method() + value2 = np.random.normal(5, 10) + dvalue2 = np.abs(np.random.normal(0, 1)) + test_obs2 = pe.pseudo_Obs(value2, dvalue2, 't') + test_obs2.gamma_method() + cov_ab = pe.covariance(test_obs1, test_obs2) + cov_ba = pe.covariance(test_obs2, test_obs1) + assert np.abs(cov_ab - cov_ba) <= 10 * np.finfo(np.float).eps + assert np.abs(cov_ab) < test_obs1.dvalue * test_obs2.dvalue * (1 + 10 * np.finfo(np.float).eps) + + +@pytest.mark.parametrize('n', np.arange(test_iterations)) +def test_gamma_method(n): + # Construct pseudo Obs with random shape + value = np.random.normal(5, 10) + dvalue = np.abs(np.random.normal(0, 1)) + + test_obs = pe.pseudo_Obs(value, dvalue, 't', int(1000 * (1 + np.random.rand()))) + + # Test if the error is processed correctly + test_obs.gamma_method(e_tag=1) + assert np.abs(test_obs.value - value) < 1e-12 + assert abs(test_obs.dvalue - dvalue) < 1e-10 * dvalue + + +@pytest.mark.parametrize('n', np.arange(test_iterations)) +def test_overloading(n): + # Construct pseudo Obs with random shape + obs_list = [] + for i in range(5): + value = np.abs(np.random.normal(5, 2)) + 2.0 + dvalue = np.abs(np.random.normal(0, 0.1)) + 1e-5 + obs_list.append(pe.pseudo_Obs(value, dvalue, 't', 2000)) + + # Test if the error is processed correctly + def f(x): + return x[0] * x[1] + np.sin(x[2]) * np.exp(x[3] / x[1] / x[0]) - np.sqrt(2) / np.cosh(x[4] / x[0]) + + o_obs = f(obs_list) + d_obs = pe.derived_observable(f, obs_list) + + assert np.max(np.abs((o_obs.deltas['t'] - d_obs.deltas['t']) / o_obs.deltas['t'])) < 1e-7, str(obs_list) + assert np.abs((o_obs.value - d_obs.value) / o_obs.value) < 1e-10 + + +@pytest.mark.parametrize('n', np.arange(test_iterations)) +def test_derived_observables(n): + # Construct pseudo Obs with random shape + test_obs = pe.pseudo_Obs(2, 0.1 * (1 + np.random.rand()), 't', int(1000 * (1 + np.random.rand()))) + + # Check if autograd and numgrad give the same result + d_Obs_ad = pe.derived_observable(lambda x, **kwargs: x[0] * x[1] * np.sin(x[0] * x[1]), [test_obs, test_obs]) + d_Obs_ad.gamma_method() + d_Obs_fd = pe.derived_observable(lambda x, **kwargs: x[0] * x[1] * np.sin(x[0] * x[1]), [test_obs, test_obs], num_grad=True) + d_Obs_fd.gamma_method() + + assert d_Obs_ad.value == d_Obs_fd.value + assert np.abs(4.0 * np.sin(4.0) - d_Obs_ad.value) < 1000 * np.finfo(np.float).eps * np.abs(d_Obs_ad.value) + assert np.abs(d_Obs_ad.dvalue-d_Obs_fd.dvalue) < 1000 * np.finfo(np.float).eps * d_Obs_ad.dvalue + + i_am_one = pe.derived_observable(lambda x, **kwargs: x[0] / x[1], [d_Obs_ad, d_Obs_ad]) + i_am_one.gamma_method(e_tag=1) + + assert i_am_one.value == 1.0 + assert i_am_one.dvalue < 2 * np.finfo(np.float).eps + assert i_am_one.e_dvalue['t'] <= 2 * np.finfo(np.float).eps + assert i_am_one.e_ddvalue['t'] <= 2 * np.finfo(np.float).eps + + +@pytest.mark.parametrize('n', np.arange(test_iterations // 10)) +def test_multi_ens_system(n): + names = [] + for i in range(100 + int(np.random.rand() * 50)): + tmp_string = '' + for _ in range(int(2 + np.random.rand() * 4)): + tmp_string += random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) + names.append(tmp_string) + names = list(set(names)) + samples = [np.random.rand(5)] * len(names) + new_obs = pe.Obs(samples, names) + + for e_tag_length in range(1, 6): + new_obs.gamma_method(e_tag=e_tag_length) + e_names = sorted(set([n[:e_tag_length] for n in names])) + assert e_names == new_obs.e_names + assert sorted(x for y in sorted(new_obs.e_content.values()) for x in y) == sorted(new_obs.names) + + +@pytest.mark.parametrize('n', np.arange(test_iterations)) +def test_overloaded_functions(n): + funcs = [np.exp, np.log, np.sin, np.cos, np.tan, np.sinh, np.cosh, np.arcsinh, np.arccosh] + deriv = [np.exp, lambda x: 1 / x, np.cos, lambda x: -np.sin(x), lambda x: 1 / np.cos(x) ** 2, np.cosh, np.sinh, lambda x: 1 / np.sqrt(x ** 2 + 1), lambda x: 1 / np.sqrt(x ** 2 - 1)] + val = 3 + 0.5 * np.random.rand() + dval = 0.3 + 0.4 * np.random.rand() + test_obs = pe.pseudo_Obs(val, dval, 't', int(1000 * (1 + np.random.rand()))) + + for i, item in enumerate(funcs): + ad_obs = item(test_obs) + fd_obs = pe.derived_observable(lambda x, **kwargs: item(x[0]), [test_obs], num_grad=True) + ad_obs.gamma_method(S=0.01, e_tag=1) + assert np.max((ad_obs.deltas['t'] - fd_obs.deltas['t']) / ad_obs.deltas['t']) < 1e-8, item.__name__ + assert np.abs((ad_obs.value - item(val)) / ad_obs.value) < 1e-10, item.__name__ + assert np.abs(ad_obs.dvalue - dval * np.abs(deriv[i](val))) < 1e-6, item.__name__ + + +@pytest.mark.parametrize('n', np.arange(test_iterations // 10)) +def test_matrix_functions(n): + dim = 3 + int(4 * np.random.rand()) + print(dim) + matrix = [] + for i in range(dim): + row = [] + for j in range(dim): + row.append(pe.pseudo_Obs(np.random.rand(), 0.2 + 0.1 * np.random.rand(), 'e1')) + matrix.append(row) + matrix = np.array(matrix) @ np.identity(dim) + + # Check inverse of matrix + inv = pe.linalg.mat_mat_op(np.linalg.inv, matrix) + check_inv = matrix @ inv + + for (i, j), entry in np.ndenumerate(check_inv): + entry.gamma_method() + if(i == j): + assert math.isclose(entry.value, 1.0, abs_tol=1e-9), 'value ' + str(i) + ',' + str(j) + ' ' + str(entry.value) + else: + assert math.isclose(entry.value, 0.0, abs_tol=1e-9), 'value ' + str(i) + ',' + str(j) + ' ' + str(entry.value) + assert math.isclose(entry.dvalue, 0.0, abs_tol=1e-9), 'dvalue ' + str(i) + ',' + str(j) + ' ' + str(entry.dvalue) + + # Check Cholesky decomposition + sym = np.dot(matrix, matrix.T) + cholesky = pe.linalg.mat_mat_op(np.linalg.cholesky, sym) + check = cholesky @ cholesky.T + + for (i, j), entry in np.ndenumerate(check): + diff = entry - sym[i, j] + diff.gamma_method() + assert math.isclose(diff.value, 0.0, abs_tol=1e-9), 'value ' + str(i) + ',' + str(j) + assert math.isclose(diff.dvalue, 0.0, abs_tol=1e-9), 'dvalue ' + str(i) + ',' + str(j) + + # Check eigh + e, v = pe.linalg.eigh(sym) + for i in range(dim): + tmp = sym @ v[:, i] - v[:, i] * e[i] + for j in range(dim): + tmp[j].gamma_method() + assert math.isclose(tmp[j].value, 0.0, abs_tol=1e-9), 'value ' + str(i) + ',' + str(j) + assert math.isclose(tmp[j].dvalue, 0.0, abs_tol=1e-9), 'dvalue ' + str(i) + ',' + str(j) +