Commit 069a5c5b authored by Kloss's avatar Kloss

packing spectrum for PyPI

parent f31331ec
[run]
omit =
*tests*
*__init__*
kwant_spectrum/_kwant_spectrum_version.py
kwant_spectrum/version.py
branch = True
[report]
exclude_lines =
skip coverage
@abc.abstractmethod
@abc.abstractproperty
......@@ -3,3 +3,5 @@ __pycache__/
/dist/
/doc/build/
*~
.coverage
The Kwant-Spectrum authors can be reached at tkwant-authors@kwant-project.org.
Kwant-Spectrum has been developed by
* Thomas Kloss (CEA Grenoble)
Contributors
* Christoph Groth (CEA Grenoble)
* Xavier Waintal (CEA Grenoble)
(CEA = Commissariat à l'énergie atomique et aux énergies alternatives)
Installation
============
This section covers the installation of Kwant_Spectrum on a GNU/Linux
system as Debian and Ubuntu via the command line.
Requirements
^^^^^^^^^^^^
Kwant_Spectrum has following non-Python dependency:
- `Kwant <https://kwant-project.org/>`_
The non-Python dependencies of Kwant_Spectrum can be installed with the following command::
sudo apt-add-repository -s ppa:kwant-project/ppa
sudo apt-get update
sudo apt-get install python3-kwant
Kwant_Spectrum requires at least Python 3.5. The following packages must
be installed to build Kwant_Spectrum:
- `NumPy <https://numpy.org/>`_
- `SciPy <https://www.scipy.org/>`_
Most packages can be installed from the command line
by the standard Python package manager `pip <https://pip.pypa.io/en/stable/>`_ via::
sudo pip3 install numpy scipy
The *pip* command can be also used within the Anaconda Python distribution,
see the instructions for `Conda <#conda>`__.
For version requirements we refer to the *requirements* section in
:download:`setup.py <../../../setup.py>`.
Testing requirements
--------------------
The Kwant_Spectrum test suite requires the following Python packages:
- `pytest <https://docs.pytest.org/en/latest/>`_
- `pytest-cov <https://pytest-cov.readthedocs.io/en/latest/>`_
- `pytest-flake8 <https://pypi.org/project/pytest-flake8/>`_
The packages can be installed by the standard *pip* command::
sudo pip3 install pytest pytest-cov pytest-flake8
Documentation requirements
--------------------------
The Kwant_Spectrum test suite requires the following Python packages:
- `sphinx <https://www.sphinx-doc.org/en/master/>`_
- `jupyter-sphinx <https://jupyter-sphinx.readthedocs.io/en/latest/>`_
The packages can be installed by the standard *pip* command::
sudo pip3 install sphinx jupyter-sphinx
Installating Kwant_Spectrum
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Kwant_Spectrum can be installed with pip via::
sudo pip3 install kwant_spectrum
Building Kwant_Spectrum for development
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For development, Kwant_Spectrum should first be cloned from the official repository::
git clone https://gitlab.kwant-project.org/kwant/spectrum.git
Then, after *cd* into the local repository,
one can locally build kwant_spectrum with the command::
python3 setup.py build_ext -i
Conda
^^^^^
.. _conda:
Kwant_Spectrum provides no dedicated Anaconda support. It is however possible to
install packages via *pip* and *git* similarly with conda.
First, *pip* and *git* must be installed for conda with::
conda install git pip
Kwant-Spectrum can then be installed with the commands given above.
Kwant-Spectrum is an extension to `Kwant <http://kwant-project.org/>`_ that
About Kwant-Spectrum
====================
Kwant-Spectrum is an extension to `Kwant <http://kwant-project.org/>`__ that
adaptively analyzes band structures of infinite quasi-1d systems. The
bandstructure is approximated to an arbitrary precision by piecewise cubic
polynomials. Functionality to deal with special points, intervals, and the
periodic nature of the spectrum is provided.
`Full documentation including a tutorial
<https://kwant-project.org/extensions/spectrum/>`_ is available . Report bugs
and follow development through the `Kwant-Spectrum repository
<https://gitlab.kwant-project.org/kwant/spectrum>`_.
Kwant_Spectrum is distributed under the `2-clause BSD license <https://gitlab.kwant-project.org/kwant/spectrum/-/blob/master/LICENSE.rst>`_
Website: https://kwant-project.org/extensions/spectrum
Source code: https://gitlab.kwant-project.org/kwant/spectrum
Installation
############
This section covers the installation of Kwant_Spectrum on a GNU/Linux
system as Debian and Ubuntu via the command line.
Requirements
^^^^^^^^^^^^
Kwant_Spectrum has following non-Python dependency:
- `Kwant <https://kwant-project.org/>`__
The non-Python dependencies of Kwant_Spectrum can be installed with the following command::
sudo apt-add-repository -s ppa:kwant-project/ppa
sudo apt-get update
sudo apt-get install python3-kwant
Kwant_Spectrum requires at least Python 3.5. The following packages must
be installed to build Kwant_Spectrum:
- `NumPy <https://numpy.org/>`_
- `SciPy <https://www.scipy.org/>`_
Most packages can be installed from the command line
by the standard Python package manager `pip <https://pip.pypa.io/en/stable/>`_ via::
sudo pip3 install numpy scipy
Testing requirements
--------------------
The Kwant_Spectrum test suite requires the following Python packages:
- `pytest <https://docs.pytest.org/en/latest/>`_
- `pytest-cov <https://pytest-cov.readthedocs.io/en/latest/>`_
- `pytest-flake8 <https://pypi.org/project/pytest-flake8/>`_
The packages can be installed by the standard *pip* command::
sudo pip3 install pytest pytest-cov pytest-flake8
Documentation requirements
--------------------------
The Kwant_Spectrum test suite requires the following Python packages:
- `sphinx <https://www.sphinx-doc.org/en/master/>`_
- `jupyter-sphinx <https://jupyter-sphinx.readthedocs.io/en/latest/>`_
The packages can be installed by the standard *pip* command::
sudo pip3 install sphinx jupyter-sphinx
Building Kwant_Spectrum
^^^^^^^^^^^^^^^^^^^^^^^
Kwant-Spectrum can be installed from PyPI with::
sudo pip3 install kwant_spectrum
Alternatively, it can be installed directly from the source code repository::
sudo pip3 install git+https://gitlab.kwant-project.org/kwant/spectrum.git
For development, Kwant_Spectrum should first be cloned from the official repository::
git clone https://gitlab.kwant-project.org/kwant/spectrum.git
Then, after *cd* into the local repository,
one can locally build kwant_spectrum with the command::
python3 setup.py build
Test suite
----------
Unittests can be run directly in the local source repository from the command line::
pytest
Building the documentation
--------------------------
The documentation can be build directly in the ``/doc`` folder of the
local source repository from the command line::
make html
The generated html documentation can be browsed
by opening the file ``doc/build/html/index.html`` with a web browser.
Documentation
#############
Full documentation including a tutorial:
- https://kwant-project.org/extensions/spectrum
Contributing
############
Contributions and feedback are always welcome.
Report bugs and follow development through the project repository.
Authors can be reached by email
or a merge request may be opened on the project's website.
Please make sure that the test suite runs without errors before opening
a new merge request.
License
#######
Kwant_Spectrum distributed under BSD license, see ``LICENSE.rst`` in the
project repository.
Authors
#######
The principle developer of Kwant-Spectrum is:
* Thomas Kloss (CEA Grenoble)
Contributors to the project are:
* Christoph Groth (CEA Grenoble)
* Xavier Waintal (CEA Grenoble)
* Benoît Rossignol (CEA Grenoble)
(CEA = Commissariat à l'énergie atomique et aux énergies alternatives)
.. include:: ../../README.rst
......@@ -3,7 +3,8 @@ Kwant-Spectrum |release| documentation
.. toctree::
:maxdepth: 2
:caption: Contents:
:numbered: 3
about
tutorial
reference
......@@ -15,7 +15,7 @@ model with three crossing bands.
from kwant.physics import dispersion
def make_lead_with_crossing_bands():
lat = kwant.lattice.square(1)
lat = kwant.lattice.square(1, norbs=1)
sym = kwant.TranslationalSymmetry((-2, 0))
H = kwant.Builder(sym)
H[lat(0, 0)] = 0
......@@ -580,7 +580,7 @@ always finds the gap in a first nesting step.
for i, gap in enumerate([1E-1, 1E-2, 1E-3]):
func = partial(gap_function, gap=gap, x0=0.3)
x, y, dy, *_ = ks._match_functions(func, xmin=-1, xmax=1, tol=tol)
x, y, dy, *_ = ks._match_functions(func, xmin=-1, xmax=1, tol=tol, min_iter=1)
plt.subplot(1, 3, i+1)
plt.plot(x, y, '--o')
......@@ -599,7 +599,7 @@ smallest gap value. We can increase the tolerance with the keyword
for i, gap in enumerate([1E-1, 1E-2, 1E-3]):
func = partial(gap_function, gap=gap, x0=0.3)
x, y, dy, *_ = ks._match_functions(func, xmin=-1, xmax=1, tol=tol)
x, y, dy, *_ = ks._match_functions(func, xmin=-1, xmax=1, tol=tol, min_iter=1)
plt.subplot(1, 3, i+1)
plt.plot(x, y, '--o')
......@@ -646,6 +646,6 @@ to the original continous vector function
.. jupyter-execute::
xx, yy, dyy, *_ = ks._match_functions(model_func, xmin=-5, xmax=5)
xx, yy, dyy, *_ = ks._match_functions(model_func, xmin=-5, xmax=5, min_iter=1)
plt.plot(xx, yy, '--o')
plt.show()
# Copyright 2018-2020 Kwant-Spectrum authors.
#
# This file is part of Kwant-Spectrum. It is subject to the license terms in
# the file LICENSE.rst found in the top-level directory of this distribution.
from . import version
version.ensure_python()
__version__ = version.version
__all__ = []
for module in ('kwant_spectrum', ):
exec('from . import {0}'.format(module))
__all__.append(module)
available = [
('kwant_spectrum', kwant_spectrum.__all__)
]
for module, names in available:
exec('from .{0} import {1}'.format(module, ', '.join(names)))
__all__.extend(names)
# This file will be overwritten by setup.py when a source or binary
# distribution is made.
version = "__use_git__"
# These values are only set if the distribution was created with 'git archive'
refnames = "$Format:%D$"
git_hash = "$Format:%h$"
# Copyright 2018-2019 Kwant-Spectrum authors.
# Copyright 2018-2020 Kwant-Spectrum authors.
#
# This file is part of Kwant-Spectrum. It is subject to the license terms in
# the file LICENSE.rst found in the top-level directory of this distribution.
......@@ -13,7 +13,7 @@ import warnings
from kwant.physics import Bands
__all__ = ['spectrum', 'spectra', 'intersect_intervals', 'BandSketching']
__all__ = ['spectrum', 'spectra', 'intersect_intervals', 'BandSketching', '_match_functions']
def _scale_estimate(onsite_hamiltonian, hopping_elements):
......
# -*- coding: utf-8 -*-
"""Test package"""
# Copyright 2018-2019 Kwant-Spectrum authors.
# Copyright 2018-2020 Kwant-Spectrum authors.
#
# This file is part of Kwant-Spectrum. It is subject to the license terms in
# the file LICENSE.rst found in the top-level directory of this distribution.
......@@ -9,7 +9,7 @@ from numpy.testing import assert_array_almost_equal, assert_array_equal
import pytest
from pytest import raises
import kwant
import kwant_spectrum as ks
from .. import kwant_spectrum as ks
def test_cubic_coeffs_raise():
......@@ -22,7 +22,7 @@ def test_cubic_coeffs_raise():
x = np.linspace(-1, 1)
raises(ValueError, ks._cubic_coeffs, np.append(x, 2), np.sin(x), np.cos(x))
raises(ValueError, ks._cubic_coeffs, x, np.sin(x), np.cos(np.append(x, 2)))
raises(ValueError, ks._cubic_coeffs, x, np.sin(x), 1j*np.cos(x))
raises(ValueError, ks._cubic_coeffs, x, np.sin(x), 1j * np.cos(x))
raises(ValueError, ks._cubic_coeffs, x[::-1], np.sin(x), np.cos(x))
raises(ValueError, ks._cubic_coeffs, x, np.sin(x), np.cos(x), axis=1)
raises(ValueError, ks._cubic_coeffs, x * np.nan, np.sin(x), np.cos(x))
......@@ -52,7 +52,7 @@ def test_interpolation():
return (x - 0.5) * (x + 0.7) * (x + 0.2)
def dfunc(x):
return (x + 0.7)*(x + 0.2) + (x - 0.5)*(x + 0.2) + (x - 0.5)*(x + 0.7)
return (x + 0.7) * (x + 0.2) + (x - 0.5) * (x + 0.2) + (x - 0.5) * (x + 0.7)
x = np.linspace(-1, 1, 50)
cb = ks._cubic_interpolation(x, func(x), dfunc(x))
......@@ -80,10 +80,10 @@ def test_symmetric_function_matching():
def test_function_matching():
def model_func(xx, ordering='magnitude'):
def f(x):
return np.array([np.sin(x), -2*np.cos(2*x)])
return np.array([np.sin(x), -2 * np.cos(2 * x)])
def df(x):
return np.array([np.cos(x), 4*np.sin(2*x)])
return np.array([np.cos(x), 4 * np.sin(2 * x)])
if ordering == 'magnitude': # ordering like band structure
order = np.argsort(f(xx))
......@@ -131,7 +131,7 @@ def test_gap_detection_tolerance():
yy = func(x)[0].T
return np.allclose(y, yy)
for gap in np.power(1/10, [i for i in range(3, 8)]):
for gap in np.power(1 / 10, [i for i in range(3, 8)]):
for x0 in np.linspace(0.1, 0.9, 9):
assert not gap_detected(x0, gap, tol=1E-3)
assert gap_detected(x0, gap, tol=1E-14)
......@@ -141,10 +141,10 @@ def test_scale_invariance():
def make_lead(scale=1):
syst = kwant.Builder(kwant.TranslationalSymmetry((-1, 0)))
lat = kwant.lattice.square(norbs=1)
syst[lat(0, 0)] = 1*scale
syst[lat(0, 1)] = 8*scale
syst[lat(1, 0), lat(0, 0)] = -1*scale
syst[lat(1, 1), lat(0, 1)] = 2*scale
syst[lat(0, 0)] = 1 * scale
syst[lat(0, 1)] = 8 * scale
syst[lat(1, 0), lat(0, 0)] = -1 * scale
syst[lat(1, 1), lat(0, 1)] = 2 * scale
return syst
# create two systems at very different energy scales and check that
# the matching algorithm takes the same number of steps
......@@ -187,28 +187,28 @@ def test_band_analysis_methods():
# momenta, for which band energy = *energy*
assert len(ba.intersect(f=0, band=0)) == 0
assert len(ba.intersect(f=0, band=1)) == 0
assert_array_almost_equal(ba.intersect(f=0, band=2), [-pi/2, pi/2])
assert_array_almost_equal(ba.intersect(f=0, band=2), [-pi / 2, pi / 2])
# crossings over an extended range
assert len(ba.intersect(f=0, band=0, kmin=-2*pi, kmax=3*pi)) == 0
assert len(ba.intersect(f=0, band=1, kmin=-2*pi, kmax=3*pi)) == 0
assert_array_almost_equal(ba.intersect(f=0, band=2, kmin=-2*pi, kmax=3*pi),
np.array([-3, -1, 1, 3, 5]) * pi/2)
assert len(ba.intersect(f=0, band=0, kmin=-2 * pi, kmax=3 * pi)) == 0
assert len(ba.intersect(f=0, band=1, kmin=-2 * pi, kmax=3 * pi)) == 0
assert_array_almost_equal(ba.intersect(f=0, band=2, kmin=-2 * pi, kmax=3 * pi),
np.array([-3, -1, 1, 3, 5]) * pi / 2)
# zeros of the velocity
for band in range(ba.nbands):
velocity_zeros = ba.intersect(f=0, band=band, derivative_order=1)
assert_array_almost_equal(velocity_zeros, pi*np.array([-1, 0, 1]))
assert_array_almost_equal(velocity_zeros, pi * np.array([-1, 0, 1]))
velocity_zeros = ba.intersect(f=0, band=band, derivative_order=1,
kmin=-3*pi, kmax=2*pi)
kmin=-3 * pi, kmax=2 * pi)
assert_array_almost_equal(velocity_zeros,
pi*np.array([-3, -2, -1, 0, 1, 2]))
pi * np.array([-3, -2, -1, 0, 1, 2]))
# momentum intervals over extended range with band energies: energy <= 0
intervals = ba.intervals(band=0, upper=0, kmin=-3*pi, kmax=3*pi)
assert_array_almost_equal(intervals, [[-3*pi, 3*pi]])
intervals = ba.intervals(band=1, upper=0, kmin=-3*pi, kmax=3*pi)
intervals = ba.intervals(band=0, upper=0, kmin=-3 * pi, kmax=3 * pi)
assert_array_almost_equal(intervals, [[-3 * pi, 3 * pi]])
intervals = ba.intervals(band=1, upper=0, kmin=-3 * pi, kmax=3 * pi)
assert len(intervals) == 0
intervals = ba.intervals(band=2, upper=0, kmin=-3*np.pi, kmax=3*np.pi)
assert_array_almost_equal(intervals, [[-3*pi, -5/2*pi], [-3/2*pi, -1/2*pi],
[1/2*pi, 3/2*pi], [5/2*pi, 3*pi]])
intervals = ba.intervals(band=2, upper=0, kmin=-3 * np.pi, kmax=3 * np.pi)
assert_array_almost_equal(intervals, [[-3 * pi, -5 / 2 * pi], [-3 / 2 * pi, -1 / 2 * pi],
[1 / 2 * pi, 3 / 2 * pi], [5 / 2 * pi, 3 * pi]])
# momentum intervals, with band energies: -1.8 <= energy <= 0
intervals = ba.intervals(band=0, lower=-1.8, upper=0)
assert_array_almost_equal(intervals, [[-pi, pi]])
......@@ -217,7 +217,7 @@ def test_band_analysis_methods():
intervals = ba.intervals(band=2, lower=-1.8, upper=0)
num_bound = 2.6905658418
assert_array_almost_equal(intervals,
[[-num_bound, -pi/2], [pi/2, num_bound]])
[[-num_bound, -pi / 2], [pi / 2, num_bound]])
# momentum intervals with positive velocity
intervals = ba.intervals(band=0, lower=0, derivative_order=1)
assert_array_almost_equal(intervals, [[0, pi]])
......@@ -237,14 +237,14 @@ def test_band_analysis_methods():
intervals_e = ba.intervals(band=2, lower=-1.8, upper=0)
intervals_v = ba.intervals(band=2, lower=0, derivative_order=1)
intervals = ks.intersect_intervals(intervals_e, intervals_v)
assert_array_almost_equal(intervals, [[-num_bound, -pi/2]])
assert_array_almost_equal(intervals, [[-num_bound, -pi / 2]])
# check energy and velocity interpolant and periodicity
assert_array_almost_equal(ba.y, ba(ba.x))
assert_array_almost_equal(ba.y, ba(ba.x + 2*pi))
assert_array_almost_equal(ba.y, ba(ba.x - 2*pi))
assert_array_almost_equal(ba.y, ba(ba.x + 2 * pi))
assert_array_almost_equal(ba.y, ba(ba.x - 2 * pi))
assert_array_almost_equal(ba.dy, ba(ba.x, derivative_order=1))
assert_array_almost_equal(ba.dy, ba(ba.x + 2*pi, derivative_order=1))
assert_array_almost_equal(ba.dy, ba(ba.x - 2*pi, derivative_order=1))
assert_array_almost_equal(ba.dy, ba(ba.x + 2 * pi, derivative_order=1))
assert_array_almost_equal(ba.dy, ba(ba.x - 2 * pi, derivative_order=1))
# band-mode mapping from momentum
ba1 = ks.spectrum(make_simple_lead().finalized())
mode = ba1.momentum_to_scattering_mode
......@@ -272,10 +272,10 @@ def test_band_analysis_methods():
def test_spectrum_with_flat_band():
# edgecase with tree bands, where the second band is flat but with tiny noise
def make_lead_with_flat_band(l=3):
def make_lead_with_flat_band(ll=3):
lat = kwant.lattice.square(norbs=1)
lead = kwant.Builder(kwant.TranslationalSymmetry((-1, 1)))
lead[[lat(0, j) for j in range(l)]] = 0
lead[[lat(0, j) for j in range(ll)]] = 0
lead[lat.neighbors()] = -1
return lead
......@@ -301,10 +301,10 @@ def test_function_mapping():
# the two functions in f(x) cross at
# x = [-1, (3 - np.sqrt(13)) / 2, (3 + np.sqrt(13)) / 2]
def f(x):
return np.array([x*(x - 2)*(x + 1), x**2 + 2*x + 1])
return np.array([x * (x - 2) * (x + 1), x**2 + 2 * x + 1])
def df(x):
return np.array([3*x*x - 2*x - 2, 2*x + 2])
return np.array([3 * x * x - 2 * x - 2, 2 * x + 2])
return np.array([f(xx), df(xx)])
# test function ordering
......@@ -334,7 +334,7 @@ def test_function_mapping():
# is required (which can be simulated by setting min_split = 1) the
# algorithm will erroneously assume to be converged with only three points.
def f(x):
return np.array([[np.cos(2*x)], [-2*np.sin(2*x)]])
return np.array([[np.cos(2 * x)], [-2 * np.sin(2 * x)]])
x, y, dy, *_ = ks._match_functions(f, xmin=-np.pi, xmax=np.pi)
......@@ -345,7 +345,7 @@ def test_cost_matrix():
# take linear functions since cost matrix is calculated in linear approx.
def func(xx):
def f(x):
return np.array([5*x + 1, -2*x + 3])
return np.array([5 * x + 1, -2 * x + 3])
df = np.array([5, -2])
return np.array([f(xx), df])
......@@ -355,7 +355,7 @@ def test_cost_matrix():
# explicit form of the cost matrix
# m_ij = (\int_x0^x1 (f_i - f_j)^2 dx) / (x1 - x0)
def fint(x):
return 49/3 * x**3 - 14*x**2 + 4*x
return 49 / 3 * x**3 - 14 * x**2 + 4 * x
a = (fint(x1) - fint(x0)) / (x1 - x0)
cost = np.array([[0, a], [a, 0]])
......@@ -379,11 +379,11 @@ def test_helper_functions():
eps = 1E-14
# point at pi, -pi ambigous without epsilon
x = np.linspace(-np.pi + eps, np.pi - eps)
assert_array_almost_equal(x, ks._periodic(x+2*np.pi))
assert_array_almost_equal(x, ks._periodic(x-2*np.pi))
assert_array_almost_equal(x, ks._periodic(x + 2 * np.pi))
assert_array_almost_equal(x, ks._periodic(x - 2 * np.pi))
xeps = np.append(x, x+eps)
assert_array_equal(x, ks._unique(xeps, tol=2*eps))
xeps = np.append(x, x + eps)
assert_array_equal(x, ks._unique(xeps, tol=2 * eps))
# TODO: check tolerance
assert_array_equal(xeps, ks._unique(xeps, tol=eps/10))
assert_array_equal(xeps, ks._unique(xeps, tol=eps / 10))
# Copyright 2018-2020 Kwant-Spectrum authors.
#
# This file is part of Kwant-Spectrum. It is subject to the license terms in
# the file LICENSE.rst found in the top-level directory of this distribution.
import sys
import subprocess
import os
# No public API
__all__ = []
package_root = os.path.dirname(os.path.realpath(__file__))
distr_root = os.path.dirname(package_root)
def ensure_python(required_version=(3, 5)):
v = sys.version_info
if v[:3] < required_version:
error = "This version of Kwant_Spectrum requires Python {} or above.".format(
".".join(str(p) for p in required_version))
print(error, file=sys.stderr)
sys.exit(1)
def get_version_from_git():
try:
p = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'],
cwd=distr_root,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
except OSError: