dgpost 2.1.2__tar.gz → 2.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dgpost-2.1.2/src/dgpost.egg-info → dgpost-2.2.1}/PKG-INFO +20 -34
- dgpost-2.2.1/pyproject.toml +69 -0
- dgpost-2.2.1/setup.cfg +4 -0
- dgpost-2.2.1/src/dgpost/__init__.py +8 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/main.py +4 -30
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/transform/catalysis.py +3 -4
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/transform/chromatography.py +2 -2
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/transform/circuit_utils/circuit_components.py +1 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/transform/circuit_utils/circuit_parser.py +5 -4
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/transform/electrochemistry.py +8 -7
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/transform/impedance.py +1 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/transform/rates.py +1 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/transform/reflection.py +37 -33
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/transform/table.py +1 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/utils/__init__.py +2 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/utils/extract.py +13 -9
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/utils/helpers.py +16 -21
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/utils/load.py +3 -2
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/utils/parse.py +19 -3
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/utils/pivot.py +1 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/utils/plot.py +1 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/utils/save.py +2 -1
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/utils/transform.py +1 -0
- {dgpost-2.1.2 → dgpost-2.2.1/src/dgpost.egg-info}/PKG-INFO +20 -34
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost.egg-info/SOURCES.txt +1 -5
- dgpost-2.2.1/src/dgpost.egg-info/requires.txt +20 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_catalysis_conversion.py +1 -1
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_extract.py +15 -3
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_impedance.py +1 -1
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_load.py +2 -2
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_main.py +2 -4
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_parse.py +7 -11
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_reflection.py +0 -1
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_roundtrip.py +4 -4
- dgpost-2.1.2/MANIFEST.in +0 -2
- dgpost-2.1.2/setup.cfg +0 -12
- dgpost-2.1.2/setup.py +0 -65
- dgpost-2.1.2/src/dgpost/__init__.py +0 -8
- dgpost-2.1.2/src/dgpost/_version.py +0 -21
- dgpost-2.1.2/src/dgpost.egg-info/requires.txt +0 -29
- dgpost-2.1.2/versioneer.py +0 -2189
- {dgpost-2.1.2 → dgpost-2.2.1}/LICENSE +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/README.md +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/transform/__init__.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost/transform/circuit_utils/__init__.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost.egg-info/dependency_links.txt +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost.egg-info/entry_points.txt +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/src/dgpost.egg-info/top_level.txt +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_catalysis_atbal.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_catalysis_selectivity.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_catalysis_yield.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_chromatography.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_electrochemistry_charge.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_electrochemistry_current.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_electrochemistry_fe.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_electrochemistry_nernst.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_pivot.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_plot.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_rates_batchtomolar.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_rates_flowtomolar.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_realworld.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_save.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_table_combine_columns.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_table_combine_namespaces.py +0 -0
- {dgpost-2.1.2 → dgpost-2.2.1}/tests/test_table_set_uncertainty.py +0 -0
|
@@ -1,56 +1,42 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: dgpost
|
|
3
|
-
Version: 2.1
|
|
3
|
+
Version: 2.2.1
|
|
4
4
|
Summary: datagram post-processing toolkit
|
|
5
|
-
|
|
6
|
-
Author: Peter Kraus
|
|
7
|
-
|
|
8
|
-
Project-URL:
|
|
9
|
-
Project-URL:
|
|
10
|
-
|
|
5
|
+
Author: Ueli Sauter
|
|
6
|
+
Author-email: Peter Kraus <peter.kraus@tu-berlin.de>
|
|
7
|
+
Maintainer-email: Peter Kraus <peter.kraus@tu-berlin.de>
|
|
8
|
+
Project-URL: Documentation, https://dgbowl.github.io/dgpost/master
|
|
9
|
+
Project-URL: Issues, https://github.com/dgbowl/dgpost/issues
|
|
10
|
+
Project-URL: Repository, https://github.com/dgbowl/dgpost/
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
11
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
16
|
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
16
17
|
Classifier: Operating System :: OS Independent
|
|
17
|
-
Requires-Python: >=3.
|
|
18
|
+
Requires-Python: >=3.10
|
|
18
19
|
Description-Content-Type: text/markdown
|
|
19
20
|
License-File: LICENSE
|
|
20
|
-
Requires-Dist: numpy
|
|
21
|
-
Requires-Dist: numpy>=1.2.0; python_version >= "3.10"
|
|
21
|
+
Requires-Dist: numpy>=1.20
|
|
22
22
|
Requires-Dist: uncertainties<3.2
|
|
23
|
-
Requires-Dist: pandas
|
|
24
|
-
Requires-Dist: pandas>=2.1; python_version >= "3.10"
|
|
23
|
+
Requires-Dist: pandas
|
|
25
24
|
Requires-Dist: openpyxl
|
|
26
|
-
Requires-Dist: pint>=0.
|
|
25
|
+
Requires-Dist: pint>=0.24.1
|
|
27
26
|
Requires-Dist: chemicals>=1.0.0
|
|
28
27
|
Requires-Dist: rdkit>=2022.3
|
|
29
28
|
Requires-Dist: h5netcdf>=1.0
|
|
30
|
-
Requires-Dist: xarray
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist: dgbowl-schemas>=116
|
|
29
|
+
Requires-Dist: xarray>=2024.10.0
|
|
30
|
+
Requires-Dist: dgbowl-schemas>=122
|
|
33
31
|
Requires-Dist: matplotlib>=3.5.0
|
|
34
|
-
Requires-Dist: requests
|
|
35
32
|
Provides-Extra: testing
|
|
36
33
|
Requires-Dist: pytest; extra == "testing"
|
|
37
|
-
Requires-Dist:
|
|
34
|
+
Requires-Dist: ruff; extra == "testing"
|
|
38
35
|
Provides-Extra: docs
|
|
39
36
|
Requires-Dist: sphinx~=7.2; extra == "docs"
|
|
40
|
-
Requires-Dist: sphinx-rtd-theme; extra == "docs"
|
|
41
|
-
Requires-Dist:
|
|
42
|
-
|
|
43
|
-
Dynamic: author
|
|
44
|
-
Dynamic: author-email
|
|
45
|
-
Dynamic: classifier
|
|
46
|
-
Dynamic: description
|
|
47
|
-
Dynamic: description-content-type
|
|
48
|
-
Dynamic: home-page
|
|
49
|
-
Dynamic: project-url
|
|
50
|
-
Dynamic: provides-extra
|
|
51
|
-
Dynamic: requires-dist
|
|
52
|
-
Dynamic: requires-python
|
|
53
|
-
Dynamic: summary
|
|
37
|
+
Requires-Dist: sphinx-rtd-theme~=1.3.0; extra == "docs"
|
|
38
|
+
Requires-Dist: autodoc-pydantic~=2.1.0; extra == "docs"
|
|
39
|
+
Dynamic: license-file
|
|
54
40
|
|
|
55
41
|
# dgpost: datagram post-processing toolkit
|
|
56
42
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools >= 61.0", "setuptools-git-versioning"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
dynamic = ["version"]
|
|
7
|
+
name = "dgpost"
|
|
8
|
+
authors = [
|
|
9
|
+
{name = "Peter Kraus", email = "peter.kraus@tu-berlin.de"},
|
|
10
|
+
{name = "Ueli Sauter"},
|
|
11
|
+
]
|
|
12
|
+
maintainers = [
|
|
13
|
+
{name = "Peter Kraus", email = "peter.kraus@tu-berlin.de"},
|
|
14
|
+
]
|
|
15
|
+
description = "datagram post-processing toolkit"
|
|
16
|
+
readme = "README.md"
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 5 - Production/Stable",
|
|
19
|
+
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
|
|
20
|
+
"Programming Language :: Python :: 3.10",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
"Operating System :: OS Independent",
|
|
25
|
+
]
|
|
26
|
+
requires-python = ">= 3.10"
|
|
27
|
+
dependencies = [
|
|
28
|
+
"numpy >= 1.20",
|
|
29
|
+
"uncertainties < 3.2",
|
|
30
|
+
"pandas",
|
|
31
|
+
"openpyxl",
|
|
32
|
+
"pint >= 0.24.1",
|
|
33
|
+
"chemicals >= 1.0.0",
|
|
34
|
+
"rdkit >= 2022.3",
|
|
35
|
+
"h5netcdf >= 1.0",
|
|
36
|
+
"xarray >= 2024.10.0",
|
|
37
|
+
"dgbowl-schemas >= 122",
|
|
38
|
+
"matplotlib >= 3.5.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.optional-dependencies]
|
|
42
|
+
testing = [
|
|
43
|
+
"pytest",
|
|
44
|
+
"ruff",
|
|
45
|
+
]
|
|
46
|
+
docs = [
|
|
47
|
+
"sphinx ~= 7.2",
|
|
48
|
+
"sphinx-rtd-theme ~= 1.3.0",
|
|
49
|
+
"autodoc-pydantic ~= 2.1.0",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[project.urls]
|
|
53
|
+
Documentation = "https://dgbowl.github.io/dgpost/master"
|
|
54
|
+
Issues = "https://github.com/dgbowl/dgpost/issues"
|
|
55
|
+
Repository = "https://github.com/dgbowl/dgpost/"
|
|
56
|
+
|
|
57
|
+
[project.scripts]
|
|
58
|
+
dgpost = "dgpost:run_with_arguments"
|
|
59
|
+
|
|
60
|
+
[tool.setuptools-git-versioning]
|
|
61
|
+
enabled = true
|
|
62
|
+
dev_template = "{tag}.dev{ccount}"
|
|
63
|
+
dirty_template = "{tag}.dev{ccount}"
|
|
64
|
+
|
|
65
|
+
[tool.ruff]
|
|
66
|
+
|
|
67
|
+
[tool.pytest.ini_options]
|
|
68
|
+
log_cli = false
|
|
69
|
+
log_cli_level = "DEBUG"
|
dgpost-2.2.1/setup.cfg
ADDED
|
@@ -5,13 +5,11 @@ dgpost.main
|
|
|
5
5
|
Module containing the execution functions for dgpost.
|
|
6
6
|
|
|
7
7
|
"""
|
|
8
|
+
|
|
8
9
|
import argparse
|
|
9
10
|
import logging
|
|
10
11
|
from importlib import metadata
|
|
11
12
|
import copy
|
|
12
|
-
import requests
|
|
13
|
-
import json
|
|
14
|
-
from packaging import version
|
|
15
13
|
|
|
16
14
|
from dgpost.utils import parse, load, extract, transform, save, plot, pivot
|
|
17
15
|
from dgpost.utils.helpers import combine_tables
|
|
@@ -19,29 +17,6 @@ from dgpost.utils.helpers import combine_tables
|
|
|
19
17
|
logger = logging.getLogger(__name__)
|
|
20
18
|
|
|
21
19
|
|
|
22
|
-
def version_check(project="dgpost"):
|
|
23
|
-
url = f"https://pypi.org/pypi/{project}/json"
|
|
24
|
-
try:
|
|
25
|
-
res = requests.get(url, timeout=1)
|
|
26
|
-
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
|
|
27
|
-
logger.debug(f"Version check could not proceed due to Exception={e}.")
|
|
28
|
-
return
|
|
29
|
-
jsdata = json.loads(res.text)
|
|
30
|
-
versions = sorted([version.parse(i) for i in jsdata["releases"].keys()])
|
|
31
|
-
latest = versions[-1]
|
|
32
|
-
current = version.parse(metadata.version(project))
|
|
33
|
-
if latest > current:
|
|
34
|
-
logger.warning("You are using an out-of-date version of '%s'. ", project)
|
|
35
|
-
logger.info(
|
|
36
|
-
"The latest version is '%s', the current version is '%s'.", latest, current
|
|
37
|
-
)
|
|
38
|
-
logger.info(
|
|
39
|
-
"Consider updating using: pip install --upgrade %s==%s", project, latest
|
|
40
|
-
)
|
|
41
|
-
else:
|
|
42
|
-
logger.debug("Your version of '%s' is up-to-date.", project)
|
|
43
|
-
|
|
44
|
-
|
|
45
20
|
def run(path: str, patch: str = None) -> tuple[dict, dict]:
|
|
46
21
|
"""
|
|
47
22
|
Main API execution function. Loads the `recipe` from the provided ``path``,
|
|
@@ -83,8 +58,8 @@ def run(path: str, patch: str = None) -> tuple[dict, dict]:
|
|
|
83
58
|
tables = {}
|
|
84
59
|
|
|
85
60
|
logger.info("Processing 'load'.")
|
|
86
|
-
|
|
87
|
-
for el in
|
|
61
|
+
ldict = spec.pop("load")
|
|
62
|
+
for el in ldict:
|
|
88
63
|
if patch is None:
|
|
89
64
|
fp = el["path"]
|
|
90
65
|
else:
|
|
@@ -187,7 +162,7 @@ def run_with_arguments():
|
|
|
187
162
|
parser.add_argument(
|
|
188
163
|
"--version",
|
|
189
164
|
action="version",
|
|
190
|
-
version=f
|
|
165
|
+
version=f"%(prog)s version {metadata.version('dgpost')}",
|
|
191
166
|
)
|
|
192
167
|
|
|
193
168
|
parser.add_argument(
|
|
@@ -225,5 +200,4 @@ def run_with_arguments():
|
|
|
225
200
|
logging.basicConfig(level=loglevel)
|
|
226
201
|
logging.debug(f"loglevel set to '{logging._levelToName[loglevel]}'")
|
|
227
202
|
|
|
228
|
-
version_check()
|
|
229
203
|
run(args.infile, patch=args.patch)
|
|
@@ -36,9 +36,6 @@ import pint
|
|
|
36
36
|
import logging
|
|
37
37
|
import numpy as np
|
|
38
38
|
from typing import Iterable
|
|
39
|
-
|
|
40
|
-
logger = logging.getLogger(__name__)
|
|
41
|
-
|
|
42
39
|
from dgpost.utils.helpers import (
|
|
43
40
|
name_to_chem,
|
|
44
41
|
columns_to_smiles,
|
|
@@ -48,6 +45,8 @@ from dgpost.utils.helpers import (
|
|
|
48
45
|
separate_data,
|
|
49
46
|
)
|
|
50
47
|
|
|
48
|
+
logger = logging.getLogger(__name__)
|
|
49
|
+
|
|
51
50
|
|
|
52
51
|
@load_data(
|
|
53
52
|
("xin", None, dict),
|
|
@@ -182,7 +181,7 @@ def conversion(
|
|
|
182
181
|
if product is not None:
|
|
183
182
|
logger.warning(
|
|
184
183
|
"Specifying reactant- and product-based conversion using "
|
|
185
|
-
|
|
184
|
+
"'product' is deprecated and will stop working in dgpost-2.0. "
|
|
186
185
|
"Use 'type={product,reactant,mixed}' instead."
|
|
187
186
|
)
|
|
188
187
|
type = "product" if product else "reactant"
|
|
@@ -61,7 +61,7 @@ def integrate_trace(
|
|
|
61
61
|
and interpolating between the ends of all matched peaks. If consecutive
|
|
62
62
|
peaks are found, the interpolation spans the whole domain.
|
|
63
63
|
#) The baseline is subtracted from the signal and the peak areas are
|
|
64
|
-
integrated using the :func:`numpy.
|
|
64
|
+
integrated using the :func:`numpy.trapezoid` function.
|
|
65
65
|
#) The peak height is taken from the original ``signal`` data.
|
|
66
66
|
|
|
67
67
|
The format of the ``species`` specification, used for peak matching, is as follows:
|
|
@@ -227,7 +227,7 @@ def integrate_trace(
|
|
|
227
227
|
e = v["rlim"] + 1
|
|
228
228
|
py = signal[s:e] - baseline[s:e]
|
|
229
229
|
px = time[s:e]
|
|
230
|
-
A = np.
|
|
230
|
+
A = np.trapezoid(py, px)
|
|
231
231
|
retval[f"{output}->area->{k}"] = A
|
|
232
232
|
retval[f"{output}->height->{k}"] = py[v["max"] - s]
|
|
233
233
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
dgpost.transform.circuit_utils.circuit_parser
|
|
3
3
|
=============================================
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
import re
|
|
6
7
|
import warnings
|
|
7
8
|
import logging
|
|
@@ -156,7 +157,7 @@ def fit_routine(
|
|
|
156
157
|
with warnings.catch_warnings():
|
|
157
158
|
warnings.filterwarnings("ignore", message="overflow encountered in tanh")
|
|
158
159
|
|
|
159
|
-
logger.debug(
|
|
160
|
+
logger.debug("Started fitting routine")
|
|
160
161
|
for i in range(repeat):
|
|
161
162
|
logger.debug(f"Fitting routine pass {i}")
|
|
162
163
|
opt_result = least_squares(
|
|
@@ -168,7 +169,7 @@ def fit_routine(
|
|
|
168
169
|
ftol=1e-9,
|
|
169
170
|
)
|
|
170
171
|
initial_value = opt_result.x
|
|
171
|
-
logger.debug(
|
|
172
|
+
logger.debug("Finished least squares")
|
|
172
173
|
opt_result = minimize(
|
|
173
174
|
opt_func,
|
|
174
175
|
initial_value,
|
|
@@ -178,6 +179,6 @@ def fit_routine(
|
|
|
178
179
|
method="Nelder-Mead",
|
|
179
180
|
)
|
|
180
181
|
initial_value = opt_result.x
|
|
181
|
-
logger.debug(
|
|
182
|
-
logger.debug(
|
|
182
|
+
logger.debug("Finished Nelder-Mead")
|
|
183
|
+
logger.debug("Finished fitting routine")
|
|
183
184
|
return opt_result
|
|
@@ -19,6 +19,7 @@ charge and timestamps.
|
|
|
19
19
|
nernst
|
|
20
20
|
|
|
21
21
|
"""
|
|
22
|
+
|
|
22
23
|
import pint
|
|
23
24
|
import numpy as np
|
|
24
25
|
import pandas as pd
|
|
@@ -48,7 +49,7 @@ ureg = pint.get_application_registry()
|
|
|
48
49
|
def nernst(
|
|
49
50
|
Ewe: pint.Quantity,
|
|
50
51
|
R: pint.Quantity = pint.Quantity(0.0, "Ω"),
|
|
51
|
-
I: pint.Quantity = pint.Quantity(0.0, "A"),
|
|
52
|
+
I: pint.Quantity = pint.Quantity(0.0, "A"), # noqa: E741
|
|
52
53
|
Eref: pint.Quantity = pint.Quantity(0.0, "V"),
|
|
53
54
|
T: pint.Quantity = pint.Quantity(298.15, "K"),
|
|
54
55
|
n: int = None,
|
|
@@ -148,7 +149,7 @@ def nernst(
|
|
|
148
149
|
)
|
|
149
150
|
def fe(
|
|
150
151
|
rate: dict[str, pint.Quantity],
|
|
151
|
-
I: pint.Quantity,
|
|
152
|
+
I: pint.Quantity, # noqa: E741
|
|
152
153
|
charges: dict[str, int],
|
|
153
154
|
output: str = None,
|
|
154
155
|
) -> dict[str, pint.Quantity]:
|
|
@@ -214,7 +215,7 @@ def fe(
|
|
|
214
215
|
)
|
|
215
216
|
def charge(
|
|
216
217
|
time: pint.Quantity,
|
|
217
|
-
I: pint.Quantity,
|
|
218
|
+
I: pint.Quantity, # noqa: E741
|
|
218
219
|
t0: pint.Quantity = None,
|
|
219
220
|
output: str = "Q",
|
|
220
221
|
) -> dict[str, pint.Quantity]:
|
|
@@ -327,10 +328,10 @@ def average_current(
|
|
|
327
328
|
dt = np.diff(time)
|
|
328
329
|
dQ = np.diff(Q)
|
|
329
330
|
|
|
330
|
-
|
|
331
|
+
current = dQ / dt
|
|
331
332
|
|
|
332
|
-
if len(
|
|
333
|
-
|
|
333
|
+
if len(current) != nts:
|
|
334
|
+
current = np.insert(current, 0, ureg.Quantity(0, "A"))
|
|
334
335
|
|
|
335
|
-
ret = {output:
|
|
336
|
+
ret = {output: current}
|
|
336
337
|
return ret
|
|
@@ -27,25 +27,28 @@ factors to the reflection trace data. The use of the peak-height based pruning v
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
"""
|
|
30
|
+
|
|
30
31
|
import pint
|
|
31
32
|
import numpy as np
|
|
32
33
|
import uncertainties as uc
|
|
33
34
|
from scipy.optimize import curve_fit
|
|
35
|
+
from scipy.signal import find_peaks
|
|
34
36
|
|
|
35
37
|
from dgpost.utils.helpers import separate_data, load_data
|
|
36
38
|
|
|
37
39
|
|
|
38
|
-
def _find_peak(near, absgamma, freq) -> int:
|
|
40
|
+
def _find_peak(near, absgamma, freq, height=0.2) -> int:
|
|
39
41
|
if near is None:
|
|
40
|
-
|
|
41
|
-
return np.argmax(logmag)
|
|
42
|
+
return np.argmax((1 - absgamma))
|
|
42
43
|
else:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
peaks, _ = find_peaks((1 - absgamma), height=height)
|
|
45
|
+
nearest = None
|
|
46
|
+
for pi in peaks:
|
|
47
|
+
if nearest is None:
|
|
48
|
+
nearest = pi
|
|
49
|
+
elif abs(freq[pi] - near) < abs(freq[nearest] - near):
|
|
50
|
+
nearest = pi
|
|
51
|
+
return nearest
|
|
49
52
|
|
|
50
53
|
|
|
51
54
|
@load_data(
|
|
@@ -60,6 +63,7 @@ def prune_cutoff(
|
|
|
60
63
|
freq: pint.Quantity,
|
|
61
64
|
near: pint.Quantity = None,
|
|
62
65
|
cutoff: float = 0.4,
|
|
66
|
+
height: float = 0.2,
|
|
63
67
|
output: str = "pruned",
|
|
64
68
|
) -> dict[str, pint.Quantity]:
|
|
65
69
|
"""
|
|
@@ -87,17 +91,18 @@ def prune_cutoff(
|
|
|
87
91
|
|
|
88
92
|
near
|
|
89
93
|
A frequency used to select the point around which to prune. By default, pruning
|
|
90
|
-
is performed around the highest peak in :math
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
means that for a trace size of 20001 points, 2000 points below and 2000 points
|
|
94
|
-
above the point corresponding to the selected frequency will be used to find a
|
|
95
|
-
local maximum.
|
|
94
|
+
is performed around the highest peak in :math:`(1 - \\Gamma)`. When ``near`` is
|
|
95
|
+
set, the peak nearest in frequency as identified using :func:`~scipy.signal.find_peaks`
|
|
96
|
+
will be used for pruning.
|
|
96
97
|
|
|
97
98
|
cutoff
|
|
98
99
|
Relative peak height below which the reflection trace should be pruned.
|
|
99
100
|
Uses a fraction of normalised :math:`|\\Gamma|`. Defaults to ``0.4``.
|
|
100
101
|
|
|
102
|
+
height
|
|
103
|
+
Peak height in :math:`(1 - \\Gamma)` passed to :func:`~scipy.signal.find_peaks`,
|
|
104
|
+
defaults to ``0.2``.
|
|
105
|
+
|
|
101
106
|
output
|
|
102
107
|
Name for the output namespace. Defaults to ``"pruned"``.
|
|
103
108
|
|
|
@@ -111,18 +116,20 @@ def prune_cutoff(
|
|
|
111
116
|
re, _, _ = separate_data(real)
|
|
112
117
|
im, _, _ = separate_data(imag)
|
|
113
118
|
absgamma = np.abs(re + 1j * im)
|
|
114
|
-
|
|
119
|
+
|
|
120
|
+
pi = _find_peak(near, absgamma, freq, height=height)
|
|
121
|
+
|
|
115
122
|
max_v = absgamma.max()
|
|
116
123
|
min_v = absgamma[pi]
|
|
117
124
|
norm = (absgamma - min_v) / (max_v - min_v)
|
|
118
|
-
for
|
|
119
|
-
li = pi -
|
|
125
|
+
for left in range(pi - 1):
|
|
126
|
+
li = pi - left
|
|
120
127
|
if norm[li] <= cutoff:
|
|
121
128
|
pass
|
|
122
129
|
else:
|
|
123
130
|
break
|
|
124
|
-
for
|
|
125
|
-
ri = pi +
|
|
131
|
+
for rght in range(len(absgamma) - pi):
|
|
132
|
+
ri = pi + rght
|
|
126
133
|
if norm[ri] <= cutoff:
|
|
127
134
|
pass
|
|
128
135
|
else:
|
|
@@ -169,13 +176,10 @@ def prune_gradient(
|
|
|
169
176
|
corresponding to the reflection coefficient data. Defaults to ``Hz``.
|
|
170
177
|
|
|
171
178
|
near
|
|
172
|
-
A frequency used to select around which
|
|
173
|
-
is performed around the highest peak in :math
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
means that for a trace size of 20001 points, 2000 points below and 2000 points
|
|
177
|
-
above the point corresponding to the selected frequency will be used to find a
|
|
178
|
-
local maximum.
|
|
179
|
+
A frequency used to select the point around which to prune. By default, pruning
|
|
180
|
+
is performed around the highest peak in :math:`(1 - \\Gamma)`. When ``near`` is
|
|
181
|
+
set, the peak nearest in frequency as identified using :func:`~scipy.signal.find_peaks`
|
|
182
|
+
will be used for pruning.
|
|
179
183
|
|
|
180
184
|
threshold
|
|
181
185
|
Threshold for the gradient in the :math:`\\text{abs}(\\Gamma)` below which the
|
|
@@ -199,15 +203,15 @@ def prune_gradient(
|
|
|
199
203
|
|
|
200
204
|
pi = _find_peak(near, absgamma, freq)
|
|
201
205
|
|
|
202
|
-
for
|
|
203
|
-
li = pi -
|
|
204
|
-
if abs(grad[li]) > threshold or
|
|
206
|
+
for left in range(pi - 1):
|
|
207
|
+
li = pi - left
|
|
208
|
+
if abs(grad[li]) > threshold or left < 100:
|
|
205
209
|
pass
|
|
206
210
|
else:
|
|
207
211
|
break
|
|
208
|
-
for
|
|
209
|
-
ri = pi +
|
|
210
|
-
if abs(grad[ri]) > threshold or
|
|
212
|
+
for rght in range(absgamma.size - pi):
|
|
213
|
+
ri = pi + rght
|
|
214
|
+
if abs(grad[ri]) > threshold or rght < 100:
|
|
211
215
|
pass
|
|
212
216
|
else:
|
|
213
217
|
break
|
|
@@ -61,10 +61,10 @@ The data pulled out of the datagram in the second step using the prescription in
|
|
|
61
61
|
are interpolated onto the index of the existing :class:`pd.DataFrame`.
|
|
62
62
|
|
|
63
63
|
"""
|
|
64
|
+
|
|
64
65
|
import numpy as np
|
|
65
66
|
import pandas as pd
|
|
66
|
-
import
|
|
67
|
-
import xarray as xr
|
|
67
|
+
from xarray import DataTree
|
|
68
68
|
import uncertainties as uc
|
|
69
69
|
import uncertainties.unumpy as unp
|
|
70
70
|
from typing import Union, Any, Optional
|
|
@@ -83,14 +83,14 @@ logger = logging.getLogger(__name__)
|
|
|
83
83
|
|
|
84
84
|
|
|
85
85
|
def get_step(
|
|
86
|
-
obj: Union[pd.DataFrame,
|
|
86
|
+
obj: Union[pd.DataFrame, DataTree, dict, None],
|
|
87
87
|
at: Optional[dict] = None,
|
|
88
|
-
) -> Union[pd.DataFrame,
|
|
88
|
+
) -> Union[pd.DataFrame, DataTree, list[dict], None]:
|
|
89
89
|
if obj is None:
|
|
90
90
|
return None
|
|
91
91
|
elif isinstance(obj, pd.DataFrame):
|
|
92
92
|
return obj
|
|
93
|
-
elif isinstance(obj,
|
|
93
|
+
elif isinstance(obj, DataTree):
|
|
94
94
|
if at is not None and "step" in at:
|
|
95
95
|
return obj[at["step"]]
|
|
96
96
|
elif at is not None and "steps" in at:
|
|
@@ -115,7 +115,7 @@ def get_step(
|
|
|
115
115
|
if isinstance(step, int):
|
|
116
116
|
assert step < len(obj["steps"]), (
|
|
117
117
|
f"extract: specified step index {step} is out of bounds "
|
|
118
|
-
f"of the supplied
|
|
118
|
+
f"of the supplied datagram with {len(obj['steps'])} steps."
|
|
119
119
|
)
|
|
120
120
|
ret += obj["steps"][step]["data"]
|
|
121
121
|
elif isinstance(step, str):
|
|
@@ -148,7 +148,7 @@ def get_constant(spec: dict, ts: pd.Index):
|
|
|
148
148
|
|
|
149
149
|
|
|
150
150
|
def extract(
|
|
151
|
-
obj: Union[dict, pd.DataFrame,
|
|
151
|
+
obj: Union[dict, pd.DataFrame, DataTree, None],
|
|
152
152
|
spec: dict,
|
|
153
153
|
index: pd.Index = None,
|
|
154
154
|
) -> pd.DataFrame:
|
|
@@ -229,8 +229,8 @@ def _(obj: pd.DataFrame, columns: list[dict]) -> list[pd.Series]:
|
|
|
229
229
|
return series
|
|
230
230
|
|
|
231
231
|
|
|
232
|
-
@extract_obj.register(
|
|
233
|
-
def _(obj:
|
|
232
|
+
@extract_obj.register(DataTree)
|
|
233
|
+
def _(obj: DataTree, columns: list[dict]) -> list[pd.Series]:
|
|
234
234
|
def get_key_recurse(dt, keys):
|
|
235
235
|
key = keys.pop(0)
|
|
236
236
|
if len(keys) == 0:
|
|
@@ -259,6 +259,8 @@ def _(obj: datatree.DataTree, columns: list[dict]) -> list[pd.Series]:
|
|
|
259
259
|
if vals.coords.dtypes[coord].kind in {"O", "U"}:
|
|
260
260
|
splits = vals[coord].values
|
|
261
261
|
break
|
|
262
|
+
else:
|
|
263
|
+
splits = [None]
|
|
262
264
|
else:
|
|
263
265
|
coord = None
|
|
264
266
|
splits = [None]
|
|
@@ -276,6 +278,8 @@ def _(obj: datatree.DataTree, columns: list[dict]) -> list[pd.Series]:
|
|
|
276
278
|
if sigs is None:
|
|
277
279
|
if coord is None:
|
|
278
280
|
data = vals
|
|
281
|
+
elif split is None:
|
|
282
|
+
data = vals.values
|
|
279
283
|
else:
|
|
280
284
|
data = vals.loc[{coord: split}]
|
|
281
285
|
name.append(split)
|