ewoksid16a 0.1.0__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.
- ewoksid16a-0.1.0/LICENSE +20 -0
- ewoksid16a-0.1.0/PKG-INFO +44 -0
- ewoksid16a-0.1.0/README.md +7 -0
- ewoksid16a-0.1.0/pyproject.toml +97 -0
- ewoksid16a-0.1.0/setup.cfg +4 -0
- ewoksid16a-0.1.0/src/ewoksid16a/__init__.py +0 -0
- ewoksid16a-0.1.0/src/ewoksid16a/tasks/__init__.py +0 -0
- ewoksid16a-0.1.0/src/ewoksid16a/tasks/fluo/norm_it.py +152 -0
- ewoksid16a-0.1.0/src/ewoksid16a/tasks/fluo/spectral_regrid.py +100 -0
- ewoksid16a-0.1.0/src/ewoksid16a/tasks/fluo/sumspectrumfit.py +165 -0
- ewoksid16a-0.1.0/src/ewoksid16a/tasks/fluo/tiffexporter.py +117 -0
- ewoksid16a-0.1.0/src/ewoksid16a/tasks/fluo/weight.py +143 -0
- ewoksid16a-0.1.0/src/ewoksid16a/tests/__init__.py +0 -0
- ewoksid16a-0.1.0/src/ewoksid16a/tests/test_dummy.py +3 -0
- ewoksid16a-0.1.0/src/ewoksid16a.egg-info/PKG-INFO +44 -0
- ewoksid16a-0.1.0/src/ewoksid16a.egg-info/SOURCES.txt +22 -0
- ewoksid16a-0.1.0/src/ewoksid16a.egg-info/dependency_links.txt +1 -0
- ewoksid16a-0.1.0/src/ewoksid16a.egg-info/entry_points.txt +22 -0
- ewoksid16a-0.1.0/src/ewoksid16a.egg-info/requires.txt +21 -0
- ewoksid16a-0.1.0/src/ewoksid16a.egg-info/top_level.txt +2 -0
- ewoksid16a-0.1.0/src/orangecontrib/ewoksid16a/__init__.py +23 -0
- ewoksid16a-0.1.0/src/orangecontrib/ewoksid16a/categories/__init__.py +26 -0
- ewoksid16a-0.1.0/src/orangecontrib/ewoksid16a/icons/__init__.py +0 -0
- ewoksid16a-0.1.0/src/orangecontrib/ewoksid16a/tutorials/__init__.py +0 -0
ewoksid16a-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
**Copyright (c) 2021-2025 European Synchrotron Radiation Facility**
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ewoksid16a
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Data processing workflows for ID16A
|
|
5
|
+
Author-email: ESRF <dau-pydev@esrf.fr>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://gitlab.esrf.fr/workflow/ewoksapps/ewoksid16a/
|
|
8
|
+
Project-URL: Documentation, https://ewoksid16a.readthedocs.io/
|
|
9
|
+
Project-URL: Repository, https://gitlab.esrf.fr/workflow/ewoksapps/ewoksid16a/
|
|
10
|
+
Project-URL: Issues, https://gitlab.esrf.fr/workflow/ewoksapps/ewoksid16a/issues
|
|
11
|
+
Project-URL: Changelog, https://gitlab.esrf.fr/workflow/ewoksapps/ewoksid16a/-/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: orange3 add-on,ewoks
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: ewoksjob
|
|
19
|
+
Requires-Dist: ewoksfluo
|
|
20
|
+
Requires-Dist: blissdata
|
|
21
|
+
Requires-Dist: ewoksorange
|
|
22
|
+
Provides-Extra: test
|
|
23
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
24
|
+
Requires-Dist: pyqt6; extra == "test"
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: ewoksid16a[test]; extra == "dev"
|
|
27
|
+
Requires-Dist: black>=25; extra == "dev"
|
|
28
|
+
Requires-Dist: flake8>=4; extra == "dev"
|
|
29
|
+
Requires-Dist: ruff; extra == "dev"
|
|
30
|
+
Requires-Dist: bandit; extra == "dev"
|
|
31
|
+
Provides-Extra: doc
|
|
32
|
+
Requires-Dist: ewoksid16a[test]; extra == "doc"
|
|
33
|
+
Requires-Dist: sphinx>=4.5; extra == "doc"
|
|
34
|
+
Requires-Dist: sphinx-autodoc-typehints>=1.16; extra == "doc"
|
|
35
|
+
Requires-Dist: pydata-sphinx-theme; extra == "doc"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# ewoksid16a
|
|
39
|
+
|
|
40
|
+
Data processing workflows for ID16A
|
|
41
|
+
|
|
42
|
+
## Documentation
|
|
43
|
+
|
|
44
|
+
https://ewoksid16a.readthedocs.io/
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools>=61",
|
|
4
|
+
]
|
|
5
|
+
build-backend = "setuptools.build_meta"
|
|
6
|
+
|
|
7
|
+
[project]
|
|
8
|
+
name = "ewoksid16a"
|
|
9
|
+
version = "0.1.0"
|
|
10
|
+
keywords = [
|
|
11
|
+
"orange3 add-on",
|
|
12
|
+
"ewoks"
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
authors = [{name = "ESRF", email = "dau-pydev@esrf.fr"}]
|
|
16
|
+
description = "Data processing workflows for ID16A"
|
|
17
|
+
readme = {file = "README.md", content-type = "text/markdown"}
|
|
18
|
+
license = "MIT"
|
|
19
|
+
license-files = ["LICENSE"]
|
|
20
|
+
classifiers = [
|
|
21
|
+
"Intended Audience :: Science/Research",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
]
|
|
24
|
+
requires-python = ">=3.9"
|
|
25
|
+
dependencies = [
|
|
26
|
+
"ewoksjob",
|
|
27
|
+
"ewoksfluo",
|
|
28
|
+
"blissdata",
|
|
29
|
+
"ewoksorange",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://gitlab.esrf.fr/workflow/ewoksapps/ewoksid16a/"
|
|
34
|
+
Documentation = "https://ewoksid16a.readthedocs.io/"
|
|
35
|
+
Repository = "https://gitlab.esrf.fr/workflow/ewoksapps/ewoksid16a/"
|
|
36
|
+
Issues = "https://gitlab.esrf.fr/workflow/ewoksapps/ewoksid16a/issues"
|
|
37
|
+
Changelog = "https://gitlab.esrf.fr/workflow/ewoksapps/ewoksid16a/-/blob/main/CHANGELOG.md"
|
|
38
|
+
|
|
39
|
+
[project.optional-dependencies]
|
|
40
|
+
test = [
|
|
41
|
+
"pytest >=7",
|
|
42
|
+
"pyqt6",
|
|
43
|
+
]
|
|
44
|
+
dev = [
|
|
45
|
+
"ewoksid16a[test]",
|
|
46
|
+
"black >=25",
|
|
47
|
+
"flake8 >=4",
|
|
48
|
+
"ruff",
|
|
49
|
+
"bandit"
|
|
50
|
+
]
|
|
51
|
+
doc = [
|
|
52
|
+
"ewoksid16a[test]",
|
|
53
|
+
"sphinx >=4.5",
|
|
54
|
+
"sphinx-autodoc-typehints >=1.16",
|
|
55
|
+
"pydata-sphinx-theme",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[tool.setuptools]
|
|
59
|
+
package-dir = {""= "src"}
|
|
60
|
+
|
|
61
|
+
[tool.setuptools.packages.find]
|
|
62
|
+
where = ["src"]
|
|
63
|
+
|
|
64
|
+
[tool.setuptools.package-data]
|
|
65
|
+
"ewoksid16a.tests.data"= ["*/*"]
|
|
66
|
+
"*" = ["*.ows", "*.png", "*.svg"]
|
|
67
|
+
|
|
68
|
+
[project.entry-points."ewoks.tasks.class"]
|
|
69
|
+
"ewoksid16a.tasks.*" = "ewoksid16a"
|
|
70
|
+
|
|
71
|
+
[project.entry-points."orange3.addon"]
|
|
72
|
+
"ewoksid16a" = "orangecontrib.ewoksid16a"
|
|
73
|
+
|
|
74
|
+
[project.entry-points."orange.widgets"]
|
|
75
|
+
"Examples" = "orangecontrib.ewoksid16a"
|
|
76
|
+
"ExamplesCategories" = "orangecontrib.ewoksid16a.categories"
|
|
77
|
+
|
|
78
|
+
[project.entry-points."orangecanvas.examples"]
|
|
79
|
+
"Examples" = "orangecontrib.ewoksid16a.tutorials"
|
|
80
|
+
"Examples1" = "orangecontrib.ewoksid16a.categories.examples1.tutorials"
|
|
81
|
+
"Examples2" = "orangecontrib.ewoksid16a.categories.examples2.tutorials"
|
|
82
|
+
|
|
83
|
+
[project.entry-points."orange.widgets.tutorials"]
|
|
84
|
+
"Examples" = "orangecontrib.ewoksid16a.tutorials"
|
|
85
|
+
"Examples1" = "orangecontrib.ewoksid16a.categories.examples1.tutorials"
|
|
86
|
+
"Examples2" = "orangecontrib.ewoksid16a.categories.examples2.tutorials"
|
|
87
|
+
|
|
88
|
+
[project.entry-points."orange.canvas.help"]
|
|
89
|
+
"html-index" = "orangecontrib.ewoksid16a:WIDGET_HELP_PATH"
|
|
90
|
+
|
|
91
|
+
[tool.coverage.run]
|
|
92
|
+
omit = [
|
|
93
|
+
"*/tests/*"
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[tool.bandit.assert_used]
|
|
97
|
+
skips = ["*/test_*.py"]
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
from ewokscore import Task
|
|
2
|
+
|
|
3
|
+
from ewoksfluo.tasks import nexus_utils
|
|
4
|
+
from ewoksfluo.tasks.hdf5_utils import link_bliss_scan, create_hdf5_link
|
|
5
|
+
|
|
6
|
+
# import h5py
|
|
7
|
+
# import hdf5plugin # noqa: F401
|
|
8
|
+
import numpy as np
|
|
9
|
+
from configparser import ConfigParser
|
|
10
|
+
|
|
11
|
+
from silx.io import h5py_utils
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class NormalizeCurrent(
|
|
15
|
+
Task,
|
|
16
|
+
input_names=[
|
|
17
|
+
"bliss_scan_uri",
|
|
18
|
+
"output_root_uri",
|
|
19
|
+
"current_counter",
|
|
20
|
+
"reference_uri",
|
|
21
|
+
"dwelltime_counter",
|
|
22
|
+
"ref_current_counter",
|
|
23
|
+
"diode_factor",
|
|
24
|
+
],
|
|
25
|
+
optional_input_names=["gamma_coef", "min_ref", "max_ref", "exp_default"],
|
|
26
|
+
output_names=["bliss_scan_uri", "output_root_uri"],
|
|
27
|
+
):
|
|
28
|
+
"""Add single-scan XRF results of multiple detectors"""
|
|
29
|
+
|
|
30
|
+
def run(self):
|
|
31
|
+
start_time = nexus_utils.now()
|
|
32
|
+
bliss_scan_uri = self.inputs.bliss_scan_uri
|
|
33
|
+
output_root_uri = self.inputs.output_root_uri
|
|
34
|
+
scanuris = bliss_scan_uri.split("::")
|
|
35
|
+
|
|
36
|
+
filename = scanuris[0]
|
|
37
|
+
scanno = scanuris[1]
|
|
38
|
+
|
|
39
|
+
counter_template = f"/{scanno}/instrument/%s/data"
|
|
40
|
+
|
|
41
|
+
ref_scanuris = self.inputs.reference_uri.split("::")
|
|
42
|
+
|
|
43
|
+
ref_filename = ref_scanuris[0]
|
|
44
|
+
ref_scanno = ref_scanuris[1]
|
|
45
|
+
|
|
46
|
+
ref_counter_template = f"/{ref_scanno}/instrument/%s/data"
|
|
47
|
+
|
|
48
|
+
with h5py_utils.open_item(
|
|
49
|
+
ref_filename, ref_counter_template % self.inputs["ref_current_counter"]
|
|
50
|
+
) as ds: # type: ignore[reportGeneralTypeIssues]
|
|
51
|
+
# ref_epoch = np.array(fd[ref_counter_template%self.inputs.get("ref_epoch_counter", "epoch")])
|
|
52
|
+
ref_values = np.array(ds)
|
|
53
|
+
|
|
54
|
+
with h5py_utils.open_item(filename, "/") as fd: # type: ignore[reportGeneralTypeIssues]
|
|
55
|
+
# epoch = np.array(fd[ref_counter_template%self.inputs.get("data_epoch_counter", "epoch_trig")])
|
|
56
|
+
values = np.array(fd[counter_template % self.inputs["current_counter"]])
|
|
57
|
+
dwelltime = np.mean(fd[counter_template % self.inputs["dwelltime_counter"]])
|
|
58
|
+
|
|
59
|
+
min_ref = self.get_input_value("min_ref", 1e8)
|
|
60
|
+
max_ref = self.get_input_value("max_ref", 1e15)
|
|
61
|
+
|
|
62
|
+
diode_factor = self.inputs.diode_factor * 1e12 # Convert ph/pA to ph/A
|
|
63
|
+
|
|
64
|
+
ref_msk = np.logical_and(
|
|
65
|
+
ref_values * diode_factor > min_ref, ref_values * diode_factor < max_ref
|
|
66
|
+
) # When shutter was open and not saturated
|
|
67
|
+
|
|
68
|
+
# ref_epoch = ref_epoch[ref_msk]
|
|
69
|
+
ref_values = ref_values[ref_msk]
|
|
70
|
+
|
|
71
|
+
gamma = np.mean(values) / (np.mean(ref_values) * dwelltime)
|
|
72
|
+
gamma_coef = self.get_input_value("gamma_coef", 2.0)
|
|
73
|
+
|
|
74
|
+
real_gamma_exp = np.log10(gamma / gamma_coef)
|
|
75
|
+
gamma_exp = np.round(real_gamma_exp)
|
|
76
|
+
|
|
77
|
+
gamma = gamma_coef * 10**gamma_exp
|
|
78
|
+
|
|
79
|
+
with nexus_utils.save_in_ewoks_process(
|
|
80
|
+
output_root_uri,
|
|
81
|
+
start_time,
|
|
82
|
+
process_config={"real_gamma_exp": real_gamma_exp, "gamma_exp": gamma_exp},
|
|
83
|
+
default_levels=(scanno, "scaled_it"),
|
|
84
|
+
) as (process_group, already_existed):
|
|
85
|
+
outentry = process_group.parent
|
|
86
|
+
if not already_existed:
|
|
87
|
+
|
|
88
|
+
link_bliss_scan(outentry, bliss_scan_uri, retry_timeout=0)
|
|
89
|
+
|
|
90
|
+
nxdata = nexus_utils.create_nxdata(
|
|
91
|
+
process_group, "scaled_it", signal="data"
|
|
92
|
+
)
|
|
93
|
+
nxdata.attrs["interpretation"] = "spectrum"
|
|
94
|
+
dset = nxdata.create_dataset("data", data=values / gamma * diode_factor)
|
|
95
|
+
|
|
96
|
+
nxdetector = outentry["instrument"].create_group("scaled_it")
|
|
97
|
+
nxdetector.attrs["NX_class"] = "NXdetector"
|
|
98
|
+
create_hdf5_link(nxdetector, "data", dset)
|
|
99
|
+
create_hdf5_link(outentry["measurement"], "scaled_it", dset)
|
|
100
|
+
|
|
101
|
+
output_root_uri = f"{outentry.file.filename}::{outentry.name}"
|
|
102
|
+
|
|
103
|
+
self.outputs.bliss_scan_uri = bliss_scan_uri
|
|
104
|
+
self.outputs.output_root_uri = output_root_uri
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class NormalizationFactorFromConfig(
|
|
108
|
+
Task,
|
|
109
|
+
input_names=["bliss_scan_uri", "xrf_results_uri", "config_file"],
|
|
110
|
+
output_names=[
|
|
111
|
+
"bliss_scan_uri",
|
|
112
|
+
"xrf_results_uri",
|
|
113
|
+
"counter_normalization_template",
|
|
114
|
+
],
|
|
115
|
+
):
|
|
116
|
+
"""Add single-scan XRF results of multiple detectors"""
|
|
117
|
+
|
|
118
|
+
def get_from_cfg(self, cfg):
|
|
119
|
+
cp = ConfigParser()
|
|
120
|
+
cp.read(cfg)
|
|
121
|
+
|
|
122
|
+
flux = cp.getfloat("concentrations", "flux")
|
|
123
|
+
dwelltime = cp.getfloat("concentrations", "time")
|
|
124
|
+
|
|
125
|
+
matrix = cp.get("attenuators", "Matrix")
|
|
126
|
+
matdat = matrix.replace(" ", "").split(",")
|
|
127
|
+
matrix_composition = matdat[1]
|
|
128
|
+
matrix_density = float(matdat[2])
|
|
129
|
+
matrix_thickness = float(matdat[3])
|
|
130
|
+
print("INFO FROM CONFIG FILE")
|
|
131
|
+
print("Config input flux: {0:g} (ph/s)".format(flux))
|
|
132
|
+
print("Config dwell time: {0} (s)".format(dwelltime))
|
|
133
|
+
print("Matrix composition: {0}".format(matrix_composition))
|
|
134
|
+
print("Matrix density: {0} (g/cm**3)".format(matrix_density))
|
|
135
|
+
print("Matrix thickness: {0} (cm)".format(matrix_thickness))
|
|
136
|
+
areal_dens_ratio = matrix_density * matrix_thickness * 1e7 # ng/mm**2
|
|
137
|
+
return flux, areal_dens_ratio, dwelltime
|
|
138
|
+
|
|
139
|
+
def run(self):
|
|
140
|
+
|
|
141
|
+
self.outputs.bliss_scan_uri = self.inputs.bliss_scan_uri
|
|
142
|
+
self.outputs.xrf_results_uri = self.inputs.xrf_results_uri
|
|
143
|
+
|
|
144
|
+
cfg_flux, areal_dens_ratio, cfg_dwelltime = self.get_from_cfg(
|
|
145
|
+
self.inputs.config_file
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
factor = cfg_flux * cfg_dwelltime * areal_dens_ratio
|
|
149
|
+
|
|
150
|
+
self.outputs.counter_normalization_template = (
|
|
151
|
+
f"{factor:.04e}/<instrument/{{}}/data>"
|
|
152
|
+
)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import h5py
|
|
2
|
+
import hdf5plugin # noqa: F401
|
|
3
|
+
from silx.io import h5py_utils
|
|
4
|
+
import numpy as np
|
|
5
|
+
from ewokscore import Task
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SpectralRegrid(
|
|
9
|
+
Task,
|
|
10
|
+
input_names=["bliss_scan_uri", "output_root_uri", "counter_name"],
|
|
11
|
+
optional_input_names=[],
|
|
12
|
+
output_names=["bliss_scan_uri", "output_root_uri"],
|
|
13
|
+
):
|
|
14
|
+
"""Regrid raw spectrums"""
|
|
15
|
+
|
|
16
|
+
def run(self):
|
|
17
|
+
|
|
18
|
+
_uris = self.inputs.bliss_scan_uri.split("::")
|
|
19
|
+
filename_src = _uris[0]
|
|
20
|
+
scan_src = _uris[1]
|
|
21
|
+
cntnam = self.inputs.counter_name
|
|
22
|
+
|
|
23
|
+
fscanuri = f"{scan_src}/instrument/fscan_parameters"
|
|
24
|
+
|
|
25
|
+
with h5py_utils.open_item(filename_src, "/") as fd: # type: ignore[reportGeneralTypeIssues]
|
|
26
|
+
fastmot = fd[f"{fscanuri}/fast_motor"][()].decode()
|
|
27
|
+
mode = fd[f"{fscanuri}/fast_motor_mode"][()].decode()
|
|
28
|
+
fast_n = fd[f"{fscanuri}/fast_npoints"][()]
|
|
29
|
+
slow_n = fd[f"{fscanuri}/slow_npoints"][()]
|
|
30
|
+
|
|
31
|
+
cnt = fd[f"{scan_src}/instrument/{cntnam}/data"]
|
|
32
|
+
cnt_shape = cnt.shape
|
|
33
|
+
cnt_dtype = cnt.dtype
|
|
34
|
+
|
|
35
|
+
A = np.arange(fast_n * slow_n)
|
|
36
|
+
A.shape = (fast_n, slow_n)
|
|
37
|
+
|
|
38
|
+
if fastmot.endswith("z"):
|
|
39
|
+
A = A.swapaxes(0, 1)
|
|
40
|
+
|
|
41
|
+
if mode == "ZIGZAG":
|
|
42
|
+
A[1::2, :] = A[1::2, :][:, ::-1]
|
|
43
|
+
|
|
44
|
+
_uris = self.inputs.output_root_uri.split("::")
|
|
45
|
+
filename = _uris[0]
|
|
46
|
+
scan = _uris[1]
|
|
47
|
+
|
|
48
|
+
with h5py_utils.open_item(filename, "/", mode="a") as fd: # type: ignore[reportGeneralTypeIssues]
|
|
49
|
+
grp = fd
|
|
50
|
+
S = scan.split("/")
|
|
51
|
+
|
|
52
|
+
for i, s in enumerate(S):
|
|
53
|
+
if s == "":
|
|
54
|
+
continue
|
|
55
|
+
|
|
56
|
+
grp = grp.require_group(s)
|
|
57
|
+
|
|
58
|
+
if i == len(S) - 1:
|
|
59
|
+
grp.attrs.update(
|
|
60
|
+
{
|
|
61
|
+
"NX_class": "NXdata",
|
|
62
|
+
"signal": "data",
|
|
63
|
+
"interpretation": "image",
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
else:
|
|
67
|
+
grp.attrs.update({"NX_class": "NXcollection", "default": S[i + 1]})
|
|
68
|
+
|
|
69
|
+
layout = h5py.VirtualLayout(
|
|
70
|
+
shape=(
|
|
71
|
+
cnt_shape[1],
|
|
72
|
+
*A.shape,
|
|
73
|
+
),
|
|
74
|
+
dtype=cnt_dtype,
|
|
75
|
+
)
|
|
76
|
+
layoutpymca = h5py.VirtualLayout(
|
|
77
|
+
shape=(
|
|
78
|
+
*A.shape,
|
|
79
|
+
cnt_shape[1],
|
|
80
|
+
),
|
|
81
|
+
dtype=cnt_dtype,
|
|
82
|
+
)
|
|
83
|
+
vsource = h5py.VirtualSource(
|
|
84
|
+
filename_src,
|
|
85
|
+
f"{scan_src}/instrument/{cntnam}/data",
|
|
86
|
+
shape=cnt_shape,
|
|
87
|
+
dtype=cnt.dtype,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
for i in range(cnt_shape[0]):
|
|
91
|
+
# print(np.unravel_index(i, A.shape), layout.shape, vsource[A.flat[i]].shape)
|
|
92
|
+
|
|
93
|
+
layout[(slice(None), *np.unravel_index(i, A.shape))] = vsource[
|
|
94
|
+
A.flat[i]
|
|
95
|
+
]
|
|
96
|
+
layoutpymca[(*np.unravel_index(i, A.shape), slice(None))] = vsource[
|
|
97
|
+
A.flat[i]
|
|
98
|
+
]
|
|
99
|
+
grp.create_virtual_dataset("data", layout, fillvalue=-1)
|
|
100
|
+
grp.create_virtual_dataset("pymca", layoutpymca, fillvalue=-1)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
from PyMca5.PyMcaIO import ConfigDict
|
|
2
|
+
|
|
3
|
+
# import h5py
|
|
4
|
+
# import hdf5plugin # noqa: F401
|
|
5
|
+
from silx.io import h5py_utils
|
|
6
|
+
import numpy as np
|
|
7
|
+
import time
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
from PyMca5.PyMcaPhysics.xrf.ClassMcaTheory import ClassMcaTheory
|
|
11
|
+
import matplotlib.pyplot as plt
|
|
12
|
+
import os
|
|
13
|
+
from ewokscore import Task
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AdvancedFitSumSingleDetector(
|
|
17
|
+
Task,
|
|
18
|
+
input_names=[
|
|
19
|
+
"bliss_scan_uri",
|
|
20
|
+
"detector_name",
|
|
21
|
+
"config",
|
|
22
|
+
"output_root_uri",
|
|
23
|
+
],
|
|
24
|
+
optional_input_names=[
|
|
25
|
+
"figure_filename",
|
|
26
|
+
"batchconfig_suffix",
|
|
27
|
+
"instrument_data_template",
|
|
28
|
+
"batch_force",
|
|
29
|
+
"waitForConfigFile",
|
|
30
|
+
"retryPeriod",
|
|
31
|
+
"retryN",
|
|
32
|
+
],
|
|
33
|
+
output_names=[
|
|
34
|
+
"bliss_scan_uri",
|
|
35
|
+
"detector_name",
|
|
36
|
+
"output_root_uri",
|
|
37
|
+
"batch_config_filename",
|
|
38
|
+
],
|
|
39
|
+
):
|
|
40
|
+
|
|
41
|
+
def run(self):
|
|
42
|
+
|
|
43
|
+
input_uri = self.inputs.bliss_scan_uri
|
|
44
|
+
output_uri = self.inputs.output_root_uri
|
|
45
|
+
detector_name = self.inputs.detector_name
|
|
46
|
+
config_file = self.inputs.config
|
|
47
|
+
|
|
48
|
+
dettmpl = self.get_input_value("instrument_data_template", "instrument/{}/data")
|
|
49
|
+
batch_suffix = self.get_input_value("batchconfig_suffix", None)
|
|
50
|
+
batch_force = self.get_input_value(
|
|
51
|
+
"batch_force", {"fit.stripflag": 0, "fit.escapeflag": 0, "fit.fitweight": 0}
|
|
52
|
+
)
|
|
53
|
+
waitForConfigFile = self.get_input_value("waitForConfigFile", True)
|
|
54
|
+
retryPeriod = self.get_input_value("retryPeriod", 3)
|
|
55
|
+
retryN = self.get_input_value("retryN", 1200)
|
|
56
|
+
|
|
57
|
+
figure_filename = self.get_input_value("figure_filename", None)
|
|
58
|
+
|
|
59
|
+
uris = input_uri.split("::")
|
|
60
|
+
filename = uris[0]
|
|
61
|
+
datpath = uris[1] + "/" + dettmpl.format(detector_name)
|
|
62
|
+
|
|
63
|
+
if waitForConfigFile:
|
|
64
|
+
for i in range(retryN):
|
|
65
|
+
if os.path.isfile(config_file):
|
|
66
|
+
break
|
|
67
|
+
time.sleep(retryPeriod)
|
|
68
|
+
else:
|
|
69
|
+
raise RuntimeError(f"Config file {config_file} not found!")
|
|
70
|
+
|
|
71
|
+
with h5py_utils.open_item(filename, datpath) as ds: # type: ignore[reportGeneralTypeIssues]
|
|
72
|
+
data = np.array(ds)
|
|
73
|
+
|
|
74
|
+
batch_savefile = None
|
|
75
|
+
|
|
76
|
+
if batch_suffix is not None:
|
|
77
|
+
batch_savefile = config_file + batch_suffix
|
|
78
|
+
|
|
79
|
+
if not os.path.isfile(batch_suffix):
|
|
80
|
+
|
|
81
|
+
cfg = ConfigDict.ConfigDict(filelist=config_file)
|
|
82
|
+
|
|
83
|
+
for k in batch_force:
|
|
84
|
+
_c = cfg
|
|
85
|
+
kk = k.split(".")
|
|
86
|
+
for _k in kk[:-1]:
|
|
87
|
+
_c = _c[_k]
|
|
88
|
+
|
|
89
|
+
_c[kk[-1]] = batch_force[k]
|
|
90
|
+
|
|
91
|
+
cfg.write(batch_savefile)
|
|
92
|
+
|
|
93
|
+
data = np.sum(data, keepdims=True, axis=0) / data.shape[0]
|
|
94
|
+
|
|
95
|
+
mcafit = ClassMcaTheory(config_file)
|
|
96
|
+
mcafit.setData(x=np.arange(data.shape[1]), y=data)
|
|
97
|
+
mcafit.estimate()
|
|
98
|
+
p, fit = mcafit.startfit(digest=1)
|
|
99
|
+
|
|
100
|
+
egy = fit["energy"]
|
|
101
|
+
bkg = fit["continuum"]
|
|
102
|
+
grps = fit["groups"]
|
|
103
|
+
yfit = fit["yfit"]
|
|
104
|
+
ydata = fit["ydata"]
|
|
105
|
+
|
|
106
|
+
ouris = output_uri.split("::")
|
|
107
|
+
out_filename = ouris[0]
|
|
108
|
+
out_path = ouris[1]
|
|
109
|
+
|
|
110
|
+
with h5py_utils.open_item(out_filename, "/", mode="a") as fd: # type: ignore[reportGeneralTypeIssues]
|
|
111
|
+
|
|
112
|
+
_res = fd
|
|
113
|
+
for g in out_path.split("/"):
|
|
114
|
+
_g = g.strip()
|
|
115
|
+
if len(_g) == 0:
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
_res = _res.require_group(_g)
|
|
119
|
+
_res.attrs["NX_class"] = "NXcollection"
|
|
120
|
+
|
|
121
|
+
_res.attrs["NX_class"] = "NXdata"
|
|
122
|
+
_res.attrs["signal"] = "fit"
|
|
123
|
+
_res.attrs["auxiliary_signals"] = [
|
|
124
|
+
"background",
|
|
125
|
+
"spectrum",
|
|
126
|
+
] + grps
|
|
127
|
+
_res.attrs["axes"] = ["energy"]
|
|
128
|
+
|
|
129
|
+
egyds = _res.create_dataset("energy", data=egy)
|
|
130
|
+
egyds.attrs["units"] = "keV"
|
|
131
|
+
|
|
132
|
+
_res.create_dataset("fit", data=yfit)
|
|
133
|
+
_res.create_dataset("spectrum", data=ydata)
|
|
134
|
+
_res.create_dataset("background", data=bkg)
|
|
135
|
+
|
|
136
|
+
for g in grps:
|
|
137
|
+
_res.create_dataset(g, data=fit[f"y{g}"])
|
|
138
|
+
|
|
139
|
+
if figure_filename is not None:
|
|
140
|
+
|
|
141
|
+
figpath = os.path.dirname(figure_filename)
|
|
142
|
+
os.makedirs(figpath, exist_ok=True)
|
|
143
|
+
|
|
144
|
+
fig, ax = plt.subplots(figsize=(8, 5), layout="constrained")
|
|
145
|
+
colors = plt.get_cmap("nipy_spectral")(np.linspace(0.1, 0.9, len(grps)))
|
|
146
|
+
|
|
147
|
+
ax.plot(egy, ydata, "-", color="0.7", label="Data", linewidth=4)
|
|
148
|
+
# ax.plot(egy, yfit, 'r-', label="Fit", linewidth=2)
|
|
149
|
+
|
|
150
|
+
for c, g in zip(colors, grps):
|
|
151
|
+
ax.plot(egy, fit[f"y{g}"] + bkg, "--", label=g, linewidth=1.5, color=c)
|
|
152
|
+
|
|
153
|
+
ax.plot(egy, bkg, "b", label="Background", linewidth=2)
|
|
154
|
+
|
|
155
|
+
fig.legend(loc="outside right upper")
|
|
156
|
+
|
|
157
|
+
ax.set_yscale("log")
|
|
158
|
+
ax.set_xlabel("Energy (keV)")
|
|
159
|
+
|
|
160
|
+
fig.savefig(figure_filename)
|
|
161
|
+
|
|
162
|
+
self.outputs.output_root_uri = output_uri
|
|
163
|
+
self.outputs.detector_name = detector_name
|
|
164
|
+
self.outputs.bliss_scan_uri = input_uri
|
|
165
|
+
self.outputs.batch_config_filename = batch_savefile
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# import h5py
|
|
2
|
+
# import hdf5plugin # noqa: F401
|
|
3
|
+
from silx.io import h5py_utils
|
|
4
|
+
import os
|
|
5
|
+
from ewokscore import Task
|
|
6
|
+
import numpy as np
|
|
7
|
+
import matplotlib.pyplot as plt
|
|
8
|
+
import matplotlib as mpl
|
|
9
|
+
|
|
10
|
+
from PIL import Image
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TiffExporterFromRegrid(
|
|
14
|
+
Task,
|
|
15
|
+
input_names=[
|
|
16
|
+
"regrid_uri",
|
|
17
|
+
"output_path",
|
|
18
|
+
],
|
|
19
|
+
optional_input_names=[
|
|
20
|
+
"output_prefix",
|
|
21
|
+
"output_suffix",
|
|
22
|
+
"output_gallery_path",
|
|
23
|
+
],
|
|
24
|
+
output_names=[],
|
|
25
|
+
):
|
|
26
|
+
|
|
27
|
+
def run(self):
|
|
28
|
+
|
|
29
|
+
regrid_uri = self.inputs.regrid_uri
|
|
30
|
+
output_path = self.inputs.output_path
|
|
31
|
+
output_prefix = self.get_input_value("output_prefix", "IMG_")
|
|
32
|
+
output_suffix = self.get_input_value("output_suffix", "")
|
|
33
|
+
output_gallery_path = self.get_input_value("output_gallery_path", None)
|
|
34
|
+
|
|
35
|
+
os.makedirs(output_path, exist_ok=True)
|
|
36
|
+
if output_gallery_path is not None:
|
|
37
|
+
os.makedirs(output_gallery_path, exist_ok=True)
|
|
38
|
+
|
|
39
|
+
uris = regrid_uri.split("::")
|
|
40
|
+
input_filename = uris[0]
|
|
41
|
+
grp = uris[1]
|
|
42
|
+
|
|
43
|
+
with h5py_utils.open_item(input_filename, "/") as fd: # type: ignore[reportGeneralTypeIssues]
|
|
44
|
+
_res = fd[grp]
|
|
45
|
+
is_nxdata = "NX_class" in _res.attrs and _res.attrs["NX_class"] == "NXdata"
|
|
46
|
+
|
|
47
|
+
while not is_nxdata:
|
|
48
|
+
_res = _res[_res.attrs["default"]]
|
|
49
|
+
is_nxdata = (
|
|
50
|
+
"NX_class" in _res.attrs and _res.attrs["NX_class"] == "NXdata"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
grps = []
|
|
54
|
+
if "signal" in _res.attrs:
|
|
55
|
+
grps += [
|
|
56
|
+
_res.attrs["signal"],
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
if "auxiliary_signals" in _res.attrs:
|
|
60
|
+
grps += list(_res.attrs["auxiliary_signals"])
|
|
61
|
+
|
|
62
|
+
kwargs = {}
|
|
63
|
+
axes = []
|
|
64
|
+
axnames = []
|
|
65
|
+
if "axes" in _res.attrs:
|
|
66
|
+
resolutions = []
|
|
67
|
+
for a in _res.attrs["axes"]:
|
|
68
|
+
axnames += [
|
|
69
|
+
a,
|
|
70
|
+
]
|
|
71
|
+
d = np.array(_res[a])
|
|
72
|
+
axes += [
|
|
73
|
+
d,
|
|
74
|
+
]
|
|
75
|
+
resolutions += [
|
|
76
|
+
1e4 / float(np.mean(np.diff(d))),
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
kwargs["resolution_unit"] = 3
|
|
80
|
+
kwargs["resolution"] = resolutions
|
|
81
|
+
|
|
82
|
+
cmap = "jet"
|
|
83
|
+
|
|
84
|
+
for g in grps:
|
|
85
|
+
data = np.array(_res[g], dtype=np.float32)
|
|
86
|
+
im = Image.fromarray(data, mode="F")
|
|
87
|
+
gg = g.replace(" ", "_")
|
|
88
|
+
im.save(
|
|
89
|
+
os.path.join(
|
|
90
|
+
output_path, f"{output_prefix}{gg}{output_suffix}.tiff"
|
|
91
|
+
),
|
|
92
|
+
**kwargs,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# ArraySave.save2DArrayListAsMonochromaticTiff([data], os.path.join(output_path, f"{output_prefix}{gg}.tiff"), dtype=np.float32)
|
|
96
|
+
if output_gallery_path is not None:
|
|
97
|
+
norm = mpl.colors.Normalize(0, np.max(data))
|
|
98
|
+
f, ax = plt.subplots()
|
|
99
|
+
ax.pcolor(*axes, data, norm=norm, cmap=cmap)
|
|
100
|
+
ax.invert_yaxis()
|
|
101
|
+
|
|
102
|
+
if len(axnames) == 2:
|
|
103
|
+
ax.set_xlabel(f"{axnames[1]} (um)")
|
|
104
|
+
ax.set_ylabel(f"{axnames[0]} (um)")
|
|
105
|
+
|
|
106
|
+
f.suptitle(g)
|
|
107
|
+
f.colorbar(
|
|
108
|
+
mpl.cm.ScalarMappable(norm=norm, cmap=cmap),
|
|
109
|
+
ax=ax,
|
|
110
|
+
label="Areal mass density ($ng/mm^2$)",
|
|
111
|
+
)
|
|
112
|
+
f.savefig(
|
|
113
|
+
os.path.join(
|
|
114
|
+
output_gallery_path,
|
|
115
|
+
f"{output_prefix}{gg}{output_suffix}.jpg",
|
|
116
|
+
)
|
|
117
|
+
)
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
from typing import Sequence
|
|
2
|
+
|
|
3
|
+
from ewokscore import Task
|
|
4
|
+
|
|
5
|
+
from ewoksfluo.tasks import xrf_results
|
|
6
|
+
from ewoksfluo.io.hdf5 import ReadHdf5File
|
|
7
|
+
import h5py
|
|
8
|
+
import hdf5plugin # noqa: F401
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class WeightedSumResults(
|
|
13
|
+
Task,
|
|
14
|
+
input_names=[
|
|
15
|
+
"xrf_norm_uris",
|
|
16
|
+
"xrf_fit_uris",
|
|
17
|
+
"bliss_scan_uri",
|
|
18
|
+
"detector_names",
|
|
19
|
+
"output_root_uri",
|
|
20
|
+
],
|
|
21
|
+
optional_input_names=["detector_normalization_template"],
|
|
22
|
+
output_names=["xrf_results_uri", "bliss_scan_uri", "output_root_uri"],
|
|
23
|
+
):
|
|
24
|
+
"""Add single-scan XRF results of multiple detectors"""
|
|
25
|
+
|
|
26
|
+
def _read_xrf_results(self, uri):
|
|
27
|
+
|
|
28
|
+
res = dict()
|
|
29
|
+
|
|
30
|
+
fit_filename, fit_h5path = uri.split("::")
|
|
31
|
+
|
|
32
|
+
fit_h5path += "/results"
|
|
33
|
+
|
|
34
|
+
with ReadHdf5File(fit_filename) as h5file:
|
|
35
|
+
try:
|
|
36
|
+
xrf_results_group = h5file[fit_h5path]
|
|
37
|
+
except KeyError:
|
|
38
|
+
raise KeyError(
|
|
39
|
+
f"HDF5 path not found: '{fit_h5path}' in file '{fit_filename}'"
|
|
40
|
+
)
|
|
41
|
+
if not isinstance(xrf_results_group, h5py.Group):
|
|
42
|
+
raise TypeError(
|
|
43
|
+
f"Expected HDF5 Group at '{fit_h5path}', but got {type(xrf_results_group)}"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
if "massfractions" not in xrf_results_group:
|
|
47
|
+
raise KeyError(f"'massfractions' group missing under '{fit_h5path}'")
|
|
48
|
+
param_group = xrf_results_group["massfractions"]
|
|
49
|
+
if not isinstance(param_group, h5py.Group):
|
|
50
|
+
raise TypeError(
|
|
51
|
+
f"Expected HDF5 Group for 'massfractions', but got {type(param_group)}"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
for dset_name, dset in param_group.items():
|
|
55
|
+
if not xrf_results.is_peak_area(dset):
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
res[dset_name] = np.array(param_group[dset_name][()])
|
|
59
|
+
|
|
60
|
+
return res
|
|
61
|
+
|
|
62
|
+
def _dict_op(self, fun, a, b):
|
|
63
|
+
|
|
64
|
+
ka = set(a.keys())
|
|
65
|
+
kb = set(b.keys())
|
|
66
|
+
|
|
67
|
+
s = dict()
|
|
68
|
+
|
|
69
|
+
for k in set.intersection(ka, kb):
|
|
70
|
+
s[k] = fun(a[k], b[k])
|
|
71
|
+
|
|
72
|
+
return s
|
|
73
|
+
|
|
74
|
+
def dict_op(self, fun, *op):
|
|
75
|
+
|
|
76
|
+
if len(op) <= 1:
|
|
77
|
+
return op
|
|
78
|
+
|
|
79
|
+
res = self._dict_op(fun, op[0], op[1])
|
|
80
|
+
|
|
81
|
+
for i in range(2, len(op)):
|
|
82
|
+
res = self._dict_op(fun, res, op[i])
|
|
83
|
+
|
|
84
|
+
return res
|
|
85
|
+
|
|
86
|
+
def dict_plus(self, *op):
|
|
87
|
+
return self.dict_op(lambda a, b: a + b, *op)
|
|
88
|
+
|
|
89
|
+
def dict_mult(self, *op):
|
|
90
|
+
return self.dict_op(lambda a, b: a * b, *op)
|
|
91
|
+
|
|
92
|
+
def run(self) -> None:
|
|
93
|
+
params = {**self.get_input_values()}
|
|
94
|
+
|
|
95
|
+
xrf_norm_uris: Sequence[str] = params["xrf_norm_uris"]
|
|
96
|
+
xrf_fit_uris: Sequence[str] = params["xrf_fit_uris"]
|
|
97
|
+
bliss_scan_uri: str = params["bliss_scan_uri"]
|
|
98
|
+
output_root_uri: str = params["output_root_uri"]
|
|
99
|
+
|
|
100
|
+
if len(xrf_norm_uris) < 1:
|
|
101
|
+
raise ValueError("Expected at least 1 detector to sum")
|
|
102
|
+
|
|
103
|
+
if len(xrf_norm_uris) != len(xrf_fit_uris):
|
|
104
|
+
raise ValueError(
|
|
105
|
+
"Expected the same number of elements in _norm_ and _fit_ arrays."
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
summed_fit = None
|
|
109
|
+
summed_prod = None
|
|
110
|
+
|
|
111
|
+
config = {"xrf_norm_uris": xrf_norm_uris, "xrf_fit_uris": xrf_fit_uris}
|
|
112
|
+
|
|
113
|
+
for norm_uri, fit_uri in zip(xrf_norm_uris, xrf_fit_uris):
|
|
114
|
+
|
|
115
|
+
norm_data = self._read_xrf_results(norm_uri)
|
|
116
|
+
fit_data = self._read_xrf_results(fit_uri)
|
|
117
|
+
|
|
118
|
+
if summed_fit is None:
|
|
119
|
+
summed_fit = fit_data
|
|
120
|
+
else:
|
|
121
|
+
summed_fit = self.dict_plus(summed_fit, fit_data)
|
|
122
|
+
|
|
123
|
+
if summed_prod is None:
|
|
124
|
+
summed_prod = self.dict_mult(norm_data, fit_data)
|
|
125
|
+
else:
|
|
126
|
+
summed_prod = self.dict_plus(
|
|
127
|
+
summed_prod, self.dict_mult(norm_data, fit_data)
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
weighted = self._dict_op(lambda a, b: a / b, summed_prod, summed_fit)
|
|
131
|
+
|
|
132
|
+
xrf_results.save_xrf_results(
|
|
133
|
+
output_root_uri,
|
|
134
|
+
"weighted_ngmm2",
|
|
135
|
+
config,
|
|
136
|
+
None,
|
|
137
|
+
None,
|
|
138
|
+
weighted,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
self.outputs.bliss_scan_uri = bliss_scan_uri
|
|
142
|
+
self.outputs.output_root_uri = output_root_uri
|
|
143
|
+
self.outputs.xrf_results_uri = output_root_uri + "/results"
|
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ewoksid16a
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Data processing workflows for ID16A
|
|
5
|
+
Author-email: ESRF <dau-pydev@esrf.fr>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://gitlab.esrf.fr/workflow/ewoksapps/ewoksid16a/
|
|
8
|
+
Project-URL: Documentation, https://ewoksid16a.readthedocs.io/
|
|
9
|
+
Project-URL: Repository, https://gitlab.esrf.fr/workflow/ewoksapps/ewoksid16a/
|
|
10
|
+
Project-URL: Issues, https://gitlab.esrf.fr/workflow/ewoksapps/ewoksid16a/issues
|
|
11
|
+
Project-URL: Changelog, https://gitlab.esrf.fr/workflow/ewoksapps/ewoksid16a/-/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: orange3 add-on,ewoks
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: ewoksjob
|
|
19
|
+
Requires-Dist: ewoksfluo
|
|
20
|
+
Requires-Dist: blissdata
|
|
21
|
+
Requires-Dist: ewoksorange
|
|
22
|
+
Provides-Extra: test
|
|
23
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
24
|
+
Requires-Dist: pyqt6; extra == "test"
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: ewoksid16a[test]; extra == "dev"
|
|
27
|
+
Requires-Dist: black>=25; extra == "dev"
|
|
28
|
+
Requires-Dist: flake8>=4; extra == "dev"
|
|
29
|
+
Requires-Dist: ruff; extra == "dev"
|
|
30
|
+
Requires-Dist: bandit; extra == "dev"
|
|
31
|
+
Provides-Extra: doc
|
|
32
|
+
Requires-Dist: ewoksid16a[test]; extra == "doc"
|
|
33
|
+
Requires-Dist: sphinx>=4.5; extra == "doc"
|
|
34
|
+
Requires-Dist: sphinx-autodoc-typehints>=1.16; extra == "doc"
|
|
35
|
+
Requires-Dist: pydata-sphinx-theme; extra == "doc"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# ewoksid16a
|
|
39
|
+
|
|
40
|
+
Data processing workflows for ID16A
|
|
41
|
+
|
|
42
|
+
## Documentation
|
|
43
|
+
|
|
44
|
+
https://ewoksid16a.readthedocs.io/
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/ewoksid16a/__init__.py
|
|
5
|
+
src/ewoksid16a.egg-info/PKG-INFO
|
|
6
|
+
src/ewoksid16a.egg-info/SOURCES.txt
|
|
7
|
+
src/ewoksid16a.egg-info/dependency_links.txt
|
|
8
|
+
src/ewoksid16a.egg-info/entry_points.txt
|
|
9
|
+
src/ewoksid16a.egg-info/requires.txt
|
|
10
|
+
src/ewoksid16a.egg-info/top_level.txt
|
|
11
|
+
src/ewoksid16a/tasks/__init__.py
|
|
12
|
+
src/ewoksid16a/tasks/fluo/norm_it.py
|
|
13
|
+
src/ewoksid16a/tasks/fluo/spectral_regrid.py
|
|
14
|
+
src/ewoksid16a/tasks/fluo/sumspectrumfit.py
|
|
15
|
+
src/ewoksid16a/tasks/fluo/tiffexporter.py
|
|
16
|
+
src/ewoksid16a/tasks/fluo/weight.py
|
|
17
|
+
src/ewoksid16a/tests/__init__.py
|
|
18
|
+
src/ewoksid16a/tests/test_dummy.py
|
|
19
|
+
src/orangecontrib/ewoksid16a/__init__.py
|
|
20
|
+
src/orangecontrib/ewoksid16a/categories/__init__.py
|
|
21
|
+
src/orangecontrib/ewoksid16a/icons/__init__.py
|
|
22
|
+
src/orangecontrib/ewoksid16a/tutorials/__init__.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[ewoks.tasks.class]
|
|
2
|
+
ewoksid16a.tasks.* = ewoksid16a
|
|
3
|
+
|
|
4
|
+
[orange.canvas.help]
|
|
5
|
+
html-index = orangecontrib.ewoksid16a:WIDGET_HELP_PATH
|
|
6
|
+
|
|
7
|
+
[orange.widgets]
|
|
8
|
+
Examples = orangecontrib.ewoksid16a
|
|
9
|
+
ExamplesCategories = orangecontrib.ewoksid16a.categories
|
|
10
|
+
|
|
11
|
+
[orange.widgets.tutorials]
|
|
12
|
+
Examples = orangecontrib.ewoksid16a.tutorials
|
|
13
|
+
Examples1 = orangecontrib.ewoksid16a.categories.examples1.tutorials
|
|
14
|
+
Examples2 = orangecontrib.ewoksid16a.categories.examples2.tutorials
|
|
15
|
+
|
|
16
|
+
[orange3.addon]
|
|
17
|
+
ewoksid16a = orangecontrib.ewoksid16a
|
|
18
|
+
|
|
19
|
+
[orangecanvas.examples]
|
|
20
|
+
Examples = orangecontrib.ewoksid16a.tutorials
|
|
21
|
+
Examples1 = orangecontrib.ewoksid16a.categories.examples1.tutorials
|
|
22
|
+
Examples2 = orangecontrib.ewoksid16a.categories.examples2.tutorials
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
ewoksjob
|
|
2
|
+
ewoksfluo
|
|
3
|
+
blissdata
|
|
4
|
+
ewoksorange
|
|
5
|
+
|
|
6
|
+
[dev]
|
|
7
|
+
ewoksid16a[test]
|
|
8
|
+
black>=25
|
|
9
|
+
flake8>=4
|
|
10
|
+
ruff
|
|
11
|
+
bandit
|
|
12
|
+
|
|
13
|
+
[doc]
|
|
14
|
+
ewoksid16a[test]
|
|
15
|
+
sphinx>=4.5
|
|
16
|
+
sphinx-autodoc-typehints>=1.16
|
|
17
|
+
pydata-sphinx-theme
|
|
18
|
+
|
|
19
|
+
[test]
|
|
20
|
+
pytest>=7
|
|
21
|
+
pyqt6
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import sysconfig
|
|
2
|
+
|
|
3
|
+
NAME = "ewoksid16a"
|
|
4
|
+
|
|
5
|
+
DESCRIPTION = "Data processing workflows for ID16A"
|
|
6
|
+
|
|
7
|
+
LONG_DESCRIPTION = "Data processing workflows for ID16A"
|
|
8
|
+
|
|
9
|
+
ICON = "icons/category.svg"
|
|
10
|
+
|
|
11
|
+
BACKGROUND = "light-blue"
|
|
12
|
+
|
|
13
|
+
WIDGET_HELP_PATH = (
|
|
14
|
+
# Development documentation (make htmlhelp in ./doc)
|
|
15
|
+
("{DEVELOP_ROOT}/doc/_build/htmlhelp/index.html", None),
|
|
16
|
+
# Documentation included in wheel
|
|
17
|
+
(
|
|
18
|
+
"{}/help/ewoksid16a/index.html".format(sysconfig.get_path("data")),
|
|
19
|
+
None,
|
|
20
|
+
),
|
|
21
|
+
# Online documentation url
|
|
22
|
+
("https://ewoksid16a.readthedocs.io", ""),
|
|
23
|
+
)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import sysconfig
|
|
2
|
+
|
|
3
|
+
WIDGET_HELP_PATH = (
|
|
4
|
+
# Development documentation (make htmlhelp in ./doc)
|
|
5
|
+
("{DEVELOP_ROOT}/doc/_build/htmlhelp/index.html", None),
|
|
6
|
+
# Documentation included in wheel
|
|
7
|
+
(
|
|
8
|
+
"{}/help/ewoksid16a/index.html".format(sysconfig.get_path("data")),
|
|
9
|
+
None,
|
|
10
|
+
),
|
|
11
|
+
# Online documentation url
|
|
12
|
+
("https://ewoksid16a.readthedocs.io", ""),
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Entry point for main Orange categories/widgets discovery
|
|
17
|
+
def widget_discovery(discovery):
|
|
18
|
+
from ewoksorange.pkg_meta import get_distribution
|
|
19
|
+
|
|
20
|
+
dist = get_distribution("ewoksid16a")
|
|
21
|
+
pkgs = [
|
|
22
|
+
"orangecontrib.ewoksid16a.categories.examples1",
|
|
23
|
+
"orangecontrib.ewoksid16a.categories.examples2",
|
|
24
|
+
]
|
|
25
|
+
for pkg in pkgs:
|
|
26
|
+
discovery.process_category_package(pkg, distribution=dist)
|
|
File without changes
|
|
File without changes
|