Compare commits

..

No commits in common. "master" and "0.8.5" have entirely different histories.

45 changed files with 5550 additions and 2989 deletions

4
.gitignore vendored
View File

@ -114,10 +114,6 @@ ENV/
env.bak/
venv.bak/
#direnv
.envrc
.direnv
# Spyder project settings
.spyderproject
.spyproject

View File

@ -2,125 +2,6 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [1.5.0](https://gitea.deepak.science:2222/physics/pdme/compare/1.4.0...1.5.0) (2024-05-17)
### Features
* adds mcmc chain that returns number of repeats ([6193ecb](https://gitea.deepak.science:2222/physics/pdme/commit/6193ecb9c9f7a21d24e860987a7107549a4b2fa7))
## [1.4.0](https://gitea.deepak.science:2222/physics/pdme/compare/1.3.0...1.4.0) (2024-05-17)
### Features
* adds relative squared diff calc utility method ([9b1538b](https://gitea.deepak.science:2222/physics/pdme/commit/9b1538b3c63bfaf2a779bb109cd160a8d7887195))
## [1.3.0](https://gitea.deepak.science:2222/physics/pdme/compare/1.2.0...1.3.0) (2024-05-17)
### Features
* adds utility function for sorting samples by frequency for subspace simulation ([e5fc120](https://gitea.deepak.science:2222/physics/pdme/commit/e5fc1207a8b7d5b67208ad825907baa442eec648))
## [1.2.0](https://gitea.deepak.science:2222/physics/pdme/compare/1.1.0...1.2.0) (2024-05-03)
### Features
* adds pdme fast calc for e field xs ([9e6d1df](https://gitea.deepak.science:2222/physics/pdme/commit/9e6d1df559e58998851a1c2bf24fcc46d8c1b148))
## [1.1.0](https://gitea.deepak.science:2222/physics/pdme/compare/1.0.0...1.1.0) (2024-05-02)
### Features
* adds both electric potential and electric field x sources, makes some fast util tests use the slower explicit versions as double check ([e9e3416](https://gitea.deepak.science:2222/physics/pdme/commit/e9e34162a3b84faad5c18ddeda327c2f7f5ac5aa))
## [1.0.0](https://gitea.deepak.science:2222/physics/pdme/compare/0.9.3...1.0.0) (2024-04-29)
### Bug Fixes
* fixes the broken implementation of the tarucha frequency calculation ([631ba13](https://gitea.deepak.science:2222/physics/pdme/commit/631ba13c791c71ad8922d39a13b780a40eac2391))
### [0.9.3](https://gitea.deepak.science:2222/physics/pdme/compare/0.9.2...0.9.3) (2024-02-26)
### Features
* adds util func for calculating arg using sign instead of complex arithmetic ([3ebe2bb](https://gitea.deepak.science:2222/physics/pdme/commit/3ebe2bb82430d677680383c42a1c269df83d99cd))
### Bug Fixes
* fixes stupid cost shape issue ([ed9dd2c](https://gitea.deepak.science:2222/physics/pdme/commit/ed9dd2c94f88a08c36f581f05b26a87a6b780d5b))
### [0.9.2](https://gitea.deepak.science:2222/physics/pdme/compare/0.9.1...0.9.2) (2023-07-24)
### Bug Fixes
* update tests but for git also don't wrap costs ([50f98ed](https://gitea.deepak.science:2222/physics/pdme/commit/50f98ed89b2a05cd47c41958036dd50bc872e07c))
### [0.9.1](https://gitea.deepak.science:2222/physics/pdme/compare/0.9.0...0.9.1) (2023-07-24)
### Bug Fixes
* fixes some of the shape mangling of our mcmc code ([e01d0e1](https://gitea.deepak.science:2222/physics/pdme/commit/e01d0e14a9bcd6d7e8fe9449ce562dbf1b8fd25c))
## [0.9.0](https://gitea.deepak.science:2222/physics/pdme/compare/0.8.9...0.9.0) (2023-07-24)
### ⚠ BREAKING CHANGES
* separates threshold cost and the seed_cost in mcmc
### Features
* separates threshold cost and the seed_cost in mcmc ([ca710e3](https://gitea.deepak.science:2222/physics/pdme/commit/ca710e359fd0cfbb620a3574a2fa4fab1be2b52a))
### [0.8.9](https://gitea.deepak.science:2222/physics/pdme/compare/0.8.8...0.8.9) (2023-07-23)
### Features
* adds a bunch of mcmc generation code for log spaced models, yay ([f280448](https://gitea.deepak.science:2222/physics/pdme/commit/f280448cfe2fcf5bdc5ac2317ee52b27523bb49d))
* adds utility functions for dealing with markov chain monte carlo ([feb0a5f](https://gitea.deepak.science:2222/physics/pdme/commit/feb0a5f6453dcb5e71a07c7749cd579dab15171c))
### [0.8.8](https://gitea.deepak.science:2222/physics/pdme/compare/0.8.7...0.8.8) (2023-04-09)
### Features
* adds fast calc that allows for variable temp ([36454d5](https://gitea.deepak.science:2222/physics/pdme/commit/36454d5044d93b6b178e016b84dd59a5ebaf15e2))
### [0.8.7](https://gitea.deepak.science:2222/physics/pdme/compare/0.8.6...0.8.7) (2022-09-17)
### Features
* adds xy model for convenience to pdme ([e894c89](https://gitea.deepak.science:2222/physics/pdme/commit/e894c897029c05a1d4754e7930ae9ba2be7a1cfd))
* moves xy model up to model package ([2a1ae3b](https://gitea.deepak.science:2222/physics/pdme/commit/2a1ae3b1a7f7e10469b7fd2930fee0b338f0c03f))
### Bug Fixes
* Correctly generates monte carlo version of xy model dipoles ([5acf0ac](https://gitea.deepak.science:2222/physics/pdme/commit/5acf0ac347382705674bb596440d27cba3730bac))
### [0.8.6](https://gitea.deepak.science:2222/physics/pdme/compare/0.8.5...0.8.6) (2022-06-13)
### Features
* makes library build system poetry-core ([ed0c6e2](https://gitea.deepak.science:2222/physics/pdme/commit/ed0c6e2858f45fec9b9a673d9b5bc98605e73508))
### Bug Fixes
* pyproject build system now core as well ([6277e84](https://gitea.deepak.science:2222/physics/pdme/commit/6277e843d5a7df8eba1878db490d2fae4052af57))
### [0.8.5](https://gitea.deepak.science:2222/physics/pdme/compare/0.8.4...0.8.5) (2022-06-04)

View File

@ -5,7 +5,7 @@
[![Jenkins](https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins.deepak.science%2Fjob%2Fgitea-physics%2Fjob%2Fpdme%2Fjob%2Fmaster&style=flat-square)](https://jenkins.deepak.science/job/gitea-physics/job/pdme/job/master/)
![Jenkins tests](https://img.shields.io/jenkins/tests?compact_message&jobUrl=https%3A%2F%2Fjenkins.deepak.science%2Fjob%2Fgitea-physics%2Fjob%2Fpdme%2Fjob%2Fmaster%2F&style=flat-square)
![Jenkins Coverage](https://img.shields.io/jenkins/coverage/cobertura?jobUrl=https%3A%2F%2Fjenkins.deepak.science%2Fjob%2Fgitea-physics%2Fjob%2Fpdme%2Fjob%2Fmaster%2F&style=flat-square)
![Maintenance](https://img.shields.io/maintenance/yes/2024?style=flat-square)
![Maintenance](https://img.shields.io/maintenance/yes/2022?style=flat-square)
This repo has library code for evaluating dipole models.

5029
diagnosis1.nb Normal file

File diff suppressed because it is too large Load Diff

38
do.sh Normal file
View File

@ -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
}
test() {
echo "I am ${FUNCNAME[0]}ing"
poetry run flake8 pdme tests
poetry run mypy pdme
poetry run pytest
}
fmt() {
poetry run black .
find . -type f -name "*.py" -exec sed -i -e 's/ /\t/g' {} \;
}
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 '|' -))"

95
flake.lock generated
View File

@ -1,95 +0,0 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1648297722,
"narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1653893745,
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1648854265,
"narHash": "sha256-e/RlfodBOMr2SH9diDPYMraTWvhOWSSsXDQikHFdUvM=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e194871435cad8ffb1d64b64fb7df3b2b8a10088",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e194871435cad8ffb1d64b64fb7df3b2b8a10088",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1655043425,
"narHash": "sha256-A+oT+aQGhW5lXy8H0cqBLsYtgcnT5glmGOXWQDcGw6I=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "914ef51ffa88d9b386c71bdc88bffc5273c08ada",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"poetry2nix": {
"inputs": {
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1654921554,
"narHash": "sha256-hkfMdQAHSwLWlg0sBVvgrQdIiBP45U1/ktmFpY4g2Mo=",
"owner": "nix-community",
"repo": "poetry2nix",
"rev": "7b71679fa7df00e1678fc3f1d1d4f5f372341b63",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "poetry2nix",
"rev": "7b71679fa7df00e1678fc3f1d1d4f5f372341b63",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"poetry2nix": "poetry2nix"
}
}
},
"root": "root",
"version": 7
}

View File

@ -1,55 +0,0 @@
{
description = "Application packaged using poetry2nix";
inputs.flake-utils.url = "github:numtide/flake-utils?rev=0f8662f1319ad6abf89b3380dd2722369fc51ade";
inputs.nixpkgs.url = "github:NixOS/nixpkgs?rev=e194871435cad8ffb1d64b64fb7df3b2b8a10088";
inputs.poetry2nix.url = "github:nix-community/poetry2nix?rev=7b71679fa7df00e1678fc3f1d1d4f5f372341b63";
outputs = { self, nixpkgs, flake-utils, poetry2nix }:
{
# Nixpkgs overlay providing the application
overlay = nixpkgs.lib.composeManyExtensions [
poetry2nix.overlay
(final: prev: {
# The application
pdme = prev.poetry2nix.mkPoetryApplication {
overrides = [
prev.poetry2nix.defaultPoetryOverrides
];
projectDir = ./.;
};
pdmeEnv = prev.poetry2nix.mkPoetryEnv {
overrides = [
prev.poetry2nix.defaultPoetryOverrides
];
projectDir = ./.;
};
})
];
} // (flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ self.overlay ];
};
in
{
apps = {
pdme = pkgs.pdme;
};
defaultApp = pkgs.pdme;
devShell = pkgs.mkShell {
buildInputs = [
pkgs.poetry
pkgs.pdmeEnv
pkgs.pdme
];
shellHook = ''
export DO_NIX_CUSTOM=1
'';
packages = [ pkgs.nodejs-16_x pkgs.gnupg ];
};
}));
}

View File

@ -1,64 +0,0 @@
# execute default build
default: build
# builds the python module using poetry
build:
echo "building..."
poetry build
# print a message displaying whether nix is being used
checknix:
#!/usr/bin/env bash
set -euxo pipefail
if [[ "${DO_NIX_CUSTOM:=0}" -eq 1 ]]; then
echo "In an interactive nix env."
else
echo "Using poetry as runner, no nix detected."
fi
# run all tests
test: fmt
#!/usr/bin/env bash
set -euxo pipefail
if [[ "${DO_NIX_CUSTOM:=0}" -eq 1 ]]; then
echo "testing, using nix..."
flake8 pdme tests
mypy pdme
pytest
else
echo "testing..."
poetry run flake8 pdme tests
poetry run mypy pdme
poetry run pytest
fi
# update all test snapshots, use if snapshots are out of date
update-snapshots:
#!/usr/bin/env bash
set -euxo pipefail
if [[ "${DO_NIX_CUSTOM:=0}" -eq 1 ]]; then
pytest --snapshot-update
else
poetry run pytest --snapshot-update
fi
# format code
fmt:
#!/usr/bin/env bash
set -euxo pipefail
if [[ "${DO_NIX_CUSTOM:=0}" -eq 1 ]]; then
black .
else
poetry run black .
fi
find pdme -type f -name "*.py" -exec sed -i -e 's/ /\t/g' {} \;
find tests -type f -name "*.py" -exec sed -i -e 's/ /\t/g' {} \;
# release the app, checking that our working tree is clean and ready for release
release:
./scripts/release.sh
htmlcov:
poetry run pytest --cov-report=html

View File

@ -1,46 +0,0 @@
"""
This module is a canonical source of the accurate expressions we want to use for calculating our noise.
No reference to class or anything, just a straight set of math functions.
"""
import numpy
def telegraph_beta(f: float, w: float) -> float:
"""
This function represents the frequency component of analytic telegraph noise.
We're assuming we care about the one-sided PSD where we are ignoring negative frequencies.
This matches with experimental data from say Connors et al., and I think is better than keeping with one-sided.
Note that this means that it will only be comparable then with time series data assuming one-sided!
Don't bikeshed yet, if we care about two-sided things for any reason down the line divide this by two or just change it then.
"""
return 2 * w / ((numpy.pi * f) ** 2 + w**2)
def electric_potential(p: numpy.ndarray, s: numpy.ndarray, r: numpy.ndarray) -> float:
"""
Gives the electric potential of a defect with dipole moment p, located at position s,
as measured from position r.
p, s, r, are numpy arrays of length 3
"""
diff = r - s
return (p.dot(diff) / (numpy.linalg.norm(diff) ** 3)).item()
def electric_field(
p: numpy.ndarray, s: numpy.ndarray, r: numpy.ndarray
) -> numpy.ndarray:
"""
Gives the electric field of a defect with dipole moment p, located at position s,
as measured from position r.
p, s, r, are numpy arrays of length 3
Returns an array of length 3, ideally.
"""
diff = r - s
norm_diff = numpy.linalg.norm(diff)
return ((3 * (p.dot(diff) * diff) / (norm_diff**2)) - p) / (norm_diff**3)

View File

@ -7,7 +7,6 @@ from pdme.measurement.dot_pair_measure import (
DotPairMeasurement,
DotPairRangeMeasurement,
)
import pdme.calculations
from pdme.measurement.input_types import DotInput, DotPairInput
@ -39,78 +38,29 @@ class OscillatingDipole:
self.p = numpy.array(self.p)
self.s = numpy.array(self.s)
def _alpha_electric_potential(self, r: numpy.ndarray) -> float:
def s_at_position(self, r: numpy.ndarray, f: float) -> float:
"""
Returns the electric potential of this dipole at position r.
"""
return pdme.calculations.electric_potential(self.p, self.s, r)
Returns the noise potential at a point r, at some frequency f.
def _alpha_electric_field(self, r: numpy.ndarray) -> numpy.ndarray:
Parameters
----------
r : numpy.ndarray
The position of the dot.
f : float
The dot frequency to sample.
"""
Returns the electric field of this dipole at position r.
"""
return pdme.calculations.electric_field(self.p, self.s, r)
return (self._alpha(r)) ** 2 * self._b(f)
def _alpha(self, r: numpy.ndarray) -> float:
diff = r - self.s
return self.p.dot(diff) / (numpy.linalg.norm(diff) ** 3)
def _b(self, f: float) -> float:
return pdme.calculations.telegraph_beta(f, self.w)
return (1 / numpy.pi) * (self.w / (f**2 + self.w**2))
def s_electric_potential_at_position(self, r: numpy.ndarray, f: float) -> float:
"""
Returns the noise potential at a point r, at some frequency f.
Specifically for electric potential!
Parameters
----------
r : numpy.ndarray
The position of the dot.
f : float
The dot frequency to sample.
"""
return (self._alpha_electric_potential(r)) ** 2 * self._b(f)
def s_electric_potential_for_dot_pair(
self, r1: numpy.ndarray, r2: numpy.ndarray, f: float
) -> float:
"""
This is specifically the analytic cpsd for electric potential noise.
This should be deprecated
"""
return (
self._alpha_electric_potential(r1)
* self._alpha_electric_potential(r2)
* self._b(f)
)
def s_electric_fieldx_at_position(self, r: numpy.ndarray, f: float) -> float:
"""
Returns the noise potential at a point r, at some frequency f.
Specifically for electric potential!
Parameters
----------
r : numpy.ndarray
The position of the dot.
f : float
The dot frequency to sample.
"""
return (self._alpha_electric_field(r)[0]) ** 2 * self._b(f)
def s_electric_fieldx_for_dot_pair(
self, r1: numpy.ndarray, r2: numpy.ndarray, f: float
) -> float:
"""
This is specifically the analytic cpsd for electric potential noise.
This should be deprecated
"""
return (
self._alpha_electric_field(r1)[0]
* self._alpha_electric_field(r2)[0]
* self._b(f)
)
def s_for_dot_pair(self, r1: numpy.ndarray, r2: numpy.ndarray, f: float) -> float:
return self._alpha(r1) * self._alpha(r2) * self._b(f)
def to_flat_array(self) -> numpy.ndarray:
return numpy.concatenate([self.p, self.s, numpy.array([self.w])])
@ -128,97 +78,69 @@ class OscillatingDipoleArrangement:
def __init__(self, dipoles: Sequence[OscillatingDipole]):
self.dipoles = dipoles
def get_potential_dot_measurement(self, dot_input: DotInput) -> DotMeasurement:
def get_dot_measurement(self, dot_input: DotInput) -> DotMeasurement:
r = numpy.array(dot_input[0])
f = dot_input[1]
return DotMeasurement(
sum(
[
dipole.s_electric_potential_at_position(r, f)
for dipole in self.dipoles
]
),
r,
f,
sum([dipole.s_at_position(r, f) for dipole in self.dipoles]), r, f
)
def get_potential_dot_pair_measurement(
def get_dot_pair_measurement(
self, dot_pair_input: DotPairInput
) -> DotPairMeasurement:
r1 = numpy.array(dot_pair_input[0])
r2 = numpy.array(dot_pair_input[1])
f = dot_pair_input[2]
return DotPairMeasurement(
sum(
[
dipole.s_electric_potential_for_dot_pair(r1, r2, f)
for dipole in self.dipoles
]
),
sum([dipole.s_for_dot_pair(r1, r2, f) for dipole in self.dipoles]),
r1,
r2,
f,
)
def get_potential_dot_measurements(
def get_dot_measurements(
self, dot_inputs: Sequence[DotInput]
) -> List[DotMeasurement]:
"""
For a series of points, each with three coordinates and a frequency, return a list of the corresponding DotMeasurements.
"""
return [
self.get_potential_dot_measurement(dot_input) for dot_input in dot_inputs
]
return [self.get_dot_measurement(dot_input) for dot_input in dot_inputs]
def get_potential_dot_pair_measurements(
def get_dot_pair_measurements(
self, dot_pair_inputs: Sequence[DotPairInput]
) -> List[DotPairMeasurement]:
"""
For a series of pairs of points, each with three coordinates and a frequency, return a list of the corresponding DotPairMeasurements.
"""
return [
self.get_potential_dot_pair_measurement(dot_pair_input)
self.get_dot_pair_measurement(dot_pair_input)
for dot_pair_input in dot_pair_inputs
]
def get_percent_range_potential_dot_measurement(
def get_percent_range_dot_measurement(
self, dot_input: DotInput, low_percent: float, high_percent: float
) -> DotRangeMeasurement:
r = numpy.array(dot_input[0])
f = dot_input[1]
return DotRangeMeasurement(
low_percent
* sum(
[
dipole.s_electric_potential_at_position(r, f)
for dipole in self.dipoles
]
),
high_percent
* sum(
[
dipole.s_electric_potential_at_position(r, f)
for dipole in self.dipoles
]
),
low_percent * sum([dipole.s_at_position(r, f) for dipole in self.dipoles]),
high_percent * sum([dipole.s_at_position(r, f) for dipole in self.dipoles]),
r,
f,
)
def get_percent_range_potential_dot_measurements(
def get_percent_range_dot_measurements(
self, dot_inputs: Sequence[DotInput], low_percent: float, high_percent: float
) -> List[DotRangeMeasurement]:
"""
For a series of pairs of points, each with three coordinates and a frequency, and also a lower error range and upper error range, return a list of the corresponding DotPairRangeMeasurements.
"""
return [
self.get_percent_range_potential_dot_measurement(
dot_input, low_percent, high_percent
)
self.get_percent_range_dot_measurement(dot_input, low_percent, high_percent)
for dot_input in dot_inputs
]
def get_percent_range_potential_dot_pair_measurement(
def get_percent_range_dot_pair_measurement(
self, pair_input: DotPairInput, low_percent: float, high_percent: float
) -> DotPairRangeMeasurement:
r1 = numpy.array(pair_input[0])
@ -226,25 +148,15 @@ class OscillatingDipoleArrangement:
f = pair_input[2]
return DotPairRangeMeasurement(
low_percent
* sum(
[
dipole.s_electric_potential_for_dot_pair(r1, r2, f)
for dipole in self.dipoles
]
),
* sum([dipole.s_for_dot_pair(r1, r2, f) for dipole in self.dipoles]),
high_percent
* sum(
[
dipole.s_electric_potential_for_dot_pair(r1, r2, f)
for dipole in self.dipoles
]
),
* sum([dipole.s_for_dot_pair(r1, r2, f) for dipole in self.dipoles]),
r1,
r2,
f,
)
def get_percent_range_potential_dot_pair_measurements(
def get_percent_range_dot_pair_measurements(
self,
pair_inputs: Sequence[DotPairInput],
low_percent: float,
@ -254,7 +166,7 @@ class OscillatingDipoleArrangement:
For a series of pairs of points, each with three coordinates and a frequency, and also a lower error range and upper error range, return a list of the corresponding DotPairRangeMeasurements.
"""
return [
self.get_percent_range_potential_dot_pair_measurement(
self.get_percent_range_dot_pair_measurement(
pair_input, low_percent, high_percent
)
for pair_input in pair_inputs

View File

@ -11,10 +11,6 @@ from pdme.model.log_spaced_random_choice_model import (
LogSpacedRandomCountMultipleDipoleFixedMagnitudeModel,
)
from pdme.model.log_spaced_random_choice_xy_model import (
LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel,
)
from pdme.model.log_spaced_random_choice_fixed_orientation_model import (
LogSpacedRandomCountMultipleDipoleFixedMagnitudeFixedOrientationModel,
)
@ -25,6 +21,5 @@ __all__ = [
"MultipleDipoleFixedMagnitudeModel",
"RandomCountMultipleDipoleFixedMagnitudeModel",
"LogSpacedRandomCountMultipleDipoleFixedMagnitudeModel",
"LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel",
"LogSpacedRandomCountMultipleDipoleFixedMagnitudeFixedOrientationModel",
]

View File

@ -5,11 +5,6 @@ from pdme.measurement import (
OscillatingDipole,
OscillatingDipoleArrangement,
)
import logging
from typing import Optional
import pdme.subspace_simulation
_logger = logging.getLogger(__name__)
class LogSpacedRandomCountMultipleDipoleFixedMagnitudeFixedOrientationModel(
@ -129,14 +124,12 @@ class LogSpacedRandomCountMultipleDipoleFixedMagnitudeFixedOrientationModel(
p_mask = rng.binomial(1, self.prob_occupancy, shape)
# dipoles = numpy.einsum("ij,k->ijk", p_mask, self.moment_fixed)
dipoles = numpy.einsum("ij,k->ijk", p_mask, self.moment_fixed)
# Is there a better way to create the final array? probably! can create a flatter guy then reshape.
# this is easier to reason about.
p_magnitude = self.pfixed * p_mask
px = p_magnitude * numpy.sin(self.thetafixed) * numpy.cos(self.phifixed)
py = p_magnitude * numpy.sin(self.thetafixed) * numpy.sin(self.phifixed)
pz = p_magnitude * numpy.cos(self.thetafixed)
px = dipoles[:, :, 0]
py = dipoles[:, :, 1]
pz = dipoles[:, :, 2]
sx = rng.uniform(self.xmin, self.xmax, shape)
sy = rng.uniform(self.ymin, self.ymax, shape)
@ -145,51 +138,3 @@ class LogSpacedRandomCountMultipleDipoleFixedMagnitudeFixedOrientationModel(
w = 10 ** rng.uniform(self.wexp_min, self.wexp_max, shape)
return numpy.stack([px, py, pz, sx, sy, sz, w], axis=-1)
def markov_chain_monte_carlo_proposal(
self,
dipole: numpy.ndarray,
stdev: pdme.subspace_simulation.DipoleStandardDeviation,
rng_arg: Optional[numpy.random.Generator] = None,
) -> numpy.ndarray:
if rng_arg is None:
rng_to_use = self.rng
else:
rng_to_use = rng_arg
px = dipole[0]
py = dipole[1]
pz = dipole[2]
# won't change p for this model of fixed dipole moment.
rx = dipole[3]
ry = dipole[4]
rz = dipole[5]
tentative_rx = rx + stdev.rx_step * rng_to_use.uniform(-1, 1)
if tentative_rx < self.xmin or tentative_rx > self.xmax:
tentative_rx = rx
tentative_ry = ry + stdev.ry_step * rng_to_use.uniform(-1, 1)
if tentative_ry < self.ymin or tentative_ry > self.ymax:
tentative_ry = ry
tentative_rz = rz + stdev.rz_step * rng_to_use.uniform(-1, 1)
if tentative_rz < self.zmin or tentative_rz > self.zmax:
tentative_rz = rz
w = dipole[6]
tentative_w = numpy.exp(
numpy.log(w) + (stdev.w_log_step * rng_to_use.uniform(-1, 1))
)
tentative_dip = numpy.array(
[
px,
py,
pz,
tentative_rx,
tentative_ry,
tentative_rz,
tentative_w,
]
)
return tentative_dip

View File

@ -5,8 +5,6 @@ from pdme.measurement import (
OscillatingDipole,
OscillatingDipoleArrangement,
)
import pdme.subspace_simulation
from typing import Optional
class LogSpacedRandomCountMultipleDipoleFixedMagnitudeModel(DipoleModel):
@ -127,73 +125,3 @@ class LogSpacedRandomCountMultipleDipoleFixedMagnitudeModel(DipoleModel):
w = 10 ** rng.uniform(self.wexp_min, self.wexp_max, shape)
return numpy.stack([px, py, pz, sx, sy, sz, w], axis=-1)
def markov_chain_monte_carlo_proposal(
self,
dipole: numpy.ndarray,
stdev: pdme.subspace_simulation.DipoleStandardDeviation,
rng_arg: Optional[numpy.random.Generator] = None,
) -> numpy.ndarray:
if rng_arg is None:
rng_to_use = self.rng
else:
rng_to_use = rng_arg
px = dipole[0]
py = dipole[1]
pz = dipole[2]
theta = numpy.arccos(pz / self.pfixed)
phi = numpy.arctan2(py, px)
# need to step phi, theta, rx, ry, rz, w
# then p^\ast is 1/(2 phi_step) and Delta = phi_step(2 * {0, 1} - 1)
delta_phi = stdev.p_phi_step * rng_to_use.uniform(-1, 1)
tentative_phi = phi + delta_phi
# theta
delta_theta = stdev.p_theta_step * rng_to_use.uniform(-1, 1)
r = (numpy.sin(theta + delta_theta)) / (numpy.sin(theta))
if r > rng_to_use.uniform(0, 1):
tentative_theta = theta + delta_theta
else:
tentative_theta = theta
tentative_px = (
self.pfixed * numpy.sin(tentative_theta) * numpy.cos(tentative_phi)
)
tentative_py = (
self.pfixed * numpy.sin(tentative_theta) * numpy.sin(tentative_phi)
)
tentative_pz = self.pfixed * numpy.cos(tentative_theta)
rx = dipole[3]
ry = dipole[4]
rz = dipole[5]
tentative_rx = rx + stdev.rx_step * rng_to_use.uniform(-1, 1)
if tentative_rx < self.xmin or tentative_rx > self.xmax:
tentative_rx = rx
tentative_ry = ry + stdev.ry_step * rng_to_use.uniform(-1, 1)
if tentative_ry < self.ymin or tentative_ry > self.ymax:
tentative_ry = ry
tentative_rz = rz + stdev.rz_step * rng_to_use.uniform(-1, 1)
if tentative_rz < self.zmin or tentative_rz > self.zmax:
tentative_rz = rz
w = dipole[6]
tentative_w = numpy.exp(
numpy.log(w) + (stdev.w_log_step * rng_to_use.uniform(-1, 1))
)
tentative_dip = numpy.array(
[
tentative_px,
tentative_py,
tentative_pz,
tentative_rx,
tentative_ry,
tentative_rz,
tentative_w,
]
)
return tentative_dip

View File

@ -1,183 +0,0 @@
import numpy
import numpy.random
from pdme.model.model import DipoleModel
from pdme.measurement import (
OscillatingDipole,
OscillatingDipoleArrangement,
)
import pdme.subspace_simulation
from typing import Optional
class LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel(DipoleModel):
"""
Model of multiple oscillating dipoles with a fixed magnitude, but free rotation in XY plane. Spaced logarithmically.
Parameters
----------
wexp_min: log-10 lower bound for dipole frequency
wexp_min: log-10 upper bound for dipole frequency
pfixed : float
The fixed dipole magnitude.
n_max : int
The maximum number of dipoles.
prob_occupancy : float
The probability of dipole occupancy
"""
def __init__(
self,
xmin: float,
xmax: float,
ymin: float,
ymax: float,
zmin: float,
zmax: float,
wexp_min: float,
wexp_max: float,
pfixed: float,
n_max: int,
prob_occupancy: float,
) -> None:
self.xmin = xmin
self.xmax = xmax
self.ymin = ymin
self.ymax = ymax
self.zmin = zmin
self.zmax = zmax
self.wexp_min = wexp_min
self.wexp_max = wexp_max
self.pfixed = pfixed
self.rng = numpy.random.default_rng()
self.n_max = n_max
if prob_occupancy >= 1 or prob_occupancy <= 0:
raise ValueError(
f"The probability of a dipole site occupancy must be between 0 and 1, got {prob_occupancy}"
)
self.prob_occupancy = prob_occupancy
def __repr__(self) -> str:
return f"LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel({self.xmin}, {self.xmax}, {self.ymin}, {self.ymax}, {self.zmin}, {self.zmax}, {self.wexp_min}, {self.wexp_max}, {self.pfixed}, {self.n_max}, {self.prob_occupancy})"
def get_dipoles(
self, max_frequency: float, rng_to_use: numpy.random.Generator = None
) -> OscillatingDipoleArrangement:
rng: numpy.random.Generator
if rng_to_use is None:
rng = self.rng
else:
rng = rng_to_use
dipoles = []
n = rng.binomial(self.n_max, self.prob_occupancy)
for i in range(n):
phi = rng.uniform(0, 2 * numpy.pi)
px = self.pfixed * numpy.cos(phi)
py = self.pfixed * numpy.sin(phi)
pz = 0
s_pts = numpy.array(
(
rng.uniform(self.xmin, self.xmax),
rng.uniform(self.ymin, self.ymax),
rng.uniform(self.zmin, self.zmax),
)
)
frequency = 10 ** rng.uniform(self.wexp_min, self.wexp_max)
dipoles.append(
OscillatingDipole(numpy.array([px, py, pz]), s_pts, frequency)
)
return OscillatingDipoleArrangement(dipoles)
def get_monte_carlo_dipole_inputs(
self,
monte_carlo_n: int,
_: float,
rng_to_use: numpy.random.Generator = None,
) -> numpy.ndarray:
rng: numpy.random.Generator
if rng_to_use is None:
rng = self.rng
else:
rng = rng_to_use
shape = (monte_carlo_n, self.n_max)
phi = 2 * numpy.pi * rng.random(shape)
p_mask = rng.binomial(1, self.prob_occupancy, shape)
p_magnitude = self.pfixed * p_mask
px = p_magnitude * numpy.cos(phi)
py = p_magnitude * numpy.sin(phi)
pz = p_magnitude * 0
sx = rng.uniform(self.xmin, self.xmax, shape)
sy = rng.uniform(self.ymin, self.ymax, shape)
sz = rng.uniform(self.zmin, self.zmax, shape)
w = 10 ** rng.uniform(self.wexp_min, self.wexp_max, shape)
return numpy.stack([px, py, pz, sx, sy, sz, w], axis=-1)
def markov_chain_monte_carlo_proposal(
self,
dipole: numpy.ndarray,
stdev: pdme.subspace_simulation.DipoleStandardDeviation,
rng_arg: Optional[numpy.random.Generator] = None,
) -> numpy.ndarray:
if rng_arg is None:
rng_to_use = self.rng
else:
rng_to_use = rng_arg
px = dipole[0]
py = dipole[1]
pz = dipole[2]
phi = numpy.arctan2(py, px)
# need to step phi, rx, ry, rz, w
# then p^\ast is 1/(2 phi_step) and Delta = phi_step(2 * {0, 1} - 1)
delta_phi = stdev.p_phi_step * rng_to_use.uniform(-1, 1)
tentative_phi = phi + delta_phi
tentative_px = self.pfixed * numpy.cos(tentative_phi)
tentative_py = self.pfixed * numpy.sin(tentative_phi)
rx = dipole[3]
ry = dipole[4]
rz = dipole[5]
tentative_rx = rx + stdev.rx_step * rng_to_use.uniform(-1, 1)
if tentative_rx < self.xmin or tentative_rx > self.xmax:
tentative_rx = rx
tentative_ry = ry + stdev.ry_step * rng_to_use.uniform(-1, 1)
if tentative_ry < self.ymin or tentative_ry > self.ymax:
tentative_ry = ry
tentative_rz = rz + stdev.rz_step * rng_to_use.uniform(-1, 1)
if tentative_rz < self.zmin or tentative_rz > self.zmax:
tentative_rz = rz
w = dipole[6]
tentative_w = numpy.exp(
numpy.log(w) + (stdev.w_log_step * rng_to_use.uniform(-1, 1))
)
tentative_dip = numpy.array(
[
tentative_px,
tentative_py,
pz,
tentative_rx,
tentative_ry,
tentative_rz,
tentative_w,
]
)
return tentative_dip

View File

@ -4,8 +4,7 @@ from pdme.measurement import (
OscillatingDipoleArrangement,
)
import logging
import pdme.subspace_simulation
from typing import List, Tuple, Optional
_logger = logging.getLogger(__name__)
@ -33,131 +32,3 @@ class DipoleModel:
For a given DipoleModel, gets a set of dipole collections as a monte_carlo_n x dipole_count x 7 numpy array.
"""
raise NotImplementedError
def markov_chain_monte_carlo_proposal(
self,
dipole: numpy.ndarray,
stdev: pdme.subspace_simulation.DipoleStandardDeviation,
rng_arg: Optional[numpy.random.Generator] = None,
) -> numpy.ndarray:
raise NotImplementedError
def get_mcmc_chain(
self,
seed,
cost_function,
chain_length,
threshold_cost: float,
stdevs: pdme.subspace_simulation.MCMCStandardDeviation,
initial_cost: Optional[float] = None,
rng_arg: Optional[numpy.random.Generator] = None,
) -> List[Tuple[float, numpy.ndarray]]:
"""
performs constrained markov chain monte carlo starting on seed parameter.
The cost function given is used as a constrained to condition the chain;
a new state is only accepted if cost_function(state) < cost_function(previous_state).
The stdevs passed in are the stdevs we're expected to use.
Because we're using this for subspace simulation where our proposal function is not too important, we're in good shape.
Note that for our adaptive stdevs to work, there's an unwritten contract that we sort each dipole in the state by frequency (increasing).
The seed is a list of dipoles, and each chain state is a list of dipoles as well.
initial_cost is a performance guy that lets you pre-populate the initial cost used to define the condition.
Probably premature optimisation.
Returns a chain of [ (cost: float, state: dipole_ndarray ) ] format.
"""
_logger.debug(
f"Starting Markov Chain Monte Carlo with seed: {seed} for chain length {chain_length} and provided stdevs {stdevs}"
)
chain: List[Tuple[float, numpy.ndarray]] = []
if initial_cost is None:
current_cost = cost_function(numpy.array([seed]))
else:
current_cost = initial_cost
current = seed
for i in range(chain_length):
dips = []
for dipole_index, dipole in enumerate(current):
_logger.debug(dipole_index)
_logger.debug(dipole)
stdev = stdevs[dipole_index]
tentative_dip = self.markov_chain_monte_carlo_proposal(
dipole, stdev, rng_arg
)
dips.append(tentative_dip)
dips_array = pdme.subspace_simulation.sort_array_of_dipoles_by_frequency(
dips
)
tentative_cost = cost_function(numpy.array([dips_array]))[0]
if tentative_cost < threshold_cost:
chain.append((numpy.squeeze(tentative_cost).item(), dips_array))
current = dips_array
current_cost = tentative_cost
else:
chain.append((numpy.squeeze(current_cost).item(), current))
return chain
def get_repeat_counting_mcmc_chain(
self,
seed,
cost_function,
chain_length,
threshold_cost: float,
stdevs: pdme.subspace_simulation.MCMCStandardDeviation,
initial_cost: Optional[float] = None,
rng_arg: Optional[numpy.random.Generator] = None,
) -> Tuple[int, List[Tuple[float, numpy.ndarray]]]:
"""
performs constrained markov chain monte carlo starting on seed parameter.
The cost function given is used as a constrained to condition the chain;
a new state is only accepted if cost_function(state) < cost_function(previous_state).
The stdevs passed in are the stdevs we're expected to use.
Because we're using this for subspace simulation where our proposal function is not too important, we're in good shape.
Note that for our adaptive stdevs to work, there's an unwritten contract that we sort each dipole in the state by frequency (increasing).
The seed is a list of dipoles, and each chain state is a list of dipoles as well.
initial_cost is a performance guy that lets you pre-populate the initial cost used to define the condition.
Probably premature optimisation.
Chain has type of [ (cost: float, state: dipole_ndarray ) ] format,
returning (repeat_count, chain) to keep track of number of repeats
"""
_logger.debug(
f"Starting Markov Chain Monte Carlo with seed: {seed} for chain length {chain_length} and provided stdevs {stdevs}"
)
chain: List[Tuple[float, numpy.ndarray]] = []
if initial_cost is None:
current_cost = cost_function(numpy.array([seed]))
else:
current_cost = initial_cost
current = seed
repeat_event_count = 0
for _ in range(chain_length):
dips = []
for dipole_index, dipole in enumerate(current):
_logger.debug(dipole_index)
_logger.debug(dipole)
stdev = stdevs[dipole_index]
tentative_dip = self.markov_chain_monte_carlo_proposal(
dipole, stdev, rng_arg
)
dips.append(tentative_dip)
dips_array = pdme.subspace_simulation.sort_array_of_dipoles_by_frequency(
dips
)
tentative_cost = cost_function(numpy.array([dips_array]))[0]
if tentative_cost < threshold_cost:
chain.append((numpy.squeeze(tentative_cost).item(), dips_array))
current = dips_array
current_cost = tentative_cost
else:
# repeating a sample, increase count
repeat_event_count += 1
chain.append((numpy.squeeze(current_cost).item(), current))
return (repeat_event_count, chain)

View File

@ -1,74 +0,0 @@
from dataclasses import dataclass
from typing import Sequence
import numpy
from pdme.subspace_simulation.mcmc_costs import (
proportional_cost,
proportional_costs_vs_actual_measurement,
)
@dataclass
class DipoleStandardDeviation:
"""
contains the dipole standard deviation to be used in porposals for markov chain monte carlo
"""
p_phi_step: float
p_theta_step: float
rx_step: float
ry_step: float
rz_step: float
w_log_step: float
class MCMCStandardDeviation:
"""
wrapper for multiple standard deviations, allows for flexible length stuff
"""
def __init__(self, stdevs: Sequence[DipoleStandardDeviation]):
self.stdevs = stdevs
if len(stdevs) < 1:
raise ValueError(f"Got stdevs: {stdevs}, must have length > 1")
def __getitem__(self, key):
newkey = key % len(self.stdevs)
return self.stdevs[newkey]
def sort_array_of_dipoles_by_frequency(configuration) -> numpy.ndarray:
"""
Say we have a situation of 2 dipoles, and we've created 8 samples. Then we'll have an (8, 2, 7) numpy array.
For each of the 8 samples, we want the 2 dipoles to be in order of frequency.
This just sorts each sample, the 2x7 array.
Utility function.
"""
return numpy.array(sorted(configuration, key=lambda l: l[6]))
def sort_array_of_dipoleses_by_frequency(configurations) -> numpy.ndarray:
"""
Say we have a situation of 2 dipoles, and we've created 8 samples. Then we'll have an (8, 2, 7) numpy array.
For each of the 8 samples, we want the 2 dipoles to be in order of frequency.
This is the wrapper that sorts everything.
Utility function.
"""
return numpy.array(
[
sort_array_of_dipoles_by_frequency(configuration)
for configuration in configurations
]
)
__all__ = [
"DipoleStandardDeviation",
"MCMCStandardDeviation",
"sort_array_of_dipoles_by_frequency",
"proportional_cost",
"proportional_costs_vs_actual_measurement",
]

View File

@ -1,30 +0,0 @@
import numpy
import numpy.typing
import pdme.util.fast_v_calc
def proportional_cost(a: numpy.ndarray, b: numpy.ndarray) -> numpy.ndarray:
tops = numpy.max(b / a, axis=-1)
bottoms = numpy.max(a / b, axis=-1)
return numpy.maximum(tops, bottoms)
def proportional_costs_vs_actual_measurement(
dot_inputs_array: numpy.ndarray,
actual_measurement_array: numpy.ndarray,
dipoles_to_test: numpy.ndarray,
) -> numpy.ndarray:
vals = pdme.util.fast_v_calc.fast_vs_for_dipoleses(
dot_inputs_array, dipoles_to_test
)
return proportional_cost(actual_measurement_array, vals)
def relative_square_diffs(
approx: numpy.ndarray, target: numpy.ndarray
) -> numpy.ndarray:
# Assume that both approx and target are arrays of length m
# Approx can broadcast if additional indexes to the left
# diffs.shape = [ m ]
diffs = (approx - target) ** 2 / (target**2)
return diffs.sum(axis=-1)

View File

@ -45,7 +45,7 @@ def fast_s_nonlocal(
_logger.debug(f"alphses1: {alphses1}")
_logger.debug(f"alphses2: {alphses2}")
bses = 2 * ws[:, None] / ((numpy.pi * f1s) ** 2 + ws[:, None] ** 2)
bses = (1 / numpy.pi) * (ws[:, None] / (f1s**2 + ws[:, None] ** 2))
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug(f"bses: {bses}")
@ -58,216 +58,43 @@ def fast_s_nonlocal_dipoleses(
"""
No error correction here baby.
"""
# We're going to annotate the indices on this class.
# Let's define some indices:
# A -> index of dipoleses configurations
# measurement_index -> if we have 100 frequencies for example, indexes which one of them it is
# j -> within a particular configuration, indexes dipole j
# If we need to use numbers, let's use A -> 2, j -> 10, measurement_index -> 9 for consistency with
# my other notes
# cart -> {x, y, z} is a cartesian axis
# ps, ss have shape [A, j, cart]
ps = dipoleses[:, :, 0:3]
ss = dipoleses[:, :, 3:6]
# ws shape [A, j]
ws = dipoleses[:, :, 6]
_logger.debug(f"ps: {ps}")
_logger.debug(f"ss: {ss}")
_logger.debug(f"ws: {ws}")
# rs have shape [meas_idx, {}, cart], where the inner index goes away leaving
# [meas, cart]
r1s = dot_pair_inputs[:, 0, 0:3]
r2s = dot_pair_inputs[:, 1, 0:3]
# fs have index [meas_idx], this makes sense
f1s = dot_pair_inputs[:, 0, 3]
f2s = dot_pair_inputs[:, 1, 3]
if (f1s != f2s).all():
raise ValueError(f"Dot pair frequencies are inconsistent: {dot_pair_inputs}")
# r1s have shape [meas, cart], adding the none makes it
# r1s[:, None].shape = [meas, 1, cart]
# ss[:, None, :].shape = [A, 1, j, cart]
# subtracting broadcasts by matching from the right to the left, giving a final shape of
# diffses.shape [A, meas, j, cart]
diffses1 = r1s[:, None] - ss[:, None, :]
diffses2 = r2s[:, None] - ss[:, None, :]
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug(f"diffses1: {diffses1}")
_logger.debug(f"diffses2: {diffses2}")
# norming on the cartesian axis, which is axis 3 as seen above
# norms.shape [A, meas, j]
norms1 = numpy.linalg.norm(diffses1, axis=3) ** 3
norms2 = numpy.linalg.norm(diffses2, axis=3) ** 3
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug(f"norms1: {norms1}")
_logger.debug(f"norms2: {norms2}")
# diffses shape [A, meas, j, cart]
# ps shape [A, j, cart]
# so we're summing over the d axis, the cartesian one.
# final shape of numerator is [A, meas, j]
# denom shape is [A, meas, j]
# final shape stayes [A, meas, j]
alphses1 = numpy.einsum("abcd,acd->abc", diffses1, ps) / norms1
alphses2 = numpy.einsum("abcd,acd->abc", diffses2, ps) / norms2
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug(f"alphses1: {alphses1}")
_logger.debug(f"alphses2: {alphses2}")
# ws shape [A, j], so numerator has shape [A, 1, j]
# f1s shape is [meas], so first term of denom is [meas, 1]
# ws[:, None, :].shape [A, 1, j] so breadcasting the sum in denom gives
# denom.shape [A meas, j]
# so now overall shape is [A, meas, j]
bses = 2 * ws[:, None, :] / ((numpy.pi * f1s[:, None]) ** 2 + ws[:, None, :] ** 2)
bses = (1 / numpy.pi) * (ws[:, None, :] / (f1s[:, None] ** 2 + ws[:, None, :] ** 2))
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug(f"bses: {bses}")
# so our output shape is [A, meas, j]
_logger.debug(f"Raw pair calc: [{alphses1 * alphses2 * bses}]")
return numpy.einsum("...j->...", alphses1 * alphses2 * bses)
def fast_s_spin_qubit_tarucha_nonlocal_dipoleses(
dot_pair_inputs: numpy.ndarray, dipoleses: numpy.ndarray
) -> numpy.ndarray:
"""
No error correction here baby.
"""
# We're going to annotate the indices on this class.
# Let's define some indices:
# A -> index of dipoleses configurations
# j -> within a particular configuration, indexes dipole j
# measurement_index -> if we have 100 frequencies for example, indexes which one of them it is
# If we need to use numbers, let's use A -> 2, j -> 10, measurement_index -> 9 for consistency with
# my other notes
# axes are [dipole_config_idx A, dipole_idx j, {px, py, pz}3]
ps = dipoleses[:, :, 0:3]
# axes are [dipole_config_idx A, dipole_idx j, {sx, sy, sz}3]
ss = dipoleses[:, :, 3:6]
# axes are [dipole_config_idx A, dipole_idx j, w], last axis is just 1
ws = dipoleses[:, :, 6]
_logger.debug(f"ps: {ps}")
_logger.debug(f"ss: {ss}")
_logger.debug(f"ws: {ws}")
# dot_index is either 0 or 1 for dot1 or dot2
# hopefully this adhoc grammar is making sense, with the explicit labelling of the values of the last axis in cartesian space
# axes are [measurement_idx, {dot_index}, {rx, ry, rz}] where the inner {dot_index} is gone
# [measurement_idx, cartesian3]
r1s = dot_pair_inputs[:, 0, 0:3]
r2s = dot_pair_inputs[:, 1, 0:3]
# axes are [measurement_idx]
f1s = dot_pair_inputs[:, 0, 3]
f2s = dot_pair_inputs[:, 1, 3]
if (f1s != f2s).all():
raise ValueError(f"Dot pair frequencies are inconsistent: {dot_pair_inputs}")
# first operation!
# r1s has shape [measurement_idx, rxs]
# None inserts an extra axis so the r1s[:, None] has shape
# [measurement_idx, 1]([rxs]) with the last rxs hidden
#
# ss has shape [ A, j, {sx, sy, sz}3], so second term has shape [A, 1, j]([sxs])
# these broadcast from right to left
# [ measurement_idx, 1, rxs]
# [A, 1, j, sxs]
# resulting in [A, measurement_idx, j, cart3] sxs rxs are both cart3
diffses1 = r1s[:, None] - ss[:, None, :]
diffses2 = r2s[:, None] - ss[:, None, :]
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug(f"diffses1: {diffses1}")
_logger.debug(f"diffses2: {diffses2}")
# norms takes out axis 3, the last one, giving [A, measurement_idx, j]
norms1 = numpy.linalg.norm(diffses1, axis=3)
norms2 = numpy.linalg.norm(diffses2, axis=3)
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug(f"norms1: {norms1}")
_logger.debug(f"norms2: {norms2}")
# _logger.info(f"norms1: {norms1}")
# _logger.info(f"norms1 shape: {norms1.shape}")
#
# diffses1 (A, measurement_idx, j, xs)
# ps: (A, j, px)
# result is (A, measurement_idx, j)
# intermediate_dot_prod = numpy.einsum("abcd,acd->abc", diffses1, ps)
# _logger.info(f"dot product shape: {intermediate_dot_prod.shape}")
# transpose makes it (j, measurement_idx, A)
# transp_intermediate_dot_prod = numpy.transpose(numpy.einsum("abcd,acd->abc", diffses1, ps) / (norms1**3))
# transpose of diffses has shape (xs, j, measurement_idx, A)
# numpy.transpose(diffses1)
# _logger.info(f"dot product shape: {transp_intermediate_dot_prod.shape}")
# inner transpose is (j, measurement_idx, A) * (xs, j, measurement_idx, A)
# next transpose puts it back to (A, measurement_idx, j, xs)
# p_dot_r_times_r_term = 3 * numpy.transpose(numpy.transpose(numpy.einsum("abcd,acd->abc", diffses1, ps) / (norms1**3)) * numpy.transpose(diffses1))
# _logger.info(f"p_dot_r_times_r_term: {p_dot_r_times_r_term.shape}")
# only x axis puts us at (A, measurement_idx, j)
# p_dot_r_times_r_term_x_only = p_dot_r_times_r_term[:, :, :, 0]
# _logger.info(f"p_dot_r_times_r_term_x_only.shape: {p_dot_r_times_r_term_x_only.shape}")
# now to complete the numerator we subtract the ps, which are (A, j, px):
# slicing off the end gives us (A, j), so we newaxis to get (A, 1, j)
# _logger.info(ps[:, numpy.newaxis, :, 0].shape)
alphses1 = (
(
3
* numpy.transpose(
numpy.transpose(
numpy.einsum("abcd,acd->abc", diffses1, ps) / (norms1**2)
)
* numpy.transpose(diffses1)
)[:, :, :, 0]
)
- ps[:, numpy.newaxis, :, 0]
) / (norms1**3)
alphses2 = (
(
3
* numpy.transpose(
numpy.transpose(
numpy.einsum("abcd,acd->abc", diffses2, ps) / (norms2**2)
)
* numpy.transpose(diffses2)
)[:, :, :, 0]
)
- ps[:, numpy.newaxis, :, 0]
) / (norms2**3)
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug(f"alphses1: {alphses1}")
_logger.debug(f"alphses2: {alphses2}")
# ws has shape (A, j), so it becomes (A, 1, j) in numerator with the new axis
# f1s has shape (m), so we get in the denominator (m, 1) + (A, 1, j)
# This becomes (A, m, j)
bses = 2 * ws[:, None, :] / ((numpy.pi * f1s[:, None]) ** 2 + ws[:, None, :] ** 2)
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug(f"bses: {bses}")
# alphas have (A, 1, j), betas have (A, m, j)
# Final result is (A, m, j)
_logger.debug(f"Raw pair calc: [{alphses1 * alphses2 * bses}]")
return numpy.einsum("...j->...", alphses1 * alphses2 * bses)
def signarg(x, **kwargs):
"""
uses numpy.sign to implement Arg for real numbers only. Should return pi for negative inputs, 0 for positive.
Passes through args to numpy.sign
"""
return numpy.pi * (numpy.sign(x, **kwargs) - 1) / (-2)

View File

@ -12,44 +12,27 @@ def fast_vs_for_dipoles(
No error correction here baby.
Expects dot_inputs to be numpy array of [rx, ry, rz, f] entries, so a n by 4 where n is number of measurement points.
"""
# name indexes:
# A: dipole config index
# cart: cartesian index
# m: measurement index
# [A, cart]
ps = dipoles[:, 0:3]
ss = dipoles[:, 3:6]
# [A]
ws = dipoles[:, 6]
_logger.debug(f"ps: {ps}")
_logger.debug(f"ss: {ss}")
_logger.debug(f"ws: {ws}")
# [m, cart]
rs = dot_inputs[:, 0:3]
# [m]
fs = dot_inputs[:, 3]
# [m, cart] - [A, 1, cart]
# [A, m, cart]
diffses = rs - ss[:, None]
_logger.debug(f"diffses: {diffses}")
# [A, m]
norms = numpy.linalg.norm(diffses, axis=2) ** 3
_logger.debug(f"norms: {norms}")
# [A, m, cart] [A, cart] -> [A, m]
ases = (numpy.einsum("...ji, ...i", diffses, ps) / norms) ** 2
_logger.debug(f"ases: {ases}")
# [A, 1], denom [m] + [A, 1] -> [A, m]
# [A, m]
bses = 2 * ws[:, None] / ((numpy.pi * fs) ** 2 + ws[:, None] ** 2)
bses = (1 / numpy.pi) * (ws[:, None] / (fs**2 + ws[:, None] ** 2))
_logger.debug(f"bses: {bses}")
# returns shape [A, m]
return ases * bses
@ -81,170 +64,11 @@ def fast_vs_for_dipoleses(
ases = (numpy.einsum("abcd,acd->abc", diffses, ps) / norms) ** 2
_logger.debug(f"ases: {ases}")
bses = 2 * ws[:, None, :] / ((numpy.pi * fs[:, None]) ** 2 + ws[:, None, :] ** 2)
bses = (1 / numpy.pi) * (ws[:, None, :] / (fs[:, None] ** 2 + ws[:, None, :] ** 2))
_logger.debug(f"bses: {bses}")
return numpy.einsum("...j->...", ases * bses)
def fast_efieldxs_for_dipoles(
dot_inputs: numpy.ndarray, dipoles: numpy.ndarray
) -> numpy.ndarray:
"""
No error correction here baby.
Expects dot_inputs to be numpy array of [rx, ry, rz, f] entries, so a n by 4 where n is number of measurement points.
"""
# name indexes:
# A: dipole config index
# j: dipole index within a config
# cart: cartesian index
# m: measurement index
# Indexes [A, cart]
ps = dipoles[:, 0:3]
ss = dipoles[:, 3:6]
# Indexes [A]
ws = dipoles[:, 6]
# Indexes [m, cart]
rs = dot_inputs[:, 0:3]
# Indexes [m]
fs = dot_inputs[:, 3]
# Indexes [m, cart] - [A, 1, cart]
# Broadcasting from right
# diffses.indexes [A, m, cart]
diffses = rs - ss[:, None, :]
# [A, m, cart][2] = cart
# norms takes out axis 2, the last one, giving [A, m]
norms = numpy.linalg.norm(diffses, axis=2)
# long story but this ends up becoming (A, 1, j)
# Some evidence is looking at ps term, which has shape (A, 1, j, cart=0) becoming (A, 1, j)
# [A, m, cart] einsum [A, cart] explicitly gives [A, m]
dot_products = numpy.einsum("amc,ac->am", diffses, ps) / (norms**2)
# [m, A] * [cart, m, A] -> [cart, m, A], transpose that and you get [A, m, cart]
projections = numpy.transpose(
numpy.transpose(dot_products) * numpy.transpose(diffses)
)
# numerator [A, m, cart] - [A, 1, cart] -> [A, m, cart][:, :, 0] -> [A, m]
alphas = (3 * projections - ps[:, numpy.newaxis])[:, :, 0] / norms**3
# [A, m]
ases = alphas**2
# [A, 1], denom [m] + [A, 1] -> [A, m]
# [A, m]
bses = 2 * ws[:, None] / ((numpy.pi * fs) ** 2 + ws[:, None] ** 2)
# return shape [A, m, j]
return ases * bses
def fast_efieldxs_for_dipoleses(
dot_inputs: numpy.ndarray, dipoleses: numpy.ndarray
) -> numpy.ndarray:
"""
No error correction here baby.
Expects dot_inputs to be numpy array of [rx, ry, rz, f] entries, so a n by 4 where n is number of measurement points.
Dipoleses are expected to be array of arrays of arrays:
list of sets of dipoles which are part of a single arrangement to be added together.
"""
# name indexes:
# A: dipole config index
# j: dipole index within a config
# cart: cartesian index
# m: measurement index
# Indexes [A, j, cart]
ps = dipoleses[:, :, 0:3]
ss = dipoleses[:, :, 3:6]
# Indexes [A, j]
ws = dipoleses[:, :, 6]
# Indexes [m, cart]
rs = dot_inputs[:, 0:3]
# Indexes [m]
fs = dot_inputs[:, 3]
# Indexes [m, 1, cart] - [A, 1, j, cart]
# Broadcasting from right
# diffses.indexes [A, m, j, cart]
diffses = rs[:, None] - ss[:, None, :]
# norms takes out axis 3, the last one, giving [A, m, j]
norms = numpy.linalg.norm(diffses, axis=3)
# long story but this ends up becoming (A, 1, j)
# Some evidence is looking at ps term, which has shape (A, 1, j, cart=0) becoming (A, 1, j)
alphas = (
(
3
* numpy.transpose(
numpy.transpose(
numpy.einsum("abcd,acd->abc", diffses, ps) / (norms**2)
)
* numpy.transpose(diffses)
)[:, :, :, 0]
)
- ps[:, numpy.newaxis, :, 0]
) / (norms**3)
ases = alphas**2
# bses.shape [A, m, j)]
bses = 2 * ws[:, None, :] / ((numpy.pi * fs[:, None]) ** 2 + ws[:, None, :] ** 2)
# return shape [A, m, j]
return numpy.einsum("...j->...", ases * bses)
def fast_vs_for_asymmetric_dipoleses(
dot_inputs: numpy.ndarray, dipoleses: numpy.ndarray, temp: numpy.ndarray
) -> numpy.ndarray:
"""
No error correction here baby.
Expects dot_inputs to be numpy array of [rx, ry, rz, f] entries, so a n by 4 where n is number of measurement points.
Dipoleses are expected to be array of arrays of arrays:
list of sets of dipoles which are part of a single arrangement to be added together.
Within each dipole, the expected format is [px, py, pz, sx, sy, sz, e1, e2, w]
The passed in w is expected to be half the actual. This is bad, but here for historical reasons to be changed later.
"""
raw_ps = dipoleses[:, :, 0:3]
ss = dipoleses[:, :, 3:6]
e1s = dipoleses[:, :, 6]
e2s = dipoleses[:, :, 7]
raw_ws = dipoleses[:, :, 8]
rs = dot_inputs[:, 0:3]
fs = dot_inputs[:, 3]
diffses = rs[:, None] - ss[:, None, :]
_logger.warning(
"This method is very likely to be broken, and should not be used without more thought"
)
w1s = numpy.exp(-e1s / temp) * raw_ws
w2s = numpy.exp(-e2s / temp) * raw_ws
mag_prefactor = 4 * ((w1s * w2s) / ((w1s + w2s) ** 2))
ws = w1s + w2s
# some annoying broadcast thing here?
ps = (raw_ps.T * mag_prefactor.T).T
norms = numpy.linalg.norm(diffses, axis=3) ** 3
ases = (numpy.einsum("abcd,acd->abc", diffses, ps) / norms) ** 2
bses = ws[:, None, :] / ((numpy.pi * fs[:, None]) ** 2 + ws[:, None, :] ** 2)
return numpy.einsum("...j->...", ases * bses)
def between(a: numpy.ndarray, low: numpy.ndarray, high: numpy.ndarray) -> numpy.ndarray:
"""
Intended specifically for the case where a is a list of arrays, and each array must be between the single array low and high, but without error checking.

444
poetry.lock generated
View File

@ -20,6 +20,28 @@ six = "*"
[package.extras]
test = ["astroid", "pytest"]
[[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 = "backcall"
version = "0.2.0"
@ -69,24 +91,16 @@ category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "colored"
version = "1.4.4"
description = "Simple library for color and formatting to terminal"
category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "coverage"
version = "7.2.7"
version = "6.4"
description = "Code coverage measurement for Python"
category = "dev"
optional = false
python-versions = ">=3.7"
[package.dependencies]
tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
tomli = {version = "*", optional = true, markers = "python_version < \"3.11\" and extra == \"toml\""}
[package.extras]
toml = ["tomli"]
@ -99,17 +113,6 @@ category = "dev"
optional = false
python-versions = ">=3.5"
[[package]]
name = "exceptiongroup"
version = "1.1.2"
description = "Backport of PEP 654 (exception groups)"
category = "dev"
optional = false
python-versions = ">=3.7"
[package.extras]
test = ["pytest (>=6)"]
[[package]]
name = "executing"
version = "0.8.3"
@ -210,7 +213,7 @@ python-versions = "*"
[[package]]
name = "mypy"
version = "0.961"
version = "0.960"
description = "Optional static typing for Python"
category = "dev"
optional = false
@ -346,6 +349,14 @@ python-versions = "*"
[package.extras]
tests = ["pytest"]
[[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 = "pycodestyle"
version = "2.8.0"
@ -383,30 +394,32 @@ diagrams = ["jinja2", "railroad-diagrams"]
[[package]]
name = "pytest"
version = "7.4.0"
version = "6.2.5"
description = "pytest: simple powerful testing with Python"
category = "dev"
optional = false
python-versions = ">=3.7"
python-versions = ">=3.6"
[package.dependencies]
atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
attrs = ">=19.2.0"
colorama = {version = "*", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
iniconfig = "*"
packaging = "*"
pluggy = ">=0.12,<2.0"
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
py = ">=1.8.2"
toml = "*"
[package.extras]
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
[[package]]
name = "pytest-cov"
version = "4.1.0"
version = "3.0.0"
description = "Pytest plugin for measuring coverage."
category = "dev"
optional = false
python-versions = ">=3.7"
python-versions = ">=3.6"
[package.dependencies]
coverage = {version = ">=5.2.1", extras = ["toml"]}
@ -417,19 +430,14 @@ testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtuale
[[package]]
name = "scipy"
version = "1.10.0"
description = "Fundamental algorithms for scientific computing in Python"
version = "1.8.0"
description = "SciPy: Scientific Library for Python"
category = "main"
optional = false
python-versions = "<3.12,>=3.8"
python-versions = ">=3.8,<3.11"
[package.dependencies]
numpy = ">=1.19.5,<1.27.0"
[package.extras]
test = ["pytest", "pytest-cov", "pytest-timeout", "pytest-xdist", "asv", "mpmath", "gmpy2", "threadpoolctl", "scikit-umfpack", "pooch"]
doc = ["sphinx (!=4.1.0)", "pydata-sphinx-theme (==0.9.0)", "sphinx-design (>=0.2.0)", "matplotlib (>2)", "numpydoc"]
dev = ["mypy", "typing-extensions", "pycodestyle", "flake8", "rich-click", "click", "doit (>=0.36.0)", "pydevtool"]
numpy = ">=1.17.3,<1.25.0"
[[package]]
name = "six"
@ -456,16 +464,12 @@ pure-eval = "*"
tests = ["pytest", "typeguard", "pygments", "littleutils", "cython"]
[[package]]
name = "syrupy"
version = "4.0.8"
description = "Pytest Snapshot Test Utility"
name = "toml"
version = "0.10.2"
description = "Python Library for Tom's Obvious, Minimal Language"
category = "dev"
optional = false
python-versions = ">=3.8.1,<4"
[package.dependencies]
colored = ">=1.3.92,<2.0.0"
pytest = ">=7.0.0,<8.0.0"
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
name = "tomli"
@ -504,51 +508,307 @@ python-versions = "*"
[metadata]
lock-version = "1.1"
python-versions = ">=3.8.1,<3.10"
content-hash = "b5275c33449e8f85acbf9c0f6dfe1ec4e7296adfa16360d782b33534e1223638"
python-versions = "^3.8,<3.10"
content-hash = "1a1434c22079e848e65d22d2a8afae5d76bec6cb99d43d7acf7e2fa18dcb9e4f"
[metadata.files]
appnope = []
asttokens = []
backcall = []
black = []
click = []
colorama = []
colored = []
coverage = []
decorator = []
exceptiongroup = []
executing = []
flake8 = []
iniconfig = []
ipython = []
jedi = []
matplotlib-inline = []
mccabe = []
mypy = []
mypy-extensions = []
numpy = []
packaging = []
parso = []
pathspec = []
pexpect = []
pickleshare = []
platformdirs = []
pluggy = []
prompt-toolkit = []
ptyprocess = []
pure-eval = []
pycodestyle = []
pyflakes = []
pygments = []
pyparsing = []
pytest = []
pytest-cov = []
scipy = []
six = []
stack-data = []
syrupy = []
tomli = []
traitlets = []
typing-extensions = []
wcwidth = []
appnope = [
{file = "appnope-0.1.2-py2.py3-none-any.whl", hash = "sha256:93aa393e9d6c54c5cd570ccadd8edad61ea0c4b9ea7a01409020c9aa019eb442"},
{file = "appnope-0.1.2.tar.gz", hash = "sha256:dd83cd4b5b460958838f6eb3000c660b1f9caf2a5b1de4264e941512f603258a"},
]
asttokens = [
{file = "asttokens-2.0.5-py2.py3-none-any.whl", hash = "sha256:0844691e88552595a6f4a4281a9f7f79b8dd45ca4ccea82e5e05b4bbdb76705c"},
{file = "asttokens-2.0.5.tar.gz", hash = "sha256:9a54c114f02c7a9480d56550932546a3f1fe71d8a02f1bc7ccd0ee3ee35cf4d5"},
]
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"},
]
backcall = [
{file = "backcall-0.2.0-py2.py3-none-any.whl", hash = "sha256:fbbce6a29f263178a1f7915c1940bde0ec2b2a967566fe1c65c1dfb7422bd255"},
{file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"},
]
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.2-py3-none-any.whl", hash = "sha256:24e1a4a9ec5bf6299411369b208c1df2188d9eb8d916302fe6bf03faed227f1e"},
{file = "click-8.1.2.tar.gz", hash = "sha256:479707fe14d9ec9a0757618b7a100a0ae4c4e236fac5b7f80ca68028141a1a72"},
]
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.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50ed480b798febce113709846b11f5d5ed1e529c88d8ae92f707806c50297abf"},
{file = "coverage-6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:26f8f92699756cb7af2b30720de0c5bb8d028e923a95b6d0c891088025a1ac8f"},
{file = "coverage-6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60c2147921da7f4d2d04f570e1838db32b95c5509d248f3fe6417e91437eaf41"},
{file = "coverage-6.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:750e13834b597eeb8ae6e72aa58d1d831b96beec5ad1d04479ae3772373a8088"},
{file = "coverage-6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af5b9ee0fc146e907aa0f5fb858c3b3da9199d78b7bb2c9973d95550bd40f701"},
{file = "coverage-6.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a022394996419142b33a0cf7274cb444c01d2bb123727c4bb0b9acabcb515dea"},
{file = "coverage-6.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5a78cf2c43b13aa6b56003707c5203f28585944c277c1f3f109c7b041b16bd39"},
{file = "coverage-6.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9229d074e097f21dfe0643d9d0140ee7433814b3f0fc3706b4abffd1e3038632"},
{file = "coverage-6.4-cp310-cp310-win32.whl", hash = "sha256:fb45fe08e1abc64eb836d187b20a59172053999823f7f6ef4f18a819c44ba16f"},
{file = "coverage-6.4-cp310-cp310-win_amd64.whl", hash = "sha256:3cfd07c5889ddb96a401449109a8b97a165be9d67077df6802f59708bfb07720"},
{file = "coverage-6.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:03014a74023abaf5a591eeeaf1ac66a73d54eba178ff4cb1fa0c0a44aae70383"},
{file = "coverage-6.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c82f2cd69c71698152e943f4a5a6b83a3ab1db73b88f6e769fabc86074c3b08"},
{file = "coverage-6.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b546cf2b1974ddc2cb222a109b37c6ed1778b9be7e6b0c0bc0cf0438d9e45a6"},
{file = "coverage-6.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc173f1ce9ffb16b299f51c9ce53f66a62f4d975abe5640e976904066f3c835d"},
{file = "coverage-6.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c53ad261dfc8695062fc8811ac7c162bd6096a05a19f26097f411bdf5747aee7"},
{file = "coverage-6.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:eef5292b60b6de753d6e7f2d128d5841c7915fb1e3321c3a1fe6acfe76c38052"},
{file = "coverage-6.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:543e172ce4c0de533fa892034cce260467b213c0ea8e39da2f65f9a477425211"},
{file = "coverage-6.4-cp37-cp37m-win32.whl", hash = "sha256:00c8544510f3c98476bbd58201ac2b150ffbcce46a8c3e4fb89ebf01998f806a"},
{file = "coverage-6.4-cp37-cp37m-win_amd64.whl", hash = "sha256:b84ab65444dcc68d761e95d4d70f3cfd347ceca5a029f2ffec37d4f124f61311"},
{file = "coverage-6.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d548edacbf16a8276af13063a2b0669d58bbcfca7c55a255f84aac2870786a61"},
{file = "coverage-6.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:033ebec282793bd9eb988d0271c211e58442c31077976c19c442e24d827d356f"},
{file = "coverage-6.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:742fb8b43835078dd7496c3c25a1ec8d15351df49fb0037bffb4754291ef30ce"},
{file = "coverage-6.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d55fae115ef9f67934e9f1103c9ba826b4c690e4c5bcf94482b8b2398311bf9c"},
{file = "coverage-6.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cd698341626f3c77784858427bad0cdd54a713115b423d22ac83a28303d1d95"},
{file = "coverage-6.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:62d382f7d77eeeaff14b30516b17bcbe80f645f5cf02bb755baac376591c653c"},
{file = "coverage-6.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:016d7f5cf1c8c84f533a3c1f8f36126fbe00b2ec0ccca47cc5731c3723d327c6"},
{file = "coverage-6.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:69432946f154c6add0e9ede03cc43b96e2ef2733110a77444823c053b1ff5166"},
{file = "coverage-6.4-cp38-cp38-win32.whl", hash = "sha256:83bd142cdec5e4a5c4ca1d4ff6fa807d28460f9db919f9f6a31babaaa8b88426"},
{file = "coverage-6.4-cp38-cp38-win_amd64.whl", hash = "sha256:4002f9e8c1f286e986fe96ec58742b93484195defc01d5cc7809b8f7acb5ece3"},
{file = "coverage-6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e4f52c272fdc82e7c65ff3f17a7179bc5f710ebc8ce8a5cadac81215e8326740"},
{file = "coverage-6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b5578efe4038be02d76c344007b13119b2b20acd009a88dde8adec2de4f630b5"},
{file = "coverage-6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8099ea680201c2221f8468c372198ceba9338a5fec0e940111962b03b3f716a"},
{file = "coverage-6.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a00441f5ea4504f5abbc047589d09e0dc33eb447dc45a1a527c8b74bfdd32c65"},
{file = "coverage-6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e76bd16f0e31bc2b07e0fb1379551fcd40daf8cdf7e24f31a29e442878a827c"},
{file = "coverage-6.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8d2e80dd3438e93b19e1223a9850fa65425e77f2607a364b6fd134fcd52dc9df"},
{file = "coverage-6.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:341e9c2008c481c5c72d0e0dbf64980a4b2238631a7f9780b0fe2e95755fb018"},
{file = "coverage-6.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:21e6686a95025927775ac501e74f5940cdf6fe052292f3a3f7349b0abae6d00f"},
{file = "coverage-6.4-cp39-cp39-win32.whl", hash = "sha256:968ed5407f9460bd5a591cefd1388cc00a8f5099de9e76234655ae48cfdbe2c3"},
{file = "coverage-6.4-cp39-cp39-win_amd64.whl", hash = "sha256:e35217031e4b534b09f9b9a5841b9344a30a6357627761d4218818b865d45055"},
{file = "coverage-6.4-pp36.pp37.pp38-none-any.whl", hash = "sha256:e637ae0b7b481905358624ef2e81d7fb0b1af55f5ff99f9ba05442a444b11e45"},
{file = "coverage-6.4.tar.gz", hash = "sha256:727dafd7f67a6e1cad808dc884bd9c5a2f6ef1f8f6d2f22b37b96cb0080d4f49"},
]
decorator = [
{file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"},
{file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"},
]
executing = [
{file = "executing-0.8.3-py2.py3-none-any.whl", hash = "sha256:d1eef132db1b83649a3905ca6dd8897f71ac6f8cac79a7e58a1a09cf137546c9"},
{file = "executing-0.8.3.tar.gz", hash = "sha256:c6554e21c6b060590a6d3be4b82fb78f8f0194d809de5ea7df1c093763311501"},
]
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"},
]
ipython = [
{file = "ipython-8.2.0-py3-none-any.whl", hash = "sha256:1b672bfd7a48d87ab203d9af8727a3b0174a4566b4091e9447c22fb63ea32857"},
{file = "ipython-8.2.0.tar.gz", hash = "sha256:70e5eb132cac594a34b5f799bd252589009905f05104728aea6a403ec2519dc1"},
]
jedi = [
{file = "jedi-0.18.1-py2.py3-none-any.whl", hash = "sha256:637c9635fcf47945ceb91cd7f320234a7be540ded6f3e99a50cb6febdfd1ba8d"},
{file = "jedi-0.18.1.tar.gz", hash = "sha256:74137626a64a99c8eb6ae5832d99b3bdd7d29a3850fe2aa80a4126b2a7d949ab"},
]
matplotlib-inline = [
{file = "matplotlib-inline-0.1.3.tar.gz", hash = "sha256:a04bfba22e0d1395479f866853ec1ee28eea1485c1d69a6faf00dc3e24ff34ee"},
{file = "matplotlib_inline-0.1.3-py3-none-any.whl", hash = "sha256:aed605ba3b72462d64d475a21a9296f400a19c4f74a31b59103d2a99ffd5aa5c"},
]
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.960-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3a3e525cd76c2c4f90f1449fd034ba21fcca68050ff7c8397bb7dd25dd8b8248"},
{file = "mypy-0.960-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7a76dc4f91e92db119b1be293892df8379b08fd31795bb44e0ff84256d34c251"},
{file = "mypy-0.960-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffdad80a92c100d1b0fe3d3cf1a4724136029a29afe8566404c0146747114382"},
{file = "mypy-0.960-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7d390248ec07fa344b9f365e6ed9d205bd0205e485c555bed37c4235c868e9d5"},
{file = "mypy-0.960-cp310-cp310-win_amd64.whl", hash = "sha256:925aa84369a07846b7f3b8556ccade1f371aa554f2bd4fb31cb97a24b73b036e"},
{file = "mypy-0.960-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:239d6b2242d6c7f5822163ee082ef7a28ee02e7ac86c35593ef923796826a385"},
{file = "mypy-0.960-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f1ba54d440d4feee49d8768ea952137316d454b15301c44403db3f2cb51af024"},
{file = "mypy-0.960-cp36-cp36m-win_amd64.whl", hash = "sha256:cb7752b24528c118a7403ee955b6a578bfcf5879d5ee91790667c8ea511d2085"},
{file = "mypy-0.960-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:826a2917c275e2ee05b7c7b736c1e6549a35b7ea5a198ca457f8c2ebea2cbecf"},
{file = "mypy-0.960-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3eabcbd2525f295da322dff8175258f3fc4c3eb53f6d1929644ef4d99b92e72d"},
{file = "mypy-0.960-cp37-cp37m-win_amd64.whl", hash = "sha256:f47322796c412271f5aea48381a528a613f33e0a115452d03ae35d673e6064f8"},
{file = "mypy-0.960-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2c7f8bb9619290836a4e167e2ef1f2cf14d70e0bc36c04441e41487456561409"},
{file = "mypy-0.960-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:fbfb873cf2b8d8c3c513367febde932e061a5f73f762896826ba06391d932b2a"},
{file = "mypy-0.960-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cc537885891382e08129d9862553b3d00d4be3eb15b8cae9e2466452f52b0117"},
{file = "mypy-0.960-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:481f98c6b24383188c928f33dd2f0776690807e12e9989dd0419edd5c74aa53b"},
{file = "mypy-0.960-cp38-cp38-win_amd64.whl", hash = "sha256:29dc94d9215c3eb80ac3c2ad29d0c22628accfb060348fd23d73abe3ace6c10d"},
{file = "mypy-0.960-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:33d53a232bb79057f33332dbbb6393e68acbcb776d2f571ba4b1d50a2c8ba873"},
{file = "mypy-0.960-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8d645e9e7f7a5da3ec3bbcc314ebb9bb22c7ce39e70367830eb3c08d0140b9ce"},
{file = "mypy-0.960-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:85cf2b14d32b61db24ade8ac9ae7691bdfc572a403e3cb8537da936e74713275"},
{file = "mypy-0.960-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a85a20b43fa69efc0b955eba1db435e2ffecb1ca695fe359768e0503b91ea89f"},
{file = "mypy-0.960-cp39-cp39-win_amd64.whl", hash = "sha256:0ebfb3f414204b98c06791af37a3a96772203da60636e2897408517fcfeee7a8"},
{file = "mypy-0.960-py3-none-any.whl", hash = "sha256:bfd4f6536bd384c27c392a8b8f790fd0ed5c0cf2f63fc2fed7bce56751d53026"},
{file = "mypy-0.960.tar.gz", hash = "sha256:d4fccf04c1acf750babd74252e0f2db6bd2ac3aa8fe960797d9f3ef41cf2bfd4"},
]
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"},
]
parso = [
{file = "parso-0.8.3-py2.py3-none-any.whl", hash = "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75"},
{file = "parso-0.8.3.tar.gz", hash = "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0"},
]
pathspec = [
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
]
pexpect = [
{file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"},
{file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"},
]
pickleshare = [
{file = "pickleshare-0.7.5-py2.py3-none-any.whl", hash = "sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"},
{file = "pickleshare-0.7.5.tar.gz", hash = "sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca"},
]
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"},
]
prompt-toolkit = [
{file = "prompt_toolkit-3.0.28-py3-none-any.whl", hash = "sha256:30129d870dcb0b3b6a53efdc9d0a83ea96162ffd28ffe077e94215b233dc670c"},
{file = "prompt_toolkit-3.0.28.tar.gz", hash = "sha256:9f1cd16b1e86c2968f2519d7fb31dd9d669916f515612c269d14e9ed52b51650"},
]
ptyprocess = [
{file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"},
{file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"},
]
pure-eval = [
{file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"},
{file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"},
]
py = [
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
]
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"},
]
pygments = [
{file = "Pygments-2.11.2-py3-none-any.whl", hash = "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65"},
{file = "Pygments-2.11.2.tar.gz", hash = "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a"},
]
pyparsing = [
{file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"},
{file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"},
]
pytest = [
{file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"},
{file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"},
]
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"},
]
six = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
]
stack-data = [
{file = "stack_data-0.2.0-py3-none-any.whl", hash = "sha256:999762f9c3132308789affa03e9271bbbe947bf78311851f4d485d8402ed858e"},
{file = "stack_data-0.2.0.tar.gz", hash = "sha256:45692d41bd633a9503a5195552df22b583caf16f0b27c4e58c98d88c8b648e12"},
]
toml = [
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
]
tomli = [
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
]
traitlets = [
{file = "traitlets-5.1.1-py3-none-any.whl", hash = "sha256:2d313cc50a42cd6c277e7d7dc8d4d7fedd06a2c215f78766ae7b1a66277e0033"},
{file = "traitlets-5.1.1.tar.gz", hash = "sha256:059f456c5a7c1c82b98c2e8c799f39c9b8128f6d0d46941ee118daace9eb70c7"},
]
typing-extensions = [
{file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"},
{file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"},
]
wcwidth = [
{file = "wcwidth-0.2.5-py2.py3-none-any.whl", hash = "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784"},
{file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
]

View File

@ -1,35 +1,32 @@
[tool.poetry]
name = "pdme"
version = "1.5.0"
version = "0.8.5"
description = "Python dipole model evaluator"
authors = ["Deepak <dmallubhotla+github@gmail.com>"]
license = "GPL-3.0-only"
readme = "README.md"
[tool.poetry.dependencies]
python = ">=3.8.1,<3.10"
python = "^3.8,<3.10"
numpy = "^1.22.3"
scipy = "~1.10"
scipy = "~1.8"
[tool.poetry.dev-dependencies]
pytest = ">=6"
flake8 = "^4.0.0"
pytest-cov = "^4.1.0"
mypy = "^0.961"
pytest-cov = "^3.0.0"
mypy = "^0.960"
ipython = "^8.2.0"
black = "^22.3.0"
syrupy = "^4.0.8"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--junitxml pytest.xml --cov pdme --cov-report=xml:coverage.xml --cov-fail-under=50 --cov-report=html"
junit_family = "xunit1"
log_format = "%(asctime)s | %(levelname)s | %(pathname)s:%(lineno)d | %(message)s"
log_level = "WARNING"
[tool.mypy]
plugins = "numpy.typing.mypy_plugin"

View File

@ -1,4 +1,4 @@
const pattern = /(\[tool\.poetry\]\nname = "pdme"\nversion = ")(?<vers>\d+\.\d+\.\d+)(")/mg;
const pattern = /(\[tool\.poetry\]\nname = "pdme"\nversion = ")(?<vers>\d+\.\d+\.\d)(")/mg;
module.exports.readVersion = function (contents) {
const result = pattern.exec(contents);

View File

@ -1,81 +0,0 @@
# serializer version: 1
# name: test_multiple_electric_field_alphas
list([
list([
0.009579434215333742,
0.007714411624737791,
0.0035604976729559034,
]),
list([
0.005036717012002481,
0.006259221141129298,
-0.009682232702684382,
]),
list([
0.01503516326014651,
0.012028130608117207,
0.009021097956087907,
]),
list([
0.0033871215792458027,
0.0038182097802407235,
-0.005604146612933966,
]),
list([
0.007409666906433089,
0.006778734778841714,
0.003467602973242188,
]),
list([
0.004730939083250055,
0.0046546336141653774,
-0.011766303332857395,
]),
list([
-0.010766266772985707,
-0.012631289363581657,
-0.010851040527103707,
]),
list([
-0.008410828408392494,
-0.020391368873835285,
0.009877833363344673,
]),
list([
-0.015035163260146511,
-0.018042195912175815,
-0.021049228564205113,
]),
list([
-0.005850482727788205,
-0.012193637685284892,
0.0054809785555068454,
]),
list([
-0.007682229585552562,
-0.010584517372472879,
-0.009352937859414517,
]),
list([
-0.009767100042838822,
-0.020831393060117175,
0.014024945217763873,
]),
])
# ---
# name: test_multiple_electric_potential_alphas
list([
0.05035560994609065,
-0.03369221379873504,
0.07216878364870323,
-0.024633611485424027,
0.04496779459769236,
-0.03108684810509794,
-0.08019597139562586,
0.08293468011996319,
-0.10825317547305485,
0.060044427995721066,
-0.06935710692186449,
0.08733923991432278,
])
# ---

View File

@ -1,102 +0,0 @@
import pdme.calculations
import pytest
import numpy
import numpy.testing
# generated in mathematica to compare here
beta_test_data = [
[-2, -2, 0.8072976151],
[-1, -2, 0.008105366193],
[0, -2, 0.00008105691406],
[1, -2, 8.105694659e-7],
[2, -2, 8.105694691e-9],
[-2, -1, 5.768008783],
[-1, -1, 0.08072976151],
[0, -1, 0.0008105366193],
[1, -1, 8.105691406e-6],
[2, -1, 8.105694659e-8],
[-2, 0, 1.951840272],
[-1, 0, 0.5768008783],
[0, 0, 0.008072976151],
[1, 0, 0.00008105366193],
[2, 0, 8.105691406e-7],
[-2, 1, 0.1999506642],
[-1, 1, 0.1951840272],
[0, 1, 0.05768008783],
[1, 1, 0.0008072976151],
[2, 1, 8.105366193e-6],
[-2, 2, 0.01999995065],
[-1, 2, 0.01999506642],
[0, 2, 0.01951840272],
[1, 2, 0.005768008783],
[2, 2, 0.00008072976151],
]
@pytest.mark.parametrize("f, w, expected", beta_test_data)
def test_calculations_beta_func(f, w, expected):
# there's nothing special about the 5 * 10^ f and 10^w passing in logs
# this was just to get a variety of orders of magnitude in results.
actual = pdme.calculations.telegraph_beta(5 * 10**f, 10**w)
numpy.testing.assert_allclose(actual, expected, atol=0, rtol=1e-8)
def test_multiple_electric_potential_alphas(snapshot):
"""
Manually compare these with mathematica stuff because manually including a list is a bit annoying.
Basically just visually compare the snapshot values to make sure they're actually correct.
"""
dipole_ps = [
numpy.array([1, 2, 3]),
numpy.array([-4, -3, -2]),
]
dipole_ss = [
numpy.array([0, 0, 1]),
numpy.array([1, 1, 1]),
numpy.array([0, -0.5, 0.5]),
]
test_rs = [
numpy.array([5, 5, 5]),
numpy.array([-4, -6, 2]),
]
actuals = [
pdme.calculations.electric_potential(p, s, r)
for p in dipole_ps
for s in dipole_ss
for r in test_rs
]
assert actuals == snapshot
def test_multiple_electric_field_alphas(snapshot):
"""
Manually compare these with mathematica stuff because manually including a list is a bit annoying.
Basically just visually compare the snapshot values to make sure they're actually correct.
"""
dipole_ps = [
numpy.array([1, 2, 3]),
numpy.array([-4, -3, -2]),
]
dipole_ss = [
numpy.array([0, 0, 1]),
numpy.array([1, 1, 1]),
numpy.array([0, -0.5, 0.5]),
]
test_rs = [
numpy.array([5, 5, 5]),
numpy.array([-4, -6, 2]),
]
actuals = [
pdme.calculations.electric_field(p, s, r).tolist()
for p in dipole_ps
for s in dipole_ss
for r in test_rs
]
assert actuals == snapshot

View File

@ -2,30 +2,23 @@ import numpy
import pdme.measurement
def test_static_dipole_electric_potential():
d1 = pdme.measurement.OscillatingDipole(
numpy.array((1, 2, 3)), numpy.array([4, 5, 6]), 7
)
d2 = pdme.measurement.OscillatingDipole(
numpy.array([2, 5, 3]), numpy.array([4, -5, -6]), 2
)
def test_static_dipole():
d1 = pdme.measurement.OscillatingDipole((1, 2, 3), (4, 5, 6), 7)
d2 = pdme.measurement.OscillatingDipole((2, 5, 3), (4, -5, -6), 2)
dipoles = pdme.measurement.OscillatingDipoleArrangement([d1, d2])
dot_position1 = numpy.array([-1, -1, -1])
dot_position1 = (-1, -1, -1)
dot_frequency1 = 11
expected_v1 = 0.00001221710876727626
expected_v2 = 7.257229625870065e-6
expected_v1 = 0.00001421963287022476
expected_v2 = 0.00001107180225755457
numpy.testing.assert_allclose(
d1.s_electric_potential_at_position(dot_position1, dot_frequency1),
d1.s_at_position(dot_position1, dot_frequency1),
expected_v1,
err_msg="Voltage at dot isn't as expected.",
)
dot_measurements = dipoles.get_potential_dot_measurements(
[(dot_position1, dot_frequency1)]
)
dot_measurements = dipoles.get_dot_measurements([(dot_position1, dot_frequency1)])
assert len(dot_measurements) == 1, "Should have only had one dot measurement."
measurement = dot_measurements[0]
numpy.testing.assert_allclose(
@ -45,57 +38,24 @@ def test_static_dipole_electric_potential():
)
def test_static_dipole_electric_field_x():
d1 = pdme.measurement.OscillatingDipole(
numpy.array((1, 2, 3)), numpy.array([4, 5, 6]), 7
)
d2 = pdme.measurement.OscillatingDipole(
numpy.array([2, 5, 3]), numpy.array([4, -5, -6]), 2
)
# dipoles = pdme.measurement.OscillatingDipoleArrangement([d1, d2])
dot_position1 = numpy.array([-1, -1, -1])
dot_frequency1 = 11
# these should be true for electric field
expected_v1 = 1.479556451978925e-7
expected_v2 = 6.852024308908262e-7
numpy.testing.assert_allclose(
d1.s_electric_fieldx_at_position(dot_position1, dot_frequency1),
expected_v1,
err_msg="Fieldx noise at dot isn't as expected.",
)
numpy.testing.assert_allclose(
d2.s_electric_fieldx_at_position(dot_position1, dot_frequency1),
expected_v2,
err_msg="Fieldx at dot isn't as expected.",
)
def test_dipole_dot_pair():
d1 = pdme.measurement.OscillatingDipole(
numpy.array([1, 2, 3]), numpy.array([4, 5, 6]), 7
)
d1 = pdme.measurement.OscillatingDipole((1, 2, 3), (4, 5, 6), 7)
dipoles = pdme.measurement.OscillatingDipoleArrangement([d1])
dot_position1 = numpy.array([-1, -1, -1])
dot_position2 = numpy.array([1, 2, 3])
dot_position1 = (-1, -1, -1)
dot_position2 = (1, 2, 3)
dot_frequency = 8
expected_sij = 0.00008692058236162933
expected_sij = 0.000083328037100902801698
numpy.testing.assert_allclose(
d1.s_electric_potential_for_dot_pair(
dot_position1, dot_position2, dot_frequency
),
d1.s_for_dot_pair(dot_position1, dot_position2, dot_frequency),
expected_sij,
err_msg="Sij for dot pair isn't as expected.",
)
numpy.testing.assert_allclose(
[
m.v
for m in dipoles.get_potential_dot_pair_measurements(
for m in dipoles.get_dot_pair_measurements(
[(dot_position1, dot_position2, dot_frequency)]
)
],
@ -105,17 +65,15 @@ def test_dipole_dot_pair():
def test_range_pairs():
d1 = pdme.measurement.OscillatingDipole(
numpy.array([1, 2, 3]), numpy.array([4, 5, 6]), 7
)
d1 = pdme.measurement.OscillatingDipole((1, 2, 3), (4, 5, 6), 7)
dipoles = pdme.measurement.OscillatingDipoleArrangement([d1])
dot_position1 = numpy.array([-1, -1, -1])
dot_position2 = numpy.array([1, 2, 3])
dot_position1 = (-1, -1, -1)
dot_position2 = (1, 2, 3)
dot_frequency = 8
expected_sij = 0.00008692058236162933
expected_sij = 0.000083328037100902801698
actuals = dipoles.get_percent_range_potential_dot_pair_measurements(
actuals = dipoles.get_percent_range_dot_pair_measurements(
[(dot_position1, dot_position2, dot_frequency)], 0.5, 1.5
)
assert len(actuals) == 1, "should have only been one pair"
@ -128,26 +86,22 @@ def test_range_pairs():
def test_range_dipole_measurements():
d1 = pdme.measurement.OscillatingDipole(
numpy.array([1, 2, 3]), numpy.array([4, 5, 6]), 7
)
d2 = pdme.measurement.OscillatingDipole(
numpy.array([2, 5, 3]), numpy.array([4, -5, -6]), 2
)
d1 = pdme.measurement.OscillatingDipole((1, 2, 3), (4, 5, 6), 7)
d2 = pdme.measurement.OscillatingDipole((2, 5, 3), (4, -5, -6), 2)
dipoles = pdme.measurement.OscillatingDipoleArrangement([d1, d2])
dot_position1 = numpy.array([-1, -1, -1])
dot_position1 = (-1, -1, -1)
dot_frequency1 = 11
expected_v1 = 0.00001221710876727626
expected_v2 = 7.257229625870065e-6
expected_v1 = 0.00001421963287022476
expected_v2 = 0.00001107180225755457
numpy.testing.assert_allclose(
d1.s_electric_potential_at_position(dot_position1, dot_frequency1),
d1.s_at_position(dot_position1, dot_frequency1),
expected_v1,
err_msg="Voltage at dot isn't as expected.",
)
range_dot_measurements = dipoles.get_percent_range_potential_dot_measurements(
range_dot_measurements = dipoles.get_percent_range_dot_measurements(
[(dot_position1, dot_frequency1)], 0.5, 1.5
)
assert len(range_dot_measurements) == 1, "Should have only had one dot measurement."

View File

@ -1,55 +0,0 @@
# serializer version: 1
# name: test_log_spaced_fixedxy_orientation_mcmc_basic
list([
tuple(
3984.4199552664,
array([[ 9.55610128, 2.94634152, 0. , 9.21529051, -2.46576127,
2.42481096, 9.19034554]]),
),
tuple(
8583.8032728084,
array([[ 9.99991539, 0.04113671, 0. , 8.71258954, -2.26599865,
2.60452102, 6.37042214]]),
),
tuple(
6215.5671525452,
array([[ 9.81950685, -1.89137124, 0. , 8.90637055, -2.48043039,
2.28444435, 8.84239221]]),
),
tuple(
424.7282747232,
array([[ 1.00028483, 9.94984574, 0. , 8.53064898, -2.59230757,
2.33774773, 8.6714416 ]]),
),
tuple(
300.920463669,
array([[ 1.4003442 , 9.90146636, 0. , 8.05557992, -2.6753126 ,
2.65915755, 13.02021385]]),
),
tuple(
2400.0053792245,
array([[ 9.97761813, 0.66868263, 0. , 8.69171028, -2.73145011,
2.90140456, 19.94999593]]),
),
tuple(
5001.4154377966,
array([[ 9.93976109, -1.09596962, 0. , 8.95245025, -2.59409162,
2.90140456, 9.75535945]]),
),
tuple(
195.2191433934,
array([[ 0.20690762, 9.99785923, 0. , 9.59636585, -2.83240984,
2.90140456, 16.14771567]]),
),
tuple(
2698.2459654601,
array([[-9.68130127, -2.50447712, 0. , 8.94823619, -2.92889659,
2.77065328, 13.63173263]]),
),
tuple(
1193.6653292625,
array([[-6.16597091, -7.87278875, 0. , 9.62210721, -2.75993924,
2.77065328, 5.64553534]]),
),
])
# ---

View File

@ -1,55 +0,0 @@
# serializer version: 1
# name: test_log_spaced_free_orientation_mcmc_basic
list([
tuple(
3167.6603875494,
array([[ 9.60483896, -1.41627817, -2.3960853 , -4.76615152, -1.80902942,
2.11809123, 16.17452242]]),
),
tuple(
3167.6603875494,
array([[ 9.60483896, -1.41627817, -2.3960853 , -4.76615152, -1.80902942,
2.11809123, 16.17452242]]),
),
tuple(
3167.6603875494,
array([[ 9.60483896, -1.41627817, -2.3960853 , -4.76615152, -1.80902942,
2.11809123, 16.17452242]]),
),
tuple(
2320.6090682509,
array([[ 4.1660069 , -8.11557337, 4.0965663 , -4.35968351, -1.97945216,
2.43615641, 12.92143144]]),
),
tuple(
2320.6090682509,
array([[ 4.1660069 , -8.11557337, 4.0965663 , -4.35968351, -1.97945216,
2.43615641, 12.92143144]]),
),
tuple(
2320.6090682509,
array([[ 4.1660069 , -8.11557337, 4.0965663 , -4.35968351, -1.97945216,
2.43615641, 12.92143144]]),
),
tuple(
2248.0760851141,
array([[-1.71755535, -5.59925137, 8.10545419, -4.03306318, -1.81098441,
2.77407111, 32.28020575]]),
),
tuple(
1663.3101472167,
array([[-5.16785855, 2.7558756 , 8.10545419, -3.34620897, -1.74763642,
2.42770463, 52.98214008]]),
),
tuple(
1329.2703365134,
array([[ -1.39600464, 9.69718343, -2.00394725, -2.59147366,
-1.91246681, 2.07361175, 123.01833742]]),
),
tuple(
355.7695549121,
array([[ 9.76047401, 0.84696075, -2.00394725, -3.04310053,
-1.99338573, 2.1185589 , 271.35743739]]),
),
])
# ---

View File

@ -1,55 +0,0 @@
# serializer version: 1
# name: test_log_spaced_fixed_orientation_mcmc_basic
list([
tuple(
50.5632126772,
array([[ 0. , 0. , 10. , -2.3960853 , 4.23246234,
2.26169242, 39.39900844]]),
),
tuple(
50.5632126772,
array([[ 0. , 0. , 10. , -2.3960853 , 4.23246234,
2.26169242, 39.39900844]]),
),
tuple(
47.4038652151,
array([[ 0. , 0. , 10. , -2.03666518, 4.14084039,
2.21309317, 47.82371559]]),
),
tuple(
47.4038652151,
array([[ 0. , 0. , 10. , -2.03666518, 4.14084039,
2.21309317, 47.82371559]]),
),
tuple(
47.4038652151,
array([[ 0. , 0. , 10. , -2.03666518, 4.14084039,
2.21309317, 47.82371559]]),
),
tuple(
47.4038652151,
array([[ 0. , 0. , 10. , -2.03666518, 4.14084039,
2.21309317, 47.82371559]]),
),
tuple(
22.9304785991,
array([[ 0. , 0. , 10. , -1.63019717, 3.97041764,
2.53115835, 38.2051999 ]]),
),
tuple(
28.8090658953,
array([[ 0. , 0. , 10. , -1.14570315, 4.07709911,
2.48697441, 49.58615195]]),
),
tuple(
28.8090658953,
array([[ 0. , 0. , 10. , -1.14570315, 4.07709911,
2.48697441, 49.58615195]]),
),
tuple(
40.9699102596,
array([[ 0. , 0. , 10. , -0.50178755, 3.83878089,
2.93560796, 82.07827571]]),
),
])
# ---

View File

@ -1,31 +0,0 @@
# serializer version: 1
# name: test_random_count_multiple_dipole_fixed_or_fixed_mag_model_get_n_dipoles
list([
list([
list([
10.0,
0.0,
6.123233995736766e-16,
-2.3960852996076447,
4.232462337639554,
2.2616924238635443,
39.399008444891905,
]),
]),
])
# ---
# name: test_random_count_multiple_dipole_fixed_or_fixed_mag_model_get_n_dipoles.1
list([
list([
list([
10.0,
0.0,
6.123233995736766e-16,
-2.3960852996076447,
4.232462337639554,
2.2616924238635443,
39.399008444891905,
]),
]),
])
# ---

View File

@ -1,100 +0,0 @@
from pdme.model import (
LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel,
)
import pdme.inputs
import pdme.measurement.input_types
import pdme.subspace_simulation
import numpy
import logging
_logger = logging.getLogger(__name__)
SEED_TO_USE = 42
def get_cost_function():
x_min = -10
x_max = 10
y_min = -5
y_max = 5
z_min = 2
z_max = 3
p_fixed = 10
max_frequency = 5
model = LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel(
x_min,
x_max,
y_min,
y_max,
z_min,
z_max,
0,
max_frequency,
p_fixed,
1,
0.5,
)
model.rng = numpy.random.default_rng(SEED_TO_USE)
freqs = [0.01, 0.1, 1, 10, 100]
dot_positions = [[-1.5, 0, 0], [-0.5, 0, 0], [0.5, 0, 0], [1.5, 0, 0]]
dot_inputs = pdme.inputs.inputs_with_frequency_range(dot_positions, freqs)
dot_input_array = pdme.measurement.input_types.dot_inputs_to_array(dot_inputs)
actual_dipoles = model.get_dipoles(0, numpy.random.default_rng(SEED_TO_USE))
actual_measurements = actual_dipoles.get_potential_dot_measurements(dot_inputs)
actual_measurements_array = numpy.array([m.v for m in actual_measurements])
def cost_to_use(sample_dipoleses: numpy.ndarray) -> numpy.ndarray:
return pdme.subspace_simulation.proportional_costs_vs_actual_measurement(
dot_input_array, actual_measurements_array, sample_dipoleses
)
return cost_to_use
def test_log_spaced_fixedxy_orientation_mcmc_basic(snapshot):
x_min = -10
x_max = 10
y_min = -5
y_max = 5
z_min = 2
z_max = 3
p_fixed = 10
max_frequency = 5
model = LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel(
x_min,
x_max,
y_min,
y_max,
z_min,
z_max,
0,
max_frequency,
p_fixed,
1,
0.5,
)
model.rng = numpy.random.default_rng(1234)
seed = model.get_monte_carlo_dipole_inputs(1, -1)
cost_function = get_cost_function()
stdev = pdme.subspace_simulation.DipoleStandardDeviation(2, 2, 1, 0.25, 0.5, 1)
stdevs = pdme.subspace_simulation.MCMCStandardDeviation([stdev])
chain = model.get_mcmc_chain(
seed[0],
cost_function,
10,
cost_function(seed)[0],
stdevs,
rng_arg=numpy.random.default_rng(1515),
)
chain_rounded = [(round(cost, 10), dipoles) for (cost, dipoles) in chain]
assert chain_rounded == snapshot

View File

@ -1,100 +0,0 @@
from pdme.model import (
LogSpacedRandomCountMultipleDipoleFixedMagnitudeModel,
)
import pdme.inputs
import pdme.measurement.input_types
import pdme.subspace_simulation
import numpy
import logging
_logger = logging.getLogger(__name__)
SEED_TO_USE = 42
def get_cost_function():
x_min = -10
x_max = 10
y_min = -5
y_max = 5
z_min = 2
z_max = 3
p_fixed = 10
max_frequency = 5
model = LogSpacedRandomCountMultipleDipoleFixedMagnitudeModel(
x_min,
x_max,
y_min,
y_max,
z_min,
z_max,
0,
max_frequency,
p_fixed,
1,
0.5,
)
model.rng = numpy.random.default_rng(SEED_TO_USE)
freqs = [0.01, 0.1, 1, 10, 100]
dot_positions = [[-1.5, 0, 0], [-0.5, 0, 0], [0.5, 0, 0], [1.5, 0, 0]]
dot_inputs = pdme.inputs.inputs_with_frequency_range(dot_positions, freqs)
dot_input_array = pdme.measurement.input_types.dot_inputs_to_array(dot_inputs)
actual_dipoles = model.get_dipoles(0, numpy.random.default_rng(SEED_TO_USE))
actual_measurements = actual_dipoles.get_potential_dot_measurements(dot_inputs)
actual_measurements_array = numpy.array([m.v for m in actual_measurements])
def cost_to_use(sample_dipoleses: numpy.ndarray) -> numpy.ndarray:
return pdme.subspace_simulation.proportional_costs_vs_actual_measurement(
dot_input_array, actual_measurements_array, sample_dipoleses
)
return cost_to_use
def test_log_spaced_free_orientation_mcmc_basic(snapshot):
x_min = -10
x_max = 10
y_min = -5
y_max = 5
z_min = 2
z_max = 3
p_fixed = 10
max_frequency = 5
model = LogSpacedRandomCountMultipleDipoleFixedMagnitudeModel(
x_min,
x_max,
y_min,
y_max,
z_min,
z_max,
0,
max_frequency,
p_fixed,
1,
0.5,
)
model.rng = numpy.random.default_rng(1234)
seed = model.get_monte_carlo_dipole_inputs(1, -1)
cost_function = get_cost_function()
stdev = pdme.subspace_simulation.DipoleStandardDeviation(2, 2, 1, 0.25, 0.5, 1)
stdevs = pdme.subspace_simulation.MCMCStandardDeviation([stdev])
chain = model.get_mcmc_chain(
seed[0],
cost_function,
10,
cost_function(seed)[0],
stdevs,
rng_arg=numpy.random.default_rng(1515),
)
chain_rounded = [(round(cost, 10), dipoles) for (cost, dipoles) in chain]
assert chain_rounded == snapshot

View File

@ -1,108 +0,0 @@
from pdme.model import (
LogSpacedRandomCountMultipleDipoleFixedMagnitudeFixedOrientationModel,
)
import pdme.inputs
import pdme.measurement.input_types
import pdme.subspace_simulation
import numpy
import logging
_logger = logging.getLogger(__name__)
SEED_TO_USE = 42
def get_cost_function():
x_min = -10
x_max = 10
y_min = -5
y_max = 5
z_min = 2
z_max = 3
p_fixed = 10
theta = 0
phi = 0
max_frequency = 5
model = LogSpacedRandomCountMultipleDipoleFixedMagnitudeFixedOrientationModel(
x_min,
x_max,
y_min,
y_max,
z_min,
z_max,
0,
max_frequency,
p_fixed,
theta,
phi,
1,
0.5,
)
model.rng = numpy.random.default_rng(SEED_TO_USE)
freqs = [0.01, 0.1, 1, 10, 100]
dot_positions = [[-1.5, 0, 0], [-0.5, 0, 0], [0.5, 0, 0], [1.5, 0, 0]]
dot_inputs = pdme.inputs.inputs_with_frequency_range(dot_positions, freqs)
dot_input_array = pdme.measurement.input_types.dot_inputs_to_array(dot_inputs)
actual_dipoles = model.get_dipoles(0, numpy.random.default_rng(SEED_TO_USE))
actual_measurements = actual_dipoles.get_potential_dot_measurements(dot_inputs)
actual_measurements_array = numpy.array([m.v for m in actual_measurements])
def cost_to_use(sample_dipoleses: numpy.ndarray) -> numpy.ndarray:
return pdme.subspace_simulation.proportional_costs_vs_actual_measurement(
dot_input_array, actual_measurements_array, sample_dipoleses
)
return cost_to_use
def test_log_spaced_fixed_orientation_mcmc_basic(snapshot):
x_min = -10
x_max = 10
y_min = -5
y_max = 5
z_min = 2
z_max = 3
p_fixed = 10
theta = 0
phi = 0
max_frequency = 5
model = LogSpacedRandomCountMultipleDipoleFixedMagnitudeFixedOrientationModel(
x_min,
x_max,
y_min,
y_max,
z_min,
z_max,
0,
max_frequency,
p_fixed,
theta,
phi,
1,
0.5,
)
model.rng = numpy.random.default_rng(1234)
seed = model.get_monte_carlo_dipole_inputs(1, -1)
cost_function = get_cost_function()
stdev = pdme.subspace_simulation.DipoleStandardDeviation(2, 2, 1, 0.25, 0.5, 1)
stdevs = pdme.subspace_simulation.MCMCStandardDeviation([stdev])
chain = model.get_mcmc_chain(
seed[0],
cost_function,
10,
cost_function(seed)[0],
stdevs,
rng_arg=numpy.random.default_rng(1515),
)
chain_rounded = [(round(cost, 10), dipoles) for (cost, dipoles) in chain]
assert chain_rounded == snapshot

View File

@ -1,206 +0,0 @@
from pdme.model import LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel
import numpy
import logging
import pytest
_logger = logging.getLogger(__name__)
def test_random_count_multiple_dipole_xy_wrong_probability():
with pytest.raises(ValueError):
LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel(
-10, 10, -5, 5, 2, 3, 1, 2, 10, 5, 2
)
def test_repr_random_count_multiple_dipole_fixed_mag_xy():
model = LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel(
-10, 10, -5, 5, 2, 3, 1, 2, 10, 5, 0.5
)
assert (
repr(model)
== "LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel(-10, 10, -5, 5, 2, 3, 1, 2, 10, 5, 0.5)"
), "Repr should be what I want."
def test_random_count_multiple_dipole_fixed_mag_model_get_dipoles_multiple_xy():
p_fixed = 10
dipole_count = 5
model = LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel(
-10, 10, -5, 5, 2, 3, 0, 5, p_fixed, dipole_count, 0.5
)
dipole_arrangement = model.get_dipoles(20, numpy.random.default_rng(1234))
dipoles = dipole_arrangement.dipoles
assert (
len(dipoles) == dipole_count
), "Should have had multiple dipole based on count generated."
def test_random_count_multiple_dipole_fixed_mag_model_get_dipoles_invariant_xy():
x_min = -10
x_max = 10
y_min = -5
y_max = 5
z_min = 2
z_max = 3
p_fixed = 10
max_frequency = 5
model = LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel(
x_min, x_max, y_min, y_max, z_min, z_max, 0, max_frequency, p_fixed, 1, 0.5
)
model.rng = numpy.random.default_rng(1234)
dipole_arrangement = model.get_dipoles(5)
dipoles = dipole_arrangement.dipoles
assert len(dipoles) == 1, "Should have only had one dipole generated."
for i in range(10):
dipole_arrangement = model.get_dipoles(max_frequency)
dipoles = dipole_arrangement.dipoles
assert len(dipoles) in (
0,
1,
), "Should have either zero or one dipole generated."
if len(dipoles) > 0:
min_s = numpy.array([x_min, y_min, z_min])
max_s = numpy.array([x_max, y_max, z_max])
numpy.testing.assert_equal(
numpy.logical_and(min_s < dipoles[0].s, max_s > dipoles[0].s),
True,
f"Dipole location [{dipoles[0].s}] should have been between min [{min_s}] and max [{max_s}] bounds.",
)
assert (
dipoles[0].w < 10 ** max_frequency and dipoles[0].w > 10**0
), "Dipole frequency should have been between 0 and max."
numpy.testing.assert_allclose(
numpy.linalg.norm(dipoles[0].p),
p_fixed,
err_msg="Should have had the expected dipole moment magnitude.",
)
_logger.warning(dipoles[0].p)
numpy.testing.assert_allclose(
dipoles[0].p[2],
0,
err_msg="Should have had zero z magnitude.",
)
def test_random_count_multiple_dipole_fixed_mag_model_get_dipoles_invariant_monte_carlo_xy():
x_min = -10
x_max = 10
y_min = -5
y_max = 5
z_min = 2
z_max = 3
p_fixed = 10
max_frequency = 5
monte_carlo_n = 20
model = LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel(
x_min, x_max, y_min, y_max, z_min, z_max, 0, max_frequency, p_fixed, 1, 0.5
)
model.rng = numpy.random.default_rng(1234)
dipole_arrangement = model.get_dipoles(5)
dipoles = dipole_arrangement.dipoles
assert len(dipoles) == 1, "Should have only had one dipole generated."
for i in range(10):
dipoles = model.get_monte_carlo_dipole_inputs(monte_carlo_n, max_frequency)
min_s = numpy.array([x_min, y_min, z_min])
max_s = numpy.array([x_max, y_max, z_max])
_logger.warning(dipoles)
_logger.warning(dipoles[:, 0, 0:3])
_logger.warning(dipoles[:, 0, 3:6])
_logger.warning(dipoles[:, 0, 6])
ps = dipoles[:, 0, 0:3]
ss = dipoles[:, 0, 3:6]
ws = dipoles[:, 0, 6]
numpy.testing.assert_equal(
numpy.logical_and(min_s < ss, max_s > ss).all(),
True,
f"Dipole location [{ss}] should have been between min [{min_s}] and max [{max_s}] bounds.",
)
assert (ws < 10**max_frequency).all() and (
ws > 10**0
).all(), "Dipole frequency should have been between 0 and max."
norms = numpy.linalg.norm(ps, axis=1)
filtered_norms = norms[norms > 0]
numpy.testing.assert_allclose(
filtered_norms,
p_fixed,
err_msg="Should have had the expected dipole moment magnitude.",
)
numpy.testing.assert_allclose(
ps[:, 2],
0,
err_msg="Should have had zero z magnitude.",
)
def test_random_count_multiple_dipole_shape():
x_min = -10
x_max = 10
y_min = -5
y_max = 5
z_min = 2
z_max = 3
p_fixed = 10
max_frequency = 5
num_dipoles = 13
monte_carlo_n = 11
model = LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel(
x_min,
x_max,
y_min,
y_max,
z_min,
z_max,
0,
max_frequency,
p_fixed,
num_dipoles,
0.5,
)
model.rng = numpy.random.default_rng(1234)
actual_shape = model.get_monte_carlo_dipole_inputs(
monte_carlo_n, max_frequency
).shape
numpy.testing.assert_equal(
actual_shape,
(monte_carlo_n, num_dipoles, 7),
err_msg="shape was wrong for monte carlo outputs",
)
actual_shape = model.get_monte_carlo_dipole_inputs(
monte_carlo_n, max_frequency, rng_to_use=numpy.random.default_rng(1515)
).shape
numpy.testing.assert_equal(
actual_shape,
(monte_carlo_n, num_dipoles, 7),
err_msg="shape was wrong for monte carlo outputs",
)

View File

@ -115,7 +115,8 @@ def test_random_count_multiple_dipole_fixed_mag_model_get_dipoles_invariant():
)
def test_random_count_multiple_dipole_fixed_or_fixed_mag_model_get_n_dipoles(snapshot):
def test_random_count_multiple_dipole_fixed_or_fixed_mag_model_get_n_dipoles():
# TODO: this test is a bit garbage just calls things without testing.
x_min = -10
x_max = 10
y_min = -5
@ -144,9 +145,7 @@ def test_random_count_multiple_dipole_fixed_or_fixed_mag_model_get_n_dipoles(sna
)
model.rng = numpy.random.default_rng(1234)
actual_inputs = model.get_monte_carlo_dipole_inputs(1, max_frequency)
assert actual_inputs.tolist() == snapshot
actual_monte_carlo_inputs = model.get_monte_carlo_dipole_inputs(
model.get_monte_carlo_dipole_inputs(1, max_frequency)
model.get_monte_carlo_dipole_inputs(
1, max_frequency, numpy.random.default_rng(1234)
)
assert actual_monte_carlo_inputs.tolist() == snapshot

View File

@ -1,4 +0,0 @@
# serializer version: 1
# name: test_proportional_costs
7000.0
# ---

View File

@ -1,94 +0,0 @@
# serializer version: 1
# name: test_sort_dipoles_by_freq
list([
list([
100.0,
200.0,
300.0,
400.0,
500.0,
600.0,
0.07,
]),
list([
1.0,
2.0,
3.0,
4.0,
5.0,
6.0,
7.0,
]),
list([
10.0,
200.0,
30.0,
41.0,
315.0,
0.31,
100.0,
]),
])
# ---
# name: test_sort_dipoleses_by_freq
list([
list([
list([
100.0,
200.0,
300.0,
400.0,
500.0,
600.0,
0.07,
]),
list([
1.0,
2.0,
3.0,
4.0,
5.0,
6.0,
7.0,
]),
list([
10.0,
200.0,
30.0,
41.0,
315.0,
0.31,
100.0,
]),
]),
list([
list([
1.0,
1.0,
1.0,
1.0,
1.0,
1.0,
100.0,
]),
list([
22.0,
22.2,
2.2,
222.0,
22.0,
2.0,
200.0,
]),
list([
33.0,
33.3,
33.0,
3.3,
0.33,
0.3,
300.0,
]),
]),
])
# ---

View File

@ -1,22 +0,0 @@
# serializer version: 1
# name: test_return_four
DipoleStandardDeviation(p_phi_step=1, p_theta_step=2, rx_step=3, ry_step=4, rz_step=5, w_log_step=6)
# ---
# name: test_return_four.1
DipoleStandardDeviation(p_phi_step=10, p_theta_step=20, rx_step=30, ry_step=40, rz_step=50, w_log_step=60)
# ---
# name: test_return_four.2
DipoleStandardDeviation(p_phi_step=0.1, p_theta_step=0.2, rx_step=0.3, ry_step=0.4, rz_step=0.5, w_log_step=0.6)
# ---
# name: test_return_four.3
DipoleStandardDeviation(p_phi_step=1, p_theta_step=2, rx_step=3, ry_step=4, rz_step=5, w_log_step=6)
# ---
# name: test_return_four.4
DipoleStandardDeviation(p_phi_step=10, p_theta_step=20, rx_step=30, ry_step=40, rz_step=50, w_log_step=60)
# ---
# name: test_return_four.5
DipoleStandardDeviation(p_phi_step=0.1, p_theta_step=0.2, rx_step=0.3, ry_step=0.4, rz_step=0.5, w_log_step=0.6)
# ---
# name: test_return_one
DipoleStandardDeviation(p_phi_step=1, p_theta_step=2, rx_step=3, ry_step=4, rz_step=5, w_log_step=6)
# ---

View File

@ -1,31 +0,0 @@
import pdme.subspace_simulation
import pdme.subspace_simulation.mcmc_costs
import numpy
def test_proportional_costs(snapshot):
a = numpy.array([2, 4, 5, 6, 7, 8, 10])
b = numpy.array([51, 13, 1, 31, 0.001, 3, 1])
actual_result = pdme.subspace_simulation.proportional_cost(a, b).tolist()
assert actual_result == snapshot
def test_squared_costs_manual():
target = numpy.array([100, 400, 900])
approx1 = numpy.array([0, 400, 800])
approx2 = numpy.array([200, 400, 600])
expected1 = 1.0123456790123457
expected2 = 1.1111111111111111
actual1 = pdme.subspace_simulation.mcmc_costs.relative_square_diffs(approx1, target)
assert actual1 == expected1
actual2 = pdme.subspace_simulation.mcmc_costs.relative_square_diffs(approx2, target)
assert actual2 == expected2
combined_actual = pdme.subspace_simulation.mcmc_costs.relative_square_diffs(
numpy.array([approx1, approx2]), target
)
numpy.testing.assert_allclose(combined_actual, [expected1, expected2], rtol=1e-14)

View File

@ -1,40 +0,0 @@
import numpy
import pdme.subspace_simulation
def test_sort_dipoles_by_freq(snapshot):
orig = numpy.array(
[
[1, 2, 3, 4, 5, 6, 7],
[100, 200, 300, 400, 500, 600, 0.07],
[10, 200, 30, 41, 315, 0.31, 100],
]
)
actual_sorted = pdme.subspace_simulation.sort_array_of_dipoles_by_frequency(orig)
assert actual_sorted.tolist() == snapshot
def test_sort_dipoleses_by_freq(snapshot):
sample_1 = numpy.array(
[
[1, 2, 3, 4, 5, 6, 7],
[100, 200, 300, 400, 500, 600, 0.07],
[10, 200, 30, 41, 315, 0.31, 100],
]
)
sample_2 = numpy.array(
[
[1, 1, 1, 1, 1, 1, 100],
[33, 33.3, 33, 3.3, 0.33, 0.3, 300],
[22, 22.2, 2.2, 222, 22, 2, 200],
]
)
original_samples = numpy.array([sample_1, sample_2])
actual_sorted = pdme.subspace_simulation.sort_array_of_dipoleses_by_frequency(
original_samples
)
assert actual_sorted.tolist() == snapshot

View File

@ -1,38 +0,0 @@
import pytest
import pdme.subspace_simulation
def test_empty():
with pytest.raises(ValueError):
pdme.subspace_simulation.MCMCStandardDeviation([])
def test_return_one(snapshot):
stdev = pdme.subspace_simulation.DipoleStandardDeviation(
1,
2,
3,
4,
5,
6,
)
stdevs = pdme.subspace_simulation.MCMCStandardDeviation([stdev])
assert stdevs[3] == snapshot
assert stdevs[3] == stdev
def test_return_four(snapshot):
stdev_list = [
pdme.subspace_simulation.DipoleStandardDeviation(1, 2, 3, 4, 5, 6),
pdme.subspace_simulation.DipoleStandardDeviation(10, 20, 30, 40, 50, 60),
pdme.subspace_simulation.DipoleStandardDeviation(0.1, 0.2, 0.3, 0.4, 0.5, 0.6),
]
stdevs = pdme.subspace_simulation.MCMCStandardDeviation(stdev_list)
assert stdevs[0] == snapshot
assert stdevs[1] == snapshot
assert stdevs[2] == snapshot
assert stdevs[3] == snapshot
assert stdevs[4] == snapshot
assert stdevs[5] == snapshot

View File

@ -1,20 +0,0 @@
# serializer version: 1
# name: test_arg
list([
list([
-0.0,
-0.0,
-0.0,
]),
list([
3.141592653589793,
-0.0,
-0.0,
]),
list([
-0.0,
-0.0,
3.141592653589793,
]),
])
# ---

View File

@ -1,25 +0,0 @@
# serializer version: 1
# name: test_fast_nonlocal_calc_multidipole_phase_snapshot
list([
list([
-0.0,
-0.0,
]),
list([
-0.0,
3.141592653589793,
]),
])
# ---
# name: test_fast_spin_qubit_frequency_tarucha_calc
list([
list([
1.1471308805198364,
0.042486328908142086,
]),
list([
0.0008292459978410822,
0.0006214312613006971,
]),
])
# ---

View File

@ -1,24 +1,9 @@
import numpy
import pdme.util.fast_nonlocal_spectrum
import pdme.measurement
import logging
import pytest
def dipole_from_array(arr: numpy.ndarray) -> pdme.measurement.OscillatingDipole:
return pdme.measurement.OscillatingDipole(arr[0:3], arr[3:6], arr[6])
def s_potential_from_arrays(
dipole_array: numpy.ndarray, dotf_pair_array: numpy.ndarray
) -> float:
dipole = dipole_from_array(dipole_array)
r1 = dotf_pair_array[0][0:3]
f1 = dotf_pair_array[0][3]
r2 = dotf_pair_array[1][0:3]
return dipole.s_electric_potential_for_dot_pair(r1, r2, f1)
def test_fast_nonlocal_calc():
d1 = [1, 2, 3, 4, 5, 6, 7]
d2 = [1, 2, 3, 4, 5, 6, 8]
@ -31,11 +16,21 @@ def test_fast_nonlocal_calc():
[[[-1, -2, -3, 11], [-1, 2, 5, 11]], [[-1, -2, -3, 6], [2, 4, 6, 6]]]
)
# expected_ij is for pair i, dipole j
expected_11 = 0.000021124454334947546213
expected_12 = 0.000022184755131682365135
expected_13 = 0.0000053860643617855849275
expected_14 = -0.0000023069501696755220764
expected_21 = 0.00022356021100884617796
expected_22 = 0.00021717277640859343002
expected_23 = 0.000017558321044891869169
expected_24 = -0.000034714318479634499683
expected = numpy.array(
[
[s_potential_from_arrays(dipole_array, dot_pair) for dot_pair in dot_pairs]
for dipole_array in dipoles
[expected_11, expected_21],
[expected_12, expected_22],
[expected_13, expected_23],
[expected_14, expected_24],
]
)
@ -58,11 +53,3 @@ def test_fast_nonlocal_frequency_check():
with pytest.raises(ValueError):
pdme.util.fast_nonlocal_spectrum.fast_s_nonlocal(dot_pairs, dipoles)
def test_arg(snapshot):
test_input = numpy.array([[1, 2, 3], [-1, 1, 3], [3, 5, -1]])
actual_result = pdme.util.fast_nonlocal_spectrum.signarg(test_input)
assert actual_result.tolist() == snapshot

View File

@ -1,25 +1,8 @@
import numpy
import pdme.util.fast_nonlocal_spectrum
import pdme.measurement
import logging
import pytest
_logger = logging.getLogger(__name__)
def dipole_from_array(arr: numpy.ndarray) -> pdme.measurement.OscillatingDipole:
return pdme.measurement.OscillatingDipole(arr[0:3], arr[3:6], arr[6])
def s_potential_from_arrays(
dipole_array: numpy.ndarray, dotf_pair_array: numpy.ndarray
) -> float:
dipole = dipole_from_array(dipole_array)
r1 = dotf_pair_array[0][0:3]
f1 = dotf_pair_array[0][3]
r2 = dotf_pair_array[1][0:3]
return dipole.s_electric_potential_for_dot_pair(r1, r2, f1)
def test_fast_nonlocal_calc_multidipole():
d1 = [1, 2, 3, 4, 5, 6, 7]
@ -33,19 +16,19 @@ def test_fast_nonlocal_calc_multidipole():
[[[-1, -2, -3, 11], [-1, 2, 5, 11]], [[-1, -2, -3, 6], [2, 4, 6, 6]]]
)
# expected_ij is for pair i, dipole j
expected_11 = 0.000021124454334947546213
expected_12 = 0.000022184755131682365135
expected_13 = 0.0000053860643617855849275
expected_14 = -0.0000023069501696755220764
expected_21 = 0.00022356021100884617796
expected_22 = 0.00021717277640859343002
expected_23 = 0.000017558321044891869169
expected_24 = -0.000034714318479634499683
expected = numpy.array(
[
[
sum(
[
s_potential_from_arrays(dipole_array, dot_pair)
for dipole_array in dipoles
]
)
for dot_pair in dot_pairs
]
for dipoles in dipoleses
[expected_11 + expected_12, expected_21 + expected_22],
[expected_13 + expected_14, expected_23 + expected_24],
]
)
@ -70,44 +53,3 @@ def test_fast_nonlocal_frequency_check_multidipole():
with pytest.raises(ValueError):
pdme.util.fast_nonlocal_spectrum.fast_s_nonlocal_dipoleses(dot_pairs, dipoles)
def test_fast_nonlocal_calc_multidipole_phase_snapshot(snapshot):
d1 = [1, 2, 3, 4, 5, 6, 7]
d2 = [1, 2, 3, 4, 5, 6, 8]
d3 = [2, 5, 3, 4, -5, -6, 2]
d4 = [-3, 2, 1, 4, 5, 6, 10]
dipoleses = numpy.array([[d1, d2], [d3, d4]])
dot_pairs = numpy.array(
[[[-1, -2, -3, 11], [-1, 2, 5, 11]], [[-1, -2, -3, 6], [2, 4, 6, 6]]]
)
# this is a bit silly but just set the logger to debug so that the coverage stats don't get affected by the debug statements.
pdme.util.fast_nonlocal_spectrum._logger.setLevel(logging.DEBUG)
actual_phases = pdme.util.fast_nonlocal_spectrum.signarg(
pdme.util.fast_nonlocal_spectrum.fast_s_nonlocal_dipoleses(dot_pairs, dipoleses)
)
assert actual_phases.tolist() == snapshot
def test_fast_spin_qubit_frequency_tarucha_calc(snapshot):
d1 = [1, 2, 3, 0, 0, 0, 5]
d2 = [6, 7, 8, 5, 4, 3, 8]
dipoleses = numpy.array([[d1], [d2]])
dot_pairs = numpy.array(
[[[1, 0, 0, 1], [1, 0, 0, 1]], [[1, 0, 0, 1], [3, 0, 0, 1]]]
)
actual = (
pdme.util.fast_nonlocal_spectrum.fast_s_spin_qubit_tarucha_nonlocal_dipoleses(
dot_pairs, dipoleses
)
)
pdme.util.fast_nonlocal_spectrum._logger.setLevel(logging.DEBUG)
_logger.info(actual)
assert actual.tolist() == snapshot

View File

@ -1,30 +1,6 @@
import numpy
import pdme.util.fast_v_calc
import pdme.measurement
def dipole_from_array(arr: numpy.ndarray) -> pdme.measurement.OscillatingDipole:
return pdme.measurement.OscillatingDipole(arr[0:3], arr[3:6], arr[6])
def s_potential_from_arrays(
dipole_array: numpy.ndarray, dotf_array: numpy.ndarray
) -> float:
dipole = dipole_from_array(dipole_array)
r = dotf_array[0:3]
f = dotf_array[3]
return dipole.s_electric_potential_at_position(r, f)
def s_electric_field_x_from_arrays(
dipole_array: numpy.ndarray, dotf_array: numpy.ndarray
) -> float:
dipole = dipole_from_array(dipole_array)
r = dotf_array[0:3]
f = dotf_array[3]
return dipole.s_electric_fieldx_at_position(r, f)
def test_fast_v_calc():
d1 = [1, 2, 3, 4, 5, 6, 7]
@ -33,11 +9,11 @@ def test_fast_v_calc():
dipoles = numpy.array([d1, d2])
dot_inputs = numpy.array([[-1, -1, -1, 11], [2, 3, 1, 5.5]])
expected_11 = s_potential_from_arrays(dipoles[0], dot_inputs[0])
expected_12 = s_potential_from_arrays(dipoles[1], dot_inputs[0])
expected_21 = s_potential_from_arrays(dipoles[0], dot_inputs[1])
expected_22 = s_potential_from_arrays(dipoles[1], dot_inputs[1])
# expected_ij is for dot i, dipole j
expected_11 = 0.00001421963287022476
expected_12 = 0.00001107180225755457
expected_21 = 0.000345021108583681380388722
expected_22 = 0.0000377061050587914705139781
expected = numpy.array([[expected_11, expected_21], [expected_12, expected_22]])
@ -55,11 +31,11 @@ def test_fast_v_calc_multidipoles():
dipoles = numpy.array([[d1, d2]])
dot_inputs = numpy.array([[-1, -1, -1, 11], [2, 3, 1, 5.5]])
expected_11 = s_potential_from_arrays(dipoles[0][0], dot_inputs[0])
expected_12 = s_potential_from_arrays(dipoles[0][1], dot_inputs[0])
expected_21 = s_potential_from_arrays(dipoles[0][0], dot_inputs[1])
expected_22 = s_potential_from_arrays(dipoles[0][1], dot_inputs[1])
# expected_ij is for dot i, dipole j
expected_11 = 0.00001421963287022476
expected_12 = 0.00001107180225755457
expected_21 = 0.000345021108583681380388722
expected_22 = 0.0000377061050587914705139781
expected = numpy.array([[expected_11 + expected_12, expected_21 + expected_22]])
@ -72,7 +48,7 @@ def test_fast_v_calc_multidipoles():
def test_fast_v_calc_big_multidipole():
dipoleses = numpy.array(
dipoles = numpy.array(
[
[
[1, 1, 5, 6, 3, 1, 1],
@ -96,116 +72,30 @@ def test_fast_v_calc_big_multidipole():
]
)
expected = [
expected = numpy.array(
[
sum(
[
s_potential_from_arrays(dipole_array, dot_input)
for dipole_array in dipole_config
0.0010151687742365581690202135,
0.00077627527320628609782627266,
0.00043313471258511003340648713,
0.000077184305988088453637005111,
],
[
0.000041099091967966890657097060,
0.0019377687238977568792327845,
0.0085903193415282984161225029,
0.00014557676715208209310911838,
],
]
)
for dot_input in dot_inputs
]
for dipole_config in dipoleses
]
numpy.testing.assert_allclose(
pdme.util.fast_v_calc.fast_vs_for_dipoleses(dot_inputs, dipoleses),
pdme.util.fast_v_calc.fast_vs_for_dipoleses(dot_inputs, dipoles),
expected,
err_msg="Voltages at dot aren't as expected for multidipole calc.",
)
def test_fast_electric_field_x_calc():
d1 = [1, 2, 3, 4, 5, 6, 7]
d2 = [2, 5, 3, 4, -5, -6, 2]
dipoles = numpy.array([d1, d2])
dot_inputs = numpy.array([[-1, -1, -1, 11], [2, 3, 1, 5.5]])
expected_11 = s_electric_field_x_from_arrays(dipoles[0], dot_inputs[0])
expected_12 = s_electric_field_x_from_arrays(dipoles[1], dot_inputs[0])
expected_21 = s_electric_field_x_from_arrays(dipoles[0], dot_inputs[1])
expected_22 = s_electric_field_x_from_arrays(dipoles[1], dot_inputs[1])
expected = numpy.array([[expected_11, expected_21], [expected_12, expected_22]])
numpy.testing.assert_allclose(
pdme.util.fast_v_calc.fast_efieldxs_for_dipoles(dot_inputs, dipoles),
expected,
err_msg="E x fast calc at dot aren't as expected.",
)
def test_fast_electric_field_x_calc_multidipoles():
d1 = [1, 2, 3, 4, 5, 6, 7]
d2 = [2, 5, 3, 4, -5, -6, 2]
dipoles = numpy.array([[d1, d2]])
dot_inputs = numpy.array([[-1, -1, -1, 11], [2, 3, 1, 5.5]])
expected_11 = s_electric_field_x_from_arrays(dipoles[0][0], dot_inputs[0])
expected_12 = s_electric_field_x_from_arrays(dipoles[0][1], dot_inputs[0])
expected_21 = s_electric_field_x_from_arrays(dipoles[0][0], dot_inputs[1])
expected_22 = s_electric_field_x_from_arrays(dipoles[0][1], dot_inputs[1])
expected = numpy.array([[expected_11 + expected_12, expected_21 + expected_22]])
numpy.testing.assert_allclose(
pdme.util.fast_v_calc.fast_efieldxs_for_dipoleses(dot_inputs, dipoles),
expected,
err_msg="E x fast calc at dot aren't as expected for multidipole calc.",
)
def test_fast_electric_field_x_calc_big_multidipole():
dipoleses = numpy.array(
[
[
[1, 1, 5, 6, 3, 1, 1],
[5, 3, 2, 13, 1, 1, 2],
[-5, -5, -3, -1, -3, 8, 3],
],
[
[-3, -1, -2, -2, -6, 3, 4],
[8, 0, 2, 0, 1, 5, 5],
[1, 4, -4, -1, -3, -5, 6],
],
]
)
dot_inputs = numpy.array(
[
[1, 1, 0, 1],
[2, 5, 6, 2],
[3, 1, 3, 3],
[0.5, 0.5, 0.5, 4],
]
)
expected = [
[
sum(
[
s_electric_field_x_from_arrays(dipole_array, dot_input)
for dipole_array in dipole_config
]
)
for dot_input in dot_inputs
]
for dipole_config in dipoleses
]
numpy.testing.assert_allclose(
pdme.util.fast_v_calc.fast_efieldxs_for_dipoleses(dot_inputs, dipoleses),
expected,
err_msg="E x fast calc at dot aren't as expected for multidipole calc.",
)
def test_between():
low = numpy.array([1, 2, 3])
high = numpy.array([6, 7, 8])