diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..cddfd28
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,7 @@
+root = true
+
+# Unix-style newlines with a newline ending every file
+[*]
+end_of_line = lf
+# insert_final_newline = true
+indent_style = tab
diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000..cd33aba
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,3 @@
+[flake8]
+ignore = W191, E501, W503, W504
+max-line-length = 120
diff --git a/.gitignore b/.gitignore
index 75aa508..125bfe3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,140 +1,142 @@
-.idea/**/*
-
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-*$py.class
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-wheels/
-share/python-wheels/
-*.egg-info/
-.installed.cfg
-*.egg
-MANIFEST
-
-# PyInstaller
-# Usually these files are written by a python script from a template
-# before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.nox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*.cover
-*.py,cover
-.hypothesis/
-.pytest_cache/
-cover/
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-local_settings.py
-db.sqlite3
-db.sqlite3-journal
-
-# Flask stuff:
-instance/
-.webassets-cache
-
-# Scrapy stuff:
-.scrapy
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-.pybuilder/
-target/
-
-# Jupyter Notebook
-.ipynb_checkpoints
-
-# IPython
-profile_default/
-ipython_config.py
-
-# pyenv
-# For a library or package, you might want to ignore these files since the code is
-# intended to run in multiple environments; otherwise, check them in:
-# .python-version
-
-# pipenv
-# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
-# However, in case of collaboration, if having platform-specific dependencies or dependencies
-# having no cross-platform support, pipenv may install dependencies that don't work, or not
-# install all needed dependencies.
-#Pipfile.lock
-
-# PEP 582; used by e.g. github.com/David-OConnor/pyflow
-__pypackages__/
-
-# Celery stuff
-celerybeat-schedule
-celerybeat.pid
-
-# SageMath parsed files
-*.sage.py
-
-# Environments
-.env
-.venv
-env/
-venv/
-ENV/
-env.bak/
-venv.bak/
-
-# Spyder project settings
-.spyderproject
-.spyproject
-
-# Rope project settings
-.ropeproject
-
-# mkdocs documentation
-/site
-
-# mypy
-.mypy_cache/
-.dmypy.json
-dmypy.json
-
-# Pyre type checker
-.pyre/
-
-# pytype static type analyzer
-.pytype/
-
-# Cython debug symbols
-cython_debug/
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+pytest.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+.csv
+.idea
diff --git a/.versionrc b/.versionrc
new file mode 100644
index 0000000..7889a88
--- /dev/null
+++ b/.versionrc
@@ -0,0 +1,10 @@
+{
+ "bumpFiles": [
+ {
+ "filename": "pyproject.toml",
+ "updater": "scripts/standard-version/pyproject-updater.js"
+ }
+ ],
+ "sign": true,
+ "tag-prefix": ""
+}
diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..f40513d
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,81 @@
+pipeline {
+ agent {
+ kubernetes {
+ label 'pynam' // all your pods will be named with this prefix, followed by a unique id
+ idleMinutes 5 // how long the pod will live after no jobs have run on it
+ yamlFile 'jenkins/ci-agent-pod.yaml' // path to the pod definition relative to the root of our project
+ defaultContainer 'poetry' // define a default container if more than a few stages use it, will default to jnlp container
+ }
+ }
+
+ options {
+ parallelsAlwaysFailFast()
+ }
+
+ stages {
+ stage('Build') {
+ steps {
+ echo 'Building...'
+ sh 'python --version'
+ sh 'poetry --version'
+ sh 'poetry install'
+ }
+ }
+ stage('Test') {
+ parallel{
+ stage('pytest') {
+ steps {
+ sh 'poetry run pytest --benchmark-skip'
+ }
+ }
+ stage('lint') {
+ steps {
+ sh 'poetry run flake8 pynam tests'
+ }
+ }
+ stage('mypy') {
+ steps {
+ sh 'poetry run mypy pynam'
+ }
+ }
+ }
+ }
+
+ stage('Deploy') {
+ environment {
+ PYPI=credentials("pypi-pynam")
+ }
+
+ when {
+ buildingTag()
+ }
+ steps {
+ echo 'Deploying...'
+ sh 'poetry publish -u ${PYPI_USR} -p ${PYPI_PSW} --build'
+ }
+ }
+
+ }
+ post {
+ always {
+ echo 'This will always run'
+ junit 'pytest.xml'
+ cobertura coberturaReportFile: 'coverage.xml'
+ mail (bcc: '',
+ body: "Project: ${env.JOB_NAME}
Build Number: ${env.BUILD_NUMBER}
Build URL: ${env.BUILD_URL}", cc: '', charset: 'UTF-8', from: 'jenkins@jenkins.deepak.science', mimeType: 'text/html', replyTo: 'dmallubhotla+jenkins@gmail.com', subject: "${env.JOB_NAME} #${env.BUILD_NUMBER}: Build ${currentBuild.currentResult}", to: "dmallubhotla+ci@gmail.com")
+ }
+ success {
+ echo 'This will run only if successful'
+ }
+ failure {
+ echo 'This will run only if failed'
+ }
+ unstable {
+ echo 'This will run only if the run was marked as unstable'
+ }
+ changed {
+ echo 'This will run only if the state of the Pipeline has changed'
+ echo 'For example, if the Pipeline was previously failing but is now successful'
+ }
+ }
+}
diff --git a/do.sh b/do.sh
new file mode 100644
index 0000000..2ab1420
--- /dev/null
+++ b/do.sh
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+# Do - The Simplest Build Tool on Earth.
+# Documentation and examples see https://github.com/8gears/do
+
+set -Eeuo pipefail # -e "Automatic exit from bash shell script on error" -u "Treat unset variables and parameters as errors"
+
+build() {
+ echo "I am ${FUNCNAME[0]}ing"
+ poetry build
+}
+
+fmt() {
+ poetry run black .
+ find . -type f -name "*.py" -exec sed -i -e 's/ /\t/g' {} \;
+}
+
+test() {
+ echo "I am ${FUNCNAME[0]}ing"
+ poetry run flake8 pynam tests
+ poetry run mypy pynam
+ poetry run pytest
+}
+
+htmlcov() {
+ poetry run pytest --cov-report=html
+}
+
+release() {
+ ./scripts/release.sh
+}
+
+all() {
+ build && test
+}
+
+"$@" # <- execute the task
+
+[ "$#" -gt 0 ] || printf "Usage:\n\t./do.sh %s\n" "($(compgen -A function | grep '^[^_]' | paste -sd '|' -))"
diff --git a/jenkins/ci-agent-pod.yaml b/jenkins/ci-agent-pod.yaml
new file mode 100644
index 0000000..f3ed483
--- /dev/null
+++ b/jenkins/ci-agent-pod.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Pod
+spec:
+ imagePullSecrets:
+ - name: regcreds
+ containers: # list of containers that you want present for your build, you can define a default container in the Jenkinsfile
+ - name: poetry
+ image: ghcr.io/dmallubhotla/poetry-image:1
+ command: ["tail", "-f", "/dev/null"] # this or any command that is bascially a noop is required, this is so that you don't overwrite the entrypoint of the base container
+ imagePullPolicy: Always # use cache or pull image for agent
+ resources: # limits the resources your build contaienr
+ requests:
+ memory: "2Gi"
+ cpu: "500m"
+ limits:
+ memory: "2Gi"
diff --git a/poetry.lock b/poetry.lock
index 06aa4c7..ee55f54 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,260 +1,539 @@
-[[package]]
-category = "dev"
-description = "Atomic file writes."
-name = "atomicwrites"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.4.0"
-
-[[package]]
-category = "dev"
-description = "Classes Without Boilerplate"
-name = "attrs"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "19.3.0"
-
-[package.extras]
-azure-pipelines = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "pytest-azurepipelines"]
-dev = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "sphinx", "pre-commit"]
-docs = ["sphinx", "zope.interface"]
-tests = ["coverage", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"]
-
-[[package]]
-category = "dev"
-description = "Cross-platform colored terminal text."
-marker = "sys_platform == \"win32\""
-name = "colorama"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "0.4.3"
-
-[[package]]
-category = "dev"
-description = "Read metadata from Python packages"
-marker = "python_version < \"3.8\""
-name = "importlib-metadata"
-optional = false
-python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
-version = "1.7.0"
-
-[package.dependencies]
-zipp = ">=0.5"
-
-[package.extras]
-docs = ["sphinx", "rst.linker"]
-testing = ["packaging", "pep517", "importlib-resources (>=1.3)"]
-
-[[package]]
-category = "dev"
-description = "More routines for operating on iterables, beyond itertools"
-name = "more-itertools"
-optional = false
-python-versions = ">=3.5"
-version = "8.4.0"
-
-[[package]]
-category = "main"
-description = "NumPy is the fundamental package for array computing with Python."
-name = "numpy"
-optional = false
-python-versions = ">=3.6"
-version = "1.19.0"
-
-[[package]]
-category = "dev"
-description = "plugin and hook calling mechanisms for python"
-name = "pluggy"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "0.13.1"
-
-[package.dependencies]
-[package.dependencies.importlib-metadata]
-python = "<3.8"
-version = ">=0.12"
-
-[package.extras]
-dev = ["pre-commit", "tox"]
-
-[[package]]
-category = "dev"
-description = "library with cross-python path, ini-parsing, io, code, log facilities"
-name = "py"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "1.9.0"
-
-[[package]]
-category = "dev"
-description = "Get CPU info with pure Python 2 & 3"
-name = "py-cpuinfo"
-optional = false
-python-versions = "*"
-version = "7.0.0"
-
-[[package]]
-category = "dev"
-description = "pytest: simple powerful testing with Python"
-name = "pytest"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
-version = "3.10.1"
-
-[package.dependencies]
-atomicwrites = ">=1.0"
-attrs = ">=17.4.0"
-colorama = "*"
-more-itertools = ">=4.0.0"
-pluggy = ">=0.7"
-py = ">=1.5.0"
-setuptools = "*"
-six = ">=1.10.0"
-
-[[package]]
-category = "dev"
-description = "A ``pytest`` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer. See calibration_ and FAQ_."
-name = "pytest-benchmark"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
-version = "3.2.3"
-
-[package.dependencies]
-py-cpuinfo = "*"
-pytest = ">=3.8"
-
-[package.extras]
-aspect = ["aspectlib"]
-elasticsearch = ["elasticsearch"]
-histogram = ["pygal", "pygaljs"]
-
-[[package]]
-category = "main"
-description = "SciPy: Scientific Library for Python"
-name = "scipy"
-optional = false
-python-versions = ">=3.6"
-version = "1.5.1"
-
-[package.dependencies]
-numpy = ">=1.14.5"
-
-[[package]]
-category = "dev"
-description = "Python 2 and 3 compatibility utilities"
-name = "six"
-optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
-version = "1.15.0"
-
-[[package]]
-category = "dev"
-description = "Backport of pathlib-compatible object wrapper for zip files"
-marker = "python_version < \"3.8\""
-name = "zipp"
-optional = false
-python-versions = ">=3.6"
-version = "3.1.0"
-
-[package.extras]
-docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
-testing = ["jaraco.itertools", "func-timeout"]
-
-[metadata]
-content-hash = "02f8a795ac396fe3c5adcc163c673e4e53b1c63fb5d0840c5319169093cd3a5f"
-python-versions = "^3.7"
-
-[metadata.files]
-atomicwrites = [
- {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
- {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
-]
-attrs = [
- {file = "attrs-19.3.0-py2.py3-none-any.whl", hash = "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c"},
- {file = "attrs-19.3.0.tar.gz", hash = "sha256:f7b7ce16570fe9965acd6d30101a28f62fb4a7f9e926b3bbc9b61f8b04247e72"},
-]
-colorama = [
- {file = "colorama-0.4.3-py2.py3-none-any.whl", hash = "sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff"},
- {file = "colorama-0.4.3.tar.gz", hash = "sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1"},
-]
-importlib-metadata = [
- {file = "importlib_metadata-1.7.0-py2.py3-none-any.whl", hash = "sha256:dc15b2969b4ce36305c51eebe62d418ac7791e9a157911d58bfb1f9ccd8e2070"},
- {file = "importlib_metadata-1.7.0.tar.gz", hash = "sha256:90bb658cdbbf6d1735b6341ce708fc7024a3e14e99ffdc5783edea9f9b077f83"},
-]
-more-itertools = [
- {file = "more-itertools-8.4.0.tar.gz", hash = "sha256:68c70cc7167bdf5c7c9d8f6954a7837089c6a36bf565383919bb595efb8a17e5"},
- {file = "more_itertools-8.4.0-py3-none-any.whl", hash = "sha256:b78134b2063dd214000685165d81c154522c3ee0a1c0d4d113c80361c234c5a2"},
-]
-numpy = [
- {file = "numpy-1.19.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:63d971bb211ad3ca37b2adecdd5365f40f3b741a455beecba70fd0dde8b2a4cb"},
- {file = "numpy-1.19.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:b6aaeadf1e4866ca0fdf7bb4eed25e521ae21a7947c59f78154b24fc7abbe1dd"},
- {file = "numpy-1.19.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:13af0184177469192d80db9bd02619f6fa8b922f9f327e077d6f2a6acb1ce1c0"},
- {file = "numpy-1.19.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:356f96c9fbec59974a592452ab6a036cd6f180822a60b529a975c9467fcd5f23"},
- {file = "numpy-1.19.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:fa1fe75b4a9e18b66ae7f0b122543c42debcf800aaafa0212aaff3ad273c2596"},
- {file = "numpy-1.19.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:cbe326f6d364375a8e5a8ccb7e9cd73f4b2f6dc3b2ed205633a0db8243e2a96a"},
- {file = "numpy-1.19.0-cp36-cp36m-win32.whl", hash = "sha256:a2e3a39f43f0ce95204beb8fe0831199542ccab1e0c6e486a0b4947256215632"},
- {file = "numpy-1.19.0-cp36-cp36m-win_amd64.whl", hash = "sha256:7b852817800eb02e109ae4a9cef2beda8dd50d98b76b6cfb7b5c0099d27b52d4"},
- {file = "numpy-1.19.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d97a86937cf9970453c3b62abb55a6475f173347b4cde7f8dcdb48c8e1b9952d"},
- {file = "numpy-1.19.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:a86c962e211f37edd61d6e11bb4df7eddc4a519a38a856e20a6498c319efa6b0"},
- {file = "numpy-1.19.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:d34fbb98ad0d6b563b95de852a284074514331e6b9da0a9fc894fb1cdae7a79e"},
- {file = "numpy-1.19.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:658624a11f6e1c252b2cd170d94bf28c8f9410acab9f2fd4369e11e1cd4e1aaf"},
- {file = "numpy-1.19.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:4d054f013a1983551254e2379385e359884e5af105e3efe00418977d02f634a7"},
- {file = "numpy-1.19.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:26a45798ca2a4e168d00de75d4a524abf5907949231512f372b217ede3429e98"},
- {file = "numpy-1.19.0-cp37-cp37m-win32.whl", hash = "sha256:3c40c827d36c6d1c3cf413694d7dc843d50997ebffbc7c87d888a203ed6403a7"},
- {file = "numpy-1.19.0-cp37-cp37m-win_amd64.whl", hash = "sha256:be62aeff8f2f054eff7725f502f6228298891fd648dc2630e03e44bf63e8cee0"},
- {file = "numpy-1.19.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:dd53d7c4a69e766e4900f29db5872f5824a06827d594427cf1a4aa542818b796"},
- {file = "numpy-1.19.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:30a59fb41bb6b8c465ab50d60a1b298d1cd7b85274e71f38af5a75d6c475d2d2"},
- {file = "numpy-1.19.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:df1889701e2dfd8ba4dc9b1a010f0a60950077fb5242bb92c8b5c7f1a6f2668a"},
- {file = "numpy-1.19.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:33c623ef9ca5e19e05991f127c1be5aeb1ab5cdf30cb1c5cf3960752e58b599b"},
- {file = "numpy-1.19.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:26f509450db547e4dfa3ec739419b31edad646d21fb8d0ed0734188b35ff6b27"},
- {file = "numpy-1.19.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:7b57f26e5e6ee2f14f960db46bd58ffdca25ca06dd997729b1b179fddd35f5a3"},
- {file = "numpy-1.19.0-cp38-cp38-win32.whl", hash = "sha256:a8705c5073fe3fcc297fb8e0b31aa794e05af6a329e81b7ca4ffecab7f2b95ef"},
- {file = "numpy-1.19.0-cp38-cp38-win_amd64.whl", hash = "sha256:c2edbb783c841e36ca0fa159f0ae97a88ce8137fb3a6cd82eae77349ba4b607b"},
- {file = "numpy-1.19.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:8cde829f14bd38f6da7b2954be0f2837043e8b8d7a9110ec5e318ae6bf706610"},
- {file = "numpy-1.19.0.zip", hash = "sha256:76766cc80d6128750075378d3bb7812cf146415bd29b588616f72c943c00d598"},
-]
-pluggy = [
- {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
- {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
-]
-py = [
- {file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"},
- {file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"},
-]
-py-cpuinfo = [
- {file = "py-cpuinfo-7.0.0.tar.gz", hash = "sha256:9aa2e49675114959697d25cf57fec41c29b55887bff3bc4809b44ac6f5730097"},
-]
-pytest = [
- {file = "pytest-3.10.1-py2.py3-none-any.whl", hash = "sha256:3f193df1cfe1d1609d4c583838bea3d532b18d6160fd3f55c9447fdca30848ec"},
- {file = "pytest-3.10.1.tar.gz", hash = "sha256:e246cf173c01169b9617fc07264b7b1316e78d7a650055235d6d897bc80d9660"},
-]
-pytest-benchmark = [
- {file = "pytest-benchmark-3.2.3.tar.gz", hash = "sha256:ad4314d093a3089701b24c80a05121994c7765ce373478c8f4ba8d23c9ba9528"},
- {file = "pytest_benchmark-3.2.3-py2.py3-none-any.whl", hash = "sha256:01f79d38d506f5a3a0a9ada22ded714537bbdfc8147a881a35c1655db07289d9"},
-]
-scipy = [
- {file = "scipy-1.5.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:058e84930407927f71963a4ad8c1dc96c4d2d075636a68578195648c81f78810"},
- {file = "scipy-1.5.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:7908c85854c5b5b6d3ce7fefafac1ca3e23ff9ac41edabc2d46ae5dc9fa070ac"},
- {file = "scipy-1.5.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8302d69fb1528ea7c7f2a1ea640d354c981b6eb8192d1c175349874209397604"},
- {file = "scipy-1.5.1-cp36-cp36m-win32.whl", hash = "sha256:35d042d6499caf1a5d171baed0ebf01eb665b7af2ad98a8ff1b0e6e783654540"},
- {file = "scipy-1.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:5e0bb43ff581811ab7f27425f6b96c1ddf7591ccad2e486c9af0b910c18f7185"},
- {file = "scipy-1.5.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b4858ccbd88f4b53950fb9fc0069c1d9fea83d7cff2382e1d8b023d3f4883014"},
- {file = "scipy-1.5.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:eb46d8b5947ca27b0bc972cecfba8130f088a83ab3d08c1a6033d9070b3046b3"},
- {file = "scipy-1.5.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fff15df01bef1243468be60c55178ed7576270b200aab08a7ffd5b8e0bbc340c"},
- {file = "scipy-1.5.1-cp37-cp37m-win32.whl", hash = "sha256:81859ed3aad620752dd2c07c32b5d3a80a0d47c5e3813904621954a78a0ae899"},
- {file = "scipy-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:c05c6fe76228cc13c5214e9faf5f2a871a1da54473bc417ab9da310d0e5fff8b"},
- {file = "scipy-1.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:71742889393a724dfce755b6b61228677873d269a4234e51ddaf08b998433c91"},
- {file = "scipy-1.5.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:9323d268775991b79690f7b9a28a4e8b8c4f2b160ed9f8a90123127314e2d3c1"},
- {file = "scipy-1.5.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:06b19a650471781056c1a2172eeeeb777b8b516e9434005dd392a4559e0938b9"},
- {file = "scipy-1.5.1-cp38-cp38-win32.whl", hash = "sha256:57a0f2be3063dbe1e3daf31ec9005576e8fd1022a28159d0db71d14566899d16"},
- {file = "scipy-1.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:c06e731aa46c0dfc563cc636155758178ebc019ef78b9b0f4370effe2ac0f0e6"},
- {file = "scipy-1.5.1.tar.gz", hash = "sha256:039572f0ca9578a466683558c5bf1e65d442860ec6e13307d528749cfe6d07b8"},
-]
-six = [
- {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"},
- {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"},
-]
-zipp = [
- {file = "zipp-3.1.0-py3-none-any.whl", hash = "sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b"},
- {file = "zipp-3.1.0.tar.gz", hash = "sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"},
-]
+[[package]]
+name = "atomicwrites"
+version = "1.4.0"
+description = "Atomic file writes."
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[[package]]
+name = "attrs"
+version = "21.4.0"
+description = "Classes Without Boilerplate"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[package.extras]
+dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"]
+docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
+tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
+tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"]
+
+[[package]]
+name = "black"
+version = "22.3.0"
+description = "The uncompromising code formatter."
+category = "dev"
+optional = false
+python-versions = ">=3.6.2"
+
+[package.dependencies]
+click = ">=8.0.0"
+mypy-extensions = ">=0.4.3"
+pathspec = ">=0.9.0"
+platformdirs = ">=2"
+tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""}
+typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""}
+
+[package.extras]
+colorama = ["colorama (>=0.4.3)"]
+d = ["aiohttp (>=3.7.4)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
+[[package]]
+name = "click"
+version = "8.1.0"
+description = "Composable command line interface toolkit"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.4"
+description = "Cross-platform colored terminal text."
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[[package]]
+name = "coverage"
+version = "6.3.2"
+description = "Code coverage measurement for Python"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
+[package.dependencies]
+tomli = {version = "*", optional = true, markers = "extra == \"toml\""}
+
+[package.extras]
+toml = ["tomli"]
+
+[[package]]
+name = "flake8"
+version = "4.0.1"
+description = "the modular source code checker: pep8 pyflakes and co"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+mccabe = ">=0.6.0,<0.7.0"
+pycodestyle = ">=2.8.0,<2.9.0"
+pyflakes = ">=2.4.0,<2.5.0"
+
+[[package]]
+name = "iniconfig"
+version = "1.1.1"
+description = "iniconfig: brain-dead simple config-ini parsing"
+category = "dev"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "mccabe"
+version = "0.6.1"
+description = "McCabe checker, plugin for flake8"
+category = "dev"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "mypy"
+version = "0.942"
+description = "Optional static typing for Python"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+mypy-extensions = ">=0.4.3"
+tomli = ">=1.1.0"
+typing-extensions = ">=3.10"
+
+[package.extras]
+dmypy = ["psutil (>=4.0)"]
+python2 = ["typed-ast (>=1.4.0,<2)"]
+reports = ["lxml"]
+
+[[package]]
+name = "mypy-extensions"
+version = "0.4.3"
+description = "Experimental type system extensions for programs checked with the mypy typechecker."
+category = "dev"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "numpy"
+version = "1.22.3"
+description = "NumPy is the fundamental package for array computing with Python."
+category = "main"
+optional = false
+python-versions = ">=3.8"
+
+[[package]]
+name = "packaging"
+version = "21.3"
+description = "Core utilities for Python packages"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
+
+[[package]]
+name = "pathspec"
+version = "0.9.0"
+description = "Utility library for gitignore style pattern matching of file paths."
+category = "dev"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+
+[[package]]
+name = "platformdirs"
+version = "2.5.1"
+description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
+[package.extras]
+docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
+test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
+
+[[package]]
+name = "pluggy"
+version = "1.0.0"
+description = "plugin and hook calling mechanisms for python"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
+[[package]]
+name = "py"
+version = "1.11.0"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[[package]]
+name = "py-cpuinfo"
+version = "8.0.0"
+description = "Get CPU info with pure Python 2 & 3"
+category = "dev"
+optional = false
+python-versions = "*"
+
+[[package]]
+name = "pycodestyle"
+version = "2.8.0"
+description = "Python style guide checker"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[[package]]
+name = "pyflakes"
+version = "2.4.0"
+description = "passive checker of Python programs"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[[package]]
+name = "pyparsing"
+version = "3.0.7"
+description = "Python parsing module"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+diagrams = ["jinja2", "railroad-diagrams"]
+
+[[package]]
+name = "pytest"
+version = "7.1.1"
+description = "pytest: simple powerful testing with Python"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
+[package.dependencies]
+atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
+attrs = ">=19.2.0"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+py = ">=1.8.2"
+tomli = ">=1.0.0"
+
+[package.extras]
+testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
+
+[[package]]
+name = "pytest-benchmark"
+version = "3.4.1"
+description = "A ``pytest`` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer."
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[package.dependencies]
+py-cpuinfo = "*"
+pytest = ">=3.8"
+
+[package.extras]
+aspect = ["aspectlib"]
+elasticsearch = ["elasticsearch"]
+histogram = ["pygal", "pygaljs"]
+
+[[package]]
+name = "pytest-cov"
+version = "3.0.0"
+description = "Pytest plugin for measuring coverage."
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+coverage = {version = ">=5.2.1", extras = ["toml"]}
+pytest = ">=4.6"
+
+[package.extras]
+testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"]
+
+[[package]]
+name = "scipy"
+version = "1.8.0"
+description = "SciPy: Scientific Library for Python"
+category = "main"
+optional = false
+python-versions = ">=3.8,<3.11"
+
+[package.dependencies]
+numpy = ">=1.17.3,<1.25.0"
+
+[[package]]
+name = "tomli"
+version = "2.0.1"
+description = "A lil' TOML parser"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
+[[package]]
+name = "typing-extensions"
+version = "4.1.1"
+description = "Backported and Experimental Type Hints for Python 3.6+"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[metadata]
+lock-version = "1.1"
+python-versions = "^3.8,<3.10"
+content-hash = "d7ee7d61a1643514f418ae5fd9d76c6557a597bc9bf43355ed335db8f1fdda7d"
+
+[metadata.files]
+atomicwrites = [
+ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
+ {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
+]
+attrs = [
+ {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
+ {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
+]
+black = [
+ {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"},
+ {file = "black-22.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5795a0375eb87bfe902e80e0c8cfaedf8af4d49694d69161e5bd3206c18618bb"},
+ {file = "black-22.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e3556168e2e5c49629f7b0f377070240bd5511e45e25a4497bb0073d9dda776a"},
+ {file = "black-22.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67c8301ec94e3bcc8906740fe071391bce40a862b7be0b86fb5382beefecd968"},
+ {file = "black-22.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:fd57160949179ec517d32ac2ac898b5f20d68ed1a9c977346efbac9c2f1e779d"},
+ {file = "black-22.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc1e1de68c8e5444e8f94c3670bb48a2beef0e91dddfd4fcc29595ebd90bb9ce"},
+ {file = "black-22.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d2fc92002d44746d3e7db7cf9313cf4452f43e9ea77a2c939defce3b10b5c82"},
+ {file = "black-22.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a6342964b43a99dbc72f72812bf88cad8f0217ae9acb47c0d4f141a6416d2d7b"},
+ {file = "black-22.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:328efc0cc70ccb23429d6be184a15ce613f676bdfc85e5fe8ea2a9354b4e9015"},
+ {file = "black-22.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06f9d8846f2340dfac80ceb20200ea5d1b3f181dd0556b47af4e8e0b24fa0a6b"},
+ {file = "black-22.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4efa5fad66b903b4a5f96d91461d90b9507a812b3c5de657d544215bb7877a"},
+ {file = "black-22.3.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8477ec6bbfe0312c128e74644ac8a02ca06bcdb8982d4ee06f209be28cdf163"},
+ {file = "black-22.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:637a4014c63fbf42a692d22b55d8ad6968a946b4a6ebc385c5505d9625b6a464"},
+ {file = "black-22.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:863714200ada56cbc366dc9ae5291ceb936573155f8bf8e9de92aef51f3ad0f0"},
+ {file = "black-22.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10dbe6e6d2988049b4655b2b739f98785a884d4d6b85bc35133a8fb9a2233176"},
+ {file = "black-22.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:cee3e11161dde1b2a33a904b850b0899e0424cc331b7295f2a9698e79f9a69a0"},
+ {file = "black-22.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5891ef8abc06576985de8fa88e95ab70641de6c1fca97e2a15820a9b69e51b20"},
+ {file = "black-22.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:30d78ba6bf080eeaf0b7b875d924b15cd46fec5fd044ddfbad38c8ea9171043a"},
+ {file = "black-22.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ee8f1f7228cce7dffc2b464f07ce769f478968bfb3dd1254a4c2eeed84928aad"},
+ {file = "black-22.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ee227b696ca60dd1c507be80a6bc849a5a6ab57ac7352aad1ffec9e8b805f21"},
+ {file = "black-22.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:9b542ced1ec0ceeff5b37d69838106a6348e60db7b8fdd245294dc1d26136265"},
+ {file = "black-22.3.0-py3-none-any.whl", hash = "sha256:bc58025940a896d7e5356952228b68f793cf5fcb342be703c3a2669a1488cb72"},
+ {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"},
+]
+click = [
+ {file = "click-8.1.0-py3-none-any.whl", hash = "sha256:19a4baa64da924c5e0cd889aba8e947f280309f1a2ce0947a3e3a7bcb7cc72d6"},
+ {file = "click-8.1.0.tar.gz", hash = "sha256:977c213473c7665d3aa092b41ff12063227751c41d7b17165013e10069cc5cd2"},
+]
+colorama = [
+ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
+ {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
+]
+coverage = [
+ {file = "coverage-6.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf"},
+ {file = "coverage-6.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37d1141ad6b2466a7b53a22e08fe76994c2d35a5b6b469590424a9953155afac"},
+ {file = "coverage-6.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9987b0354b06d4df0f4d3e0ec1ae76d7ce7cbca9a2f98c25041eb79eec766f1"},
+ {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26e2deacd414fc2f97dd9f7676ee3eaecd299ca751412d89f40bc01557a6b1b4"},
+ {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd8bafa458b5c7d061540f1ee9f18025a68e2d8471b3e858a9dad47c8d41903"},
+ {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:46191097ebc381fbf89bdce207a6c107ac4ec0890d8d20f3360345ff5976155c"},
+ {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6f89d05e028d274ce4fa1a86887b071ae1755082ef94a6740238cd7a8178804f"},
+ {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:58303469e9a272b4abdb9e302a780072c0633cdcc0165db7eec0f9e32f901e05"},
+ {file = "coverage-6.3.2-cp310-cp310-win32.whl", hash = "sha256:2fea046bfb455510e05be95e879f0e768d45c10c11509e20e06d8fcaa31d9e39"},
+ {file = "coverage-6.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:a2a8b8bcc399edb4347a5ca8b9b87e7524c0967b335fbb08a83c8421489ddee1"},
+ {file = "coverage-6.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f1555ea6d6da108e1999b2463ea1003fe03f29213e459145e70edbaf3e004aaa"},
+ {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5f4e1edcf57ce94e5475fe09e5afa3e3145081318e5fd1a43a6b4539a97e518"},
+ {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a15dc0a14008f1da3d1ebd44bdda3e357dbabdf5a0b5034d38fcde0b5c234b7"},
+ {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21b7745788866028adeb1e0eca3bf1101109e2dc58456cb49d2d9b99a8c516e6"},
+ {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8ce257cac556cb03be4a248d92ed36904a59a4a5ff55a994e92214cde15c5bad"},
+ {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b0be84e5a6209858a1d3e8d1806c46214e867ce1b0fd32e4ea03f4bd8b2e3359"},
+ {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:acf53bc2cf7282ab9b8ba346746afe703474004d9e566ad164c91a7a59f188a4"},
+ {file = "coverage-6.3.2-cp37-cp37m-win32.whl", hash = "sha256:8bdde1177f2311ee552f47ae6e5aa7750c0e3291ca6b75f71f7ffe1f1dab3dca"},
+ {file = "coverage-6.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b31651d018b23ec463e95cf10070d0b2c548aa950a03d0b559eaa11c7e5a6fa3"},
+ {file = "coverage-6.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07e6db90cd9686c767dcc593dff16c8c09f9814f5e9c51034066cad3373b914d"},
+ {file = "coverage-6.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c6dbb42f3ad25760010c45191e9757e7dce981cbfb90e42feef301d71540059"},
+ {file = "coverage-6.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76aeef1b95aff3905fb2ae2d96e319caca5b76fa41d3470b19d4e4a3a313512"},
+ {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cf5cfcb1521dc3255d845d9dca3ff204b3229401994ef8d1984b32746bb45ca"},
+ {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fbbdc8d55990eac1b0919ca69eb5a988a802b854488c34b8f37f3e2025fa90d"},
+ {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ec6bc7fe73a938933d4178c9b23c4e0568e43e220aef9472c4f6044bfc6dd0f0"},
+ {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9baff2a45ae1f17c8078452e9e5962e518eab705e50a0aa8083733ea7d45f3a6"},
+ {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd9e830e9d8d89b20ab1e5af09b32d33e1a08ef4c4e14411e559556fd788e6b2"},
+ {file = "coverage-6.3.2-cp38-cp38-win32.whl", hash = "sha256:f7331dbf301b7289013175087636bbaf5b2405e57259dd2c42fdcc9fcc47325e"},
+ {file = "coverage-6.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:68353fe7cdf91f109fc7d474461b46e7f1f14e533e911a2a2cbb8b0fc8613cf1"},
+ {file = "coverage-6.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b78e5afb39941572209f71866aa0b206c12f0109835aa0d601e41552f9b3e620"},
+ {file = "coverage-6.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e21876082ed887baed0146fe222f861b5815455ada3b33b890f4105d806128d"},
+ {file = "coverage-6.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34626a7eee2a3da12af0507780bb51eb52dca0e1751fd1471d0810539cefb536"},
+ {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ebf730d2381158ecf3dfd4453fbca0613e16eaa547b4170e2450c9707665ce7"},
+ {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd6fe30bd519694b356cbfcaca9bd5c1737cddd20778c6a581ae20dc8c04def2"},
+ {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96f8a1cb43ca1422f36492bebe63312d396491a9165ed3b9231e778d43a7fca4"},
+ {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dd035edafefee4d573140a76fdc785dc38829fe5a455c4bb12bac8c20cfc3d69"},
+ {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ca5aeb4344b30d0bec47481536b8ba1181d50dbe783b0e4ad03c95dc1296684"},
+ {file = "coverage-6.3.2-cp39-cp39-win32.whl", hash = "sha256:f5fa5803f47e095d7ad8443d28b01d48c0359484fec1b9d8606d0e3282084bc4"},
+ {file = "coverage-6.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:9548f10d8be799551eb3a9c74bbf2b4934ddb330e08a73320123c07f95cc2d92"},
+ {file = "coverage-6.3.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf"},
+ {file = "coverage-6.3.2.tar.gz", hash = "sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9"},
+]
+flake8 = [
+ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"},
+ {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"},
+]
+iniconfig = [
+ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
+ {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
+]
+mccabe = [
+ {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"},
+ {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"},
+]
+mypy = [
+ {file = "mypy-0.942-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5bf44840fb43ac4074636fd47ee476d73f0039f4f54e86d7265077dc199be24d"},
+ {file = "mypy-0.942-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dcd955f36e0180258a96f880348fbca54ce092b40fbb4b37372ae3b25a0b0a46"},
+ {file = "mypy-0.942-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6776e5fa22381cc761df53e7496a805801c1a751b27b99a9ff2f0ca848c7eca0"},
+ {file = "mypy-0.942-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:edf7237137a1a9330046dbb14796963d734dd740a98d5e144a3eb1d267f5f9ee"},
+ {file = "mypy-0.942-cp310-cp310-win_amd64.whl", hash = "sha256:64235137edc16bee6f095aba73be5334677d6f6bdb7fa03cfab90164fa294a17"},
+ {file = "mypy-0.942-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b840cfe89c4ab6386c40300689cd8645fc8d2d5f20101c7f8bd23d15fca14904"},
+ {file = "mypy-0.942-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2b184db8c618c43c3a31b32ff00cd28195d39e9c24e7c3b401f3db7f6e5767f5"},
+ {file = "mypy-0.942-cp36-cp36m-win_amd64.whl", hash = "sha256:1a0459c333f00e6a11cbf6b468b870c2b99a906cb72d6eadf3d1d95d38c9352c"},
+ {file = "mypy-0.942-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4c3e497588afccfa4334a9986b56f703e75793133c4be3a02d06a3df16b67a58"},
+ {file = "mypy-0.942-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6f6ad963172152e112b87cc7ec103ba0f2db2f1cd8997237827c052a3903eaa6"},
+ {file = "mypy-0.942-cp37-cp37m-win_amd64.whl", hash = "sha256:0e2dd88410937423fba18e57147dd07cd8381291b93d5b1984626f173a26543e"},
+ {file = "mypy-0.942-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:246e1aa127d5b78488a4a0594bd95f6d6fb9d63cf08a66dafbff8595d8891f67"},
+ {file = "mypy-0.942-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d8d3ba77e56b84cd47a8ee45b62c84b6d80d32383928fe2548c9a124ea0a725c"},
+ {file = "mypy-0.942-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2bc249409a7168d37c658e062e1ab5173300984a2dada2589638568ddc1db02b"},
+ {file = "mypy-0.942-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9521c1265ccaaa1791d2c13582f06facf815f426cd8b07c3a485f486a8ffc1f3"},
+ {file = "mypy-0.942-cp38-cp38-win_amd64.whl", hash = "sha256:e865fec858d75b78b4d63266c9aff770ecb6a39dfb6d6b56c47f7f8aba6baba8"},
+ {file = "mypy-0.942-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6ce34a118d1a898f47def970a2042b8af6bdcc01546454726c7dd2171aa6dfca"},
+ {file = "mypy-0.942-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:10daab80bc40f84e3f087d896cdb53dc811a9f04eae4b3f95779c26edee89d16"},
+ {file = "mypy-0.942-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3841b5433ff936bff2f4dc8d54cf2cdbfea5d8e88cedfac45c161368e5770ba6"},
+ {file = "mypy-0.942-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6f7106cbf9cc2f403693bf50ed7c9fa5bb3dfa9007b240db3c910929abe2a322"},
+ {file = "mypy-0.942-cp39-cp39-win_amd64.whl", hash = "sha256:7742d2c4e46bb5017b51c810283a6a389296cda03df805a4f7869a6f41246534"},
+ {file = "mypy-0.942-py3-none-any.whl", hash = "sha256:a1b383fe99678d7402754fe90448d4037f9512ce70c21f8aee3b8bf48ffc51db"},
+ {file = "mypy-0.942.tar.gz", hash = "sha256:17e44649fec92e9f82102b48a3bf7b4a5510ad0cd22fa21a104826b5db4903e2"},
+]
+mypy-extensions = [
+ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
+ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
+]
+numpy = [
+ {file = "numpy-1.22.3-cp310-cp310-macosx_10_14_x86_64.whl", hash = "sha256:92bfa69cfbdf7dfc3040978ad09a48091143cffb778ec3b03fa170c494118d75"},
+ {file = "numpy-1.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8251ed96f38b47b4295b1ae51631de7ffa8260b5b087808ef09a39a9d66c97ab"},
+ {file = "numpy-1.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48a3aecd3b997bf452a2dedb11f4e79bc5bfd21a1d4cc760e703c31d57c84b3e"},
+ {file = "numpy-1.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3bae1a2ed00e90b3ba5f7bd0a7c7999b55d609e0c54ceb2b076a25e345fa9f4"},
+ {file = "numpy-1.22.3-cp310-cp310-win32.whl", hash = "sha256:f950f8845b480cffe522913d35567e29dd381b0dc7e4ce6a4a9f9156417d2430"},
+ {file = "numpy-1.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:08d9b008d0156c70dc392bb3ab3abb6e7a711383c3247b410b39962263576cd4"},
+ {file = "numpy-1.22.3-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:201b4d0552831f7250a08d3b38de0d989d6f6e4658b709a02a73c524ccc6ffce"},
+ {file = "numpy-1.22.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f8c1f39caad2c896bc0018f699882b345b2a63708008be29b1f355ebf6f933fe"},
+ {file = "numpy-1.22.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:568dfd16224abddafb1cbcce2ff14f522abe037268514dd7e42c6776a1c3f8e5"},
+ {file = "numpy-1.22.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ca688e1b9b95d80250bca34b11a05e389b1420d00e87a0d12dc45f131f704a1"},
+ {file = "numpy-1.22.3-cp38-cp38-win32.whl", hash = "sha256:e7927a589df200c5e23c57970bafbd0cd322459aa7b1ff73b7c2e84d6e3eae62"},
+ {file = "numpy-1.22.3-cp38-cp38-win_amd64.whl", hash = "sha256:07a8c89a04997625236c5ecb7afe35a02af3896c8aa01890a849913a2309c676"},
+ {file = "numpy-1.22.3-cp39-cp39-macosx_10_14_x86_64.whl", hash = "sha256:2c10a93606e0b4b95c9b04b77dc349b398fdfbda382d2a39ba5a822f669a0123"},
+ {file = "numpy-1.22.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fade0d4f4d292b6f39951b6836d7a3c7ef5b2347f3c420cd9820a1d90d794802"},
+ {file = "numpy-1.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bfb1bb598e8229c2d5d48db1860bcf4311337864ea3efdbe1171fb0c5da515d"},
+ {file = "numpy-1.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97098b95aa4e418529099c26558eeb8486e66bd1e53a6b606d684d0c3616b168"},
+ {file = "numpy-1.22.3-cp39-cp39-win32.whl", hash = "sha256:fdf3c08bce27132395d3c3ba1503cac12e17282358cb4bddc25cc46b0aca07aa"},
+ {file = "numpy-1.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:639b54cdf6aa4f82fe37ebf70401bbb74b8508fddcf4797f9fe59615b8c5813a"},
+ {file = "numpy-1.22.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c34ea7e9d13a70bf2ab64a2532fe149a9aced424cd05a2c4ba662fd989e3e45f"},
+ {file = "numpy-1.22.3.zip", hash = "sha256:dbc7601a3b7472d559dc7b933b18b4b66f9aa7452c120e87dfb33d02008c8a18"},
+]
+packaging = [
+ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
+ {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
+]
+pathspec = [
+ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
+ {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
+]
+platformdirs = [
+ {file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"},
+ {file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"},
+]
+pluggy = [
+ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
+ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+]
+py = [
+ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
+ {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
+]
+py-cpuinfo = [
+ {file = "py-cpuinfo-8.0.0.tar.gz", hash = "sha256:5f269be0e08e33fd959de96b34cd4aeeeacac014dd8305f70eb28d06de2345c5"},
+]
+pycodestyle = [
+ {file = "pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20"},
+ {file = "pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f"},
+]
+pyflakes = [
+ {file = "pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e"},
+ {file = "pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c"},
+]
+pyparsing = [
+ {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"},
+ {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"},
+]
+pytest = [
+ {file = "pytest-7.1.1-py3-none-any.whl", hash = "sha256:92f723789a8fdd7180b6b06483874feca4c48a5c76968e03bb3e7f806a1869ea"},
+ {file = "pytest-7.1.1.tar.gz", hash = "sha256:841132caef6b1ad17a9afde46dc4f6cfa59a05f9555aae5151f73bdf2820ca63"},
+]
+pytest-benchmark = [
+ {file = "pytest-benchmark-3.4.1.tar.gz", hash = "sha256:40e263f912de5a81d891619032983557d62a3d85843f9a9f30b98baea0cd7b47"},
+ {file = "pytest_benchmark-3.4.1-py2.py3-none-any.whl", hash = "sha256:36d2b08c4882f6f997fd3126a3d6dfd70f3249cde178ed8bbc0b73db7c20f809"},
+]
+pytest-cov = [
+ {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"},
+ {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"},
+]
+scipy = [
+ {file = "scipy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:87b01c7d5761e8a266a0fbdb9d88dcba0910d63c1c671bdb4d99d29f469e9e03"},
+ {file = "scipy-1.8.0-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:ae3e327da323d82e918e593460e23babdce40d7ab21490ddf9fc06dec6b91a18"},
+ {file = "scipy-1.8.0-cp310-cp310-macosx_12_0_universal2.macosx_10_9_x86_64.whl", hash = "sha256:16e09ef68b352d73befa8bcaf3ebe25d3941fe1a58c82909d5589856e6bc8174"},
+ {file = "scipy-1.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c17a1878d00a5dd2797ccd73623ceca9d02375328f6218ee6d921e1325e61aff"},
+ {file = "scipy-1.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:937d28722f13302febde29847bbe554b89073fbb924a30475e5ed7b028898b5f"},
+ {file = "scipy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:8f4d059a97b29c91afad46b1737274cb282357a305a80bdd9e8adf3b0ca6a3f0"},
+ {file = "scipy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:38aa39b6724cb65271e469013aeb6f2ce66fd44f093e241c28a9c6bc64fd79ed"},
+ {file = "scipy-1.8.0-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:559a8a4c03a5ba9fe3232f39ed24f86457e4f3f6c0abbeae1fb945029f092720"},
+ {file = "scipy-1.8.0-cp38-cp38-macosx_12_0_universal2.macosx_10_9_x86_64.whl", hash = "sha256:f4a6d3b9f9797eb2d43938ac2c5d96d02aed17ef170c8b38f11798717523ddba"},
+ {file = "scipy-1.8.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:92b2c2af4183ed09afb595709a8ef5783b2baf7f41e26ece24e1329c109691a7"},
+ {file = "scipy-1.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a279e27c7f4566ef18bab1b1e2c37d168e365080974758d107e7d237d3f0f484"},
+ {file = "scipy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad5be4039147c808e64f99c0e8a9641eb5d2fa079ff5894dcd8240e94e347af4"},
+ {file = "scipy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:3d9dd6c8b93a22bf9a3a52d1327aca7e092b1299fb3afc4f89e8eba381be7b59"},
+ {file = "scipy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:5e73343c5e0d413c1f937302b2e04fb07872f5843041bcfd50699aef6e95e399"},
+ {file = "scipy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:de2e80ee1d925984c2504812a310841c241791c5279352be4707cdcd7c255039"},
+ {file = "scipy-1.8.0-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:c2bae431d127bf0b1da81fc24e4bba0a84d058e3a96b9dd6475dfcb3c5e8761e"},
+ {file = "scipy-1.8.0-cp39-cp39-macosx_12_0_universal2.macosx_10_9_x86_64.whl", hash = "sha256:723b9f878095ed994756fa4ee3060c450e2db0139c5ba248ee3f9628bd64e735"},
+ {file = "scipy-1.8.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:011d4386b53b933142f58a652aa0f149c9b9242abd4f900b9f4ea5fbafc86b89"},
+ {file = "scipy-1.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6f0cd9c0bd374ef834ee1e0f0999678d49dcc400ea6209113d81528958f97c7"},
+ {file = "scipy-1.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3720d0124aced49f6f2198a6900304411dbbeed12f56951d7c66ebef05e3df6"},
+ {file = "scipy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:3d573228c10a3a8c32b9037be982e6440e411b443a6267b067cac72f690b8d56"},
+ {file = "scipy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:bb7088e89cd751acf66195d2f00cf009a1ea113f3019664032d9075b1e727b6c"},
+ {file = "scipy-1.8.0.tar.gz", hash = "sha256:31d4f2d6b724bc9a98e527b5849b8a7e589bf1ea630c33aa563eda912c9ff0bd"},
+]
+tomli = [
+ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
+ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
+]
+typing-extensions = [
+ {file = "typing_extensions-4.1.1-py3-none-any.whl", hash = "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"},
+ {file = "typing_extensions-4.1.1.tar.gz", hash = "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42"},
+]
diff --git a/pynam/__init__.py b/pynam/__init__.py
index b794fd4..3dc1f76 100644
--- a/pynam/__init__.py
+++ b/pynam/__init__.py
@@ -1 +1 @@
-__version__ = '0.1.0'
+__version__ = "0.1.0"
diff --git a/pynam/baskets.py b/pynam/baskets.py
index 0cf069a..2f36e47 100644
--- a/pynam/baskets.py
+++ b/pynam/baskets.py
@@ -1,8 +1,13 @@
class CalculationConstants(object):
- """Holds physical constants, in SI units
- """
+ """Holds physical constants, in SI units"""
- def __init__(self, epsilon_0=8.854e-12, h_bar=1.0546e-34, c_light=3e8, electron_mass=9.10938356e-31):
+ def __init__(
+ self,
+ epsilon_0=8.854e-12,
+ h_bar=1.0546e-34,
+ c_light=3e8,
+ electron_mass=9.10938356e-31,
+ ):
"""Initialises constants in SI units, with sensible defaults
:param epsilon_0:
@@ -18,11 +23,18 @@ class CalculationConstants(object):
class CalculationParams(object):
- """Holds the parameters describing a calculation, in SI units.
- """
+ """Holds the parameters describing a calculation, in SI units."""
- def __init__(self, omega: float = None, omega_p: float = None, tau: float = None, v_f: float = None,
- t_rel: float = None, t_c: float = None, dipole_moment: float = None):
+ def __init__(
+ self,
+ omega: float = None,
+ omega_p: float = None,
+ tau: float = None,
+ v_f: float = None,
+ t_rel: float = None,
+ t_c: float = None,
+ dipole_moment: float = None,
+ ):
"""Creates parameter object, SI units
:param omega:
diff --git a/pynam/dielectric/__init__.py b/pynam/dielectric/__init__.py
index 7aa8786..bc84679 100644
--- a/pynam/dielectric/__init__.py
+++ b/pynam/dielectric/__init__.py
@@ -1,2 +1,4 @@
from pynam.dielectric.nam_dielectric_coefficient_approximator import get_nam_dielectric
from pynam.dielectric.lindhard_dielectric import get_lindhard_dielectric
+
+__all__ = ["get_nam_dielectric", "get_lindhard_dielectric"]
diff --git a/pynam/dielectric/lindhard_dielectric.py b/pynam/dielectric/lindhard_dielectric.py
index b38b3c7..a7c34c4 100644
--- a/pynam/dielectric/lindhard_dielectric.py
+++ b/pynam/dielectric/lindhard_dielectric.py
@@ -5,10 +5,21 @@ LINDHARD_SERIES_THRESHOLD = 1e4
class LindhardDielectric(object):
- def __init__(self,
- params: CalculationParams,
- constants: CalculationConstants = CalculationConstants(),
- thres=LINDHARD_SERIES_THRESHOLD):
+ def __init__(
+ self,
+ params: CalculationParams,
+ constants: CalculationConstants = CalculationConstants(),
+ thres=LINDHARD_SERIES_THRESHOLD,
+ ):
+ if params.omega is None:
+ raise ValueError("omega expected to not be None")
+ if params.v_f is None:
+ raise ValueError("v_f expected to not be None")
+ if params.omega_p is None:
+ raise ValueError("omega_p expected to not be None")
+ if params.tau is None:
+ raise ValueError("tau expected to not be None")
+
self.series_threshold = thres
self.omega = params.omega
self.v_f = params.v_f
@@ -17,12 +28,11 @@ class LindhardDielectric(object):
self.c_light = constants.c_light
self.s = 1 / (self.tau * self.omega)
- self.prefactor = 3 * (self.omega_p ** 2) / (self.omega ** 2)
+ self.prefactor = 3 * (self.omega_p**2) / (self.omega**2)
def get_eps(self):
-
def eps_lindhard(u_inverse_wavelength: float) -> complex:
- """ the lindhard dielectric function
+ """the lindhard dielectric function
:param u_inverse_wavelength: u is in units of the reciprocal vacuum wavelength (omega / c_light)
:return: returns the value of epsilon, dimensionless
@@ -37,22 +47,26 @@ class LindhardDielectric(object):
return eps_full_lindhard(u)
def eps_series(u: float) -> complex:
- rel_value = (
- (1j / (3 * (self.s - 1j))) + u ** 2 * ((-9j + 5 * self.s) / (45 * (-1j + self.s) ** 3))
+ rel_value = (1j / (3 * (self.s - 1j))) + (
+ u**2 * ((-9j + 5 * self.s) / (45 * (-1j + self.s) ** 3))
)
+
return 1 + (self.prefactor * rel_value)
def eps_full_lindhard(u: float) -> complex:
log_value = np.log((1 - u + (self.s * 1j)) / (1 + u + (self.s * 1j)))
- rel_value = (1 + ((1 + (self.s * 1j)) / (2 * u)) * log_value) / (1 + ((self.s * 1j) / (2 * u)) * log_value)
+ rel_value = (1 + ((1 + (self.s * 1j)) / (2 * u)) * log_value) / (
+ 1 + ((self.s * 1j) / (2 * u)) * log_value
+ )
- return 1 + (self.prefactor / (u ** 2)) * rel_value
+ return 1 + (self.prefactor / (u**2)) * rel_value
return eps_lindhard
-def get_lindhard_dielectric(params: CalculationParams,
- constants: CalculationConstants = CalculationConstants()):
+def get_lindhard_dielectric(
+ params: CalculationParams, constants: CalculationConstants = CalculationConstants()
+):
return LindhardDielectric(params, constants).get_eps()
diff --git a/pynam/dielectric/low_k_nam.py b/pynam/dielectric/low_k_nam.py
index 02c4ba8..318cdfe 100644
--- a/pynam/dielectric/low_k_nam.py
+++ b/pynam/dielectric/low_k_nam.py
@@ -5,17 +5,17 @@ import pynam.util
def g(w, wp):
- return ((wp * (w + wp)) + 1) / (csqrt(wp ** 2 - 1) * csqrt((w + wp) ** 2 - 1))
+ return ((wp * (w + wp)) + 1) / (csqrt(wp**2 - 1) * csqrt((w + wp) ** 2 - 1))
def f(k, e, v):
- return ((4 / 3) * 1 / (e - 1j * v)) + (4 / 15) * (1 / ((e - 1j * v) ** 3)) * k ** 2
+ return ((4 / 3) * 1 / (e - 1j * v)) + (4 / 15) * (1 / ((e - 1j * v) ** 3)) * k**2
def i1(w, wp, k, v):
gv = g(w, wp)
e1 = csqrt((w + wp) ** 2 - 1)
- e2 = csqrt(wp ** 2 - 1)
+ e2 = csqrt(wp**2 - 1)
f_upper = f(k, np.real(e1 - e2), np.imag(e1 + e2) + 2 * v) * (gv + 1)
f_lower = f(k, np.real(-e1 - e2), np.imag(e1 + e2) + 2 * v) * (gv - 1)
@@ -26,7 +26,7 @@ def i1(w, wp, k, v):
def i2(w, wp, k, v):
gv = g(w, wp)
e1 = csqrt((w + wp) ** 2 - 1)
- e2 = csqrt(wp ** 2 - 1)
+ e2 = csqrt(wp**2 - 1)
f_upper = f(k, np.real(e1 - e2), np.imag(e1 + e2) + 2 * v) * (gv + 1)
f_lower = f(k, np.real(e1 + e2), np.imag(e1 + e2) + 2 * v) * (gv - 1)
@@ -36,19 +36,18 @@ def i2(w, wp, k, v):
def a(w, k, v, t):
return pynam.util.complex_quad(
- lambda wp: np.tanh((w + wp) / (2 * t)) * (i1(w, wp, k, v)),
- 1 - w, 1
+ lambda wp: np.tanh((w + wp) / (2 * t)) * (i1(w, wp, k, v)), 1 - w, 1
)[0]
def b_int(wp, w, k, v, t):
- return (np.tanh((w + wp) / (2 * t)) * i1(w, wp, k, v)) - (np.tanh(wp / (2 * t)) * i2(w, wp, k, v))
+ return (np.tanh((w + wp) / (2 * t)) * i1(w, wp, k, v)) - (
+ np.tanh(wp / (2 * t)) * i2(w, wp, k, v)
+ )
def b(w, k, v, t, b_max=np.inf):
- return pynam.util.complex_quad(
- lambda wp: b_int(wp, w, k, v, t), 1, b_max
- )[0]
+ return pynam.util.complex_quad(lambda wp: b_int(wp, w, k, v, t), 1, b_max)[0]
def sigma_nam_alk(w, k, v, t):
diff --git a/pynam/dielectric/nam_dielectric_coefficient_approximator.py b/pynam/dielectric/nam_dielectric_coefficient_approximator.py
index 2dad7a9..951c803 100644
--- a/pynam/dielectric/nam_dielectric_coefficient_approximator.py
+++ b/pynam/dielectric/nam_dielectric_coefficient_approximator.py
@@ -11,14 +11,15 @@ FIXED_LARGE_MOMENTUM = 1e8
class DedimensionalisedParameters(object):
def __init__(
- self,
- omega: float,
- sigma_n: float,
- tau: float,
- v_f: float,
- temp: float,
- critical_temp: float,
- c_light: float):
+ self,
+ omega: float,
+ sigma_n: float,
+ tau: float,
+ v_f: float,
+ temp: float,
+ critical_temp: float,
+ c_light: float,
+ ):
gap = 0
if temp < critical_temp:
# else, problems will happen
@@ -39,7 +40,6 @@ class NamDielectricCoefficients(object):
self.u_l = np.real((-self.c + 1j * self.d) / (-self.a + 1j * self.b))
def eps(self, u_c: float):
-
def piecewise_eps(u: float):
# todo add check for u_c vs u_l
if u < self.u_l:
@@ -53,41 +53,50 @@ class NamDielectricCoefficients(object):
def get_dedimensionalised_parameters(
- omega: float,
- sigma_n: float,
- tau: float,
- v_f: float,
- temp: float,
- critical_temp: float,
- c_light: float) -> DedimensionalisedParameters:
- return DedimensionalisedParameters(omega, sigma_n, tau, v_f, temp, critical_temp, c_light)
+ omega: float,
+ sigma_n: float,
+ tau: float,
+ v_f: float,
+ temp: float,
+ critical_temp: float,
+ c_light: float,
+) -> DedimensionalisedParameters:
+ return DedimensionalisedParameters(
+ omega, sigma_n, tau, v_f, temp, critical_temp, c_light
+ )
-def get_small_momentum_coefficients(dedim_params: DedimensionalisedParameters) -> Tuple[float, float]:
+def get_small_momentum_coefficients(
+ dedim_params: DedimensionalisedParameters,
+) -> Tuple[float, float]:
prefactor = 4j * np.pi * dedim_params.b
- s = pynam.dielectric.low_k_nam.sigma_nam_alk(dedim_params.xi, 0, dedim_params.nu, dedim_params.t)
+ s = pynam.dielectric.low_k_nam.sigma_nam_alk(
+ dedim_params.xi, 0, dedim_params.nu, dedim_params.t
+ )
conductivity = prefactor * s
return -np.real(conductivity), np.imag(conductivity)
-def get_big_momentum_coefficients(dedim_params: DedimensionalisedParameters) -> Tuple[float, float]:
+def get_big_momentum_coefficients(
+ dedim_params: DedimensionalisedParameters,
+) -> Tuple[float, float]:
prefactor = 4j * np.pi * dedim_params.b * FIXED_LARGE_MOMENTUM / dedim_params.a
- s = pynam.dielectric.sigma_nam.sigma_nam(dedim_params.xi,
- FIXED_LARGE_MOMENTUM,
- dedim_params.nu,
- dedim_params.t)
+ s = pynam.dielectric.sigma_nam.sigma_nam(
+ dedim_params.xi, FIXED_LARGE_MOMENTUM, dedim_params.nu, dedim_params.t
+ )
conductivity = prefactor * s
return -np.real(conductivity), np.imag(conductivity)
def get_nam_dielectric_coefficients(
- omega: float,
- sigma_n: float,
- tau: float,
- v_f: float,
- temp: float,
- crit_temp: float,
- c_light: float) -> NamDielectricCoefficients:
+ omega: float,
+ sigma_n: float,
+ tau: float,
+ v_f: float,
+ temp: float,
+ crit_temp: float,
+ c_light: float,
+) -> NamDielectricCoefficients:
"""Gets a NamDielectricCoefficients object, using SI unit parameters
:param omega: frequency
@@ -100,20 +109,40 @@ def get_nam_dielectric_coefficients(
:return:
"""
- dedim = get_dedimensionalised_parameters(omega, sigma_n, tau, v_f, temp, crit_temp, c_light)
+ dedim = get_dedimensionalised_parameters(
+ omega, sigma_n, tau, v_f, temp, crit_temp, c_light
+ )
a, b = get_small_momentum_coefficients(dedim)
c, d = get_big_momentum_coefficients(dedim)
return NamDielectricCoefficients(a, b, c, d)
-def get_nam_dielectric(u_c: float, params: CalculationParams, constants: CalculationConstants = CalculationConstants()):
+def get_nam_dielectric(
+ u_c: float,
+ params: CalculationParams,
+ constants: CalculationConstants = CalculationConstants(),
+):
+ if params.omega is None:
+ raise ValueError("omega expected to not be None")
+ if params.v_f is None:
+ raise ValueError("v_f expected to not be None")
+ if params.omega_p is None:
+ raise ValueError("omega_p expected to not be None")
+ if params.tau is None:
+ raise ValueError("tau expected to not be None")
+ if params.t_rel is None:
+ raise ValueError("relative temp expected to not be None")
+ if params.t_c is None:
+ raise ValueError("critical temp expected to not be None")
sigma_n = params.omega_p**2 * params.tau / (4 * np.pi)
- coeffs = get_nam_dielectric_coefficients(params.omega,
- sigma_n,
- params.tau,
- params.v_f,
- params.t_rel * params.t_c,
- params.t_c,
- constants.c_light)
+ coeffs = get_nam_dielectric_coefficients(
+ params.omega,
+ sigma_n,
+ params.tau,
+ params.v_f,
+ params.t_rel * params.t_c,
+ params.t_c,
+ constants.c_light,
+ )
return coeffs.eps(u_c)
diff --git a/pynam/dielectric/sigma_nam.py b/pynam/dielectric/sigma_nam.py
index 2b4d4cb..e194928 100644
--- a/pynam/dielectric/sigma_nam.py
+++ b/pynam/dielectric/sigma_nam.py
@@ -5,7 +5,7 @@ import pynam.util
def g(w, wp):
- return ((wp * (w + wp)) + 1) / (csqrt(wp ** 2 - 1) * csqrt((w + wp) ** 2 - 1))
+ return ((wp * (w + wp)) + 1) / (csqrt(wp**2 - 1) * csqrt((w + wp) ** 2 - 1))
def s(k, e, v):
@@ -21,7 +21,7 @@ def f(k, e, v):
def i1(w, wp, k, v):
gv = g(w, wp)
e1 = csqrt((w + wp) ** 2 - 1)
- e2 = csqrt(wp ** 2 - 1)
+ e2 = csqrt(wp**2 - 1)
f_upper = f(k, np.real(e1 - e2), np.imag(e1 + e2) + 2 * v) * (gv + 1)
f_lower = f(k, np.real(-e1 - e2), np.imag(e1 + e2) + 2 * v) * (gv - 1)
@@ -32,7 +32,7 @@ def i1(w, wp, k, v):
def i2(w, wp, k, v):
gv = g(w, wp)
e1 = csqrt((w + wp) ** 2 - 1)
- e2 = csqrt(wp ** 2 - 1)
+ e2 = csqrt(wp**2 - 1)
f_upper = f(k, np.real(e1 - e2), np.imag(e1 + e2) + 2 * v) * (gv + 1)
f_lower = f(k, np.real(e1 + e2), np.imag(e1 + e2) + 2 * v) * (gv - 1)
@@ -43,21 +43,22 @@ def i2(w, wp, k, v):
def a(w, k, v, t):
result = pynam.util.complex_quad(
lambda wp: np.tanh((w + wp) / (2 * t)) * (i1(w, wp, k, v)),
- 1 - w, 1,
- epsabs=1e-10
+ 1 - w,
+ 1,
+ epsabs=1e-10,
)
return result[0]
def b_int(wp, w, k, v, t):
- return (np.tanh((w + wp) / (2 * t)) * i1(w, wp, k, v)) - (np.tanh(wp / (2 * t)) * i2(w, wp, k, v))
+ return (np.tanh((w + wp) / (2 * t)) * i1(w, wp, k, v)) - (
+ np.tanh(wp / (2 * t)) * i2(w, wp, k, v)
+ )
def b(w, k, v, t, b_max=np.inf):
- return pynam.util.complex_quad(
- lambda wp: b_int(wp, w, k, v, t), 1, b_max
- )[0]
+ return pynam.util.complex_quad(lambda wp: b_int(wp, w, k, v, t), 1, b_max)[0]
def sigma_nam(w, k, v, t):
diff --git a/pynam/noise/chi.py b/pynam/noise/chi.py
index 68e51fa..22e2a5a 100644
--- a/pynam/noise/chi.py
+++ b/pynam/noise/chi.py
@@ -10,10 +10,12 @@ def get_chi_zz_e(eps: Callable[[float], complex]) -> Callable[[float], float]:
im_ref_p = pynam.noise.im_ref.get_im_ref_p(eps)
def chi_zz_e(z: float) -> float:
-
def integrand(y: float) -> float:
return (y**2) * im_ref_p(y / z) * np.exp(-2 * y)
- return scipy.integrate.quad(integrand, 0, np.inf, epsabs=1e-10, epsrel=1e-10)[0] / (z**3)
+ integral = scipy.integrate.quad(
+ integrand, 0, np.inf, epsabs=1e-10, epsrel=1e-10
+ )
+ return integral[0] / (z**3)
return chi_zz_e
diff --git a/pynam/noise/zeta.py b/pynam/noise/zeta.py
index e9ff7fe..b8858af 100644
--- a/pynam/noise/zeta.py
+++ b/pynam/noise/zeta.py
@@ -6,8 +6,10 @@ import numpy as np
SMALL_X_BOUNDARY = 1e3
-def get_zeta_p_integrand(eps: Callable[[float], complex]) -> Callable[[float, float], complex]:
- """ Gets the integrand function zeta_p_integrand(u, y).
+def get_zeta_p_integrand(
+ eps: Callable[[float], complex]
+) -> Callable[[float, float], complex]:
+ """Gets the integrand function zeta_p_integrand(u, y).
Returns zeta_p_integrand(u, y), a complex valued function of two momenta in units of vacuum wavelength.
@@ -22,8 +24,8 @@ def get_zeta_p_integrand(eps: Callable[[float], complex]) -> Callable[[float, fl
:param y:
:return:
"""
- u2 = u ** 2
- y2 = y ** 2
+ u2 = u**2
+ y2 = y**2
k2 = u2 + y2
k = np.sqrt(k2)
eps_value = eps(k)
@@ -36,36 +38,44 @@ def get_zeta_p_integrand(eps: Callable[[float], complex]) -> Callable[[float, fl
def get_zeta_p_function(eps: Callable[[float], complex]):
def integrand1_small_x(x: float, u: float) -> complex:
- u2 = u ** 2
- x2 = x ** 2
- eps_value = eps(u * np.sqrt(1 + x ** 2))
+ u2 = u**2
+ x2 = x**2
+ eps_value = eps(u * np.sqrt(1 + x**2))
return (x2 / (eps_value - 1 - x2)) / ((1 + x2) * u2)
def integrand1_big_x(x: float, u: float) -> complex:
- u2 = u ** 2
- x2 = x ** 2
+ u2 = u**2
+ x2 = x**2
eps_value = eps(u * x)
return 1 / ((eps_value - x2) * u2)
# 1 / (eps(u * sqrt(1 + x^2))) * 1 / (1 + x^2)
def integrand2_small_x(x: float, u: float) -> complex:
- x2 = x ** 2
- eps_value = eps(u * np.sqrt(1 + x ** 2))
+ x2 = x**2
+ eps_value = eps(u * np.sqrt(1 + x**2))
return 1 / (eps_value * (1 + x2))
def integrand2_big_x(x: float, u: float) -> complex:
- x2 = x ** 2
+ x2 = x**2
eps_value = eps(u * x)
return 1 / (eps_value * x2)
def zeta_p(u: float) -> complex:
- zeta_p_integrand = get_zeta_p_integrand(eps)
+ # zeta_p_integrand = get_zeta_p_integrand(eps)
- i1_small = pynam.util.complex_quad(lambda x: integrand1_small_x(x, u), 0, SMALL_X_BOUNDARY, epsabs=1e-12)
- i1_big = pynam.util.complex_quad(lambda x: integrand1_big_x(x, u), SMALL_X_BOUNDARY, np.inf, epsabs=1e-12)
- i2_small = pynam.util.complex_quad(lambda x: integrand2_small_x(x, u), 0, SMALL_X_BOUNDARY, epsabs=1e-12)
- i2_big = pynam.util.complex_quad(lambda x: integrand2_big_x(x, u), SMALL_X_BOUNDARY, np.inf, epsabs=1e-12)
+ i1_small = pynam.util.complex_quad(
+ lambda x: integrand1_small_x(x, u), 0, SMALL_X_BOUNDARY, epsabs=1e-12
+ )
+ i1_big = pynam.util.complex_quad(
+ lambda x: integrand1_big_x(x, u), SMALL_X_BOUNDARY, np.inf, epsabs=1e-12
+ )
+ i2_small = pynam.util.complex_quad(
+ lambda x: integrand2_small_x(x, u), 0, SMALL_X_BOUNDARY, epsabs=1e-12
+ )
+ i2_big = pynam.util.complex_quad(
+ lambda x: integrand2_big_x(x, u), SMALL_X_BOUNDARY, np.inf, epsabs=1e-12
+ )
integral = sum(term[0] for term in [i1_small, i2_small, i1_big, i2_big])
diff --git a/pynam/util/__init__.py b/pynam/util/__init__.py
index 4a4cfcb..39dccdb 100644
--- a/pynam/util/__init__.py
+++ b/pynam/util/__init__.py
@@ -1 +1,3 @@
from pynam.util.complex_integrate import complex_quad, complex_quadrature
+
+__all__ = ["complex_quad", "complex_quadrature"]
diff --git a/pynam/util/complex_integrate.py b/pynam/util/complex_integrate.py
index cf1540c..0bbc857 100644
--- a/pynam/util/complex_integrate.py
+++ b/pynam/util/complex_integrate.py
@@ -3,7 +3,6 @@ from scipy.integrate import quad, quadrature
def complex_quad(func, a, b, **kwargs):
-
def real_func(x):
return np.real(func(x))
@@ -13,11 +12,14 @@ def complex_quad(func, a, b, **kwargs):
real_integral = quad(real_func, a, b, **kwargs)
imag_integral = quad(imag_func, a, b, **kwargs)
- return real_integral[0] + 1j * imag_integral[0], real_integral[1:], imag_integral[1:]
+ return (
+ real_integral[0] + 1j * imag_integral[0],
+ real_integral[1:],
+ imag_integral[1:],
+ )
def complex_quadrature(func, a, b, **kwargs):
-
def real_func(x):
return np.real(func(x))
@@ -27,4 +29,8 @@ def complex_quadrature(func, a, b, **kwargs):
real_integral = quadrature(real_func, a, b, **kwargs)
imag_integral = quadrature(imag_func, a, b, **kwargs)
- return real_integral[0] + 1j * imag_integral[0], real_integral[1:], imag_integral[1:]
+ return (
+ real_integral[0] + 1j * imag_integral[0],
+ real_integral[1:],
+ imag_integral[1:],
+ )
diff --git a/pyproject.toml b/pyproject.toml
index da0edbc..89e0efb 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,18 +1,37 @@
-[tool.poetry]
-name = "pynam"
-version = "0.1.1"
-description = ""
-authors = ["Deepak "]
-
-[tool.poetry.dependencies]
-python = "^3.7"
-numpy = "^1.19"
-scipy = "^1.5"
-
-[tool.poetry.dev-dependencies]
-pytest = "^3.0"
-pytest-benchmark = "^3.2.3"
-
-[build-system]
-requires = ["poetry>=0.12"]
-build-backend = "poetry.masonry.api"
+[tool.poetry]
+name = "pynam"
+version = "0.1.1"
+description = ""
+authors = ["Deepak "]
+
+[tool.poetry.dependencies]
+python = "^3.8,<3.10"
+numpy = "^1.21.1"
+scipy = "~1.8"
+
+[tool.poetry.dev-dependencies]
+pytest = ">=6"
+flake8 = "^4.0.0"
+pytest-cov = "^3.0.0"
+mypy = "^0.942"
+pytest-benchmark = "^3.4.1"
+black = "^22.3.0"
+
+[build-system]
+requires = ["poetry>=0.12"]
+build-backend = "poetry.masonry.api"
+
+[tool.pytest.ini_options]
+testpaths = ["tests"]
+addopts = "--junitxml pytest.xml --cov pynam --cov-report=xml:coverage.xml --cov-fail-under=50 --cov-report=html"
+junit_family = "xunit1"
+
+[tool.mypy]
+plugins = "numpy.typing.mypy_plugin"
+
+[[tool.mypy.overrides]]
+module = [
+ "scipy",
+ "scipy.integrate"
+]
+ignore_missing_imports = true
diff --git a/renovate.json b/renovate.json
new file mode 100644
index 0000000..344c613
--- /dev/null
+++ b/renovate.json
@@ -0,0 +1,3 @@
+{
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json"
+}
diff --git a/scripts/release.sh b/scripts/release.sh
new file mode 100644
index 0000000..1152a43
--- /dev/null
+++ b/scripts/release.sh
@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+set -Eeuo pipefail
+
+if [ -z "$(git status --porcelain)" ]; then
+ branch_name=$(git symbolic-ref -q HEAD)
+ branch_name=${branch_name##refs/heads/}
+ branch_name=${branch_name:-HEAD}
+ if [ $branch_name != "master" ]; then
+ echo "The current branch is not master!"
+ echo "I'd feel uncomfortable releasing from here..."
+ exit 3
+ fi
+
+ release_needed=false
+ if \
+ { git log "$( git describe --tags --abbrev=0 )..HEAD" --format='%s' | cut -d: -f1 | sort -u | sed -e 's/([^)]*)//' | grep -q -i -E '^feat|fix|perf|refactor|revert$' ; } || \
+ { git log "$( git describe --tags --abbrev=0 )..HEAD" --format='%s' | cut -d: -f1 | sort -u | sed -e 's/([^)]*)//' | grep -q -E '\!$' ; } || \
+ { git log "$( git describe --tags --abbrev=0 )..HEAD" --format='%b' | grep -q -E '^BREAKING CHANGE:' ; }
+ then
+ release_needed=true
+ fi
+
+ if ! [ "$release_needed" = true ]; then
+ echo "No release needed..."
+ exit 0
+ fi
+
+ # Working directory clean
+ echo "Doing a dry run..."
+ npx standard-version --dry-run
+ read -p "Does that look good? [y/N] " -n 1 -r
+ echo # (optional) move to a new line
+ if [[ $REPLY =~ ^[Yy]$ ]]
+ then
+ # do dangerous stuff
+ npx standard-version
+ git push --follow-tags origin master
+ else
+ echo "okay, never mind then..."
+ exit 2
+ fi
+else
+ echo "Can't create release, working tree unclean..."
+ exit 1
+fi
diff --git a/scripts/standard-version/pyproject-updater.js b/scripts/standard-version/pyproject-updater.js
new file mode 100644
index 0000000..1c8c8ab
--- /dev/null
+++ b/scripts/standard-version/pyproject-updater.js
@@ -0,0 +1,11 @@
+const pattern = /(\[tool\.poetry\]\nname = "pytest"\nversion = ")(?\d+\.\d+\.\d)(")/mg;
+
+module.exports.readVersion = function (contents) {
+ const result = pattern.exec(contents);
+ return result.groups.vers;
+}
+
+module.exports.writeVersion = function (contents, version) {
+ const newContents = contents.replace(pattern, `$1${version}$3`);
+ return newContents;
+}
diff --git a/tests/dielectric/test_lindhard_dielectric.py b/tests/dielectric/test_lindhard_dielectric.py
index 39a7e97..541bb43 100644
--- a/tests/dielectric/test_lindhard_dielectric.py
+++ b/tests/dielectric/test_lindhard_dielectric.py
@@ -9,38 +9,47 @@ def get_common_lindhard_dielectric():
return pynam.dielectric.get_lindhard_dielectric(params)
-@pytest.mark.parametrize("test_input,expected", [
- (10, -1222.185185062794 + 1.2249999998777178e8j),
- (1000, 16924.14814718176 + 1.2250000020552777e8j),
- (1e8, 83.687499999706 + 0.00022417398943752126j)
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ (10, -1222.185185062794 + 1.2249999998777178e8j),
+ (1000, 16924.14814718176 + 1.2250000020552777e8j),
+ (1e8, 83.687499999706 + 0.00022417398943752126j),
+ ],
+)
def test_lindhard_dielectric(test_input, expected):
eps_to_test = get_common_lindhard_dielectric()
np.testing.assert_almost_equal(
- eps_to_test(test_input), expected,
- decimal=6, err_msg='b function is off'
+ eps_to_test(test_input), expected, decimal=6, err_msg="b function is off"
)
-@pytest.mark.parametrize("test_input,expected", [
- ((100, 100), -883.3001542404703 + 1.2566370613549341e8j),
- ((100, 1e5), 5.827225842825694e7 + 3.933446612656656e7j),
- ((100, 1e10), 1.0084823001646925 + 2.0013975538629039e-10j),
- ((100, 1e7), 8483.300121667038 + 0.6340397839154446)
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ ((100, 100), -883.3001542404703 + 1.2566370613549341e8j),
+ ((100, 1e5), 5.827225842825694e7 + 3.933446612656656e7j),
+ ((100, 1e10), 1.0084823001646925 + 2.0013975538629039e-10j),
+ ((100, 1e7), 8483.300121667038 + 0.6340397839154446),
+ ],
+)
def test_zeta_pi_lindhard_dielectric(zeta_p_i_epsilon, test_input, expected):
u, y = test_input
actual = zeta_p_i_epsilon(np.sqrt(u**2 + y**2))
np.testing.assert_allclose(
- actual, expected,
- rtol=10**3.8, err_msg='lindhard dielectric differs from Mathematica'
+ actual,
+ expected,
+ rtol=10**3.8,
+ err_msg="lindhard dielectric differs from Mathematica",
)
@pytest.fixture
def zeta_p_i_epsilon():
- params = CalculationParams(omega=1e9, omega_p=3.544907701811032e15, tau=1e-14, v_f=2e6)
+ params = CalculationParams(
+ omega=1e9, omega_p=3.544907701811032e15, tau=1e-14, v_f=2e6
+ )
return pynam.dielectric.get_lindhard_dielectric(params)
diff --git a/tests/dielectric/test_low_k_nam.py b/tests/dielectric/test_low_k_nam.py
index 73b64db..784f79f 100644
--- a/tests/dielectric/test_low_k_nam.py
+++ b/tests/dielectric/test_low_k_nam.py
@@ -3,101 +3,115 @@ import numpy as np
import pytest
-@pytest.mark.parametrize("test_input,expected", [
- ((1, 2), 7 / (2 * np.sqrt(6))),
- ((2, 0.25), -5j / np.sqrt(39))
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [((1, 2), 7 / (2 * np.sqrt(6))), ((2, 0.25), -5j / np.sqrt(39))],
+)
def test_g(test_input, expected):
np.testing.assert_almost_equal(
- pynam.dielectric.low_k_nam.g(*test_input), expected,
- decimal=7, err_msg='g function is off'
+ pynam.dielectric.low_k_nam.g(*test_input),
+ expected,
+ decimal=7,
+ err_msg="g function is off",
)
-@pytest.mark.parametrize("test_input,expected", [
- ((1, 1, 0), 8 / 5),
- ((1, 1, 1), 3 / 5 + 11j / 15),
- ((1, 0, 1), 16j / 15)
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [((1, 1, 0), 8 / 5), ((1, 1, 1), 3 / 5 + 11j / 15), ((1, 0, 1), 16j / 15)],
+)
def test_f(test_input, expected):
np.testing.assert_almost_equal(
- pynam.dielectric.low_k_nam.f(*test_input), expected,
- decimal=7, err_msg='f function is off'
+ pynam.dielectric.low_k_nam.f(*test_input),
+ expected,
+ decimal=7,
+ err_msg="f function is off",
)
-@pytest.mark.parametrize("test_input,expected", [
- ((2, 3, 1, 0), 1.42546694754),
- ((1, 2, 3, 4), 0.0206212167 + 0.4411134527j)
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [((2, 3, 1, 0), 1.42546694754), ((1, 2, 3, 4), 0.0206212167 + 0.4411134527j)],
+)
def test_i1(test_input, expected):
np.testing.assert_almost_equal(
- pynam.dielectric.low_k_nam.i1(*test_input), expected,
- decimal=7, err_msg='i1 function is off'
+ pynam.dielectric.low_k_nam.i1(*test_input),
+ expected,
+ decimal=7,
+ err_msg="i1 function is off",
)
-@pytest.mark.parametrize("test_input,expected", [
- ((2, 3, 1, 0), 1.47903168398),
- ((1, 2, 3, 4), 0.079491440779 + 0.441113452718j)
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [((2, 3, 1, 0), 1.47903168398), ((1, 2, 3, 4), 0.079491440779 + 0.441113452718j)],
+)
def test_i2(test_input, expected):
np.testing.assert_almost_equal(
- pynam.dielectric.low_k_nam.i2(*test_input), expected,
- decimal=7, err_msg='i1 function is off'
+ pynam.dielectric.low_k_nam.i2(*test_input),
+ expected,
+ decimal=7,
+ err_msg="i1 function is off",
)
-@pytest.mark.parametrize("test_input,expected", [
- ((1, 2, 3, 4), 0.228292),
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ ((1, 2, 3, 4), 0.228292),
+ ],
+)
def test_a(test_input, expected):
actual = np.real_if_close(pynam.dielectric.low_k_nam.a(*test_input))
np.testing.assert_almost_equal(
- actual, expected,
- decimal=6, err_msg='a function is off'
+ actual, expected, decimal=6, err_msg="a function is off"
)
-@pytest.mark.parametrize("test_input,expected", [
- ((2, 1, 2, 0, 4), 0.479529593125),
- ((100, 1, 2, 3, 4), -2.62529549942e-6 + 2.60588e-12j),
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ ((2, 1, 2, 0, 4), 0.479529593125),
+ ((100, 1, 2, 3, 4), -2.62529549942e-6 + 2.60588e-12j),
+ ],
+)
def test_b_int(test_input, expected):
actual = np.real_if_close(pynam.dielectric.low_k_nam.b_int(*test_input))
np.testing.assert_almost_equal(
- actual, expected,
- decimal=6, err_msg='b int function is off'
+ actual, expected, decimal=6, err_msg="b int function is off"
)
-@pytest.mark.parametrize("test_input,expected", [
- ((1, 2, 0, 4), 3.514889721181435),
- ((1, 2, 3, 4), -0.0598057 + 0.437146j),
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ ((1, 2, 0, 4), 3.514889721181435),
+ ((1, 2, 3, 4), -0.0598057 + 0.437146j),
+ ],
+)
def test_b(test_input, expected):
actual = np.real_if_close(pynam.dielectric.low_k_nam.b(*test_input))
np.testing.assert_almost_equal(
- actual, expected,
- decimal=6, err_msg='b function is off'
+ actual, expected, decimal=6, err_msg="b function is off"
)
-@pytest.mark.parametrize("test_input,expected", [
- ((1, 2, 0, 4), 0),
- ((1, 2, 3, 4), 0.98358 + 0.648221j),
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ ((1, 2, 0, 4), 0),
+ ((1, 2, 3, 4), 0.98358 + 0.648221j),
+ ],
+)
def test_sigma_alk(test_input, expected):
actual = np.real_if_close(pynam.dielectric.low_k_nam.sigma_nam_alk(*test_input))
np.testing.assert_almost_equal(
- actual, expected,
- decimal=6, err_msg='b function is off'
+ actual, expected, decimal=6, err_msg="b function is off"
)
def test_sigma_alk_benchmark(benchmark):
result = benchmark(pynam.dielectric.low_k_nam.sigma_nam_alk, 1, 2, 3, 4)
np.testing.assert_almost_equal(
- result, 0.98358 + 0.648221j,
- decimal=6, err_msg='b function is off'
+ result, 0.98358 + 0.648221j, decimal=6, err_msg="b function is off"
)
diff --git a/tests/dielectric/test_nam_dielectric_coefficient_approximator.py b/tests/dielectric/test_nam_dielectric_coefficient_approximator.py
index 72aba86..365ab26 100644
--- a/tests/dielectric/test_nam_dielectric_coefficient_approximator.py
+++ b/tests/dielectric/test_nam_dielectric_coefficient_approximator.py
@@ -4,102 +4,136 @@ import pynam.dielectric.nam_dielectric_coefficient_approximator
from pynam.baskets import CalculationParams
-@pytest.mark.parametrize("test_input,expected", [
- # (
- # (omega, sigma_n, tau, v_f, T, T_c, c_light),
- # (xi, nu, t, A, B)
- # )
- (
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ # (
+ # (omega, sigma_n, tau, v_f, T, T_c, c_light),
+ # (xi, nu, t, A, B)
+ # )
+ (
(1e9, 1e16, 1e-14, 2e6, 0.8e11, 1e11, 3e8),
- (0.007307411691175783, 730.7411691175784, 0.5845929352940626, 0.00004871607794117188, 10000000)
- )
-])
+ (
+ 0.007307411691175783,
+ 730.7411691175784,
+ 0.5845929352940626,
+ 0.00004871607794117188,
+ 10000000,
+ ),
+ )
+ ],
+)
def test_dedimensionalise_parameters(test_input, expected):
actual_parameters = pynam.dielectric.nam_dielectric_coefficient_approximator.get_dedimensionalised_parameters(
- *test_input)
-
- np.testing.assert_almost_equal(
- actual_parameters.xi, expected[0],
- decimal=6, err_msg='xi incorrectly calculated'
+ *test_input
)
np.testing.assert_almost_equal(
- actual_parameters.nu, expected[1],
- decimal=6, err_msg='nu incorrectly calculated'
+ actual_parameters.xi,
+ expected[0],
+ decimal=6,
+ err_msg="xi incorrectly calculated",
+ )
+
+ np.testing.assert_almost_equal(
+ actual_parameters.nu,
+ expected[1],
+ decimal=6,
+ err_msg="nu incorrectly calculated",
)
np.testing.assert_almost_equal(
- actual_parameters.t, expected[2],
- decimal=6, err_msg='t incorrectly calculated'
+ actual_parameters.t, expected[2], decimal=6, err_msg="t incorrectly calculated"
)
np.testing.assert_almost_equal(
- actual_parameters.a, expected[3],
- decimal=6, err_msg='A incorrectly calculated'
+ actual_parameters.a, expected[3], decimal=6, err_msg="A incorrectly calculated"
)
np.testing.assert_almost_equal(
- actual_parameters.b, expected[4],
- decimal=6, err_msg='B incorrectly calculated'
+ actual_parameters.b, expected[4], decimal=6, err_msg="B incorrectly calculated"
)
-@pytest.mark.parametrize("test_input,expected", [
- # (
- # (omega, sigma_n, tau, v_f, T, T_c, c_light),
- # (a, b, c, d, u_l)
- # )
- (
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ # (
+ # (omega, sigma_n, tau, v_f, T, T_c, c_light),
+ # (a, b, c, d, u_l)
+ # )
+ (
(1e9, 1e16, 1e-14, 2e6, 0.8e11, 1e11, 3e8),
- (3.789672906817707e10, 3.257134605133221e8, 2.655709897616547e18, 2.15e16, 7.007759408279888e7)
- )
-])
+ (
+ 3.789672906817707e10,
+ 3.257134605133221e8,
+ 2.655709897616547e18,
+ 2.15e16,
+ 7.007759408279888e7,
+ ),
+ )
+ ],
+)
def test_nam_coefficients(test_input, expected):
actual_coefficients = pynam.dielectric.nam_dielectric_coefficient_approximator.get_nam_dielectric_coefficients(
- *test_input)
-
- np.testing.assert_allclose(
- actual_coefficients.a, expected[0],
- rtol=1e-6, err_msg='a incorrectly calculated'
+ *test_input
)
np.testing.assert_allclose(
- actual_coefficients.b, expected[1],
- rtol=1e-6, err_msg='b incorrectly calculated'
+ actual_coefficients.a,
+ expected[0],
+ rtol=1e-6,
+ err_msg="a incorrectly calculated",
+ )
+
+ np.testing.assert_allclose(
+ actual_coefficients.b,
+ expected[1],
+ rtol=1e-6,
+ err_msg="b incorrectly calculated",
)
np.testing.assert_allclose(
- actual_coefficients.c, expected[2],
- rtol=1e-2, err_msg='c incorrectly calculated'
+ actual_coefficients.c,
+ expected[2],
+ rtol=1e-2,
+ err_msg="c incorrectly calculated",
)
np.testing.assert_allclose(
- actual_coefficients.d, expected[3],
- rtol=1e-2, err_msg='d incorrectly calculated'
+ actual_coefficients.d,
+ expected[3],
+ rtol=1e-2,
+ err_msg="d incorrectly calculated",
)
np.testing.assert_allclose(
- actual_coefficients.u_l, expected[4],
- rtol=1e-5, err_msg='u_l incorrectly calculated'
+ actual_coefficients.u_l,
+ expected[4],
+ rtol=1e-5,
+ err_msg="u_l incorrectly calculated",
)
def test_nam_eps():
u_c = 1e15
- eps_to_test = pynam.dielectric.nam_dielectric_coefficient_approximator.get_nam_dielectric(u_c, CalculationParams(
- omega=1e9,
- omega_p=3.54491e15,
- tau=1e-14,
- v_f=2e6,
- t_rel=0.8,
- t_c=1e11
- ))
-
- np.testing.assert_allclose(
- eps_to_test(10), -3.789672906817707e10 + 3.257134605133221e8j,
- rtol=1e-3, err_msg='below u_l bad'
+ eps_to_test = (
+ pynam.dielectric.nam_dielectric_coefficient_approximator.get_nam_dielectric(
+ u_c,
+ CalculationParams(
+ omega=1e9, omega_p=3.54491e15, tau=1e-14, v_f=2e6, t_rel=0.8, t_c=1e11
+ ),
+ )
)
np.testing.assert_allclose(
- eps_to_test(1e10), -2.655709887616547e8 + 2.302290450767144e6j,
- rtol=1e-3, err_msg='linear region bad'
+ eps_to_test(10),
+ -3.789672906817707e10 + 3.257134605133221e8j,
+ rtol=1e-3,
+ err_msg="below u_l bad",
)
np.testing.assert_allclose(
- eps_to_test(1e17), 1,
- rtol=1e-6, err_msg='above cutoff bad'
+ eps_to_test(1e10),
+ -2.655709887616547e8 + 2.302290450767144e6j,
+ rtol=1e-3,
+ err_msg="linear region bad",
+ )
+
+ np.testing.assert_allclose(
+ eps_to_test(1e17), 1, rtol=1e-6, err_msg="above cutoff bad"
)
diff --git a/tests/dielectric/test_sigma_nam.py b/tests/dielectric/test_sigma_nam.py
index b54f743..4a3d594 100644
--- a/tests/dielectric/test_sigma_nam.py
+++ b/tests/dielectric/test_sigma_nam.py
@@ -3,120 +3,163 @@ import numpy as np
import pytest
-@pytest.mark.parametrize("test_input,expected", [
- ((1, 2), 7 / (2 * np.sqrt(6))),
- ((2, 0.25), -5j / np.sqrt(39))
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [((1, 2), 7 / (2 * np.sqrt(6))), ((2, 0.25), -5j / np.sqrt(39))],
+)
def test_g(test_input, expected):
np.testing.assert_almost_equal(
- pynam.dielectric.sigma_nam.g(*test_input), expected,
- decimal=7, err_msg='g function is off'
+ pynam.dielectric.sigma_nam.g(*test_input),
+ expected,
+ decimal=7,
+ err_msg="g function is off",
)
-@pytest.mark.parametrize("test_input,expected", [
- ((1, 2, 0), 2),
- ((1, 2, 3), 2 - 3j),
- ((1, 0, 3), -3j)
-])
+@pytest.mark.parametrize(
+ "test_input,expected", [((1, 2, 0), 2), ((1, 2, 3), 2 - 3j), ((1, 0, 3), -3j)]
+)
def test_s(test_input, expected):
np.testing.assert_almost_equal(
- pynam.dielectric.sigma_nam.s(*test_input), expected,
- decimal=7, err_msg='s function is off'
+ pynam.dielectric.sigma_nam.s(*test_input),
+ expected,
+ decimal=7,
+ err_msg="s function is off",
)
-@pytest.mark.parametrize("test_input,expected", [
- ((1, 2, 0), 4 - 3 * np.log(3)),
- ((1, 1, 0.1), 1.7258022209219421 + 0.4146045220413866j),
- ((1, 2, 1), 0.535971651563 + 0.291580606867j),
- ((1, 0, 1), (np.pi - 2)*1j),
- ((2, 1.09637631718, 0), 0.97892512273 + 1.09875591859j),
- ((2, 1, 0), 0.91197960825 + 1.17809724510j)
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ ((1, 2, 0), 4 - 3 * np.log(3)),
+ ((1, 1, 0.1), 1.7258022209219421 + 0.4146045220413866j),
+ ((1, 2, 1), 0.535971651563 + 0.291580606867j),
+ ((1, 0, 1), (np.pi - 2) * 1j),
+ ((2, 1.09637631718, 0), 0.97892512273 + 1.09875591859j),
+ ((2, 1, 0), 0.91197960825 + 1.17809724510j),
+ ],
+)
def test_f(test_input, expected):
np.testing.assert_almost_equal(
- pynam.dielectric.sigma_nam.f(*test_input), expected,
- decimal=7, err_msg='f function is off'
+ pynam.dielectric.sigma_nam.f(*test_input),
+ expected,
+ decimal=7,
+ err_msg="f function is off",
)
-@pytest.mark.parametrize("test_input,expected", [
- ((2, 3, 1, 0), 1.43292419807),
- ((1, 2, 3, 4), 0.020963572915 + 0.441546735048j),
- ((1, 2, 2, 0), 2.24702466263660598724031013350450660504 + 2.6687342075059525776833106878900822165j)
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ ((2, 3, 1, 0), 1.43292419807),
+ ((1, 2, 3, 4), 0.020963572915 + 0.441546735048j),
+ (
+ (1, 2, 2, 0),
+ 2.24702466263660598724031013350450660504
+ + 2.6687342075059525776833106878900822165j,
+ ),
+ ],
+)
def test_i1(test_input, expected):
np.testing.assert_almost_equal(
- pynam.dielectric.sigma_nam.i1(*test_input), expected,
- decimal=7, err_msg='i1 function is off'
+ pynam.dielectric.sigma_nam.i1(*test_input),
+ expected,
+ decimal=7,
+ err_msg="i1 function is off",
)
-@pytest.mark.parametrize("test_input,expected", [
- ((2, 3, 1, 0), 1.48649022993),
- ((1, 2, 3, 4), 0.079899419983 + 0.441546735048j),
- ((1, 2, 2, 0), 2.5083371377336783093007366990156440969 + 2.6687342075059525776833106878900822165j)
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ ((2, 3, 1, 0), 1.48649022993),
+ ((1, 2, 3, 4), 0.079899419983 + 0.441546735048j),
+ (
+ (1, 2, 2, 0),
+ 2.5083371377336783093007366990156440969
+ + 2.6687342075059525776833106878900822165j,
+ ),
+ ],
+)
def test_i2(test_input, expected):
np.testing.assert_almost_equal(
- pynam.dielectric.sigma_nam.i2(*test_input), expected,
- decimal=7, err_msg='i1 function is off'
+ pynam.dielectric.sigma_nam.i2(*test_input),
+ expected,
+ decimal=7,
+ err_msg="i1 function is off",
)
-@pytest.mark.parametrize("test_input,expected", [
- ((1, 2, 3, 4), 0.228396),
- ((0.007307411691175783, 1e8, 730.7411691175784, 0.5845929352940626), 1.37272e-7)
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ ((1, 2, 3, 4), 0.228396),
+ (
+ (0.007307411691175783, 1e8, 730.7411691175784, 0.5845929352940626),
+ 1.37272e-7,
+ ),
+ ],
+)
def test_a(test_input, expected):
actual = np.real_if_close(pynam.dielectric.sigma_nam.a(*test_input))
- np.testing.assert_allclose(
- actual, expected,
- rtol=1e-5, err_msg='a function is off'
- )
+ np.testing.assert_allclose(actual, expected, rtol=1e-5, err_msg="a function is off")
-@pytest.mark.parametrize("test_input,expected", [
- ((2, 1, 2, 0, 4), 0.19089933550122580816258795500979108668 + 0.30273783507819906415704926284048453889j),
- ((100, 1, 2, 3, 4), -2.62529549976e-6 + 2.60765e-12j),
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ (
+ (2, 1, 2, 0, 4),
+ 0.19089933550122580816258795500979108668
+ + 0.30273783507819906415704926284048453889j,
+ ),
+ ((100, 1, 2, 3, 4), -2.62529549976e-6 + 2.60765e-12j),
+ ],
+)
def test_b_int(test_input, expected):
actual = np.real_if_close(pynam.dielectric.sigma_nam.b_int(*test_input))
np.testing.assert_almost_equal(
- actual, expected,
- decimal=6, err_msg='b int function is off'
+ actual, expected, decimal=6, err_msg="b int function is off"
)
-@pytest.mark.parametrize("test_input,expected", [
- ((1, 2, 0, 4), 1.23149 + 2.08627j),
- ((1, 2, 3, 4), -0.0595819 + 0.437385j),
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ ((1, 2, 0, 4), 1.23149 + 2.08627j),
+ ((1, 2, 3, 4), -0.0595819 + 0.437385j),
+ ],
+)
def test_b(test_input, expected):
actual = np.real_if_close(pynam.dielectric.sigma_nam.b(*test_input))
np.testing.assert_almost_equal(
- actual, expected,
- decimal=6, err_msg='b function is off'
+ actual, expected, decimal=6, err_msg="b function is off"
)
-@pytest.mark.parametrize("test_input,expected", [
- ((1, 2, 0, 4), 0),
- ((1, 2, 3, 4), 0.984117 + 0.647951j),
- ((0.007307411691175783, 1e8, 730.7411691175784, 0.5845929352940626), 0.00008925294700016892 + 0.0102953966846717j)
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ ((1, 2, 0, 4), 0),
+ ((1, 2, 3, 4), 0.984117 + 0.647951j),
+ (
+ (0.007307411691175783, 1e8, 730.7411691175784, 0.5845929352940626),
+ 0.00008925294700016892 + 0.0102953966846717j,
+ ),
+ ],
+)
def test_sigma_nam(test_input, expected):
actual = np.real_if_close(pynam.dielectric.sigma_nam.sigma_nam(*test_input))
np.testing.assert_allclose(
- actual, expected,
- rtol=1e-3, err_msg='sigma_nam function is off'
+ actual, expected, rtol=1e-3, err_msg="sigma_nam function is off"
)
def test_sigma_nam_benchmark(benchmark):
result = benchmark(pynam.dielectric.sigma_nam.sigma_nam, 1, 2, 3, 4)
np.testing.assert_almost_equal(
- result, 0.984117 + 0.647951j,
- decimal=6, err_msg='sigma nam benchmrak function is off'
+ result,
+ 0.984117 + 0.647951j,
+ decimal=6,
+ err_msg="sigma nam benchmrak function is off",
)
diff --git a/tests/noise/test_chi.py b/tests/noise/test_chi.py
index 92ac296..84ad9e6 100644
--- a/tests/noise/test_chi.py
+++ b/tests/noise/test_chi.py
@@ -8,34 +8,50 @@ from pynam.baskets import CalculationParams
@pytest.fixture
def chi_zz_e_lindhard():
- params = CalculationParams(omega=1e9, v_f=2e6, omega_p=3.544907701811032e15, tau=1e-14)
+ params = CalculationParams(
+ omega=1e9, v_f=2e6, omega_p=3.544907701811032e15, tau=1e-14
+ )
eps_l = pynam.dielectric.get_lindhard_dielectric(params)
return pynam.noise.chi.get_chi_zz_e(eps_l)
-@pytest.mark.parametrize("test_input,expected", [
- # z chi_zz_e_lindhard(z)
- (1e-5, 4.0249088868003124e6),
- (1e-6, 4.400474453780887e9),
- (1e-7, 7.768467746685921e12),
- (1e-8, 1.8541895525296864e16),
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ # z chi_zz_e_lindhard(z)
+ (1e-5, 4.0249088868003124e6),
+ (1e-6, 4.400474453780887e9),
+ (1e-7, 7.768467746685921e12),
+ (1e-8, 1.8541895525296864e16),
+ ],
+)
def test_chi_zz_e_lindhard(chi_zz_e_lindhard, test_input, expected):
actual = chi_zz_e_lindhard(test_input)
np.testing.assert_allclose(
- actual, expected,
- rtol=1e-3, err_msg='chi_zz_e is inaccurate for Lindhard case', verbose=True
+ actual,
+ expected,
+ rtol=1e-3,
+ err_msg="chi_zz_e is inaccurate for Lindhard case",
+ verbose=True,
)
-@pytest.mark.parametrize("test_input,expected", [
- # z chi_zz_e_lindhard(z)
- (1e-6, 4.400474453780887e9),
-])
-def test_chi_zz_e_lindhard_benchmark(benchmark, chi_zz_e_lindhard, test_input, expected):
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ # z chi_zz_e_lindhard(z)
+ (1e-6, 4.400474453780887e9),
+ ],
+)
+def test_chi_zz_e_lindhard_benchmark(
+ benchmark, chi_zz_e_lindhard, test_input, expected
+):
actual = benchmark(chi_zz_e_lindhard, test_input)
np.testing.assert_allclose(
- actual, expected,
- rtol=1e-3, err_msg='chi_zz_e is inaccurate for Lindhard case', verbose=True
+ actual,
+ expected,
+ rtol=1e-3,
+ err_msg="chi_zz_e is inaccurate for Lindhard case",
+ verbose=True,
)
diff --git a/tests/noise/test_im_ref.py b/tests/noise/test_im_ref.py
index 4da1dc8..6304d09 100644
--- a/tests/noise/test_im_ref.py
+++ b/tests/noise/test_im_ref.py
@@ -8,24 +8,32 @@ from pynam.baskets import CalculationParams
@pytest.fixture
def im_ref_p_lindhard():
- params = CalculationParams(omega=1e9, v_f=2e6, omega_p=3.544907701811032e15, tau=1e-14)
+ params = CalculationParams(
+ omega=1e9, v_f=2e6, omega_p=3.544907701811032e15, tau=1e-14
+ )
eps_l = pynam.dielectric.get_lindhard_dielectric(params)
return pynam.noise.im_ref.get_im_ref_p(eps_l)
-@pytest.mark.parametrize("test_input,expected", [
- # u im_ref_p_l(u)
- # needs to be close in range around 1/z, so from 1e4 to 1e8
- # (1e4, 1.821722334939806e-8), 1e4 is too far off still
- (1e5, 1.602855764970752e-8),
- (1e6, 1.704326041013161e-8),
- (1e7, 2.674124312031195e-8),
- (1e8, 7.441319151047531e-8),
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ # u im_ref_p_l(u)
+ # needs to be close in range around 1/z, so from 1e4 to 1e8
+ # (1e4, 1.821722334939806e-8), 1e4 is too far off still
+ (1e5, 1.602855764970752e-8),
+ (1e6, 1.704326041013161e-8),
+ (1e7, 2.674124312031195e-8),
+ (1e8, 7.441319151047531e-8),
+ ],
+)
def test_im_ref_p_lindhard(im_ref_p_lindhard, test_input, expected):
actual = im_ref_p_lindhard(test_input)
np.testing.assert_allclose(
- actual, expected,
- rtol=1e-4, err_msg='imrp is inaccurate for Lindhard case', verbose=True
+ actual,
+ expected,
+ rtol=1e-4,
+ err_msg="imrp is inaccurate for Lindhard case",
+ verbose=True,
)
diff --git a/tests/noise/test_zeta.py b/tests/noise/test_zeta.py
index 72a51dd..7315581 100644
--- a/tests/noise/test_zeta.py
+++ b/tests/noise/test_zeta.py
@@ -8,49 +8,65 @@ from pynam.baskets import CalculationParams
@pytest.fixture
def zeta_p_integrand_lindhard():
- params = CalculationParams(omega=1e9, v_f=2e6, omega_p=3.544907701811032e15, tau=1e-14)
+ params = CalculationParams(
+ omega=1e9, v_f=2e6, omega_p=3.544907701811032e15, tau=1e-14
+ )
eps_l = pynam.dielectric.get_lindhard_dielectric(params)
return pynam.noise.zeta.get_zeta_p_integrand(eps_l)
-@pytest.mark.parametrize("test_input,expected", [
- # y u zeta_p_i(u, y)
- ((100, 100), -6.891930153028566e-13 - 7.957747045025948e-9j),
- ((1e5, 100), -1.0057257267146669e-10 - 4.0591966623027983e-13j),
- ((100, 1e5), 1.1789175285399862e-8 - 7.957833322596519e-9j)
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ # y u zeta_p_i(u, y)
+ ((100, 100), -6.891930153028566e-13 - 7.957747045025948e-9j),
+ ((1e5, 100), -1.0057257267146669e-10 - 4.0591966623027983e-13j),
+ ((100, 1e5), 1.1789175285399862e-8 - 7.957833322596519e-9j),
+ ],
+)
def test_zeta_p_integrand_lindhard(zeta_p_integrand_lindhard, test_input, expected):
actual = zeta_p_integrand_lindhard(*test_input)
np.testing.assert_allclose(
- actual, expected,
- rtol=1e-7, err_msg='Zeta_p is inaccurate for Lindhard case', verbose=True
+ actual,
+ expected,
+ rtol=1e-7,
+ err_msg="Zeta_p is inaccurate for Lindhard case",
+ verbose=True,
)
@pytest.fixture
def zeta_p_lindhard():
- params = CalculationParams(omega=1e9, v_f=2e6, omega_p=3.544907701811032e15, tau=1e-14)
+ params = CalculationParams(
+ omega=1e9, v_f=2e6, omega_p=3.544907701811032e15, tau=1e-14
+ )
eps_l = pynam.dielectric.get_lindhard_dielectric(params)
return pynam.noise.zeta.get_zeta_p_function(eps_l)
-@pytest.mark.parametrize("test_input,expected", [
- # u zeta_p(u)
- (1, 0.000199609 - 0.000199608j),
- # (10, 0.00019960929309663014 - 0.00019927000998506335j),
- # (100, 0.0001996175250684056 - 0.0001654898843938523j),
- # (1e3, 0.0002003339895748246 + 0.003212370020888438j),
- # (1e4, 0.00028616168676982363 + 0.34096962141224463j),
- (1e5, 0.0025183067257958545 + 34.11087430547122j),
- (1e6, 0.026829658454640887 + 3411.0870128247902j),
- (1e7, 0.4292211181081069 + 341088.797211291j),
- (1e8, 14.348462224076096 + 3.391157983312813e7j)
-])
+@pytest.mark.parametrize(
+ "test_input,expected",
+ [
+ # u zeta_p(u)
+ (1, 0.000199609 - 0.000199608j),
+ # (10, 0.00019960929309663014 - 0.00019927000998506335j),
+ # (100, 0.0001996175250684056 - 0.0001654898843938523j),
+ # (1e3, 0.0002003339895748246 + 0.003212370020888438j),
+ # (1e4, 0.00028616168676982363 + 0.34096962141224463j),
+ (1e5, 0.0025183067257958545 + 34.11087430547122j),
+ (1e6, 0.026829658454640887 + 3411.0870128247902j),
+ (1e7, 0.4292211181081069 + 341088.797211291j),
+ (1e8, 14.348462224076096 + 3.391157983312813e7j),
+ ],
+)
def test_zeta_p(zeta_p_lindhard, test_input, expected):
actual = zeta_p_lindhard(test_input)
np.testing.assert_allclose(
- actual, expected,
- rtol=1e-4, err_msg='Zeta_p is inaccurate for Lindhard case', verbose=True
+ actual,
+ expected,
+ rtol=1e-4,
+ err_msg="Zeta_p is inaccurate for Lindhard case",
+ verbose=True,
)
diff --git a/tests/test_pynam.py b/tests/test_pynam.py
index 801087d..d5628b3 100644
--- a/tests/test_pynam.py
+++ b/tests/test_pynam.py
@@ -2,4 +2,4 @@ from pynam import __version__
def test_version():
- assert __version__ == '0.1.0'
+ assert __version__ == "0.1.0"
diff --git a/tests/util/test_complex_integrate.py b/tests/util/test_complex_integrate.py
index 6088896..3068b25 100644
--- a/tests/util/test_complex_integrate.py
+++ b/tests/util/test_complex_integrate.py
@@ -3,18 +3,28 @@ import pynam.util.complex_integrate
def test_complex_quad():
- actual = pynam.util.complex_integrate.complex_quad(lambda x: x ** 2 + 1j * x ** 3, 0, 6)[0]
+ actual = pynam.util.complex_integrate.complex_quad(
+ lambda x: x**2 + 1j * x**3, 0, 6
+ )[0]
# int_1^6 dx x^2 + i x^3 should equal (1/3)6^3 + (i/4)6^4
np.testing.assert_almost_equal(
- actual, (6**3)/3 + 1j*(6**4)/4,
- decimal=7, err_msg='complex quadrature is broken', verbose=True
+ actual,
+ (6**3) / 3 + 1j * (6**4) / 4,
+ decimal=7,
+ err_msg="complex quadrature is broken",
+ verbose=True,
)
def test_complex_quadrature():
- actual = pynam.util.complex_integrate.complex_quadrature(lambda x: x ** 2 + 1j * x ** 3, 0, 6)[0]
+ actual = pynam.util.complex_integrate.complex_quadrature(
+ lambda x: x**2 + 1j * x**3, 0, 6
+ )[0]
# int_1^6 dx x^2 + i x^3 should equal (1/3)6^3 + (i/4)6^4
np.testing.assert_almost_equal(
- actual, (6**3)/3 + 1j*(6**4)/4,
- decimal=7, err_msg='complex quadrature is broken', verbose=True
+ actual,
+ (6**3) / 3 + 1j * (6**4) / 4,
+ decimal=7,
+ err_msg="complex quadrature is broken",
+ verbose=True,
)