PySpec reconstructs smeared spectral densities from lattice correlators.
Current version supports the Hansen-Lupo-Tantalo (HLT) method.
Given a target smearing kernel
K(omega) it computes the coefficients g_t
which provides the best approximation of that kernel by balancing
systematic and statistical error.
Everything is evaluated in arbitrary precision with mpmath.
Distribution: PySpec · importable as pyspec.
- The method
- Features
- Requirements
- Installation
- Quickstart
- Kernels
- Constraints
- Tuning lambda
- Project layout
- License
- Bug reports
- Author and contact
The lattice correlator is a Laplace transform of the spectral density,
C(t) = int_{E0}^{inf} b_t(omega) rho(omega) d omega,
b_t(omega) = exp(-(t+1) omega) [ + exp(-(T-t-1) omega) with periodic bc ]
Following arXiv:1903.06476
PySpec looks for coefficients g such that sum_t g_t b_t(omega) reproduces a
chosen smearing kernel K(omega), so that sum_t g_t C(t) is an
estimator of the smeared density. The coefficients minimize
(1 - lambda) A[g]/A[0] + lambda B[g]
where A[g] measures the distance between the reconstructed and the target
kernel and B[g] = g^T Cov g is the variance of the result. The minimum has a
closed form in the presence of linear constraints V g = c.
Reconstruction
Reconstructor: one instance for each kernel and set of lattice parameters. The kernel-independent blockA_{tr}is computed once, and the LU factorization ofW = (1 - lambda) A + lambda Covis cached per lambda, so scanning lambda or swapping kernel is cheap.- Periodic and non-periodic boundary conditions.
set_kernelrecomputes only the kernel-dependent terms, for scans over the energy at which the density is evaluated.
Kernels
- Currently supported kernels:
SigmoidKernel,MomentsKernel,ExpKernel,GaussDKernel,ExpMomentsKernel,SechKernel,ExpSigmoidKernel,ExpSigmoidModKernel,AsymSechKernel. - Custom kernels by subclassing
Kerneland implementingevaluate: the Laplace transform, the square integral and the area are then obtained by quadrature, and can be overridden when a closed form is known.
Constraints
NormalizationConstraint: the reconstructed kernel has the same area as the target one.PointMatchConstraint: the two kernels agree exactly at a chosen energy.LinearConstraint: template for any constraint of the formv^T g = c.
Tuning
- Automatic selection of lambda by comparing reconstructions obtained with different constraint sets, with a plateau search and a compatibility threshold in units of the statistical error.
Python >= 3.13, with mpmath, numpy and scipy: installed
automatically.
pip install "git+https://github.com/laudid46/pyspec.git@v1.0"
git clone https://github.com/laudid46/pyspec.git
cd pyspecpython3.13 -m venv .venv
source .venv/bin/activate # macOS / Linux
# .\.venv\Scripts\Activate.ps1 # Windows PowerShellFor regular/development (changes to the source are picked up immediately):
pip install . # regular installation
pip install -e . # editable installation
pip install -e ".[test]" # editable, with the test dependenciesFrom the repository root:
pytest # test package installationThis requires the test extra (see above). Expected output: 37 passed.
import numpy as np
import mpmath as mp
from pyspec import Reconstructor, GaussDKernel, NormalizationConstraint, PointMatchConstraint
mp.mp.dps = 60 # the inverse problem needs the digits
C = ... # correlator, C[t] for t = 0, 1, ...
Cov = ... # its covariance matrix, NOT normalized
kernel = GaussDKernel(omega_star=1.0, sigma=0.3)
rec = Reconstructor(kernel, [C, Cov],
tmin=0, tmax=10, # timeslices used
E0=0.05, # lower bound of integrations
T=None, # lattice time extent, None if not periodic
cov_norm=float(C[0]**2))
# coefficients at a fixed lambda
g = rec.coefficients(mp.mpf('0.5'), [NormalizationConstraint()])
# the reconstructed kernel and the smeared density
rec.K(1.0, mp.mpf('0.5'), [NormalizationConstraint()])
rec.rho(mp.mpf('0.5'), [NormalizationConstraint()])
# or let PySpec tune lambda for you
out = rec.run([[NormalizationConstraint()],
[NormalizationConstraint(), PointMatchConstraint(1.2)]],
tuning=True, N=32)
print(out['opt_info']['rho'], '+/-', out['opt_info']['sigma'])
print('lambda =', out['lambda_opt'])tmin and tmax select the timeslices t = tmin, ..., tmax-1, which use the
correlator entries C[tmin+1], ..., C[tmax]: the t = 0 entry is the
normalization, not a basis function.
Every kernel exposes four primitives in arbitrary precision:
| method | meaning |
|---|---|
evaluate(omega) |
K(omega) |
laplace(s, E0) |
int_{E0}^{inf} exp(-s omega) K(omega) d omega |
square_integral(E0) |
int_{E0}^{inf} K(omega)^2 d omega |
integral(E0) |
int_{E0}^{inf} K(omega) d omega, i.e. laplace(0, E0) |
A new kernel only needs evaluate; the rest falls back to adaptive
quadrature. If the kernel has a cusp, override laplace and
square_integral and split the integration path on it, otherwise the
quadrature silently loses several digits.
A linear constraint is a pair (v, c) enforcing v^T g = c. To add one, subclass
LinearConstraint and implement get_v, get_value and the key property,
which must return a string identifying the constraint uniquely: it is used as
the cache key.
from pyspec import LinearConstraint
class MyConstraint(LinearConstraint):
def get_v(self, kernel, tmin, tmax, E0, T=None):
... # mp.matrix of shape (tmax-tmin, 1)
def get_value(self, kernel, E0):
... # mp.mpf
@property
def key(self):
return 'MyConstraint'run scans lambda, converts each point into the corresponding A[g]/A[0],
looks for the plateau of rho, and picks the largest A[g]/A[0] at which two
different reconstruction strategies still agree within threshold sigmas.
The reconstruction is then re-run at the selected lambda, and the result is
compared with the interpolated one.
The returned dictionary contains Aopt, lambda_opt, rho_interp,
sigma_interp, the interpolation grid, the full scan for each constraint set,
the index of the selected set, and opt_info with the final rho and sigma.
See the docstring of run for every option.
PySpec/
├── LICENSE # GPL-3.0
├── README.md # this file
├── pyproject.toml # metadata and dependencies
├── CHANGELOG.md # version history
├── MANIFEST.in # files shipped in the source distribution
├── src/pyspec
│ ├── __init__.py # re-exports the whole public API
│ ├── __version__.py
│ ├── kernels.py # target smearing kernels K(omega)
│ ├── functionals.py # basis b_t, R_t, f_t, A, W and the A, B functionals
│ ├── solver.py # linear constraints and the closed-form solver
│ ├── reconstruction.py # the Reconstructor class and the tuning of lambda
│ └── utils.py # conversion to mpmath matrices
├── tests/
│ └── test_00.py # numerical test suite
└── doc/
└── pyspec_logo.png # pyspec logo
Distributed under the GNU General Public License v3.0 (GPL-3.0). See the
LICENSE file for the full terms.
https://github.com/laudid46/pyspec/issues
Davide Laudicina — davide.laudicina1@gmail.com
Repository: https://github.com/laudid46/pyspec
