Compare commits

...

66 Commits
0.1.3 ... 0.5.0

Author SHA1 Message Date
3dca288177 chore(release): 0.5.0
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
gitea-physics/deepdog/pipeline/tag This commit looks good
2022-04-30 11:19:38 -05:00
bd0b375751 Merge pull request 'betterparallel' (#7) from betterparallel into master
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
Reviewed-on: #7
2022-04-30 16:15:01 +00:00
0fabd8f7fb Merge branch 'master' into betterparallel
All checks were successful
gitea-physics/deepdog/pipeline/pr-master This commit looks good
2022-04-30 16:10:15 +00:00
3ea3d1dc56 Merge pull request 'chore(deps): update dependency mypy to ^0.950' (#6) from renovate/mypy-0.x into master
Some checks reported errors
gitea-physics/deepdog/pipeline/head Something is wrong with the build of this commit
Reviewed-on: #6
2022-04-30 16:08:57 +00:00
edf0ba6532 feat: has better parallelisation
Some checks are pending
gitea-physics/deepdog/pipeline/head Build started...
gitea-physics/deepdog/pipeline/pr-master Build queued...
2022-04-30 10:36:10 -05:00
a487309549 chore(deps): update dependency mypy to ^0.950
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
gitea-physics/deepdog/pipeline/pr-master This commit looks good
2022-04-28 01:31:10 +00:00
42829c0327 fix: better parallelisation hopefully
Some checks reported errors
gitea-physics/deepdog/pipeline/head Something is wrong with the build of this commit
2022-04-24 12:13:10 -05:00
349341b405 fix: Uses correct filename arg for passed in rng
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
2022-04-18 16:00:19 -05:00
50dbc4835e feat!: simulpairs now uses different rng calculator 2022-04-18 12:04:30 -05:00
0954429e2d fix: stronger names 2022-04-16 13:11:08 -05:00
4c06b3912c fix: uses correct filename for pairs guy
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
2022-04-16 13:04:39 -05:00
5684af783e fmt: Adds newlines to make fmt idempotent 2022-04-16 13:04:11 -05:00
f00b29391c style: run doo fmt
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
2022-04-16 12:55:52 -05:00
492a5e6681 fix: Makes altbayessimulpairs available in package 2022-04-16 12:55:29 -05:00
e9277c3da7 feat: adds simulpairs run 2022-04-16 12:54:30 -05:00
1e2657adad chore: adds doo fmt 2022-04-16 12:51:31 -05:00
f168666045 chore(release): 0.4.0
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
gitea-physics/deepdog/pipeline/tag This commit looks good
2022-04-10 10:21:47 -05:00
604916a829 Merge pull request 'pairs' (#5) from pairs into master
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
Reviewed-on: #5
2022-04-10 15:20:05 +00:00
941313a14c style: whitespace fixes
All checks were successful
gitea-physics/deepdog/pipeline/pr-master This commit looks good
2022-04-10 10:05:15 -05:00
cb64c0b7b6 Merge branch 'master' into pairs 2022-04-10 10:03:47 -05:00
ec7b4cac39 feat: Adds dynamic cycle count increases to help reach minimum success count
Some checks failed
gitea-physics/deepdog/pipeline/pr-master There was a failure building this commit
2022-03-28 15:46:40 -05:00
31e6cfaf51 lint: lint fixes
Some checks failed
gitea-physics/deepdog/pipeline/head This commit looks good
gitea-physics/deepdog/pipeline/pr-master There was a failure building this commit
2022-03-28 12:28:24 -05:00
c1c711f47b fix: uses bigfix from pdme for negatives
Some checks failed
gitea-physics/deepdog/pipeline/head There was a failure building this commit
2022-03-28 10:52:28 -05:00
6463b135ef feat!: Adds pair calculations, with changing api format
Some checks reported errors
gitea-physics/deepdog/pipeline/head Something is wrong with the build of this commit
2022-03-27 19:01:14 -05:00
a283cbd670 Merge pull request 'chore(deps): update dependency mypy to ^0.942' (#3) from renovate/mypy-0.x into master
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
Reviewed-on: #3
2022-03-25 13:15:07 +00:00
0b45172ca0 chore(deps): update dependency mypy to ^0.942
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
gitea-physics/deepdog/pipeline/pr-master This commit looks good
2022-03-25 01:30:47 +00:00
b6383d0a47 Merge pull request 'chore(deps): update dependency mypy to ^0.941' (#2) from renovate/mypy-0.x into master
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
Reviewed-on: #2
2022-03-19 00:54:39 +00:00
450d8e0ec9 chore(deps): update dependency mypy to ^0.941
All checks were successful
gitea-physics/deepdog/pipeline/pr-master This commit looks good
2022-03-15 01:30:59 +00:00
f81904a898 chore(release): 0.3.5
All checks were successful
gitea-physics/deepdog/pipeline/tag This commit looks good
gitea-physics/deepdog/pipeline/head This commit looks good
2022-03-06 18:42:26 -06:00
88d961313c feat: makes chunksize configurable
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
2022-03-06 18:42:05 -06:00
fa82caa752 chore(release): 0.3.4
All checks were successful
gitea-physics/deepdog/pipeline/tag This commit looks good
gitea-physics/deepdog/pipeline/head This commit looks good
2022-03-06 17:31:47 -06:00
0784cd53d7 feat: Changes chunksize for multiprocessing
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
2022-03-06 17:31:17 -06:00
fb4b012491 chore(release): 0.3.3
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
gitea-physics/deepdog/pipeline/tag This commit looks good
2022-03-06 17:23:15 -06:00
8617e4d274 fix: Fixes count to use cycles as well
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
2022-03-06 17:22:52 -06:00
fe2af1644e chore(release): 0.3.2
All checks were successful
gitea-physics/deepdog/pipeline/tag This commit looks good
gitea-physics/deepdog/pipeline/head This commit looks good
2022-03-06 17:18:42 -06:00
e6d8d33c27 feat: Adds monte carlo cycles to trade off space and cpu 2022-03-06 17:18:24 -06:00
e00dc95f02 docs: readme badges
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
2022-03-06 16:48:49 -06:00
527be26fb2 chore(release): 0.3.1
All checks were successful
gitea-physics/deepdog/pipeline/tag This commit looks good
gitea-physics/deepdog/pipeline/head This commit looks good
2022-03-06 16:45:45 -06:00
456c81bca5 Merge branch 'master' of ssh://gitea.deepak.science:2222/physics/deepdog 2022-03-06 16:45:16 -06:00
7284dbeb34 feat: Adds alt bayes solver with monte carlo sampler 2022-03-06 16:45:09 -06:00
d078004773 feat: Updates to pdme version for faster bayes resolution 2022-03-06 15:53:49 -06:00
0441cde421 chore: adds release to do.sh 2022-03-06 15:51:32 -06:00
a9e91779bc chore: adds standard-version release stuff 2022-03-06 15:50:39 -06:00
751bc66704 Merge pull request 'Configure Renovate' (#1) from renovate/configure into master
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
Reviewed-on: #1
2022-02-23 19:44:38 +00:00
413ff16acc chore(deps): add renovate.json 2022-02-23 19:42:04 +00:00
5118173f09 chore: Adds semantic release to dev dependencies
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
2022-02-14 10:00:59 -06:00
semantic-release
6dfc26104a 0.3.0
Some checks reported errors
gitea-physics/deepdog/pipeline/head This commit looks good
gitea-physics/deepdog/pipeline/tag Something is wrong with the build of this commit
Automatically generated by python-semantic-release
2022-02-14 09:57:42 -06:00
3a6be738b1 feat: Actually uses probabilities to update bayes
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
2022-02-14 09:51:02 -06:00
bd240900b4 fix: Actually logs end threshold 2022-02-14 09:50:08 -06:00
0e1fbec043 fix: Fixes bug with end_threshold and better error logging 2022-02-14 09:44:04 -06:00
3d3b1a83f6 feat: Adds end threshold for early abort 2022-02-14 09:27:40 -06:00
63cecba824 Created version 0.2.4
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
gitea-physics/deepdog/pipeline/tag This commit looks good
2022-02-06 19:50:07 -06:00
344998835d fix: Fixes linting 2022-02-06 19:49:02 -06:00
838aeb0cf3 Created version 0.2.3
Some checks failed
gitea-physics/deepdog/pipeline/head There was a failure building this commit
gitea-physics/deepdog/pipeline/tag There was a failure building this commit
2022-02-06 19:46:10 -06:00
e715d329fd fix: diagnostic adds frequencies 2022-02-06 19:46:05 -06:00
521b49f14c Created version 0.2.2
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
gitea-physics/deepdog/pipeline/tag This commit looks good
2022-02-06 19:37:15 -06:00
6d65e8dec5 fix: ignores extra fields in dictwriter 2022-02-06 19:36:59 -06:00
36354c2f2c Adds patch
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
gitea-physics/deepdog/pipeline/tag This commit looks good
2022-02-06 19:29:17 -06:00
3534593557 fix: Take first element of solution list 2022-02-06 19:28:54 -06:00
6ada52f82c Minor version bump
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
gitea-physics/deepdog/pipeline/tag This commit looks good
2022-02-06 19:03:24 -06:00
34e124b18f feat: Adds better diagnostic of full dipole info 2022-02-06 19:03:04 -06:00
c1591c9ce9 Created version 0.1.5
All checks were successful
gitea-physics/deepdog/pipeline/tag This commit looks good
gitea-physics/deepdog/pipeline/head This commit looks good
2022-01-30 20:53:48 -06:00
10358287d9 Makes frequency cappable
Some checks reported errors
gitea-physics/deepdog/pipeline/head Something is wrong with the build of this commit
2022-01-30 20:52:32 -06:00
d4f6e2f99e Created version 0.1.4
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
gitea-physics/deepdog/pipeline/tag This commit looks good
2022-01-24 11:13:29 -06:00
d64939f346 Don't break the build
All checks were successful
gitea-physics/deepdog/pipeline/head This commit looks good
2022-01-24 11:13:24 -06:00
0c6490dad7 Small fix t ocsv headers and also adds init for better imports
Some checks reported errors
gitea-physics/deepdog/pipeline/head Something is wrong with the build of this commit
2022-01-24 11:12:54 -06:00
16 changed files with 1905 additions and 211 deletions

10
.versionrc Normal file
View File

@@ -0,0 +1,10 @@
{
"bumpFiles": [
{
"filename": "pyproject.toml",
"updater": "scripts/standard-version/pyproject-updater.js"
}
],
"sign": true,
"tag-prefix": ""
}

78
CHANGELOG.md Normal file
View File

@@ -0,0 +1,78 @@
# Changelog
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.
## [0.5.0](https://gitea.deepak.science:2222/physics/deepdog/compare/0.4.0...0.5.0) (2022-04-30)
### ⚠ BREAKING CHANGES
* simulpairs now uses different rng calculator
### Features
* adds simulpairs run ([e9277c3](https://gitea.deepak.science:2222/physics/deepdog/commit/e9277c3da777359feb352c0b19f3bb029248ba2f))
* has better parallelisation ([edf0ba6](https://gitea.deepak.science:2222/physics/deepdog/commit/edf0ba6532c0588fce32341709cdb70e384b83f4))
* simulpairs now uses different rng calculator ([50dbc48](https://gitea.deepak.science:2222/physics/deepdog/commit/50dbc4835e60bace9e9b4ba37415f073a3c9e479))
### Bug Fixes
* better parallelisation hopefully ([42829c0](https://gitea.deepak.science:2222/physics/deepdog/commit/42829c0327e080e18be2fb75e746f6ac0d7c2f6d))
* Makes altbayessimulpairs available in package ([492a5e6](https://gitea.deepak.science:2222/physics/deepdog/commit/492a5e6681c85f95840e28cfd5d4ce4ca1d54eba))
* stronger names ([0954429](https://gitea.deepak.science:2222/physics/deepdog/commit/0954429e2d015a105ff16dfbb9e7a352bf53e5e9))
* Uses correct filename arg for passed in rng ([349341b](https://gitea.deepak.science:2222/physics/deepdog/commit/349341b405375a43b933f1fd7db4ee9fc501def3))
* uses correct filename for pairs guy ([4c06b39](https://gitea.deepak.science:2222/physics/deepdog/commit/4c06b3912c811c93c310b1d9e4c153f2014c4f8b))
## [0.4.0](https://gitea.deepak.science:2222/physics/deepdog/compare/0.3.5...0.4.0) (2022-04-10)
### ⚠ BREAKING CHANGES
* Adds pair calculations, with changing api format
### Features
* Adds dynamic cycle count increases to help reach minimum success count ([ec7b4ca](https://gitea.deepak.science:2222/physics/deepdog/commit/ec7b4cac393c15e94c513215c4f1ba32be2ae87a))
* Adds pair calculations, with changing api format ([6463b13](https://gitea.deepak.science:2222/physics/deepdog/commit/6463b135ef2d212b565864b5ac1b655e014d2194))
### Bug Fixes
* uses bigfix from pdme for negatives ([c1c711f](https://gitea.deepak.science:2222/physics/deepdog/commit/c1c711f47b574d3a9b8a24dbcbdd7f50b9be8ea9))
### [0.3.5](https://gitea.deepak.science:2222/physics/deepdog/compare/0.3.4...0.3.5) (2022-03-07)
### Features
* makes chunksize configurable ([88d9613](https://gitea.deepak.science:2222/physics/deepdog/commit/88d961313c1db0d49fd96939aa725a8706fa0412))
### [0.3.4](https://gitea.deepak.science:2222/physics/deepdog/compare/0.3.3...0.3.4) (2022-03-06)
### Features
* Changes chunksize for multiprocessing ([0784cd5](https://gitea.deepak.science:2222/physics/deepdog/commit/0784cd53d79e00684506604f094b5d820b3994d4))
### [0.3.3](https://gitea.deepak.science:2222/physics/deepdog/compare/0.3.2...0.3.3) (2022-03-06)
### Bug Fixes
* Fixes count to use cycles as well ([8617e4d](https://gitea.deepak.science:2222/physics/deepdog/commit/8617e4d2742b112cc824068150682ce3b2cdd879))
### [0.3.2](https://gitea.deepak.science:2222/physics/deepdog/compare/0.3.1...0.3.2) (2022-03-06)
### Features
* Adds monte carlo cycles to trade off space and cpu ([e6d8d33](https://gitea.deepak.science:2222/physics/deepdog/commit/e6d8d33c27e7922581e91c10de4f5faff2a51f8b))
### [0.3.1](https://gitea.deepak.science:2222/physics/deepdog/compare/v0.3.0...v0.3.1) (2022-03-06)
### Features
* Adds alt bayes solver with monte carlo sampler ([7284dbe](https://gitea.deepak.science:2222/physics/deepdog/commit/7284dbeb34ef46189d81fb719252dfa74b8e9fa8))
* Updates to pdme version for faster bayes resolution ([d078004](https://gitea.deepak.science:2222/physics/deepdog/commit/d078004773d9d9dccd0a9a52ca96aa57690f9b7e))

View File

@@ -1,3 +1,18 @@
# deepdog # deepdog
The dipole diagnostic tool. [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-green.svg?style=flat-square)](https://conventionalcommits.org)
[![PyPI](https://img.shields.io/pypi/v/deepdog?style=flat-square)](https://pypi.org/project/deepdog/)
[![Jenkins](https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fjenkins.deepak.science%2Fjob%2Fgitea-physics%2Fjob%2Fdeepdog%2Fjob%2Fmaster&style=flat-square)](https://jenkins.deepak.science/job/gitea-physics/job/deepdog/job/master/)
![Jenkins tests](https://img.shields.io/jenkins/tests?compact_message&jobUrl=https%3A%2F%2Fjenkins.deepak.science%2Fjob%2Fgitea-physics%2Fjob%2Fdeepdog%2Fjob%2Fmaster%2F&style=flat-square)
![Jenkins Coverage](https://img.shields.io/jenkins/coverage/cobertura?jobUrl=https%3A%2F%2Fjenkins.deepak.science%2Fjob%2Fgitea-physics%2Fjob%2Fdeepdog%2Fjob%2Fmaster%2F&style=flat-square)
![Maintenance](https://img.shields.io/maintenance/yes/2022?style=flat-square)
The DiPole DiaGnostic tool.
## Getting started
`poetry install` to start locally
Commit using [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/), and when commits are on master, release with `doo release`.

View File

@@ -1,13 +1,22 @@
import logging import logging
from deepdog.meta import __version__ from deepdog.meta import __version__
from deepdog.bayes_run import BayesRun from deepdog.bayes_run import BayesRun
from deepdog.alt_bayes_run import AltBayesRun
from deepdog.alt_bayes_run_simulpairs import AltBayesRunSimulPairs
from deepdog.diagnostic import Diagnostic
def get_version(): def get_version():
return __version__ return __version__
__all__ = ["get_version", "BayesRun"] __all__ = [
"get_version",
"BayesRun",
"AltBayesRun",
"AltBayesRunSimulPairs",
"Diagnostic",
]
logging.getLogger(__name__).addHandler(logging.NullHandler()) logging.getLogger(__name__).addHandler(logging.NullHandler())

307
deepdog/alt_bayes_run.py Normal file
View File

@@ -0,0 +1,307 @@
import pdme.inputs
import pdme.model
import pdme.measurement.input_types
import pdme.measurement.oscillating_dipole
import pdme.util.fast_v_calc
import pdme.util.fast_nonlocal_spectrum
from typing import Sequence, Tuple, List
import datetime
import csv
import multiprocessing
import logging
import numpy
# TODO: remove hardcode
CHUNKSIZE = 50
# TODO: It's garbage to have this here duplicated from pdme.
DotInput = Tuple[numpy.typing.ArrayLike, float]
_logger = logging.getLogger(__name__)
def get_a_result(input) -> int:
discretisation, dot_inputs, lows, highs, monte_carlo_count, max_frequency = input
sample_dipoles = discretisation.get_model().get_n_single_dipoles(
monte_carlo_count, max_frequency
)
vals = pdme.util.fast_v_calc.fast_vs_for_dipoles(dot_inputs, sample_dipoles)
return numpy.count_nonzero(pdme.util.fast_v_calc.between(vals, lows, highs))
def get_a_result_using_pairs(input) -> int:
(
discretisation,
dot_inputs,
pair_inputs,
local_lows,
local_highs,
nonlocal_lows,
nonlocal_highs,
monte_carlo_count,
max_frequency,
) = input
sample_dipoles = discretisation.get_model().get_n_single_dipoles(
monte_carlo_count, max_frequency
)
local_vals = pdme.util.fast_v_calc.fast_vs_for_dipoles(dot_inputs, sample_dipoles)
local_matches = pdme.util.fast_v_calc.between(local_vals, local_lows, local_highs)
nonlocal_vals = pdme.util.fast_nonlocal_spectrum.fast_s_nonlocal(
pair_inputs, sample_dipoles
)
nonlocal_matches = pdme.util.fast_v_calc.between(
nonlocal_vals, nonlocal_lows, nonlocal_highs
)
combined_matches = numpy.logical_and(local_matches, nonlocal_matches)
return numpy.count_nonzero(combined_matches)
class AltBayesRun:
"""
A single Bayes run for a given set of dots.
Parameters
----------
dot_inputs : Sequence[DotInput]
The dot inputs for this bayes run.
discretisations_with_names : Sequence[Tuple(str, pdme.model.Model)]
The models to evaluate.
actual_model_discretisation : pdme.model.Discretisation
The discretisation for the model which is actually correct.
filename_slug : str
The filename slug to include.
run_count: int
The number of runs to do.
"""
def __init__(
self,
dot_positions: Sequence[numpy.typing.ArrayLike],
frequency_range: Sequence[float],
discretisations_with_names: Sequence[Tuple[str, pdme.model.Discretisation]],
actual_model: pdme.model.Model,
filename_slug: str,
run_count: int = 100,
low_error: float = 0.9,
high_error: float = 1.1,
pairs_high_error=None,
pairs_low_error=None,
monte_carlo_count: int = 10000,
monte_carlo_cycles: int = 10,
target_success: int = 100,
max_monte_carlo_cycles_steps: int = 10,
max_frequency: float = 20,
end_threshold: float = None,
chunksize: int = CHUNKSIZE,
use_pairs: bool = False,
) -> None:
self.dot_inputs = pdme.inputs.inputs_with_frequency_range(
dot_positions, frequency_range
)
self.dot_inputs_array = pdme.measurement.input_types.dot_inputs_to_array(
self.dot_inputs
)
self.use_pairs = use_pairs
self.dot_pair_inputs = pdme.inputs.input_pairs_with_frequency_range(
dot_positions, frequency_range
)
self.dot_pair_inputs_array = (
pdme.measurement.input_types.dot_pair_inputs_to_array(self.dot_pair_inputs)
)
self.discretisations = [disc for (_, disc) in discretisations_with_names]
self.model_names = [name for (name, _) in discretisations_with_names]
self.actual_model = actual_model
self.model_count = len(self.discretisations)
self.monte_carlo_count = monte_carlo_count
self.monte_carlo_cycles = monte_carlo_cycles
self.target_success = target_success
self.max_monte_carlo_cycles_steps = max_monte_carlo_cycles_steps
self.run_count = run_count
self.low_error = low_error
self.high_error = high_error
if pairs_low_error is None:
self.pairs_low_error = self.low_error
else:
self.pairs_low_error = pairs_low_error
if pairs_high_error is None:
self.pairs_high_error = self.high_error
else:
self.pairs_high_error = pairs_high_error
self.csv_fields = ["dipole_moment", "dipole_location", "dipole_frequency"]
self.compensate_zeros = True
self.chunksize = chunksize
for name in self.model_names:
self.csv_fields.extend([f"{name}_success", f"{name}_count", f"{name}_prob"])
self.probabilities = [1 / self.model_count] * self.model_count
timestamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
if self.use_pairs:
self.filename = f"{timestamp}-{filename_slug}.altbayes.pairs.csv"
else:
self.filename = f"{timestamp}-{filename_slug}.altbayes.csv"
self.max_frequency = max_frequency
if end_threshold is not None:
if 0 < end_threshold < 1:
self.end_threshold: float = end_threshold
self.use_end_threshold = True
_logger.info(f"Will abort early, at {self.end_threshold}.")
else:
raise ValueError(
f"end_threshold should be between 0 and 1, but is actually {end_threshold}"
)
def go(self) -> None:
with open(self.filename, "a", newline="") as outfile:
writer = csv.DictWriter(outfile, fieldnames=self.csv_fields, dialect="unix")
writer.writeheader()
for run in range(1, self.run_count + 1):
rng = numpy.random.default_rng()
frequency = rng.uniform(1, self.max_frequency)
# Generate the actual dipoles
actual_dipoles = self.actual_model.get_dipoles(frequency)
dots = actual_dipoles.get_percent_range_dot_measurements(
self.dot_inputs, self.low_error, self.high_error
)
(
lows,
highs,
) = pdme.measurement.input_types.dot_range_measurements_low_high_arrays(
dots
)
pair_lows, pair_highs = (None, None)
if self.use_pairs:
pair_measurements = (
actual_dipoles.get_percent_range_dot_pair_measurements(
self.dot_pair_inputs,
self.pairs_low_error,
self.pairs_high_error,
)
)
(
pair_lows,
pair_highs,
) = pdme.measurement.input_types.dot_range_measurements_low_high_arrays(
pair_measurements
)
_logger.info(f"Going to work on dipole at {actual_dipoles.dipoles}")
results = []
_logger.debug("Going to iterate over discretisations now")
for disc_count, discretisation in enumerate(self.discretisations):
_logger.debug(f"Doing discretisation #{disc_count}")
with multiprocessing.Pool(multiprocessing.cpu_count() - 1 or 1) as pool:
cycle_count = 0
cycle_success = 0
cycles = 0
while (cycles < self.max_monte_carlo_cycles_steps) and (
cycle_success <= self.target_success
):
_logger.debug(f"Starting cycle {cycles}")
cycles += 1
current_success = 0
cycle_count += self.monte_carlo_count * self.monte_carlo_cycles
if self.use_pairs:
current_success = sum(
pool.imap_unordered(
get_a_result_using_pairs,
[
(
discretisation,
self.dot_inputs_array,
self.dot_pair_inputs_array,
lows,
highs,
pair_lows,
pair_highs,
self.monte_carlo_count,
self.max_frequency,
)
]
* self.monte_carlo_cycles,
self.chunksize,
)
)
else:
current_success = sum(
pool.imap_unordered(
get_a_result,
[
(
discretisation,
self.dot_inputs_array,
lows,
highs,
self.monte_carlo_count,
self.max_frequency,
)
]
* self.monte_carlo_cycles,
self.chunksize,
)
)
cycle_success += current_success
results.append((cycle_count, cycle_success))
_logger.debug("Done, constructing output now")
row = {
"dipole_moment": actual_dipoles.dipoles[0].p,
"dipole_location": actual_dipoles.dipoles[0].s,
"dipole_frequency": actual_dipoles.dipoles[0].w,
}
successes: List[float] = []
counts: List[int] = []
for model_index, (name, (count, result)) in enumerate(
zip(self.model_names, results)
):
row[f"{name}_success"] = result
row[f"{name}_count"] = count
successes.append(max(result, 0.5))
counts.append(count)
success_weight = sum(
[
(succ / count) * prob
for succ, count, prob in zip(successes, counts, self.probabilities)
]
)
new_probabilities = [
(succ / count) * old_prob / success_weight
for succ, count, old_prob in zip(successes, counts, self.probabilities)
]
self.probabilities = new_probabilities
for name, probability in zip(self.model_names, self.probabilities):
row[f"{name}_prob"] = probability
_logger.info(row)
with open(self.filename, "a", newline="") as outfile:
writer = csv.DictWriter(
outfile, fieldnames=self.csv_fields, dialect="unix"
)
writer.writerow(row)
if self.use_end_threshold:
max_prob = max(self.probabilities)
if max_prob > self.end_threshold:
_logger.info(
f"Aborting early, because {max_prob} is greater than {self.end_threshold}"
)
break

View File

@@ -0,0 +1,357 @@
import pdme.inputs
import pdme.model
import pdme.measurement.input_types
import pdme.measurement.oscillating_dipole
import pdme.util.fast_v_calc
import pdme.util.fast_nonlocal_spectrum
from typing import Sequence, Tuple, List
import datetime
import csv
import multiprocessing
import logging
import numpy
import numpy.random
# TODO: remove hardcode
CHUNKSIZE = 50
# TODO: It's garbage to have this here duplicated from pdme.
DotInput = Tuple[numpy.typing.ArrayLike, float]
_logger = logging.getLogger(__name__)
def get_a_simul_result_using_pairs(input) -> numpy.ndarray:
(
discretisation,
dot_inputs,
pair_inputs,
local_lows,
local_highs,
nonlocal_lows,
nonlocal_highs,
monte_carlo_count,
monte_carlo_cycles,
max_frequency,
seed,
) = input
rng = numpy.random.default_rng(seed)
local_total = 0
combined_total = 0
sample_dipoles = discretisation.get_model().get_n_single_dipoles(
monte_carlo_count, max_frequency, rng_to_use=rng
)
local_vals = pdme.util.fast_v_calc.fast_vs_for_dipoles(
dot_inputs, sample_dipoles
)
local_matches = pdme.util.fast_v_calc.between(
local_vals, local_lows, local_highs
)
nonlocal_vals = pdme.util.fast_nonlocal_spectrum.fast_s_nonlocal(
pair_inputs, sample_dipoles
)
nonlocal_matches = pdme.util.fast_v_calc.between(
nonlocal_vals, nonlocal_lows, nonlocal_highs
)
combined_matches = numpy.logical_and(local_matches, nonlocal_matches)
local_total += numpy.count_nonzero(local_matches)
combined_total += numpy.count_nonzero(combined_matches)
return numpy.array([local_total, combined_total])
class AltBayesRunSimulPairs:
"""
A dual pairs-nonpairs Bayes run for a given set of dots.
Parameters
----------
dot_inputs : Sequence[DotInput]
The dot inputs for this bayes run.
discretisations_with_names : Sequence[Tuple(str, pdme.model.Model)]
The models to evaluate.
actual_model_discretisation : pdme.model.Discretisation
The discretisation for the model which is actually correct.
filename_slug : str
The filename slug to include.
run_count: int
The number of runs to do.
"""
def __init__(
self,
dot_positions: Sequence[numpy.typing.ArrayLike],
frequency_range: Sequence[float],
discretisations_with_names: Sequence[Tuple[str, pdme.model.Discretisation]],
actual_model: pdme.model.Model,
filename_slug: str,
run_count: int = 100,
low_error: float = 0.9,
high_error: float = 1.1,
pairs_high_error=None,
pairs_low_error=None,
monte_carlo_count: int = 10000,
monte_carlo_cycles: int = 10,
target_success: int = 100,
max_monte_carlo_cycles_steps: int = 10,
max_frequency: float = 20,
end_threshold: float = None,
chunksize: int = CHUNKSIZE,
) -> None:
self.dot_inputs = pdme.inputs.inputs_with_frequency_range(
dot_positions, frequency_range
)
self.dot_inputs_array = pdme.measurement.input_types.dot_inputs_to_array(
self.dot_inputs
)
self.dot_pair_inputs = pdme.inputs.input_pairs_with_frequency_range(
dot_positions, frequency_range
)
self.dot_pair_inputs_array = (
pdme.measurement.input_types.dot_pair_inputs_to_array(self.dot_pair_inputs)
)
self.discretisations = [disc for (_, disc) in discretisations_with_names]
self.model_names = [name for (name, _) in discretisations_with_names]
self.actual_model = actual_model
self.model_count = len(self.discretisations)
self.monte_carlo_count = monte_carlo_count
self.monte_carlo_cycles = monte_carlo_cycles
self.target_success = target_success
self.max_monte_carlo_cycles_steps = max_monte_carlo_cycles_steps
self.run_count = run_count
self.low_error = low_error
self.high_error = high_error
if pairs_low_error is None:
self.pairs_low_error = self.low_error
else:
self.pairs_low_error = pairs_low_error
if pairs_high_error is None:
self.pairs_high_error = self.high_error
else:
self.pairs_high_error = pairs_high_error
self.csv_fields = ["dipole_moment", "dipole_location", "dipole_frequency"]
self.compensate_zeros = True
self.chunksize = chunksize
for name in self.model_names:
self.csv_fields.extend([f"{name}_success", f"{name}_count", f"{name}_prob"])
self.probabilities_no_pairs = [1 / self.model_count] * self.model_count
self.probabilities_pairs = [1 / self.model_count] * self.model_count
timestamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
self.filename_pairs = f"{timestamp}-{filename_slug}.simulpairs.yespairs.csv"
self.filename_no_pairs = f"{timestamp}-{filename_slug}.simulpairs.noopairs.csv"
self.max_frequency = max_frequency
if end_threshold is not None:
if 0 < end_threshold < 1:
self.end_threshold: float = end_threshold
self.use_end_threshold = True
_logger.info(f"Will abort early, at {self.end_threshold}.")
else:
raise ValueError(
f"end_threshold should be between 0 and 1, but is actually {end_threshold}"
)
def go(self) -> None:
with open(self.filename_pairs, "a", newline="") as outfile:
writer = csv.DictWriter(outfile, fieldnames=self.csv_fields, dialect="unix")
writer.writeheader()
with open(self.filename_no_pairs, "a", newline="") as outfile:
writer = csv.DictWriter(outfile, fieldnames=self.csv_fields, dialect="unix")
writer.writeheader()
for run in range(1, self.run_count + 1):
rng = numpy.random.default_rng()
frequency = rng.uniform(1, self.max_frequency)
# Generate the actual dipoles
actual_dipoles = self.actual_model.get_dipoles(frequency)
dots = actual_dipoles.get_percent_range_dot_measurements(
self.dot_inputs, self.low_error, self.high_error
)
(
lows,
highs,
) = pdme.measurement.input_types.dot_range_measurements_low_high_arrays(
dots
)
pair_lows, pair_highs = (None, None)
pair_measurements = actual_dipoles.get_percent_range_dot_pair_measurements(
self.dot_pair_inputs, self.pairs_low_error, self.pairs_high_error
)
(
pair_lows,
pair_highs,
) = pdme.measurement.input_types.dot_range_measurements_low_high_arrays(
pair_measurements
)
_logger.info(f"Going to work on dipole at {actual_dipoles.dipoles}")
# define a new seed sequence for each run
seed_sequence = numpy.random.SeedSequence(run)
results_pairs = []
results_no_pairs = []
_logger.debug("Going to iterate over discretisations now")
for disc_count, discretisation in enumerate(self.discretisations):
_logger.debug(f"Doing discretisation #{disc_count}")
core_count = multiprocessing.cpu_count() - 1 or 1
with multiprocessing.Pool(core_count) as pool:
cycle_count = 0
cycle_success_pairs = 0
cycle_success_no_pairs = 0
cycles = 0
while (cycles < self.max_monte_carlo_cycles_steps) and (
min(cycle_success_pairs, cycle_success_no_pairs)
<= self.target_success
):
_logger.debug(f"Starting cycle {cycles}")
_logger.debug(f"(pair, no_pair) successes are {(cycle_success_pairs, cycle_success_no_pairs)}")
cycles += 1
current_success_pairs = 0
current_success_no_pairs = 0
cycle_count += self.monte_carlo_count * self.monte_carlo_cycles
# generate a seed from the sequence for each core.
# note this needs to be inside the loop for monte carlo cycle steps!
# that way we get more stuff.
seeds = seed_sequence.spawn(self.monte_carlo_cycles)
_logger.debug(f"Creating {self.monte_carlo_cycles} seeds")
current_success_both = numpy.array(
sum(
pool.imap_unordered(
get_a_simul_result_using_pairs,
[
(
discretisation,
self.dot_inputs_array,
self.dot_pair_inputs_array,
lows,
highs,
pair_lows,
pair_highs,
self.monte_carlo_count,
self.monte_carlo_cycles,
self.max_frequency,
seed,
)
for seed in seeds
],
self.chunksize,
)
)
)
current_success_no_pairs = current_success_both[0]
current_success_pairs = current_success_both[1]
cycle_success_no_pairs += current_success_no_pairs
cycle_success_pairs += current_success_pairs
results_pairs.append((cycle_count, cycle_success_pairs))
results_no_pairs.append((cycle_count, cycle_success_no_pairs))
_logger.debug("Done, constructing output now")
row_pairs = {
"dipole_moment": actual_dipoles.dipoles[0].p,
"dipole_location": actual_dipoles.dipoles[0].s,
"dipole_frequency": actual_dipoles.dipoles[0].w,
}
row_no_pairs = {
"dipole_moment": actual_dipoles.dipoles[0].p,
"dipole_location": actual_dipoles.dipoles[0].s,
"dipole_frequency": actual_dipoles.dipoles[0].w,
}
successes_pairs: List[float] = []
successes_no_pairs: List[float] = []
counts: List[int] = []
for model_index, (
name,
(count_pair, result_pair),
(count_no_pair, result_no_pair),
) in enumerate(zip(self.model_names, results_pairs, results_no_pairs)):
row_pairs[f"{name}_success"] = result_pair
row_pairs[f"{name}_count"] = count_pair
successes_pairs.append(max(result_pair, 0.5))
row_no_pairs[f"{name}_success"] = result_no_pair
row_no_pairs[f"{name}_count"] = count_no_pair
successes_no_pairs.append(max(result_no_pair, 0.5))
counts.append(count_pair)
success_weight_pair = sum(
[
(succ / count) * prob
for succ, count, prob in zip(
successes_pairs, counts, self.probabilities_pairs
)
]
)
success_weight_no_pair = sum(
[
(succ / count) * prob
for succ, count, prob in zip(
successes_no_pairs, counts, self.probabilities_no_pairs
)
]
)
new_probabilities_pair = [
(succ / count) * old_prob / success_weight_pair
for succ, count, old_prob in zip(
successes_pairs, counts, self.probabilities_pairs
)
]
new_probabilities_no_pair = [
(succ / count) * old_prob / success_weight_no_pair
for succ, count, old_prob in zip(
successes_no_pairs, counts, self.probabilities_no_pairs
)
]
self.probabilities_pairs = new_probabilities_pair
self.probabilities_no_pairs = new_probabilities_no_pair
for name, probability_pair, probability_no_pair in zip(
self.model_names, self.probabilities_pairs, self.probabilities_no_pairs
):
row_pairs[f"{name}_prob"] = probability_pair
row_no_pairs[f"{name}_prob"] = probability_no_pair
_logger.debug(row_pairs)
_logger.debug(row_no_pairs)
with open(self.filename_pairs, "a", newline="") as outfile:
writer = csv.DictWriter(
outfile, fieldnames=self.csv_fields, dialect="unix"
)
writer.writerow(row_pairs)
with open(self.filename_no_pairs, "a", newline="") as outfile:
writer = csv.DictWriter(
outfile, fieldnames=self.csv_fields, dialect="unix"
)
writer.writerow(row_no_pairs)
if self.use_end_threshold:
max_prob = min(
max(self.probabilities_pairs), max(self.probabilities_no_pairs)
)
if max_prob > self.end_threshold:
_logger.info(
f"Aborting early, because {max_prob} is greater than {self.end_threshold}"
)
break

View File

@@ -20,28 +20,44 @@ DotInput = Tuple[numpy.typing.ArrayLike, float]
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
def get_a_result(discretisation, dots, index) -> Tuple[Tuple[int, ...], scipy.optimize.OptimizeResult]: def get_a_result(
discretisation, dots, index
) -> Tuple[Tuple[int, ...], scipy.optimize.OptimizeResult]:
return (index, discretisation.solve_for_index(dots, index)) return (index, discretisation.solve_for_index(dots, index))
class BayesRun(): class BayesRun:
''' """
A single Bayes run for a given set of dots. A single Bayes run for a given set of dots.
Parameters Parameters
---------- ----------
dot_inputs : Sequence[DotInput] dot_inputs : Sequence[DotInput]
The dot inputs for this bayes run. The dot inputs for this bayes run.
discretisations_with_names : Sequence[Tuple(str, pdme.model.Model)] discretisations_with_names : Sequence[Tuple(str, pdme.model.Model)]
The models to evaluate. The models to evaluate.
actual_model_discretisation : pdme.model.Discretisation actual_model_discretisation : pdme.model.Discretisation
The discretisation for the model which is actually correct. The discretisation for the model which is actually correct.
filename_slug : str filename_slug : str
The filename slug to include. The filename slug to include.
run_count: int run_count: int
The number of runs to do. The number of runs to do.
''' """
def __init__(self, dot_inputs: Sequence[DotInput], discretisations_with_names: Sequence[Tuple[str, pdme.model.Discretisation]], actual_model: pdme.model.Model, filename_slug: str, run_count: int) -> None:
def __init__(
self,
dot_inputs: Sequence[DotInput],
discretisations_with_names: Sequence[Tuple[str, pdme.model.Discretisation]],
actual_model: pdme.model.Model,
filename_slug: str,
run_count: int,
max_frequency: float = None,
end_threshold: float = None,
) -> None:
self.dot_inputs = dot_inputs self.dot_inputs = dot_inputs
self.discretisations = [disc for (_, disc) in discretisations_with_names] self.discretisations = [disc for (_, disc) in discretisations_with_names]
self.model_names = [name for (name, _) in discretisations_with_names] self.model_names = [name for (name, _) in discretisations_with_names]
@@ -50,7 +66,6 @@ class BayesRun():
self.run_count = run_count self.run_count = run_count
self.csv_fields = ["dipole_moment", "dipole_location", "dipole_frequency"] self.csv_fields = ["dipole_moment", "dipole_location", "dipole_frequency"]
self.compensate_zeros = True self.compensate_zeros = True
for name in self.model_names: for name in self.model_names:
self.csv_fields.extend([f"{name}_success", f"{name}_count", f"{name}_prob"]) self.csv_fields.extend([f"{name}_success", f"{name}_count", f"{name}_prob"])
@@ -58,6 +73,17 @@ class BayesRun():
timestamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S") timestamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
self.filename = f"{timestamp}-{filename_slug}.csv" self.filename = f"{timestamp}-{filename_slug}.csv"
self.max_frequency = max_frequency
if end_threshold is not None:
if 0 < end_threshold < 1:
self.end_threshold: float = end_threshold
self.use_end_threshold = True
_logger.info(f"Will abort early, at {self.end_threshold}.")
else:
raise ValueError(
f"end_threshold should be between 0 and 1, but is actually {end_threshold}"
)
def go(self) -> None: def go(self) -> None:
with open(self.filename, "a", newline="") as outfile: with open(self.filename, "a", newline="") as outfile:
@@ -65,7 +91,11 @@ class BayesRun():
writer.writeheader() writer.writeheader()
for run in range(1, self.run_count + 1): for run in range(1, self.run_count + 1):
dipoles = self.actual_model.get_dipoles(run) frequency: float = run
if self.max_frequency is not None and self.max_frequency > 1:
rng = numpy.random.default_rng()
frequency = rng.uniform(1, self.max_frequency)
dipoles = self.actual_model.get_dipoles(frequency)
dots = dipoles.get_dot_measurements(self.dot_inputs) dots = dipoles.get_dot_measurements(self.dot_inputs)
_logger.info(f"Going to work on dipole at {dipoles.dipoles}") _logger.info(f"Going to work on dipole at {dipoles.dipoles}")
@@ -75,16 +105,28 @@ class BayesRun():
for disc_count, discretisation in enumerate(self.discretisations): for disc_count, discretisation in enumerate(self.discretisations):
_logger.debug(f"Doing discretisation #{disc_count}") _logger.debug(f"Doing discretisation #{disc_count}")
with multiprocessing.Pool(multiprocessing.cpu_count() - 1 or 1) as pool: with multiprocessing.Pool(multiprocessing.cpu_count() - 1 or 1) as pool:
results.append(pool.starmap(get_a_result, zip(itertools.repeat(discretisation), itertools.repeat(dots), discretisation.all_indices()))) results.append(
pool.starmap(
get_a_result,
zip(
itertools.repeat(discretisation),
itertools.repeat(dots),
discretisation.all_indices(),
),
)
)
_logger.debug("Done, constructing output now") _logger.debug("Done, constructing output now")
row = { row = {
"dipole_moment": dipoles.dipoles[0].p, "dipole_moment": dipoles.dipoles[0].p,
"dipole_location": dipoles.dipoles[0].s, "dipole_location": dipoles.dipoles[0].s,
"dipole_frequency": dipoles.dipoles[0].w "dipole_frequency": dipoles.dipoles[0].w,
} }
successes: List[int] = [] successes: List[float] = []
for model_index, (name, result) in enumerate(zip(self.model_names, results)): counts: List[int] = []
for model_index, (name, result) in enumerate(
zip(self.model_names, results)
):
count = 0 count = 0
success = 0 success = 0
for idx, val in result: for idx, val in result:
@@ -94,15 +136,34 @@ class BayesRun():
row[f"{name}_success"] = success row[f"{name}_success"] = success
row[f"{name}_count"] = count row[f"{name}_count"] = count
successes.append(max(success, 1)) successes.append(max(success, 0.5))
counts.append(count)
success_weight = sum([succ * prob for succ, prob in zip(successes, self.probabilities)]) success_weight = sum(
new_probabilities = [succ * old_prob / success_weight for succ, old_prob in zip(successes, self.probabilities)] [
(succ / count) * prob
for succ, count, prob in zip(successes, counts, self.probabilities)
]
)
new_probabilities = [
(succ / count) * old_prob / success_weight
for succ, count, old_prob in zip(successes, counts, self.probabilities)
]
self.probabilities = new_probabilities self.probabilities = new_probabilities
for name, probability in zip(self.model_names, self.probabilities): for name, probability in zip(self.model_names, self.probabilities):
row[f"{name}_prob"] = probability row[f"{name}_prob"] = probability
_logger.info(row) _logger.info(row)
with open(self.filename, "a", newline="") as outfile: with open(self.filename, "a", newline="") as outfile:
writer = csv.DictWriter(outfile, fieldnames=self.csv_fields, dialect="unix") writer = csv.DictWriter(
outfile, fieldnames=self.csv_fields, dialect="unix"
)
writer.writerow(row) writer.writerow(row)
if self.use_end_threshold:
max_prob = max(self.probabilities)
if max_prob > self.end_threshold:
_logger.info(
f"Aborting early, because {max_prob} is greater than {self.end_threshold}"
)
break

View File

@@ -3,6 +3,7 @@ import pdme
from deepdog.bayes_run import DotInput from deepdog.bayes_run import DotInput
import datetime import datetime
import numpy import numpy
from dataclasses import dataclass
import logging import logging
from typing import Sequence, Tuple from typing import Sequence, Tuple
import csv import csv
@@ -16,39 +17,105 @@ def get_a_result(discretisation, dots, index):
return (index, discretisation.solve_for_index(dots, index)) return (index, discretisation.solve_for_index(dots, index))
class Diagnostic(): @dataclass
''' class SingleDipoleDiagnostic:
model: str
index: Tuple
bounds: Tuple
actual_dipole: OscillatingDipole
result_dipole: OscillatingDipole
success: bool
def __post_init__(self) -> None:
self.p_actual_x = self.actual_dipole.p[0]
self.p_actual_y = self.actual_dipole.p[1]
self.p_actual_z = self.actual_dipole.p[2]
self.s_actual_x = self.actual_dipole.s[0]
self.s_actual_y = self.actual_dipole.s[1]
self.s_actual_z = self.actual_dipole.s[2]
self.p_result_x = self.result_dipole.p[0]
self.p_result_y = self.result_dipole.p[1]
self.p_result_z = self.result_dipole.p[2]
self.s_result_x = self.result_dipole.s[0]
self.s_result_y = self.result_dipole.s[1]
self.s_result_z = self.result_dipole.s[2]
self.w_actual = self.actual_dipole.w
self.w_result = self.result_dipole.w
class Diagnostic:
"""
Represents a diagnostic for a single dipole moment given a set of discretisations. Represents a diagnostic for a single dipole moment given a set of discretisations.
Parameters Parameters
---------- ----------
dot_inputs : Sequence[DotInput] dot_inputs : Sequence[DotInput]
The dot inputs for this diagnostic. The dot inputs for this diagnostic.
discretisations_with_names : Sequence[Tuple(str, pdme.model.Model)] discretisations_with_names : Sequence[Tuple(str, pdme.model.Model)]
The models to evaluate. The models to evaluate.
actual_model_discretisation : pdme.model.Discretisation actual_model_discretisation : pdme.model.Discretisation
The discretisation for the model which is actually correct. The discretisation for the model which is actually correct.
filename_slug : str filename_slug : str
The filename slug to include. The filename slug to include.
run_count: int run_count: int
The number of runs to do. The number of runs to do.
''' """
def __init__(self, actual_dipole_moment: numpy.ndarray, actual_dipole_position: numpy.ndarray, actual_dipole_frequency: float, dot_inputs: Sequence[DotInput], discretisations_with_names: Sequence[Tuple[str, pdme.model.Discretisation]], filename_slug: str) -> None:
self.dipoles = OscillatingDipoleArrangement([OscillatingDipole(actual_dipole_moment, actual_dipole_position, actual_dipole_frequency)]) def __init__(
self,
actual_dipole_moment: numpy.ndarray,
actual_dipole_position: numpy.ndarray,
actual_dipole_frequency: float,
dot_inputs: Sequence[DotInput],
discretisations_with_names: Sequence[Tuple[str, pdme.model.Discretisation]],
filename_slug: str,
) -> None:
self.dipoles = OscillatingDipoleArrangement(
[
OscillatingDipole(
actual_dipole_moment,
actual_dipole_position,
actual_dipole_frequency,
)
]
)
self.dots = self.dipoles.get_dot_measurements(dot_inputs) self.dots = self.dipoles.get_dot_measurements(dot_inputs)
self.discretisations_with_names = discretisations_with_names self.discretisations_with_names = discretisations_with_names
self.model_count = len(self.discretisations_with_names) self.model_count = len(self.discretisations_with_names)
self.csv_fields = ["model", "index", "bounds", "actual_dipole_moment", "actual_dipole_position", "actual_dipole_freq", "success", "result"] self.csv_fields = [
"model",
"index",
"bounds",
"p_actual_x",
"p_actual_y",
"p_actual_z",
"s_actual_x",
"s_actual_y",
"s_actual_z",
"w_actual",
"success",
"p_result_x",
"p_result_y",
"p_result_z",
"s_result_x",
"s_result_y",
"s_result_z",
"w_result",
]
timestamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S") timestamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
self.filename = f"{timestamp}-{filename_slug}.csv" self.filename = f"{timestamp}-{filename_slug}.diag.csv"
def go(self): def go(self):
with open(self.filename, "a", newline="") as outfile: with open(self.filename, "a", newline="") as outfile:
# csv fields # csv fields
writer = csv.DictWriter(outfile, fieldnames=self.csv_fields, dialect='unix') writer = csv.DictWriter(outfile, fieldnames=self.csv_fields, dialect="unix")
writer.writeheader() writer.writeheader()
for (name, discretisation) in self.discretisations_with_names: for (name, discretisation) in self.discretisations_with_names:
@@ -56,25 +123,38 @@ class Diagnostic():
results = [] results = []
with multiprocessing.Pool(multiprocessing.cpu_count() - 1 or 1) as pool: with multiprocessing.Pool(multiprocessing.cpu_count() - 1 or 1) as pool:
results = pool.starmap(get_a_result, zip(itertools.repeat(discretisation), itertools.repeat(self.dots), discretisation.all_indices())) results = pool.starmap(
get_a_result,
zip(
itertools.repeat(discretisation),
itertools.repeat(self.dots),
discretisation.all_indices(),
),
)
with open(self.filename, "a", newline='') as outfile: with open(self.filename, "a", newline="") as outfile:
writer = csv.DictWriter(outfile, fieldnames=self.csv_fields, dialect='unix') writer = csv.DictWriter(
outfile,
fieldnames=self.csv_fields,
dialect="unix",
extrasaction="ignore",
)
for idx, result in results: for idx, result in results:
bounds = discretisation.bounds(idx) bounds = discretisation.bounds(idx)
actual_success = result.success and result.cost <= 1e-10 actual_success = result.success and result.cost <= 1e-10
row = { diag_row = SingleDipoleDiagnostic(
"model": name, name,
"index": idx, idx,
"bounds_px": bounds, bounds,
"actual_dipole_moment": self.dipoles.dipoles[0].p, self.dipoles.dipoles[0],
"actual_dipole_position": self.dipoles.dipoles[0].s, discretisation.model.solution_as_dipoles(result.normalised_x)[
"actual_dipole_freq": self.dipoles.dipoles[0].w, 0
"success": actual_success, ],
"result": result.normalised_x if actual_success else None, actual_success,
} )
row = vars(diag_row)
_logger.debug(f"Writing result {row}") _logger.debug(f"Writing result {row}")
writer.writerow(row) writer.writerow(row)

View File

@@ -1,3 +1,3 @@
from importlib.metadata import version from importlib.metadata import version
__version__ = version('deepdog') __version__ = version("deepdog")

9
do.sh
View File

@@ -16,6 +16,15 @@ test() {
poetry run pytest poetry run pytest
} }
fmt() {
poetry run black .
find . -type f -name "*.py" -exec sed -i -e 's/ /\t/g' {} \;
}
release() {
./scripts/release.sh
}
htmlcov() { htmlcov() {
poetry run pytest --cov-report=html poetry run pytest --cov-report=html
} }

992
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,20 @@
[tool.poetry] [tool.poetry]
name = "deepdog" name = "deepdog"
version = "0.1.3" version = "0.5.0"
description = "" description = ""
authors = ["Deepak Mallubhotla <dmallubhotla+github@gmail.com>"] authors = ["Deepak Mallubhotla <dmallubhotla+github@gmail.com>"]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = "^3.8,<3.10" python = "^3.8,<3.10"
pdme = "^0.4.1" pdme = "0.6.2"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
pytest = ">=6" pytest = ">=6"
flake8 = "^4.0.1" flake8 = "^4.0.1"
pytest-cov = "^3.0.0" pytest-cov = "^3.0.0"
mypy = "^0.931" mypy = "^0.950"
python-semantic-release = "^7.24.0"
black = "^22.3.0"
[build-system] [build-system]
requires = ["poetry-core>=1.0.0"] requires = ["poetry-core>=1.0.0"]
@@ -32,3 +34,7 @@ module = [
"scipy.optimize" "scipy.optimize"
] ]
ignore_missing_imports = true ignore_missing_imports = true
[tool.semantic_release]
version_toml = "pyproject.toml:tool.poetry.version"
tag_format = "{version}"

3
renovate.json Normal file
View File

@@ -0,0 +1,3 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json"
}

View File

@@ -1,29 +0,0 @@
#!/usr/bin/env bash
set -Eeuo pipefail
if [ -z "$(git status --porcelain)" ]; then
# Working directory clean
branch_name=$(git symbolic-ref -q HEAD)
branch_name=${branch_name##refs/heads/}
branch_name=${branch_name:-HEAD}
poetry version patch
version=`sed 's/version = "\([0-9]*.[0-9]*.[0-9]*\)"/\1/p' -n <pyproject.toml`
read -p "Create commit for version $version? " -n 1 -r
echo # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
# do dangerous stuff
echo "Creating a new patch"
git add pyproject.toml
git commit -m "Created version $version"
git tag -a "$version" -m "patch.sh created version $version"
git push --tags
else
echo "Surrendering, clean up by reverting pyproject.toml..."
exit 2
fi
else
echo "Can't create patch version, working tree unclean..."
exit 1
fi

45
scripts/release.sh Normal file
View File

@@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -Eeuo pipefail
if [ -z "$(git status --porcelain)" ]; then
branch_name=$(git symbolic-ref -q HEAD)
branch_name=${branch_name##refs/heads/}
branch_name=${branch_name:-HEAD}
if [ $branch_name != "master" ]; then
echo "The current branch is not master!"
echo "I'd feel uncomfortable releasing from here..."
exit 3
fi
release_needed=false
if \
{ git log "$( git describe --tags --abbrev=0 )..HEAD" --format='%s' | cut -d: -f1 | sort -u | sed -e 's/([^)]*)//' | grep -q -i -E '^feat|fix|perf|refactor|revert$' ; } || \
{ git log "$( git describe --tags --abbrev=0 )..HEAD" --format='%s' | cut -d: -f1 | sort -u | sed -e 's/([^)]*)//' | grep -q -E '\!$' ; } || \
{ git log "$( git describe --tags --abbrev=0 )..HEAD" --format='%b' | grep -q -E '^BREAKING CHANGE:' ; }
then
release_needed=true
fi
if ! [ "$release_needed" = true ]; then
echo "No release needed..."
exit 0
fi
# Working directory clean
echo "Doing a dry run..."
npx standard-version --dry-run
read -p "Does that look good? [y/N] " -n 1 -r
echo # (optional) move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]
then
# do dangerous stuff
npx standard-version
git push --follow-tags origin master
else
echo "okay, never mind then..."
exit 2
fi
else
echo "Can't create release, working tree unclean..."
exit 1
fi

View File

@@ -0,0 +1,11 @@
const pattern = /(\[tool\.poetry\]\nname = "deepdog"\nversion = ")(?<vers>\d+\.\d+\.\d)(")/mg;
module.exports.readVersion = function (contents) {
const result = pattern.exec(contents);
return result.groups.vers;
}
module.exports.writeVersion = function (contents, version) {
const newContents = contents.replace(pattern, `$1${version}$3`);
return newContents;
}