pymagnetos 0.1.0__tar.gz → 0.7.6__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.
- pymagnetos-0.7.6/PKG-INFO +118 -0
- pymagnetos-0.7.6/README.md +88 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/pyproject.toml +16 -6
- pymagnetos-0.7.6/src/pymagnetos/__init__.py +53 -0
- pymagnetos-0.7.6/src/pymagnetos/__main__.py +5 -0
- pymagnetos-0.7.6/src/pymagnetos/core/__init__.py +33 -0
- pymagnetos-0.1.0/src/pymagnetos/core/_processor.py → pymagnetos-0.7.6/src/pymagnetos/core/_baseprocessor.py +2 -2
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/_data.py +3 -3
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/config_models.py +1 -12
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/gui/__init__.py +1 -1
- pymagnetos-0.1.0/src/pymagnetos/core/gui/_base_mainwindow.py → pymagnetos-0.7.6/src/pymagnetos/core/gui/main.py +12 -2
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/gui/widgets/_graphs.py +6 -4
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/signal_processing.py +2 -2
- pymagnetos-0.7.6/src/pymagnetos/pytdo/__init__.py +16 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pytdo/_config.py +3 -1
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pytdo/_tdoprocessor.py +31 -9
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pytdo/gui/__init__.py +4 -1
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pytdo/gui/main.py +12 -7
- pymagnetos-0.1.0/src/pymagnetos/pytdo/gui/_worker.py → pymagnetos-0.7.6/src/pymagnetos/pytdo/gui/worker.py +3 -0
- pymagnetos-0.7.6/src/pymagnetos/pyuson/__init__.py +16 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pyuson/_config.py +1 -1
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pyuson/_echoprocessor.py +12 -10
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pyuson/gui/__init__.py +3 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pyuson/gui/main.py +1 -1
- pymagnetos-0.1.0/PKG-INFO +0 -23
- pymagnetos-0.1.0/README.md +0 -0
- pymagnetos-0.1.0/src/pymagnetos/__init__.py +0 -15
- pymagnetos-0.1.0/src/pymagnetos/core/__init__.py +0 -19
- pymagnetos-0.1.0/src/pymagnetos/pytdo/__init__.py +0 -6
- pymagnetos-0.1.0/src/pymagnetos/pyuson/__init__.py +0 -7
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/cli.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/_config.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/gui/widgets/__init__.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/gui/widgets/_batch_processing.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/gui/widgets/_configuration.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/gui/widgets/_files.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/gui/widgets/_param_content.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/gui/widgets/_popup_progressbar.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/gui/widgets/_text_logger.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/core/utils.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/log.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/py.typed +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pytdo/assets/config_default.toml +0 -0
- /pymagnetos-0.1.0/src/pymagnetos/pytdo/_config_models.py → /pymagnetos-0.7.6/src/pymagnetos/pytdo/config_models.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pytdo/gui/widgets/__init__.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pytdo/gui/widgets/_buttons.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pytdo/gui/widgets/_configuration.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pytdo/gui/widgets/_graphs.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pytdo/gui/widgets/_param_content.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pyuson/assets/config_default.toml +0 -0
- /pymagnetos-0.1.0/src/pymagnetos/pyuson/_config_models.py → /pymagnetos-0.7.6/src/pymagnetos/pyuson/config_models.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pyuson/gui/widgets/__init__.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pyuson/gui/widgets/_buttons.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pyuson/gui/widgets/_configuration.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pyuson/gui/widgets/_graphs.py +0 -0
- {pymagnetos-0.1.0 → pymagnetos-0.7.6}/src/pymagnetos/pyuson/gui/widgets/_param_content.py +0 -0
- /pymagnetos-0.1.0/src/pymagnetos/pyuson/gui/_worker.py → /pymagnetos-0.7.6/src/pymagnetos/pyuson/gui/worker.py +0 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: pymagnetos
|
|
3
|
+
Version: 0.7.6
|
|
4
|
+
Summary: Applications for high magnetic field analysis
|
|
5
|
+
Author: Guillaume Le Goc
|
|
6
|
+
Author-email: Guillaume Le Goc <guillaume.le-goc@lncmi.cnrs.fr>
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
12
|
+
Requires-Dist: fftekwfm>=0.3.0.1
|
|
13
|
+
Requires-Dist: matplotlib>=3.10.8
|
|
14
|
+
Requires-Dist: nexusformat>=2.0.0
|
|
15
|
+
Requires-Dist: numpy>=2.4.1
|
|
16
|
+
Requires-Dist: pydantic>=2.12.5
|
|
17
|
+
Requires-Dist: pyqt6>=6.10.2
|
|
18
|
+
Requires-Dist: pyqtgraph>=0.14.0
|
|
19
|
+
Requires-Dist: rich>=14.3.1
|
|
20
|
+
Requires-Dist: scipy>=1.17.0
|
|
21
|
+
Requires-Dist: tomlkit>=0.14.0
|
|
22
|
+
Requires-Dist: mkdocstrings>=1.0.2 ; extra == 'docs'
|
|
23
|
+
Requires-Dist: mkdocstrings-python>=2.0.1 ; extra == 'docs'
|
|
24
|
+
Requires-Dist: zensical>=0.0.20 ; extra == 'docs'
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
|
+
Project-URL: Source Code, https://gitlab.in2p3.fr/himagnetos/pymagnetos
|
|
27
|
+
Project-URL: Docs, https://himagnetos.pages.in2p3.fr/pymagnetos/index.html
|
|
28
|
+
Provides-Extra: docs
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# pymagnetos
|
|
32
|
+
[](https://gitlab.in2p3.fr/himagnetos/pymagnetos/-/releases)
|
|
33
|
+
[](https://pypi.org/project/pymagnetos/)
|
|
34
|
+
[](https://himagnetos.pages.in2p3.fr/pymagnetos/)
|
|
35
|
+
[](https://gitlab.in2p3.fr/himagnetos/pymagnetos/-/pipelines)
|
|
36
|
+

|
|
37
|
+
|
|
38
|
+
Collection of Python tools for high magnetic field experiments analysis.
|
|
39
|
+
|
|
40
|
+
It provides libraries and apps to analyse data acquired at the LNCMI in Toulouse.
|
|
41
|
+
|
|
42
|
+
Currently available apps :
|
|
43
|
+
- `pyuson` : for ultra-sound experiments
|
|
44
|
+
- `pytdo` : for TDO experiments
|
|
45
|
+
|
|
46
|
+
Those are also available as a library that can be used within custom Python scripts. They use a common framework that can also be used to build other experiment-specific app.
|
|
47
|
+
|
|
48
|
+
The documention is hosted [here](https://himagnetos.pages.in2p3.fr/pymagnetos/).
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
For more detailed instructions, see the [installation instructions](https://himagnetos.pages.in2p3.fr/pymagnetos/installation.html).
|
|
52
|
+
|
|
53
|
+
### Method 1 : as an app
|
|
54
|
+
If you plan to just use the graphical user interfaces, consider installing `pymagnetos` as a tool managed by [uv](https://docs.astral.sh/uv/), a modern Python package manager, that will install the required Python version and dependencies.
|
|
55
|
+
|
|
56
|
+
<details>
|
|
57
|
+
<summary>Method 1 : Click to see instructions</summary>
|
|
58
|
+
|
|
59
|
+
1. Install uv (see their official [installation instructions](https://docs.astral.sh/uv/getting-started/installation/)).
|
|
60
|
+
- On Windows, enter the following command in PowerShell :
|
|
61
|
+
```powershell
|
|
62
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
63
|
+
```
|
|
64
|
+
- On Linux and MacOS, enter the following in a shell :
|
|
65
|
+
```bash
|
|
66
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
67
|
+
```
|
|
68
|
+
2. From a shell (PowerShell in Windows), install `pymagnetos` globally :
|
|
69
|
+
```bash
|
|
70
|
+
uv tool install pymagnetos
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`pymagnetos` is now installed along its dependencies in an isolated environment with no risks to mess up with your current tools and Python versions. Its main command, `pymagnetos`, is made available from any shell.
|
|
74
|
+
|
|
75
|
+
#### Update
|
|
76
|
+
To upgrade to the latest version, run :
|
|
77
|
+
```bash
|
|
78
|
+
uv tool upgrade pymagnetos
|
|
79
|
+
```
|
|
80
|
+
</details>
|
|
81
|
+
|
|
82
|
+
### Method 2 : as a library
|
|
83
|
+
Installing `pymagnetos` as a library will allow you to use it from scripts and Jupyter notebooks (e.g. you will be able to import it with `import pymagnetos`).
|
|
84
|
+
|
|
85
|
+
<details>
|
|
86
|
+
<summary>Method 2 : Click to see instructions</summary>
|
|
87
|
+
|
|
88
|
+
From a virtual environment with Python>=3.11, install `pymagnetos` from PyPI :
|
|
89
|
+
```bash
|
|
90
|
+
pip install pymagnetos
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### Update
|
|
94
|
+
To upgrade to the latest version, run, from the virtual environment :
|
|
95
|
+
```bash
|
|
96
|
+
pip install --upgrade pymagnetos
|
|
97
|
+
```
|
|
98
|
+
</details>
|
|
99
|
+
|
|
100
|
+
## Usage
|
|
101
|
+
### Run an app
|
|
102
|
+
Once installed, the `pymagnetos` command should be available from the shell (PowerShell in Windows).
|
|
103
|
+
You can check its usage with :
|
|
104
|
+
`pymagnetos --help`
|
|
105
|
+
|
|
106
|
+
Which comes down to :
|
|
107
|
+
- Run the app for ultra-sound experiments : `pymagnetos pyuson`
|
|
108
|
+
- Run the app for TDO experiments : `pymagnetos pytdo`
|
|
109
|
+
|
|
110
|
+
Tip : hit the top arrow on the keyboard to show previous commands you ran.
|
|
111
|
+
|
|
112
|
+
Grab a configuration file template from the [`configs`](https://gitlab.in2p3.fr/himagnetos/pymagnetos/-/tree/main/configs) folder, edit it according to your settings (essentially the path to the data directory) and drag & drop in the app window.
|
|
113
|
+
|
|
114
|
+
### Use in a script
|
|
115
|
+
Subpackages (e.g. `pyuson` or `pytdo`) can be imported in Python scripts or Jupyter notebooks. There are some examples in the [`examples`](https://gitlab.in2p3.fr/himagnetos/pymagnetos/-/tree/main/examples) folder.
|
|
116
|
+
|
|
117
|
+
## Acknowledgments
|
|
118
|
+
`pymagnetos` is developed in the Laboratoire National des Champs Magnétiques Intenses ([LNCMI](https://lncmi.cnrs.fr/)) in Toulouse, France, with the support of the [OSCARS HiMagnetOS project](https://oscars-project.eu/projects/himagnetos-high-magnetic-field-open-science).
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# pymagnetos
|
|
2
|
+
[](https://gitlab.in2p3.fr/himagnetos/pymagnetos/-/releases)
|
|
3
|
+
[](https://pypi.org/project/pymagnetos/)
|
|
4
|
+
[](https://himagnetos.pages.in2p3.fr/pymagnetos/)
|
|
5
|
+
[](https://gitlab.in2p3.fr/himagnetos/pymagnetos/-/pipelines)
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
Collection of Python tools for high magnetic field experiments analysis.
|
|
9
|
+
|
|
10
|
+
It provides libraries and apps to analyse data acquired at the LNCMI in Toulouse.
|
|
11
|
+
|
|
12
|
+
Currently available apps :
|
|
13
|
+
- `pyuson` : for ultra-sound experiments
|
|
14
|
+
- `pytdo` : for TDO experiments
|
|
15
|
+
|
|
16
|
+
Those are also available as a library that can be used within custom Python scripts. They use a common framework that can also be used to build other experiment-specific app.
|
|
17
|
+
|
|
18
|
+
The documention is hosted [here](https://himagnetos.pages.in2p3.fr/pymagnetos/).
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
For more detailed instructions, see the [installation instructions](https://himagnetos.pages.in2p3.fr/pymagnetos/installation.html).
|
|
22
|
+
|
|
23
|
+
### Method 1 : as an app
|
|
24
|
+
If you plan to just use the graphical user interfaces, consider installing `pymagnetos` as a tool managed by [uv](https://docs.astral.sh/uv/), a modern Python package manager, that will install the required Python version and dependencies.
|
|
25
|
+
|
|
26
|
+
<details>
|
|
27
|
+
<summary>Method 1 : Click to see instructions</summary>
|
|
28
|
+
|
|
29
|
+
1. Install uv (see their official [installation instructions](https://docs.astral.sh/uv/getting-started/installation/)).
|
|
30
|
+
- On Windows, enter the following command in PowerShell :
|
|
31
|
+
```powershell
|
|
32
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
|
33
|
+
```
|
|
34
|
+
- On Linux and MacOS, enter the following in a shell :
|
|
35
|
+
```bash
|
|
36
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
37
|
+
```
|
|
38
|
+
2. From a shell (PowerShell in Windows), install `pymagnetos` globally :
|
|
39
|
+
```bash
|
|
40
|
+
uv tool install pymagnetos
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`pymagnetos` is now installed along its dependencies in an isolated environment with no risks to mess up with your current tools and Python versions. Its main command, `pymagnetos`, is made available from any shell.
|
|
44
|
+
|
|
45
|
+
#### Update
|
|
46
|
+
To upgrade to the latest version, run :
|
|
47
|
+
```bash
|
|
48
|
+
uv tool upgrade pymagnetos
|
|
49
|
+
```
|
|
50
|
+
</details>
|
|
51
|
+
|
|
52
|
+
### Method 2 : as a library
|
|
53
|
+
Installing `pymagnetos` as a library will allow you to use it from scripts and Jupyter notebooks (e.g. you will be able to import it with `import pymagnetos`).
|
|
54
|
+
|
|
55
|
+
<details>
|
|
56
|
+
<summary>Method 2 : Click to see instructions</summary>
|
|
57
|
+
|
|
58
|
+
From a virtual environment with Python>=3.11, install `pymagnetos` from PyPI :
|
|
59
|
+
```bash
|
|
60
|
+
pip install pymagnetos
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### Update
|
|
64
|
+
To upgrade to the latest version, run, from the virtual environment :
|
|
65
|
+
```bash
|
|
66
|
+
pip install --upgrade pymagnetos
|
|
67
|
+
```
|
|
68
|
+
</details>
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
### Run an app
|
|
72
|
+
Once installed, the `pymagnetos` command should be available from the shell (PowerShell in Windows).
|
|
73
|
+
You can check its usage with :
|
|
74
|
+
`pymagnetos --help`
|
|
75
|
+
|
|
76
|
+
Which comes down to :
|
|
77
|
+
- Run the app for ultra-sound experiments : `pymagnetos pyuson`
|
|
78
|
+
- Run the app for TDO experiments : `pymagnetos pytdo`
|
|
79
|
+
|
|
80
|
+
Tip : hit the top arrow on the keyboard to show previous commands you ran.
|
|
81
|
+
|
|
82
|
+
Grab a configuration file template from the [`configs`](https://gitlab.in2p3.fr/himagnetos/pymagnetos/-/tree/main/configs) folder, edit it according to your settings (essentially the path to the data directory) and drag & drop in the app window.
|
|
83
|
+
|
|
84
|
+
### Use in a script
|
|
85
|
+
Subpackages (e.g. `pyuson` or `pytdo`) can be imported in Python scripts or Jupyter notebooks. There are some examples in the [`examples`](https://gitlab.in2p3.fr/himagnetos/pymagnetos/-/tree/main/examples) folder.
|
|
86
|
+
|
|
87
|
+
## Acknowledgments
|
|
88
|
+
`pymagnetos` is developed in the Laboratoire National des Champs Magnétiques Intenses ([LNCMI](https://lncmi.cnrs.fr/)) in Toulouse, France, with the support of the [OSCARS HiMagnetOS project](https://oscars-project.eu/projects/himagnetos-high-magnetic-field-open-science).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "pymagnetos"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.6"
|
|
4
4
|
description = "Applications for high magnetic field analysis"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -8,10 +8,12 @@ authors = [
|
|
|
8
8
|
]
|
|
9
9
|
license = {text = "MIT"}
|
|
10
10
|
classifiers = [
|
|
11
|
+
"Programming Language :: Python :: 3.11",
|
|
12
|
+
"Programming Language :: Python :: 3.12",
|
|
11
13
|
"Programming Language :: Python :: 3.13",
|
|
12
14
|
"Programming Language :: Python :: 3.14"
|
|
13
15
|
]
|
|
14
|
-
requires-python = ">=3.
|
|
16
|
+
requires-python = ">=3.11"
|
|
15
17
|
dependencies = [
|
|
16
18
|
"fftekwfm>=0.3.0.1",
|
|
17
19
|
"matplotlib>=3.10.8",
|
|
@@ -27,6 +29,7 @@ dependencies = [
|
|
|
27
29
|
|
|
28
30
|
[project.urls]
|
|
29
31
|
"Source Code" = "https://gitlab.in2p3.fr/himagnetos/pymagnetos"
|
|
32
|
+
"Docs" = "https://himagnetos.pages.in2p3.fr/pymagnetos/index.html"
|
|
30
33
|
|
|
31
34
|
[project.scripts]
|
|
32
35
|
pymagnetos = "pymagnetos.cli:main"
|
|
@@ -35,6 +38,13 @@ pymagnetos = "pymagnetos.cli:main"
|
|
|
35
38
|
pytdo = "pymagnetos.pytdo.gui:run"
|
|
36
39
|
pyuson = "pymagnetos.pyuson.gui:run"
|
|
37
40
|
|
|
41
|
+
[project.optional-dependencies]
|
|
42
|
+
docs = [
|
|
43
|
+
"mkdocstrings>=1.0.2",
|
|
44
|
+
"mkdocstrings-python>=2.0.1",
|
|
45
|
+
"zensical>=0.0.20",
|
|
46
|
+
]
|
|
47
|
+
|
|
38
48
|
|
|
39
49
|
[build-system]
|
|
40
50
|
requires = ["uv_build>=0.9.26,<0.10.0"]
|
|
@@ -56,8 +66,8 @@ convention = "numpy"
|
|
|
56
66
|
[dependency-groups]
|
|
57
67
|
dev = [
|
|
58
68
|
"ipython>=9.9.0",
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"
|
|
62
|
-
"
|
|
69
|
+
"pytest>=9.0.2",
|
|
70
|
+
"pytest-cov>=7.0.0",
|
|
71
|
+
"ruff>=0.14.14",
|
|
72
|
+
"ty>=0.0.14",
|
|
63
73
|
]
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The pymagnetos package.
|
|
3
|
+
|
|
4
|
+
It provides analysis tools for high magnetic field experiments performed at LNCMI-T.
|
|
5
|
+
|
|
6
|
+
Experiment-specific library are specialized implementations of the base classes found in
|
|
7
|
+
the `core` subpackage. They should be generic enough to be used to build any pipeline
|
|
8
|
+
relying on a 'configuration > analysis > store' workflow :
|
|
9
|
+
|
|
10
|
+
1. Configuration : handled by the `Config` object, which uses `pydantic` models to read
|
|
11
|
+
and validate TOML configuration files. One needs to define the `pydantic` models. The
|
|
12
|
+
`BaseConfig` object provides the TOML parser and writer and interface with `pydantic`.
|
|
13
|
+
2. Analysis : handled by the `Processor` objects. It is initialized with the path to a
|
|
14
|
+
configuration file. The `BaseProcessor` object provides the base framework and some
|
|
15
|
+
shared methods related to magnetic field computation.
|
|
16
|
+
3. Store : the `Processor` objects uses the `nexusformat` library to store data
|
|
17
|
+
in-memory. The whole data structure can be easily dumped to a NeXus-compliant HDF5 file,
|
|
18
|
+
and can be consolidated (i.e. add sample- and experiment-related metadata) via the
|
|
19
|
+
configuration file. The output NeXus file is self-contained : it has the raw and
|
|
20
|
+
processed data, along with the analysis configuration. The `Processor` objects can be
|
|
21
|
+
initialized with such a file instead of a configuration file.
|
|
22
|
+
|
|
23
|
+
Graphical user interface
|
|
24
|
+
------------------------
|
|
25
|
+
pymagnetos provides graphical applications built with PyQt6. Each subpackages have a
|
|
26
|
+
`gui` submodule (that are not imported by default). The `core.gui` module contains the
|
|
27
|
+
base components to build an app with a configuration panel, a zone with graphs, action
|
|
28
|
+
buttons and a log text box. It interfaces with a `Worker` object, which is a `Processor`
|
|
29
|
+
instance set in its own thread. The components are Qt widgets that can be built upon and
|
|
30
|
+
re-used.
|
|
31
|
+
|
|
32
|
+
Available subpackages
|
|
33
|
+
---------------------
|
|
34
|
+
- `core` : base classes and components.
|
|
35
|
+
- `pytdo` : a library for TDO experiments.
|
|
36
|
+
- `pyuson` : a library for ultra-sound experiments.
|
|
37
|
+
|
|
38
|
+
Available modules
|
|
39
|
+
-----------------
|
|
40
|
+
- `sp` : signal processing functions.
|
|
41
|
+
- `utils` : utilities for dictionary manipulation.
|
|
42
|
+
- `cli` : used to run the applications.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
import nexusformat.nexus as nx
|
|
46
|
+
|
|
47
|
+
from . import core, pytdo, pyuson
|
|
48
|
+
from .core import sp, utils
|
|
49
|
+
|
|
50
|
+
__all__ = ["core", "pytdo", "pyuson", "sp", "utils"]
|
|
51
|
+
|
|
52
|
+
# Configure NeXus globally
|
|
53
|
+
nx.nxsetconfig(compression=None, encoding="utf-8", lock=0, memory=8000, recursive=True)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The core subpackage, containing base classes and components.
|
|
3
|
+
|
|
4
|
+
Those are meant to be subclassed to build experiment-specific objects.
|
|
5
|
+
|
|
6
|
+
Provides
|
|
7
|
+
--------
|
|
8
|
+
- `BaseConfig` : the base class for the `Config` object.
|
|
9
|
+
- `BaseProcessor` : the base class for the `Processor` object.
|
|
10
|
+
- `BaseData` : NeXus base interface.
|
|
11
|
+
- `DataRaw` : NeXus interface for a raw data container.
|
|
12
|
+
- `DataProcessed` : NeXus interface for a processed data container.
|
|
13
|
+
- `config_models` : `pydantic` models to define the configuration.
|
|
14
|
+
- `sp` : signal processing functions.
|
|
15
|
+
- `utils` : dictionary manipulation utility functions.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from . import config_models, utils
|
|
19
|
+
from . import signal_processing as sp
|
|
20
|
+
from ._baseprocessor import BaseProcessor
|
|
21
|
+
from ._config import BaseConfig
|
|
22
|
+
from ._data import BaseData, DataProcessed, DataRaw
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
"BaseConfig",
|
|
26
|
+
"BaseProcessor",
|
|
27
|
+
"BaseData",
|
|
28
|
+
"DataProcessed",
|
|
29
|
+
"DataRaw",
|
|
30
|
+
"config_models",
|
|
31
|
+
"sp",
|
|
32
|
+
"utils",
|
|
33
|
+
]
|
|
@@ -255,7 +255,7 @@ class BaseProcessor:
|
|
|
255
255
|
|
|
256
256
|
return data
|
|
257
257
|
|
|
258
|
-
def load_pickup(self):
|
|
258
|
+
def load_pickup(self) -> Self:
|
|
259
259
|
"""
|
|
260
260
|
Load the pickup binary file, gathering metadata (if any) and the file.
|
|
261
261
|
|
|
@@ -674,7 +674,7 @@ class BaseProcessor:
|
|
|
674
674
|
"magfield_time", checkonly=True
|
|
675
675
|
) or not self.get_data_processed("magfield", checkonly=True):
|
|
676
676
|
logger.warning("The magnetic field was not computed yet.")
|
|
677
|
-
return
|
|
677
|
+
return
|
|
678
678
|
|
|
679
679
|
fig = plt.figure()
|
|
680
680
|
plt.plot(
|
|
@@ -5,7 +5,7 @@ import importlib.metadata
|
|
|
5
5
|
import nexusformat.nexus as nx
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
class
|
|
8
|
+
class BaseData(nx.NXgroup):
|
|
9
9
|
"""Base Data class integrating NXgroup."""
|
|
10
10
|
|
|
11
11
|
def __init__(self, attr: dict = {}, **kwargs) -> None:
|
|
@@ -30,7 +30,7 @@ class DataBase(nx.NXgroup):
|
|
|
30
30
|
self.attrs[k] = v
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
class DataRaw(
|
|
33
|
+
class DataRaw(BaseData):
|
|
34
34
|
"""Store raw data in a NeXus NXdata group."""
|
|
35
35
|
|
|
36
36
|
def __init__(self, attr: dict = {}, **kwargs) -> None:
|
|
@@ -54,7 +54,7 @@ class DataRaw(DataBase):
|
|
|
54
54
|
self.nxname = "data"
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
class DataProcessed(
|
|
57
|
+
class DataProcessed(BaseData):
|
|
58
58
|
"""Store processed data in a NeXus NXprocess group."""
|
|
59
59
|
|
|
60
60
|
def __init__(
|
|
@@ -6,7 +6,7 @@ Each model corresponds to a section in the configuration file.
|
|
|
6
6
|
|
|
7
7
|
from typing import Any, Literal
|
|
8
8
|
|
|
9
|
-
from pydantic import BaseModel
|
|
9
|
+
from pydantic import BaseModel
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class File(BaseModel):
|
|
@@ -23,17 +23,6 @@ class File(BaseModel):
|
|
|
23
23
|
# For text file
|
|
24
24
|
delimiter: str | None = None
|
|
25
25
|
|
|
26
|
-
@field_validator("precision", "endian", "order", "delimiter")
|
|
27
|
-
@classmethod
|
|
28
|
-
def disallow_none(
|
|
29
|
-
cls,
|
|
30
|
-
value: int | str | Literal["<", ">"] | Literal["C", "F"],
|
|
31
|
-
info: ValidationInfo,
|
|
32
|
-
):
|
|
33
|
-
"""Prevent setting None explicitely."""
|
|
34
|
-
assert value is not None, f"{info.field_name} can't be None"
|
|
35
|
-
return value
|
|
36
|
-
|
|
37
26
|
|
|
38
27
|
class Parameters(BaseModel):
|
|
39
28
|
"""Parameters section, things related to the experiment itself."""
|
|
@@ -795,7 +795,12 @@ class BaseMainWindow(QtWidgets.QMainWindow):
|
|
|
795
795
|
|
|
796
796
|
def dragEnterEvent(self, a0: QtGui.QDropEvent | None = None) -> None:
|
|
797
797
|
"""Handle drag&drop configuration or data file."""
|
|
798
|
-
if a0
|
|
798
|
+
if a0 is None:
|
|
799
|
+
return
|
|
800
|
+
mime_data = a0.mimeData()
|
|
801
|
+
if mime_data is None:
|
|
802
|
+
return
|
|
803
|
+
if mime_data.hasText():
|
|
799
804
|
a0.accept()
|
|
800
805
|
else:
|
|
801
806
|
a0.ignore()
|
|
@@ -806,7 +811,12 @@ class BaseMainWindow(QtWidgets.QMainWindow):
|
|
|
806
811
|
|
|
807
812
|
This triggers the `load_file()` method.
|
|
808
813
|
"""
|
|
809
|
-
|
|
814
|
+
if a0 is None:
|
|
815
|
+
return
|
|
816
|
+
mime_data = a0.mimeData()
|
|
817
|
+
if mime_data is None:
|
|
818
|
+
return
|
|
819
|
+
for url in mime_data.urls():
|
|
810
820
|
file_path = url.toLocalFile()
|
|
811
821
|
if file_path.endswith(ALLOWED_FORMAT):
|
|
812
822
|
self.wconfiguration.files_parameters["file"] = file_path
|
|
@@ -36,18 +36,20 @@ class BaseGraphsWidget(QtWidgets.QWidget):
|
|
|
36
36
|
"""Set and store QPen for styling of curves and ROIs."""
|
|
37
37
|
raise NotImplementedError("Subclass must implement this method.")
|
|
38
38
|
|
|
39
|
-
def event(self,
|
|
39
|
+
def event(self, a0: QEvent | None = None) -> bool:
|
|
40
40
|
"""Handle mouse selection while holding CTRL to make a ROI zoom in plots."""
|
|
41
41
|
# Switch to rectangular zoom selection on the first Ctrl key press event
|
|
42
|
-
if
|
|
42
|
+
if a0 is None:
|
|
43
|
+
return False
|
|
44
|
+
if a0.type() == QKeyEvent.Type.KeyPress and a0.key() == Qt.Key.Key_Control: # ty:ignore[unresolved-attribute]
|
|
43
45
|
if self._mouse_pan_mode:
|
|
44
46
|
self.switch_mouse_pan_mode(False)
|
|
45
47
|
|
|
46
48
|
# Switch back to pan mode on left click when releasing the Ctrl key
|
|
47
|
-
if
|
|
49
|
+
if a0.type() == QKeyEvent.Type.KeyRelease and a0.key() == Qt.Key.Key_Control: # ty:ignore[unresolved-attribute]
|
|
48
50
|
self.switch_mouse_pan_mode(True)
|
|
49
51
|
|
|
50
|
-
return super().event(
|
|
52
|
+
return super().event(a0)
|
|
51
53
|
|
|
52
54
|
def switch_mouse_pan_mode(self, state: bool) -> None:
|
|
53
55
|
"""
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Signal processing module."""
|
|
2
2
|
|
|
3
3
|
import warnings
|
|
4
4
|
from collections.abc import Callable, Iterable
|
|
@@ -889,7 +889,7 @@ def fit_poly(
|
|
|
889
889
|
Magnetic field vector (x).
|
|
890
890
|
sig : np.ndarray
|
|
891
891
|
pyqtSignal vector (y).
|
|
892
|
-
|
|
892
|
+
boundary1, boundary2 : float
|
|
893
893
|
Do the fit only in `field` comprised in `[poly_boundary1, poly_boundary2]`.
|
|
894
894
|
poly_deg : int
|
|
895
895
|
Polynome degree.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The `pytdo` subpackage, a library for TDO experiments.
|
|
3
|
+
|
|
4
|
+
Provides
|
|
5
|
+
--------
|
|
6
|
+
- `TDOConfig` : The `Config` object specific to TDO experiments.
|
|
7
|
+
- `TDOProcessor` : the `Processor` object specific to TDO experiments.
|
|
8
|
+
- `config_models` : the `pydantic` models to define the configuration requirements.
|
|
9
|
+
- `gui` : a graphical application. It needs to be imported explicitely.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from . import config_models
|
|
13
|
+
from ._config import TDOConfig
|
|
14
|
+
from ._tdoprocessor import TDOProcessor
|
|
15
|
+
|
|
16
|
+
__all__ = ["TDOConfig", "TDOProcessor", "config_models"]
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
"""Config class for the TDOProcessor object."""
|
|
2
|
+
|
|
1
3
|
from pathlib import Path
|
|
2
4
|
from typing import Any
|
|
3
5
|
|
|
4
6
|
from ..core import BaseConfig
|
|
5
|
-
from .
|
|
7
|
+
from .config_models import TDOConfiguration
|
|
6
8
|
|
|
7
9
|
CONFIG_DEFAULT = Path(__file__).parent / "assets" / "config_default.toml"
|
|
8
10
|
|
|
@@ -228,7 +228,7 @@ class TDOProcessor(BaseProcessor):
|
|
|
228
228
|
where: Literal["raw", "processed"] = "raw",
|
|
229
229
|
force: bool = False,
|
|
230
230
|
append: str = "_full",
|
|
231
|
-
):
|
|
231
|
+
) -> None:
|
|
232
232
|
"""
|
|
233
233
|
Crop a 1D vector from `start` to `stop`.
|
|
234
234
|
|
|
@@ -656,7 +656,7 @@ class TDOProcessor(BaseProcessor):
|
|
|
656
656
|
|
|
657
657
|
return self
|
|
658
658
|
|
|
659
|
-
def _remove_data_changed(self):
|
|
659
|
+
def _remove_data_changed(self) -> None:
|
|
660
660
|
"""Remove data that was computed but the data it relied on changed."""
|
|
661
661
|
self.remove_data_processed(self._tdo_name + "_fit_inc")
|
|
662
662
|
self.remove_data_processed(self._tdo_name + "_fit_dec")
|
|
@@ -669,7 +669,7 @@ class TDOProcessor(BaseProcessor):
|
|
|
669
669
|
self.remove_data_processed("fft_inc")
|
|
670
670
|
self.remove_data_processed("fft_dec")
|
|
671
671
|
|
|
672
|
-
def _get_result_names_list(self, ud: Literal["inc", "dec"]):
|
|
672
|
+
def _get_result_names_list(self, ud: Literal["inc", "dec"]) -> list[str]:
|
|
673
673
|
"""
|
|
674
674
|
Generate the list of things to save.
|
|
675
675
|
|
|
@@ -755,31 +755,53 @@ class TDOProcessor(BaseProcessor):
|
|
|
755
755
|
|
|
756
756
|
return self
|
|
757
757
|
|
|
758
|
-
def load_csv(self, filepath: Path | str, sep: str | None = None):
|
|
758
|
+
def load_csv(self, filepath: Path | str, sep: str | None = None) -> Self:
|
|
759
759
|
"""Load data from a CSV file."""
|
|
760
760
|
filepath = Path(filepath)
|
|
761
761
|
if not filepath.is_file():
|
|
762
762
|
logger.error("File does not exist")
|
|
763
|
-
return
|
|
763
|
+
return self
|
|
764
764
|
|
|
765
765
|
reader, delimiter = self._determine_file_format(filepath, sep=sep)
|
|
766
766
|
|
|
767
767
|
if isinstance(reader, str) and reader == "unknown":
|
|
768
768
|
logger.error(f"Could not load input file ({filepath})")
|
|
769
|
-
return
|
|
769
|
+
return self
|
|
770
770
|
|
|
771
771
|
logger.info(f"Reading data from {filepath.name}...")
|
|
772
772
|
self._reinit()
|
|
773
773
|
status = reader(filepath, delimiter)
|
|
774
774
|
if not status:
|
|
775
775
|
logger.error(f"Failed to read {filepath.name}, check messages above")
|
|
776
|
-
return
|
|
776
|
+
return self
|
|
777
777
|
|
|
778
778
|
# Get the up / down indices
|
|
779
779
|
self.get_up_down_indices()
|
|
780
780
|
|
|
781
781
|
logger.info(f"Read data from {filepath.name}.")
|
|
782
782
|
|
|
783
|
+
return self
|
|
784
|
+
|
|
785
|
+
def load(self, filename: str | Path | None) -> Self:
|
|
786
|
+
"""
|
|
787
|
+
Load a previously saved NeXus file.
|
|
788
|
+
|
|
789
|
+
Use `BaseProcessor.save()` method, with additionnal steps : guess the internal
|
|
790
|
+
flags and add convenience attributes. The returned `TDOProcessor` object can be
|
|
791
|
+
used to resume analysis where it was left off.
|
|
792
|
+
|
|
793
|
+
Parameters
|
|
794
|
+
----------
|
|
795
|
+
filename : str
|
|
796
|
+
Full path to the file to load.
|
|
797
|
+
"""
|
|
798
|
+
super().load(filename)
|
|
799
|
+
|
|
800
|
+
# Find increasing/decreasing magnetic field indices
|
|
801
|
+
self.get_up_down_indices()
|
|
802
|
+
|
|
803
|
+
return self
|
|
804
|
+
|
|
783
805
|
def _determine_file_format(
|
|
784
806
|
self, filepath: Path, sep: str | None = None
|
|
785
807
|
) -> tuple[Callable[[Path, str], bool] | str, str]:
|
|
@@ -991,7 +1013,7 @@ class TDOProcessor(BaseProcessor):
|
|
|
991
1013
|
"fft_" + kw: extract_col(10),
|
|
992
1014
|
}
|
|
993
1015
|
|
|
994
|
-
def _set_map_in_data_processed(self, data: dict[str, np.ndarray]):
|
|
1016
|
+
def _set_map_in_data_processed(self, data: dict[str, np.ndarray]) -> None:
|
|
995
1017
|
"""Set data in `data_processed`."""
|
|
996
1018
|
for key, value in data.items():
|
|
997
1019
|
self.set_data_processed(key, value)
|
|
@@ -1044,7 +1066,7 @@ class TDOProcessor(BaseProcessor):
|
|
|
1044
1066
|
self._tdo_inv_inc_name, checkonly=True
|
|
1045
1067
|
) and self.get_data_processed(self._tdo_inv_dec_name, checkonly=True)
|
|
1046
1068
|
|
|
1047
|
-
def _reinit(self):
|
|
1069
|
+
def _reinit(self) -> None:
|
|
1048
1070
|
"""Clear data and initialize objects."""
|
|
1049
1071
|
super()._reinit()
|
|
1050
1072
|
|
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from PyQt6 import QtWidgets
|
|
4
4
|
|
|
5
|
+
from . import widgets
|
|
5
6
|
from .main import MainWindow
|
|
6
7
|
|
|
8
|
+
__all__ = ["MainWindow", "run", "widgets"]
|
|
9
|
+
|
|
7
10
|
|
|
8
11
|
def run(exec: bool = True) -> None | MainWindow:
|
|
9
12
|
"""
|
|
@@ -23,4 +26,4 @@ def run(exec: bool = True) -> None | MainWindow:
|
|
|
23
26
|
if exec:
|
|
24
27
|
app.exec()
|
|
25
28
|
else:
|
|
26
|
-
return win
|
|
29
|
+
return win
|
|
@@ -9,8 +9,8 @@ from PyQt6.QtCore import pyqtSignal, pyqtSlot
|
|
|
9
9
|
from pymagnetos.core.gui import BaseMainWindow
|
|
10
10
|
from pymagnetos.core.gui.widgets import BatchProcessingWidget, FileBrowserWidget
|
|
11
11
|
|
|
12
|
-
from . import
|
|
13
|
-
from .
|
|
12
|
+
from .widgets import ButtonsWidget, ConfigurationWidget, GraphsWidget, ParamContent
|
|
13
|
+
from .worker import DataWorker
|
|
14
14
|
|
|
15
15
|
ICON_PATH = str(Path(__file__).parent / "assets" / "icon.png")
|
|
16
16
|
REGEXP_EXPID_SEPARATORS = r"[_-]"
|
|
@@ -46,11 +46,11 @@ class MainWindow(BaseMainWindow):
|
|
|
46
46
|
def __init__(self):
|
|
47
47
|
# Register the widgets
|
|
48
48
|
self._type_wbatch = BatchProcessingWidget
|
|
49
|
-
self._type_wbuttons =
|
|
50
|
-
self._type_wconfiguration =
|
|
49
|
+
self._type_wbuttons = ButtonsWidget
|
|
50
|
+
self._type_wconfiguration = ConfigurationWidget
|
|
51
51
|
self._type_wfiles = FileBrowserWidget
|
|
52
|
-
self._type_wgraphs =
|
|
53
|
-
self._param_content =
|
|
52
|
+
self._type_wgraphs = GraphsWidget
|
|
53
|
+
self._param_content = ParamContent
|
|
54
54
|
self._type_worker = DataWorker
|
|
55
55
|
|
|
56
56
|
super().__init__()
|
|
@@ -608,7 +608,12 @@ class MainWindow(BaseMainWindow):
|
|
|
608
608
|
|
|
609
609
|
def dropEvent(self, a0: QtGui.QDropEvent | None = None) -> None:
|
|
610
610
|
"""Load a file when it is dropped in the main window."""
|
|
611
|
-
|
|
611
|
+
if a0 is None:
|
|
612
|
+
return
|
|
613
|
+
mime_data = a0.mimeData()
|
|
614
|
+
if mime_data is None:
|
|
615
|
+
return
|
|
616
|
+
for url in mime_data.urls():
|
|
612
617
|
file_path = url.toLocalFile()
|
|
613
618
|
if file_path.endswith(OUT_FORMAT):
|
|
614
619
|
self.load_csv_file(file_path)
|
|
@@ -69,6 +69,7 @@ class DataWorker(QObject):
|
|
|
69
69
|
self.sig_offset_finished.emit()
|
|
70
70
|
|
|
71
71
|
def align_field(self):
|
|
72
|
+
"""Align magnetic field on signal."""
|
|
72
73
|
self.proc.align_field()
|
|
73
74
|
self.sig_align_finished.emit()
|
|
74
75
|
|
|
@@ -80,6 +81,7 @@ class DataWorker(QObject):
|
|
|
80
81
|
|
|
81
82
|
@pyqtSlot()
|
|
82
83
|
def batch_process(self):
|
|
84
|
+
"""Not implemented, for compatiblity."""
|
|
83
85
|
return
|
|
84
86
|
|
|
85
87
|
@pyqtSlot(str)
|
|
@@ -102,5 +104,6 @@ class DataWorker(QObject):
|
|
|
102
104
|
|
|
103
105
|
@pyqtSlot(str)
|
|
104
106
|
def load_csv_file(self, fname: str):
|
|
107
|
+
"""Save data as CSV file."""
|
|
105
108
|
self.proc.load_csv(fname)
|
|
106
109
|
self.sig_load_csv_finished.emit()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The `pyuson` subpackage, a library for ultra-sound echoes experiments.
|
|
3
|
+
|
|
4
|
+
Provides
|
|
5
|
+
--------
|
|
6
|
+
- `EchoConfig` : The `Config` object specific to ultra-sound experiments.
|
|
7
|
+
- `EchoProcessor` : the `Processor` object specific to ultra-sound experiments.
|
|
8
|
+
- `config_models` : the `pydantic` models to define the configuration requirements.
|
|
9
|
+
- `gui` : a graphical application. It needs to be imported explicitely.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from . import config_models
|
|
13
|
+
from ._config import EchoConfig
|
|
14
|
+
from ._echoprocessor import EchoProcessor
|
|
15
|
+
|
|
16
|
+
__all__ = ["EchoConfig", "EchoProcessor", "config_models"]
|
|
@@ -4,7 +4,7 @@ from pathlib import Path
|
|
|
4
4
|
from typing import Any
|
|
5
5
|
|
|
6
6
|
from ..core import BaseConfig
|
|
7
|
-
from .
|
|
7
|
+
from .config_models import EchoConfigurationModel
|
|
8
8
|
|
|
9
9
|
CONFIG_DEFAULT = Path(__file__).parent / "assets" / "config_default.toml"
|
|
10
10
|
|
|
@@ -183,7 +183,7 @@ class EchoProcessor(BaseProcessor):
|
|
|
183
183
|
"""
|
|
184
184
|
self.cfg.settings.analysis_window = value
|
|
185
185
|
|
|
186
|
-
def _init_flags(self):
|
|
186
|
+
def _init_flags(self) -> None:
|
|
187
187
|
"""Set up flags."""
|
|
188
188
|
# Tektronix WFM files or LabVIEW binary file
|
|
189
189
|
self.is_wfm = False
|
|
@@ -204,7 +204,7 @@ class EchoProcessor(BaseProcessor):
|
|
|
204
204
|
# Moving mean was performed, if it was, use the smoothed data in data_processed
|
|
205
205
|
self.is_rollmean = {m: False for m in self.measurements}
|
|
206
206
|
|
|
207
|
-
def _guess_flags(self):
|
|
207
|
+
def _guess_flags(self) -> None:
|
|
208
208
|
"""Attempt to guess flags from data after loading a NeXus file."""
|
|
209
209
|
self.is_wfm = None # no files so irrelevant
|
|
210
210
|
self.is_us = self._check_measurement_time_us()
|
|
@@ -223,7 +223,7 @@ class EchoProcessor(BaseProcessor):
|
|
|
223
223
|
self.is_decimated = self._check_time_subsampled()
|
|
224
224
|
self.is_rollmean = self._check_rollmean()
|
|
225
225
|
|
|
226
|
-
def _init_digital(self):
|
|
226
|
+
def _init_digital(self) -> None:
|
|
227
227
|
"""Additional initializations for digital mode."""
|
|
228
228
|
# Prepare internal names
|
|
229
229
|
self._ref_name = REFNAME
|
|
@@ -249,7 +249,7 @@ class EchoProcessor(BaseProcessor):
|
|
|
249
249
|
self.is_rollmean = {m: False for m in self.measurements} # the keys changed
|
|
250
250
|
self.is_meas_processed = True
|
|
251
251
|
|
|
252
|
-
def _reinit(self):
|
|
252
|
+
def _reinit(self) -> None:
|
|
253
253
|
"""Re-initialize data objects."""
|
|
254
254
|
super()._reinit()
|
|
255
255
|
if self.is_digital:
|
|
@@ -534,7 +534,7 @@ class EchoProcessor(BaseProcessor):
|
|
|
534
534
|
|
|
535
535
|
return self
|
|
536
536
|
|
|
537
|
-
def _update_time_subsampled(self, new_npoints: int):
|
|
537
|
+
def _update_time_subsampled(self, new_npoints: int) -> None:
|
|
538
538
|
"""
|
|
539
539
|
Update time vector if subsampling was used.
|
|
540
540
|
|
|
@@ -1158,7 +1158,7 @@ class EchoProcessor(BaseProcessor):
|
|
|
1158
1158
|
"""Alias for the `average_frame_range()` method."""
|
|
1159
1159
|
return self.average_frame_range(**kwargs)
|
|
1160
1160
|
|
|
1161
|
-
def _compute_amplitude_avg(self):
|
|
1161
|
+
def _compute_amplitude_avg(self) -> None:
|
|
1162
1162
|
"""
|
|
1163
1163
|
Compute amplitude from averaged I and Q.
|
|
1164
1164
|
|
|
@@ -1239,7 +1239,7 @@ class EchoProcessor(BaseProcessor):
|
|
|
1239
1239
|
self.is_averaged = True
|
|
1240
1240
|
return
|
|
1241
1241
|
|
|
1242
|
-
def compute_phase_avg(self):
|
|
1242
|
+
def compute_phase_avg(self) -> Self:
|
|
1243
1243
|
"""Compute phase from I and Q and correct for pi jumps."""
|
|
1244
1244
|
# Get names
|
|
1245
1245
|
iname = self._i_name + "_avg"
|
|
@@ -1264,6 +1264,8 @@ class EchoProcessor(BaseProcessor):
|
|
|
1264
1264
|
# Mark for success
|
|
1265
1265
|
self.is_averaged = True
|
|
1266
1266
|
|
|
1267
|
+
return self
|
|
1268
|
+
|
|
1267
1269
|
def compute_attenuation(self) -> Self:
|
|
1268
1270
|
"""
|
|
1269
1271
|
Compute attenuation from amplitude average for the current echo.
|
|
@@ -1305,7 +1307,7 @@ class EchoProcessor(BaseProcessor):
|
|
|
1305
1307
|
|
|
1306
1308
|
return self
|
|
1307
1309
|
|
|
1308
|
-
def compute_phase_shift(self):
|
|
1310
|
+
def compute_phase_shift(self) -> Self:
|
|
1309
1311
|
"""
|
|
1310
1312
|
Compute relative phase shift given the phase average for the current echo.
|
|
1311
1313
|
|
|
@@ -1602,7 +1604,7 @@ class EchoProcessor(BaseProcessor):
|
|
|
1602
1604
|
|
|
1603
1605
|
def to_csv(
|
|
1604
1606
|
self, fname: None | str | Path = None, sep: str = "\t", to_cm: bool = False
|
|
1605
|
-
):
|
|
1607
|
+
) -> None:
|
|
1606
1608
|
r"""
|
|
1607
1609
|
Export attenuation and phase shift data as a CSV file.
|
|
1608
1610
|
|
|
@@ -1780,7 +1782,7 @@ class EchoProcessor(BaseProcessor):
|
|
|
1780
1782
|
is_rollmean[meas] = False
|
|
1781
1783
|
return is_rollmean
|
|
1782
1784
|
|
|
1783
|
-
def _check_time_subsampled(self):
|
|
1785
|
+
def _check_time_subsampled(self) -> bool:
|
|
1784
1786
|
"""
|
|
1785
1787
|
Check if measurement time vector was subsampled.
|
|
1786
1788
|
|
|
@@ -15,8 +15,8 @@ from PyQt6.QtCore import pyqtSignal, pyqtSlot
|
|
|
15
15
|
from pymagnetos import sp
|
|
16
16
|
from pymagnetos.core.gui import BaseMainWindow, widgets
|
|
17
17
|
|
|
18
|
-
from ._worker import ProcessorWorker
|
|
19
18
|
from .widgets import ButtonsWidget, ConfigurationWidget, GraphsWidget, ParamContent
|
|
19
|
+
from .worker import ProcessorWorker
|
|
20
20
|
|
|
21
21
|
ICON_PATH = str(Path(__file__).parent / "assets" / "icon.png")
|
|
22
22
|
REGEXP_EXPID_SEPARATORS = r"[_-]"
|
pymagnetos-0.1.0/PKG-INFO
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.3
|
|
2
|
-
Name: pymagnetos
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: Applications for high magnetic field analysis
|
|
5
|
-
Author: Guillaume Le Goc
|
|
6
|
-
Author-email: Guillaume Le Goc <guillaume.le-goc@lncmi.cnrs.fr>
|
|
7
|
-
License: MIT
|
|
8
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
10
|
-
Requires-Dist: fftekwfm>=0.3.0.1
|
|
11
|
-
Requires-Dist: matplotlib>=3.10.8
|
|
12
|
-
Requires-Dist: nexusformat>=2.0.0
|
|
13
|
-
Requires-Dist: numpy>=2.4.1
|
|
14
|
-
Requires-Dist: pydantic>=2.12.5
|
|
15
|
-
Requires-Dist: pyqt6>=6.10.2
|
|
16
|
-
Requires-Dist: pyqtgraph>=0.14.0
|
|
17
|
-
Requires-Dist: rich>=14.3.1
|
|
18
|
-
Requires-Dist: scipy>=1.17.0
|
|
19
|
-
Requires-Dist: tomlkit>=0.14.0
|
|
20
|
-
Requires-Python: >=3.13
|
|
21
|
-
Project-URL: Source Code, https://gitlab.in2p3.fr/himagnetos/pymagnetos
|
|
22
|
-
Description-Content-Type: text/markdown
|
|
23
|
-
|
pymagnetos-0.1.0/README.md
DELETED
|
File without changes
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
The pymagnetos package.
|
|
3
|
-
|
|
4
|
-
It provides analysis tools for high magnetic field experiments.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import nexusformat.nexus as nx
|
|
8
|
-
|
|
9
|
-
from . import core, pytdo, pyuson
|
|
10
|
-
from .core import sp, utils
|
|
11
|
-
|
|
12
|
-
__all__ = ["core", "pytdo", "pyuson", "sp", "utils"]
|
|
13
|
-
|
|
14
|
-
# Configure NeXus globally
|
|
15
|
-
nx.nxsetconfig(compression=None, encoding="utf-8", lock=0, memory=8000, recursive=True)
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
"""The core module, containing base classes and components."""
|
|
2
|
-
|
|
3
|
-
from . import config_models, gui, utils
|
|
4
|
-
from . import signal_processing as sp
|
|
5
|
-
from ._config import BaseConfig
|
|
6
|
-
from ._data import DataBase, DataProcessed, DataRaw
|
|
7
|
-
from ._processor import BaseProcessor
|
|
8
|
-
|
|
9
|
-
__all__ = [
|
|
10
|
-
"BaseConfig",
|
|
11
|
-
"BaseProcessor",
|
|
12
|
-
"DataBase",
|
|
13
|
-
"DataProcessed",
|
|
14
|
-
"DataRaw",
|
|
15
|
-
"config_models",
|
|
16
|
-
"gui",
|
|
17
|
-
"sp",
|
|
18
|
-
"utils",
|
|
19
|
-
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|