Compare commits
51 Commits
Author | SHA1 | Date | |
---|---|---|---|
885508e104 | |||
6193ecb9c9 | |||
5ad442750e | |||
9b1538b3c6 | |||
7b277fdc85 | |||
e5fc1207a8 | |||
387a607e09 | |||
9e6d1df559 | |||
45031857f2 | |||
64181eeef2 | |||
d682d50554 | |||
e9e34162a3 | |||
32a7812a43 | |||
7c39475742 | |||
1dd7569fde | |||
4a63552129 | |||
9c88c9ab96 | |||
631ba13c79 | |||
e2bdeda638 | |||
806b9b667f | |||
e61838d85f | |||
3ebe2bb824 | |||
ed9dd2c94f | |||
74c1b01a6c | |||
50f98ed89b | |||
18cc48471d | |||
d60a0cb386 | |||
e01d0e14a9 | |||
dfaf8abed5 | |||
ca710e359f | |||
dc43e4bfbc | |||
dbf924490e | |||
f280448cfe | |||
feb0a5f645 | |||
e9bb62c0a0 | |||
857391425f | |||
46dc6dd6d9 | |||
29abc8af89 | |||
23e3b95bb6 | |||
a326e80e00 | |||
56f660ff25 | |||
a5fd9c2304 | |||
0dbe874ac4 | |||
36454d5044 | |||
156019fdac | |||
c49b8eb034 | |||
c034ae81fd | |||
5acf0ac347 | |||
2a1ae3b1a7 | |||
0447b5d3a7 | |||
e894c89702 |
107
CHANGELOG.md
107
CHANGELOG.md
@ -2,6 +2,113 @@
|
||||
|
||||
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)
|
||||
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
[](https://jenkins.deepak.science/job/gitea-physics/job/pdme/job/master/)
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
This repo has library code for evaluating dipole models.
|
||||
|
||||
|
5029
diagnosis1.nb
5029
diagnosis1.nb
File diff suppressed because it is too large
Load Diff
60
do.sh
60
do.sh
@ -1,60 +0,0 @@
|
||||
#!/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"
|
||||
|
||||
checknix() {
|
||||
if [[ "${DO_NIX_CUSTOM:=0}" -eq 1 ]]; then
|
||||
echo "In an interactive nix env."
|
||||
else
|
||||
echo "Using poetry as runner, no nix detected."
|
||||
fi
|
||||
}
|
||||
|
||||
build() {
|
||||
echo "I am ${FUNCNAME[0]}ing"
|
||||
poetry build
|
||||
}
|
||||
|
||||
fmt() {
|
||||
if [[ "${DO_NIX_CUSTOM:=0}" -eq 1 ]]; then
|
||||
black .
|
||||
else
|
||||
poetry run black .
|
||||
fi
|
||||
find . -type f -name "*.py" -exec sed -i -e 's/ /\t/g' {} \;
|
||||
}
|
||||
|
||||
test() {
|
||||
echo "I am ${FUNCNAME[0]}ing"
|
||||
if [[ "${DO_NIX_CUSTOM:=0}" -eq 1 ]]; then
|
||||
flake8 pdme tests
|
||||
mypy pdme
|
||||
pytest
|
||||
else
|
||||
poetry run flake8 pdme tests
|
||||
poetry run mypy pdme
|
||||
poetry run pytest
|
||||
fi
|
||||
}
|
||||
|
||||
htmlcov() {
|
||||
if [[ "${DO_NIX_CUSTOM:=0}" -eq 1 ]]; then
|
||||
pytest --cov-report=html
|
||||
else
|
||||
poetry run pytest --cov-report=html
|
||||
fi
|
||||
}
|
||||
|
||||
release() {
|
||||
./scripts/release.sh
|
||||
}
|
||||
|
||||
all() {
|
||||
build && fmt && test
|
||||
}
|
||||
|
||||
"$@" # <- execute the task
|
||||
|
||||
[ "$#" -gt 0 ] || printf "Usage:\n\t./do.sh %s\n" "($(compgen -A function | grep '^[^_]' | paste -sd '|' -))"
|
64
justfile
Normal file
64
justfile
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
# 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
|
46
pdme/calculations/__init__.py
Normal file
46
pdme/calculations/__init__.py
Normal file
@ -0,0 +1,46 @@
|
||||
"""
|
||||
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)
|
@ -7,6 +7,7 @@ from pdme.measurement.dot_pair_measure import (
|
||||
DotPairMeasurement,
|
||||
DotPairRangeMeasurement,
|
||||
)
|
||||
import pdme.calculations
|
||||
from pdme.measurement.input_types import DotInput, DotPairInput
|
||||
|
||||
|
||||
@ -38,10 +39,27 @@ class OscillatingDipole:
|
||||
self.p = numpy.array(self.p)
|
||||
self.s = numpy.array(self.s)
|
||||
|
||||
def s_at_position(self, r: numpy.ndarray, f: float) -> float:
|
||||
def _alpha_electric_potential(self, r: numpy.ndarray) -> float:
|
||||
"""
|
||||
Returns the electric potential of this dipole at position r.
|
||||
"""
|
||||
return pdme.calculations.electric_potential(self.p, self.s, r)
|
||||
|
||||
def _alpha_electric_field(self, r: numpy.ndarray) -> numpy.ndarray:
|
||||
"""
|
||||
Returns the electric field of this dipole at position r.
|
||||
"""
|
||||
return pdme.calculations.electric_field(self.p, self.s, r)
|
||||
|
||||
def _b(self, f: float) -> float:
|
||||
return pdme.calculations.telegraph_beta(f, self.w)
|
||||
|
||||
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
|
||||
@ -50,17 +68,49 @@ class OscillatingDipole:
|
||||
f : float
|
||||
The dot frequency to sample.
|
||||
"""
|
||||
return (self._alpha(r)) ** 2 * self._b(f)
|
||||
return (self._alpha_electric_potential(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 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 _b(self, f: float) -> float:
|
||||
return (1 / numpy.pi) * (self.w / (f**2 + self.w**2))
|
||||
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.
|
||||
|
||||
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)
|
||||
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 to_flat_array(self) -> numpy.ndarray:
|
||||
return numpy.concatenate([self.p, self.s, numpy.array([self.w])])
|
||||
@ -78,69 +128,97 @@ class OscillatingDipoleArrangement:
|
||||
def __init__(self, dipoles: Sequence[OscillatingDipole]):
|
||||
self.dipoles = dipoles
|
||||
|
||||
def get_dot_measurement(self, dot_input: DotInput) -> DotMeasurement:
|
||||
def get_potential_dot_measurement(self, dot_input: DotInput) -> DotMeasurement:
|
||||
r = numpy.array(dot_input[0])
|
||||
f = dot_input[1]
|
||||
return DotMeasurement(
|
||||
sum([dipole.s_at_position(r, f) for dipole in self.dipoles]), r, f
|
||||
sum(
|
||||
[
|
||||
dipole.s_electric_potential_at_position(r, f)
|
||||
for dipole in self.dipoles
|
||||
]
|
||||
),
|
||||
r,
|
||||
f,
|
||||
)
|
||||
|
||||
def get_dot_pair_measurement(
|
||||
def get_potential_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_for_dot_pair(r1, r2, f) for dipole in self.dipoles]),
|
||||
sum(
|
||||
[
|
||||
dipole.s_electric_potential_for_dot_pair(r1, r2, f)
|
||||
for dipole in self.dipoles
|
||||
]
|
||||
),
|
||||
r1,
|
||||
r2,
|
||||
f,
|
||||
)
|
||||
|
||||
def get_dot_measurements(
|
||||
def get_potential_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_dot_measurement(dot_input) for dot_input in dot_inputs]
|
||||
return [
|
||||
self.get_potential_dot_measurement(dot_input) for dot_input in dot_inputs
|
||||
]
|
||||
|
||||
def get_dot_pair_measurements(
|
||||
def get_potential_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_dot_pair_measurement(dot_pair_input)
|
||||
self.get_potential_dot_pair_measurement(dot_pair_input)
|
||||
for dot_pair_input in dot_pair_inputs
|
||||
]
|
||||
|
||||
def get_percent_range_dot_measurement(
|
||||
def get_percent_range_potential_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_at_position(r, f) for dipole in self.dipoles]),
|
||||
high_percent * sum([dipole.s_at_position(r, f) for dipole in self.dipoles]),
|
||||
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
|
||||
]
|
||||
),
|
||||
r,
|
||||
f,
|
||||
)
|
||||
|
||||
def get_percent_range_dot_measurements(
|
||||
def get_percent_range_potential_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_dot_measurement(dot_input, low_percent, high_percent)
|
||||
self.get_percent_range_potential_dot_measurement(
|
||||
dot_input, low_percent, high_percent
|
||||
)
|
||||
for dot_input in dot_inputs
|
||||
]
|
||||
|
||||
def get_percent_range_dot_pair_measurement(
|
||||
def get_percent_range_potential_dot_pair_measurement(
|
||||
self, pair_input: DotPairInput, low_percent: float, high_percent: float
|
||||
) -> DotPairRangeMeasurement:
|
||||
r1 = numpy.array(pair_input[0])
|
||||
@ -148,15 +226,25 @@ class OscillatingDipoleArrangement:
|
||||
f = pair_input[2]
|
||||
return DotPairRangeMeasurement(
|
||||
low_percent
|
||||
* sum([dipole.s_for_dot_pair(r1, r2, f) for dipole in self.dipoles]),
|
||||
* sum(
|
||||
[
|
||||
dipole.s_electric_potential_for_dot_pair(r1, r2, f)
|
||||
for dipole in self.dipoles
|
||||
]
|
||||
),
|
||||
high_percent
|
||||
* sum([dipole.s_for_dot_pair(r1, r2, f) for dipole in self.dipoles]),
|
||||
* sum(
|
||||
[
|
||||
dipole.s_electric_potential_for_dot_pair(r1, r2, f)
|
||||
for dipole in self.dipoles
|
||||
]
|
||||
),
|
||||
r1,
|
||||
r2,
|
||||
f,
|
||||
)
|
||||
|
||||
def get_percent_range_dot_pair_measurements(
|
||||
def get_percent_range_potential_dot_pair_measurements(
|
||||
self,
|
||||
pair_inputs: Sequence[DotPairInput],
|
||||
low_percent: float,
|
||||
@ -166,7 +254,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_dot_pair_measurement(
|
||||
self.get_percent_range_potential_dot_pair_measurement(
|
||||
pair_input, low_percent, high_percent
|
||||
)
|
||||
for pair_input in pair_inputs
|
||||
|
@ -11,6 +11,10 @@ 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,
|
||||
)
|
||||
@ -21,5 +25,6 @@ __all__ = [
|
||||
"MultipleDipoleFixedMagnitudeModel",
|
||||
"RandomCountMultipleDipoleFixedMagnitudeModel",
|
||||
"LogSpacedRandomCountMultipleDipoleFixedMagnitudeModel",
|
||||
"LogSpacedRandomCountMultipleDipoleFixedMagnitudeXYModel",
|
||||
"LogSpacedRandomCountMultipleDipoleFixedMagnitudeFixedOrientationModel",
|
||||
]
|
||||
|
@ -5,6 +5,11 @@ from pdme.measurement import (
|
||||
OscillatingDipole,
|
||||
OscillatingDipoleArrangement,
|
||||
)
|
||||
import logging
|
||||
from typing import Optional
|
||||
import pdme.subspace_simulation
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LogSpacedRandomCountMultipleDipoleFixedMagnitudeFixedOrientationModel(
|
||||
@ -124,12 +129,14 @@ 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.
|
||||
px = dipoles[:, :, 0]
|
||||
py = dipoles[:, :, 1]
|
||||
pz = dipoles[:, :, 2]
|
||||
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)
|
||||
|
||||
sx = rng.uniform(self.xmin, self.xmax, shape)
|
||||
sy = rng.uniform(self.ymin, self.ymax, shape)
|
||||
@ -138,3 +145,51 @@ 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
|
||||
|
@ -5,6 +5,8 @@ from pdme.measurement import (
|
||||
OscillatingDipole,
|
||||
OscillatingDipoleArrangement,
|
||||
)
|
||||
import pdme.subspace_simulation
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class LogSpacedRandomCountMultipleDipoleFixedMagnitudeModel(DipoleModel):
|
||||
@ -125,3 +127,73 @@ 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
|
||||
|
183
pdme/model/log_spaced_random_choice_xy_model.py
Normal file
183
pdme/model/log_spaced_random_choice_xy_model.py
Normal file
@ -0,0 +1,183 @@
|
||||
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
|
@ -4,7 +4,8 @@ from pdme.measurement import (
|
||||
OscillatingDipoleArrangement,
|
||||
)
|
||||
import logging
|
||||
|
||||
import pdme.subspace_simulation
|
||||
from typing import List, Tuple, Optional
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@ -32,3 +33,131 @@ 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)
|
||||
|
74
pdme/subspace_simulation/__init__.py
Normal file
74
pdme/subspace_simulation/__init__.py
Normal file
@ -0,0 +1,74 @@
|
||||
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",
|
||||
]
|
30
pdme/subspace_simulation/mcmc_costs.py
Normal file
30
pdme/subspace_simulation/mcmc_costs.py
Normal file
@ -0,0 +1,30 @@
|
||||
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)
|
@ -45,7 +45,7 @@ def fast_s_nonlocal(
|
||||
_logger.debug(f"alphses1: {alphses1}")
|
||||
_logger.debug(f"alphses2: {alphses2}")
|
||||
|
||||
bses = (1 / numpy.pi) * (ws[:, None] / (f1s**2 + ws[:, None] ** 2))
|
||||
bses = 2 * ws[:, None] / ((numpy.pi * f1s) ** 2 + ws[:, None] ** 2)
|
||||
if _logger.isEnabledFor(logging.DEBUG):
|
||||
_logger.debug(f"bses: {bses}")
|
||||
|
||||
@ -58,43 +58,216 @@ 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}")
|
||||
|
||||
bses = (1 / numpy.pi) * (ws[:, None, :] / (f1s[:, None] ** 2 + ws[:, None, :] ** 2))
|
||||
# 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)
|
||||
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)
|
||||
|
@ -12,27 +12,44 @@ 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}")
|
||||
|
||||
bses = (1 / numpy.pi) * (ws[:, None] / (fs**2 + ws[:, None] ** 2))
|
||||
# [A, 1], denom [m] + [A, 1] -> [A, m]
|
||||
# [A, m]
|
||||
bses = 2 * ws[:, None] / ((numpy.pi * fs) ** 2 + ws[:, None] ** 2)
|
||||
|
||||
_logger.debug(f"bses: {bses}")
|
||||
# returns shape [A, m]
|
||||
return ases * bses
|
||||
|
||||
|
||||
@ -64,11 +81,170 @@ def fast_vs_for_dipoleses(
|
||||
ases = (numpy.einsum("abcd,acd->abc", diffses, ps) / norms) ** 2
|
||||
_logger.debug(f"ases: {ases}")
|
||||
|
||||
bses = (1 / numpy.pi) * (ws[:, None, :] / (fs[:, None] ** 2 + ws[:, None, :] ** 2))
|
||||
bses = 2 * ws[:, None, :] / ((numpy.pi * 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.
|
||||
|
440
poetry.lock
generated
440
poetry.lock
generated
@ -20,28 +20,6 @@ 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"
|
||||
@ -91,9 +69,17 @@ 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 = "6.4.1"
|
||||
version = "7.2.7"
|
||||
description = "Code coverage measurement for Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
@ -113,6 +99,17 @@ 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"
|
||||
@ -349,14 +346,6 @@ 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"
|
||||
@ -394,32 +383,30 @@ diagrams = ["jinja2", "railroad-diagrams"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "6.2.5"
|
||||
version = "7.4.0"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[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"
|
||||
py = ">=1.8.2"
|
||||
toml = "*"
|
||||
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
|
||||
|
||||
[package.extras]
|
||||
testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
|
||||
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-cov"
|
||||
version = "3.0.0"
|
||||
version = "4.1.0"
|
||||
description = "Pytest plugin for measuring coverage."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.dependencies]
|
||||
coverage = {version = ">=5.2.1", extras = ["toml"]}
|
||||
@ -430,14 +417,19 @@ testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtuale
|
||||
|
||||
[[package]]
|
||||
name = "scipy"
|
||||
version = "1.8.0"
|
||||
description = "SciPy: Scientific Library for Python"
|
||||
version = "1.10.0"
|
||||
description = "Fundamental algorithms for scientific computing in Python"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.8,<3.11"
|
||||
python-versions = "<3.12,>=3.8"
|
||||
|
||||
[package.dependencies]
|
||||
numpy = ">=1.17.3,<1.25.0"
|
||||
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"]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
@ -464,12 +456,16 @@ pure-eval = "*"
|
||||
tests = ["pytest", "typeguard", "pygments", "littleutils", "cython"]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.10.2"
|
||||
description = "Python Library for Tom's Obvious, Minimal Language"
|
||||
name = "syrupy"
|
||||
version = "4.0.8"
|
||||
description = "Pytest Snapshot Test Utility"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
python-versions = ">=3.8.1,<4"
|
||||
|
||||
[package.dependencies]
|
||||
colored = ">=1.3.92,<2.0.0"
|
||||
pytest = ">=7.0.0,<8.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
@ -508,307 +504,51 @@ python-versions = "*"
|
||||
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.8,<3.10"
|
||||
content-hash = "53a256043845daf5745f0553c31904a14dd3ea6c6fc9c6754fb4a8e949bed86a"
|
||||
python-versions = ">=3.8.1,<3.10"
|
||||
content-hash = "b5275c33449e8f85acbf9c0f6dfe1ec4e7296adfa16360d782b33534e1223638"
|
||||
|
||||
[metadata.files]
|
||||
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.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f1d5aa2703e1dab4ae6cf416eb0095304f49d004c39e9db1d86f57924f43006b"},
|
||||
{file = "coverage-6.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4ce1b258493cbf8aec43e9b50d89982346b98e9ffdfaae8ae5793bc112fb0068"},
|
||||
{file = "coverage-6.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83c4e737f60c6936460c5be330d296dd5b48b3963f48634c53b3f7deb0f34ec4"},
|
||||
{file = "coverage-6.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84e65ef149028516c6d64461b95a8dbcfce95cfd5b9eb634320596173332ea84"},
|
||||
{file = "coverage-6.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f69718750eaae75efe506406c490d6fc5a6161d047206cc63ce25527e8a3adad"},
|
||||
{file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e57816f8ffe46b1df8f12e1b348f06d164fd5219beba7d9433ba79608ef011cc"},
|
||||
{file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:01c5615d13f3dd3aa8543afc069e5319cfa0c7d712f6e04b920431e5c564a749"},
|
||||
{file = "coverage-6.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:75ab269400706fab15981fd4bd5080c56bd5cc07c3bccb86aab5e1d5a88dc8f4"},
|
||||
{file = "coverage-6.4.1-cp310-cp310-win32.whl", hash = "sha256:a7f3049243783df2e6cc6deafc49ea123522b59f464831476d3d1448e30d72df"},
|
||||
{file = "coverage-6.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:ee2ddcac99b2d2aec413e36d7a429ae9ebcadf912946b13ffa88e7d4c9b712d6"},
|
||||
{file = "coverage-6.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fb73e0011b8793c053bfa85e53129ba5f0250fdc0392c1591fd35d915ec75c46"},
|
||||
{file = "coverage-6.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:106c16dfe494de3193ec55cac9640dd039b66e196e4641fa8ac396181578b982"},
|
||||
{file = "coverage-6.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87f4f3df85aa39da00fd3ec4b5abeb7407e82b68c7c5ad181308b0e2526da5d4"},
|
||||
{file = "coverage-6.4.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:961e2fb0680b4f5ad63234e0bf55dfb90d302740ae9c7ed0120677a94a1590cb"},
|
||||
{file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cec3a0f75c8f1031825e19cd86ee787e87cf03e4fd2865c79c057092e69e3a3b"},
|
||||
{file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:129cd05ba6f0d08a766d942a9ed4b29283aff7b2cccf5b7ce279d50796860bb3"},
|
||||
{file = "coverage-6.4.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bf5601c33213d3cb19d17a796f8a14a9eaa5e87629a53979a5981e3e3ae166f6"},
|
||||
{file = "coverage-6.4.1-cp37-cp37m-win32.whl", hash = "sha256:269eaa2c20a13a5bf17558d4dc91a8d078c4fa1872f25303dddcbba3a813085e"},
|
||||
{file = "coverage-6.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f02cbbf8119db68455b9d763f2f8737bb7db7e43720afa07d8eb1604e5c5ae28"},
|
||||
{file = "coverage-6.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ffa9297c3a453fba4717d06df579af42ab9a28022444cae7fa605af4df612d54"},
|
||||
{file = "coverage-6.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:145f296d00441ca703a659e8f3eb48ae39fb083baba2d7ce4482fb2723e050d9"},
|
||||
{file = "coverage-6.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d44996140af8b84284e5e7d398e589574b376fb4de8ccd28d82ad8e3bea13"},
|
||||
{file = "coverage-6.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2bd9a6fc18aab8d2e18f89b7ff91c0f34ff4d5e0ba0b33e989b3cd4194c81fd9"},
|
||||
{file = "coverage-6.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3384f2a3652cef289e38100f2d037956194a837221edd520a7ee5b42d00cc605"},
|
||||
{file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9b3e07152b4563722be523e8cd0b209e0d1a373022cfbde395ebb6575bf6790d"},
|
||||
{file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1480ff858b4113db2718848d7b2d1b75bc79895a9c22e76a221b9d8d62496428"},
|
||||
{file = "coverage-6.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:865d69ae811a392f4d06bde506d531f6a28a00af36f5c8649684a9e5e4a85c83"},
|
||||
{file = "coverage-6.4.1-cp38-cp38-win32.whl", hash = "sha256:664a47ce62fe4bef9e2d2c430306e1428ecea207ffd68649e3b942fa8ea83b0b"},
|
||||
{file = "coverage-6.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:26dff09fb0d82693ba9e6231248641d60ba606150d02ed45110f9ec26404ed1c"},
|
||||
{file = "coverage-6.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d9c80df769f5ec05ad21ea34be7458d1dc51ff1fb4b2219e77fe24edf462d6df"},
|
||||
{file = "coverage-6.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:39ee53946bf009788108b4dd2894bf1349b4e0ca18c2016ffa7d26ce46b8f10d"},
|
||||
{file = "coverage-6.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5b66caa62922531059bc5ac04f836860412f7f88d38a476eda0a6f11d4724f4"},
|
||||
{file = "coverage-6.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd180ed867e289964404051a958f7cccabdeed423f91a899829264bb7974d3d3"},
|
||||
{file = "coverage-6.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84631e81dd053e8a0d4967cedab6db94345f1c36107c71698f746cb2636c63e3"},
|
||||
{file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8c08da0bd238f2970230c2a0d28ff0e99961598cb2e810245d7fc5afcf1254e8"},
|
||||
{file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d42c549a8f41dc103a8004b9f0c433e2086add8a719da00e246e17cbe4056f72"},
|
||||
{file = "coverage-6.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:309ce4a522ed5fca432af4ebe0f32b21d6d7ccbb0f5fcc99290e71feba67c264"},
|
||||
{file = "coverage-6.4.1-cp39-cp39-win32.whl", hash = "sha256:fdb6f7bd51c2d1714cea40718f6149ad9be6a2ee7d93b19e9f00934c0f2a74d9"},
|
||||
{file = "coverage-6.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:342d4aefd1c3e7f620a13f4fe563154d808b69cccef415415aece4c786665397"},
|
||||
{file = "coverage-6.4.1-pp36.pp37.pp38-none-any.whl", hash = "sha256:4803e7ccf93230accb928f3a68f00ffa80a88213af98ed338a57ad021ef06815"},
|
||||
{file = "coverage-6.4.1.tar.gz", hash = "sha256:4321f075095a096e70aff1d002030ee612b65a205a0a0f5b815280d5dc58100c"},
|
||||
]
|
||||
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.961-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:697540876638ce349b01b6786bc6094ccdaba88af446a9abb967293ce6eaa2b0"},
|
||||
{file = "mypy-0.961-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b117650592e1782819829605a193360a08aa99f1fc23d1d71e1a75a142dc7e15"},
|
||||
{file = "mypy-0.961-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bdd5ca340beffb8c44cb9dc26697628d1b88c6bddf5c2f6eb308c46f269bb6f3"},
|
||||
{file = "mypy-0.961-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3e09f1f983a71d0672bbc97ae33ee3709d10c779beb613febc36805a6e28bb4e"},
|
||||
{file = "mypy-0.961-cp310-cp310-win_amd64.whl", hash = "sha256:e999229b9f3198c0c880d5e269f9f8129c8862451ce53a011326cad38b9ccd24"},
|
||||
{file = "mypy-0.961-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b24be97351084b11582fef18d79004b3e4db572219deee0212078f7cf6352723"},
|
||||
{file = "mypy-0.961-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f4a21d01fc0ba4e31d82f0fff195682e29f9401a8bdb7173891070eb260aeb3b"},
|
||||
{file = "mypy-0.961-cp36-cp36m-win_amd64.whl", hash = "sha256:439c726a3b3da7ca84a0199a8ab444cd8896d95012c4a6c4a0d808e3147abf5d"},
|
||||
{file = "mypy-0.961-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5a0b53747f713f490affdceef835d8f0cb7285187a6a44c33821b6d1f46ed813"},
|
||||
{file = "mypy-0.961-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0e9f70df36405c25cc530a86eeda1e0867863d9471fe76d1273c783df3d35c2e"},
|
||||
{file = "mypy-0.961-cp37-cp37m-win_amd64.whl", hash = "sha256:b88f784e9e35dcaa075519096dc947a388319cb86811b6af621e3523980f1c8a"},
|
||||
{file = "mypy-0.961-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d5aaf1edaa7692490f72bdb9fbd941fbf2e201713523bdb3f4038be0af8846c6"},
|
||||
{file = "mypy-0.961-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9f5f5a74085d9a81a1f9c78081d60a0040c3efb3f28e5c9912b900adf59a16e6"},
|
||||
{file = "mypy-0.961-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f4b794db44168a4fc886e3450201365c9526a522c46ba089b55e1f11c163750d"},
|
||||
{file = "mypy-0.961-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:64759a273d590040a592e0f4186539858c948302c653c2eac840c7a3cd29e51b"},
|
||||
{file = "mypy-0.961-cp38-cp38-win_amd64.whl", hash = "sha256:63e85a03770ebf403291ec50097954cc5caf2a9205c888ce3a61bd3f82e17569"},
|
||||
{file = "mypy-0.961-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5f1332964963d4832a94bebc10f13d3279be3ce8f6c64da563d6ee6e2eeda932"},
|
||||
{file = "mypy-0.961-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:006be38474216b833eca29ff6b73e143386f352e10e9c2fbe76aa8549e5554f5"},
|
||||
{file = "mypy-0.961-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9940e6916ed9371809b35b2154baf1f684acba935cd09928952310fbddaba648"},
|
||||
{file = "mypy-0.961-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a5ea0875a049de1b63b972456542f04643daf320d27dc592d7c3d9cd5d9bf950"},
|
||||
{file = "mypy-0.961-cp39-cp39-win_amd64.whl", hash = "sha256:1ece702f29270ec6af25db8cf6185c04c02311c6bb21a69f423d40e527b75c56"},
|
||||
{file = "mypy-0.961-py3-none-any.whl", hash = "sha256:03c6cc893e7563e7b2949b969e63f02c000b32502a1b4d1314cabe391aa87d66"},
|
||||
{file = "mypy-0.961.tar.gz", hash = "sha256:f730d56cb924d371c26b8eaddeea3cc07d78ff51c521c6d04899ac6904b75492"},
|
||||
]
|
||||
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"},
|
||||
]
|
||||
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 = []
|
||||
|
@ -1,23 +1,24 @@
|
||||
[tool.poetry]
|
||||
name = "pdme"
|
||||
version = "0.8.6"
|
||||
version = "1.5.0"
|
||||
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,<3.10"
|
||||
python = ">=3.8.1,<3.10"
|
||||
numpy = "^1.22.3"
|
||||
scipy = "~1.8"
|
||||
scipy = "~1.10"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
pytest = ">=6"
|
||||
flake8 = "^4.0.0"
|
||||
pytest-cov = "^3.0.0"
|
||||
pytest-cov = "^4.1.0"
|
||||
mypy = "^0.961"
|
||||
ipython = "^8.2.0"
|
||||
black = "^22.3.0"
|
||||
syrupy = "^4.0.8"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
@ -27,6 +28,8 @@ build-backend = "poetry.core.masonry.api"
|
||||
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"
|
||||
|
@ -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);
|
||||
|
81
tests/calculations/__snapshots__/test_calculations.ambr
Normal file
81
tests/calculations/__snapshots__/test_calculations.ambr
Normal file
@ -0,0 +1,81 @@
|
||||
# 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,
|
||||
])
|
||||
# ---
|
102
tests/calculations/test_calculations.py
Normal file
102
tests/calculations/test_calculations.py
Normal file
@ -0,0 +1,102 @@
|
||||
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
|
@ -2,23 +2,30 @@ import numpy
|
||||
import pdme.measurement
|
||||
|
||||
|
||||
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)
|
||||
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
|
||||
)
|
||||
dipoles = pdme.measurement.OscillatingDipoleArrangement([d1, d2])
|
||||
|
||||
dot_position1 = (-1, -1, -1)
|
||||
dot_position1 = numpy.array([-1, -1, -1])
|
||||
dot_frequency1 = 11
|
||||
expected_v1 = 0.00001421963287022476
|
||||
expected_v2 = 0.00001107180225755457
|
||||
|
||||
expected_v1 = 0.00001221710876727626
|
||||
expected_v2 = 7.257229625870065e-6
|
||||
|
||||
numpy.testing.assert_allclose(
|
||||
d1.s_at_position(dot_position1, dot_frequency1),
|
||||
d1.s_electric_potential_at_position(dot_position1, dot_frequency1),
|
||||
expected_v1,
|
||||
err_msg="Voltage at dot isn't as expected.",
|
||||
)
|
||||
|
||||
dot_measurements = dipoles.get_dot_measurements([(dot_position1, dot_frequency1)])
|
||||
dot_measurements = dipoles.get_potential_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(
|
||||
@ -38,24 +45,57 @@ def test_static_dipole():
|
||||
)
|
||||
|
||||
|
||||
def test_dipole_dot_pair():
|
||||
d1 = pdme.measurement.OscillatingDipole((1, 2, 3), (4, 5, 6), 7)
|
||||
dipoles = pdme.measurement.OscillatingDipoleArrangement([d1])
|
||||
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 = (-1, -1, -1)
|
||||
dot_position2 = (1, 2, 3)
|
||||
dot_frequency = 8
|
||||
expected_sij = 0.000083328037100902801698
|
||||
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_for_dot_pair(dot_position1, dot_position2, dot_frequency),
|
||||
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
|
||||
)
|
||||
dipoles = pdme.measurement.OscillatingDipoleArrangement([d1])
|
||||
|
||||
dot_position1 = numpy.array([-1, -1, -1])
|
||||
dot_position2 = numpy.array([1, 2, 3])
|
||||
dot_frequency = 8
|
||||
expected_sij = 0.00008692058236162933
|
||||
|
||||
numpy.testing.assert_allclose(
|
||||
d1.s_electric_potential_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_dot_pair_measurements(
|
||||
for m in dipoles.get_potential_dot_pair_measurements(
|
||||
[(dot_position1, dot_position2, dot_frequency)]
|
||||
)
|
||||
],
|
||||
@ -65,15 +105,17 @@ def test_dipole_dot_pair():
|
||||
|
||||
|
||||
def test_range_pairs():
|
||||
d1 = pdme.measurement.OscillatingDipole((1, 2, 3), (4, 5, 6), 7)
|
||||
d1 = pdme.measurement.OscillatingDipole(
|
||||
numpy.array([1, 2, 3]), numpy.array([4, 5, 6]), 7
|
||||
)
|
||||
dipoles = pdme.measurement.OscillatingDipoleArrangement([d1])
|
||||
|
||||
dot_position1 = (-1, -1, -1)
|
||||
dot_position2 = (1, 2, 3)
|
||||
dot_position1 = numpy.array([-1, -1, -1])
|
||||
dot_position2 = numpy.array([1, 2, 3])
|
||||
dot_frequency = 8
|
||||
expected_sij = 0.000083328037100902801698
|
||||
expected_sij = 0.00008692058236162933
|
||||
|
||||
actuals = dipoles.get_percent_range_dot_pair_measurements(
|
||||
actuals = dipoles.get_percent_range_potential_dot_pair_measurements(
|
||||
[(dot_position1, dot_position2, dot_frequency)], 0.5, 1.5
|
||||
)
|
||||
assert len(actuals) == 1, "should have only been one pair"
|
||||
@ -86,22 +128,26 @@ def test_range_pairs():
|
||||
|
||||
|
||||
def test_range_dipole_measurements():
|
||||
d1 = pdme.measurement.OscillatingDipole((1, 2, 3), (4, 5, 6), 7)
|
||||
d2 = pdme.measurement.OscillatingDipole((2, 5, 3), (4, -5, -6), 2)
|
||||
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 = (-1, -1, -1)
|
||||
dot_position1 = numpy.array([-1, -1, -1])
|
||||
dot_frequency1 = 11
|
||||
expected_v1 = 0.00001421963287022476
|
||||
expected_v2 = 0.00001107180225755457
|
||||
expected_v1 = 0.00001221710876727626
|
||||
expected_v2 = 7.257229625870065e-6
|
||||
|
||||
numpy.testing.assert_allclose(
|
||||
d1.s_at_position(dot_position1, dot_frequency1),
|
||||
d1.s_electric_potential_at_position(dot_position1, dot_frequency1),
|
||||
expected_v1,
|
||||
err_msg="Voltage at dot isn't as expected.",
|
||||
)
|
||||
|
||||
range_dot_measurements = dipoles.get_percent_range_dot_measurements(
|
||||
range_dot_measurements = dipoles.get_percent_range_potential_dot_measurements(
|
||||
[(dot_position1, dot_frequency1)], 0.5, 1.5
|
||||
)
|
||||
assert len(range_dot_measurements) == 1, "Should have only had one dot measurement."
|
||||
|
@ -0,0 +1,55 @@
|
||||
# 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]]),
|
||||
),
|
||||
])
|
||||
# ---
|
@ -0,0 +1,55 @@
|
||||
# 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]]),
|
||||
),
|
||||
])
|
||||
# ---
|
@ -0,0 +1,55 @@
|
||||
# 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]]),
|
||||
),
|
||||
])
|
||||
# ---
|
@ -0,0 +1,31 @@
|
||||
# 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,
|
||||
]),
|
||||
]),
|
||||
])
|
||||
# ---
|
@ -0,0 +1,100 @@
|
||||
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
|
@ -0,0 +1,100 @@
|
||||
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
|
108
tests/model/test_log_spaced_fixed_orientation_mcmc.py
Normal file
108
tests/model/test_log_spaced_fixed_orientation_mcmc.py
Normal file
@ -0,0 +1,108 @@
|
||||
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
|
@ -0,0 +1,206 @@
|
||||
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",
|
||||
)
|
@ -115,8 +115,7 @@ 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():
|
||||
# TODO: this test is a bit garbage just calls things without testing.
|
||||
def test_random_count_multiple_dipole_fixed_or_fixed_mag_model_get_n_dipoles(snapshot):
|
||||
x_min = -10
|
||||
x_max = 10
|
||||
y_min = -5
|
||||
@ -145,7 +144,9 @@ def test_random_count_multiple_dipole_fixed_or_fixed_mag_model_get_n_dipoles():
|
||||
)
|
||||
model.rng = numpy.random.default_rng(1234)
|
||||
|
||||
model.get_monte_carlo_dipole_inputs(1, max_frequency)
|
||||
model.get_monte_carlo_dipole_inputs(
|
||||
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(
|
||||
1, max_frequency, numpy.random.default_rng(1234)
|
||||
)
|
||||
assert actual_monte_carlo_inputs.tolist() == snapshot
|
||||
|
4
tests/subspace_simulation/__snapshots__/test_costs.ambr
Normal file
4
tests/subspace_simulation/__snapshots__/test_costs.ambr
Normal file
@ -0,0 +1,4 @@
|
||||
# serializer version: 1
|
||||
# name: test_proportional_costs
|
||||
7000.0
|
||||
# ---
|
@ -0,0 +1,94 @@
|
||||
# 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,
|
||||
]),
|
||||
]),
|
||||
])
|
||||
# ---
|
22
tests/subspace_simulation/__snapshots__/test_stdevs.ambr
Normal file
22
tests/subspace_simulation/__snapshots__/test_stdevs.ambr
Normal file
@ -0,0 +1,22 @@
|
||||
# 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)
|
||||
# ---
|
31
tests/subspace_simulation/test_costs.py
Normal file
31
tests/subspace_simulation/test_costs.py
Normal file
@ -0,0 +1,31 @@
|
||||
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)
|
40
tests/subspace_simulation/test_sort_dipoles.py
Normal file
40
tests/subspace_simulation/test_sort_dipoles.py
Normal file
@ -0,0 +1,40 @@
|
||||
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
|
38
tests/subspace_simulation/test_stdevs.py
Normal file
38
tests/subspace_simulation/test_stdevs.py
Normal file
@ -0,0 +1,38 @@
|
||||
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
|
20
tests/util/__snapshots__/test_fast_nonlocal_spectrum.ambr
Normal file
20
tests/util/__snapshots__/test_fast_nonlocal_spectrum.ambr
Normal file
@ -0,0 +1,20 @@
|
||||
# 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,
|
||||
]),
|
||||
])
|
||||
# ---
|
@ -0,0 +1,25 @@
|
||||
# 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,
|
||||
]),
|
||||
])
|
||||
# ---
|
@ -1,9 +1,24 @@
|
||||
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]
|
||||
@ -16,21 +31,11 @@ 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(
|
||||
[
|
||||
[expected_11, expected_21],
|
||||
[expected_12, expected_22],
|
||||
[expected_13, expected_23],
|
||||
[expected_14, expected_24],
|
||||
[s_potential_from_arrays(dipole_array, dot_pair) for dot_pair in dot_pairs]
|
||||
for dipole_array in dipoles
|
||||
]
|
||||
)
|
||||
|
||||
@ -53,3 +58,11 @@ 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
|
||||
|
@ -1,8 +1,25 @@
|
||||
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]
|
||||
@ -16,19 +33,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(
|
||||
[
|
||||
[expected_11 + expected_12, expected_21 + expected_22],
|
||||
[expected_13 + expected_14, expected_23 + expected_24],
|
||||
[
|
||||
sum(
|
||||
[
|
||||
s_potential_from_arrays(dipole_array, dot_pair)
|
||||
for dipole_array in dipoles
|
||||
]
|
||||
)
|
||||
for dot_pair in dot_pairs
|
||||
]
|
||||
for dipoles in dipoleses
|
||||
]
|
||||
)
|
||||
|
||||
@ -53,3 +70,44 @@ 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
|
||||
|
@ -1,6 +1,30 @@
|
||||
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]
|
||||
@ -9,11 +33,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_ij is for dot i, dipole j
|
||||
expected_11 = 0.00001421963287022476
|
||||
expected_12 = 0.00001107180225755457
|
||||
expected_21 = 0.000345021108583681380388722
|
||||
expected_22 = 0.0000377061050587914705139781
|
||||
|
||||
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 = numpy.array([[expected_11, expected_21], [expected_12, expected_22]])
|
||||
|
||||
@ -31,11 +55,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_ij is for dot i, dipole j
|
||||
expected_11 = 0.00001421963287022476
|
||||
expected_12 = 0.00001107180225755457
|
||||
expected_21 = 0.000345021108583681380388722
|
||||
expected_22 = 0.0000377061050587914705139781
|
||||
|
||||
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 = numpy.array([[expected_11 + expected_12, expected_21 + expected_22]])
|
||||
|
||||
@ -48,7 +72,7 @@ def test_fast_v_calc_multidipoles():
|
||||
|
||||
def test_fast_v_calc_big_multidipole():
|
||||
|
||||
dipoles = numpy.array(
|
||||
dipoleses = numpy.array(
|
||||
[
|
||||
[
|
||||
[1, 1, 5, 6, 3, 1, 1],
|
||||
@ -72,27 +96,113 @@ def test_fast_v_calc_big_multidipole():
|
||||
]
|
||||
)
|
||||
|
||||
expected = numpy.array(
|
||||
expected = [
|
||||
[
|
||||
sum(
|
||||
[
|
||||
s_potential_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_vs_for_dipoleses(dot_inputs, dipoleses),
|
||||
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(
|
||||
[
|
||||
[
|
||||
0.0010151687742365581690202135,
|
||||
0.00077627527320628609782627266,
|
||||
0.00043313471258511003340648713,
|
||||
0.000077184305988088453637005111,
|
||||
[1, 1, 5, 6, 3, 1, 1],
|
||||
[5, 3, 2, 13, 1, 1, 2],
|
||||
[-5, -5, -3, -1, -3, 8, 3],
|
||||
],
|
||||
[
|
||||
0.000041099091967966890657097060,
|
||||
0.0019377687238977568792327845,
|
||||
0.0085903193415282984161225029,
|
||||
0.00014557676715208209310911838,
|
||||
[-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_vs_for_dipoleses(dot_inputs, dipoles),
|
||||
pdme.util.fast_v_calc.fast_efieldxs_for_dipoleses(dot_inputs, dipoleses),
|
||||
expected,
|
||||
err_msg="Voltages at dot aren't as expected for multidipole calc.",
|
||||
err_msg="E x fast calc at dot aren't as expected for multidipole calc.",
|
||||
)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user