artof 1.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.
artof-1.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Carl Magnus Meier
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, 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,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
artof-1.1.0/PKG-INFO ADDED
@@ -0,0 +1,92 @@
1
+ Metadata-Version: 2.4
2
+ Name: artof
3
+ Version: 1.1.0
4
+ Summary: The ARTOF is a tool to read, process and analyze data collected from angle resolved time of flight (ARToF) sensors of the PS-ISRR.
5
+ Home-page: https://codebase.helmholtz.cloud/carl.meier/artof
6
+ Author: Carl Magnus Meier
7
+ Author-email: magnus.meier@helmholtz-berlin.de
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: numpy
15
+ Requires-Dist: scipy
16
+ Requires-Dist: pandas
17
+ Requires-Dist: IPython
18
+ Requires-Dist: plotly
19
+ Requires-Dist: anywidget
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest; extra == "dev"
22
+ Requires-Dist: pytest-cov; extra == "dev"
23
+ Dynamic: license-file
24
+
25
+ # artof
26
+
27
+ The artof package is a jupyter notebook tool to read, process and analyze data collected from angle
28
+ resolved time of flight (ARTOF) sensors.
29
+
30
+ ## Getting started
31
+
32
+ To use this package python version >=3.10 is needed. The installation can be done using the command:
33
+
34
+ ```bash
35
+ pip install artof
36
+ ```
37
+
38
+ ## Documentation
39
+
40
+ The documentation can be found [here](https://artof-42d889.pages.hzdr.de/main/). It is automatically
41
+ generated from the docstrings in all python classes.
42
+
43
+ ## Workflow
44
+
45
+ The implementation of a new feature should be conducted as follows:
46
+
47
+ 1. Create a new branch with a sensible name as a fork from `dev`.
48
+ 2. Implement features including documentation.
49
+ 3. If required, make changes to the Sphinx documentation under `docs/source/`.
50
+ 4. Check if all existing tests are still working (cmd: `pytest`) and write new test functions.
51
+ 5. If there were changes to `dev` since the initial fork, merge it into your branch and resolve
52
+ conflicts. Check again if all tests are running.
53
+ 6. Make sure the pylint rating of each file is 8 or higher. To do so run
54
+
55
+ ```bash
56
+ pylint src/artof/{file}
57
+ ```
58
+
59
+ 7. Update documentation in the `./docs` folder using `.rst` and `sphinx`. For automatic doc
60
+ generation use `.. automodule:: artof.{module}` or `.. autoclass:: artof.{module}.{class}`. Do
61
+ not forget to add new `.rst`-files to index.
62
+ 8. Test the doc generation and ensure there are no warnings (else the pipeline will fail). To do
63
+ so run
64
+
65
+ ```bash
66
+ sphinx-build -M html docs/source docs/build
67
+ ```
68
+
69
+ 9. Increase version number in `setup.cfg` file.
70
+ 10. Push all changes to the remote repository and create a merge request to `dev`.
71
+ 11. Make sure all tests succeed in the pipeline and merge.
72
+ 12. When enough changes accumulate, create a merge request to `main` once enough features
73
+ accumulated
74
+ to roll out a new version. Make again sure all test pipelines succeed.
75
+ 13. After merging to `main` a new version of the package is released to PyPi upon a successful
76
+ pipeline run.
77
+
78
+ ## Issues and new features
79
+
80
+ Issues and new feature requests can be
81
+ added [here](https://codebase.helmholtz.cloud/carl.meier/artof/-/issues).
82
+
83
+ ## Development version
84
+
85
+ A version with features under development is available under the TestPyPi repository and can be
86
+ installed as followed:
87
+
88
+ ```bash
89
+ pip install --index-url https://test.pypi.org/simple/ artof
90
+ ```
91
+
92
+ The documentation can be found [here](https://artof-42d889.pages.hzdr.de/dev/).
artof-1.1.0/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # artof
2
+
3
+ The artof package is a jupyter notebook tool to read, process and analyze data collected from angle
4
+ resolved time of flight (ARTOF) sensors.
5
+
6
+ ## Getting started
7
+
8
+ To use this package python version >=3.10 is needed. The installation can be done using the command:
9
+
10
+ ```bash
11
+ pip install artof
12
+ ```
13
+
14
+ ## Documentation
15
+
16
+ The documentation can be found [here](https://artof-42d889.pages.hzdr.de/main/). It is automatically
17
+ generated from the docstrings in all python classes.
18
+
19
+ ## Workflow
20
+
21
+ The implementation of a new feature should be conducted as follows:
22
+
23
+ 1. Create a new branch with a sensible name as a fork from `dev`.
24
+ 2. Implement features including documentation.
25
+ 3. If required, make changes to the Sphinx documentation under `docs/source/`.
26
+ 4. Check if all existing tests are still working (cmd: `pytest`) and write new test functions.
27
+ 5. If there were changes to `dev` since the initial fork, merge it into your branch and resolve
28
+ conflicts. Check again if all tests are running.
29
+ 6. Make sure the pylint rating of each file is 8 or higher. To do so run
30
+
31
+ ```bash
32
+ pylint src/artof/{file}
33
+ ```
34
+
35
+ 7. Update documentation in the `./docs` folder using `.rst` and `sphinx`. For automatic doc
36
+ generation use `.. automodule:: artof.{module}` or `.. autoclass:: artof.{module}.{class}`. Do
37
+ not forget to add new `.rst`-files to index.
38
+ 8. Test the doc generation and ensure there are no warnings (else the pipeline will fail). To do
39
+ so run
40
+
41
+ ```bash
42
+ sphinx-build -M html docs/source docs/build
43
+ ```
44
+
45
+ 9. Increase version number in `setup.cfg` file.
46
+ 10. Push all changes to the remote repository and create a merge request to `dev`.
47
+ 11. Make sure all tests succeed in the pipeline and merge.
48
+ 12. When enough changes accumulate, create a merge request to `main` once enough features
49
+ accumulated
50
+ to roll out a new version. Make again sure all test pipelines succeed.
51
+ 13. After merging to `main` a new version of the package is released to PyPi upon a successful
52
+ pipeline run.
53
+
54
+ ## Issues and new features
55
+
56
+ Issues and new feature requests can be
57
+ added [here](https://codebase.helmholtz.cloud/carl.meier/artof/-/issues).
58
+
59
+ ## Development version
60
+
61
+ A version with features under development is available under the TestPyPi repository and can be
62
+ installed as followed:
63
+
64
+ ```bash
65
+ pip install --index-url https://test.pypi.org/simple/ artof
66
+ ```
67
+
68
+ The documentation can be found [here](https://artof-42d889.pages.hzdr.de/dev/).
@@ -0,0 +1,5 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel>=0.37.0"]
3
+ build-backend = "setuptools.build_meta"
4
+ [tool.black]
5
+ line-length = 100
artof-1.1.0/setup.cfg ADDED
@@ -0,0 +1,40 @@
1
+ [metadata]
2
+ name = artof
3
+ version = 1.1.0
4
+ author = Carl Magnus Meier
5
+ author_email = magnus.meier@helmholtz-berlin.de
6
+ description = The ARTOF is a tool to read, process and analyze data collected from angle resolved time of flight (ARToF) sensors of the PS-ISRR.
7
+ long_description = file: README.md
8
+ long_description_content_type = text/markdown
9
+ url = https://codebase.helmholtz.cloud/carl.meier/artof
10
+ classifiers =
11
+ Programming Language :: Python :: 3
12
+ License :: OSI Approved :: MIT License
13
+ Operating System :: OS Independent
14
+
15
+ [options]
16
+ package_dir =
17
+ = src
18
+ include_package_data = True
19
+ packages = find:
20
+ python_requires = >=3.10
21
+ install_requires =
22
+ numpy
23
+ scipy
24
+ pandas
25
+ IPython
26
+ plotly
27
+ anywidget
28
+
29
+ [options.packages.find]
30
+ where = src
31
+
32
+ [options.extras_require]
33
+ dev =
34
+ pytest
35
+ pytest-cov
36
+
37
+ [egg_info]
38
+ tag_build =
39
+ tag_date = 0
40
+
@@ -0,0 +1,6 @@
1
+ """
2
+ ARTOF: A Python package for loading and processing ARTOF data.
3
+ """
4
+
5
+ from .artof_loader import ARTOFLoader
6
+ from .live_loader import LiveLoader
@@ -0,0 +1,187 @@
1
+ """Module containing ARTOFLoader class for loading and processing artof data.
2
+
3
+ The ARTOFLoader class is used to load and process artof data from a specified directory.
4
+ """
5
+
6
+ import plotly.graph_objects as go
7
+ from IPython.display import display
8
+
9
+ from .base_loader import BaseLoader
10
+ from .data_process import get_axis_values, project_data
11
+ from .plotting import plot_1d, plot_2d, plot_counts
12
+
13
+
14
+ class ARTOFLoader(BaseLoader):
15
+ """
16
+ Class for loading and processing artof data.
17
+ """
18
+
19
+ def __init__(
20
+ self,
21
+ path: str,
22
+ transform_format: str,
23
+ x0: float = None,
24
+ y0: float = None,
25
+ t0: float = None,
26
+ sweep_type: str = "Sienta",
27
+ ):
28
+ """
29
+ Initialize ARTOFLoader class.
30
+
31
+ Args:
32
+ path: Path to run directory.
33
+ transform_format: Format to load data in ('raw', 'raw_SI', 'cylindrical', 'spherical').
34
+ x0: Offset for x ticks, optional (default extracted from acquisition.cfg).
35
+ y0: Offset for y ticks, optional (default extracted from acquisition.cfg).
36
+ t0: Offset for t ticks, optional (default extracted from acquisition.cfg).
37
+ sweep_type: Sweep type ('Sienta' or 'normal'), optional (default 'Sienta').
38
+ """
39
+ super().__init__(path, transform_format, x0, y0, t0, sweep_type)
40
+ self.fig = None
41
+
42
+ def transform_data(self, iter_interval: tuple = None, multithreading: bool = True):
43
+ """
44
+ Load artof data for run in directory and transform into desired format.
45
+
46
+ Args:
47
+ iter_interval: Tuple of start (including) and stop (excluding) lens iteration to load
48
+ (default None, load all).
49
+ multithreading: Use multithreading for data loading (default True).
50
+ """
51
+ if iter_interval:
52
+ self.set_iter_interval(iter_interval[0], iter_interval[1])
53
+ transformed_data = self.load_and_transform(multithreading)
54
+ self.add_transformed_data(transformed_data)
55
+
56
+ self.print_transform_stats()
57
+
58
+ def bin_data(
59
+ self, cust_bin_confs=None, norm_modes: list = None, win_config: tuple[int, int] = None
60
+ ):
61
+ """
62
+ Bin loaded data into 3D histogram.
63
+
64
+ Args:
65
+ cust_bin_confs: List of 3 custom binning configurations for the 3 parameters
66
+ [min, max, points]. F.e.: [[-1500, 1500, 101], [-1500, 1500, 101],
67
+ [12000, 18000, 201]]
68
+ norm_modes: Normalization mode for binned data ('iterations', 'dwell_time', 'sweep').
69
+ Default is None.
70
+ - `iterations`: Normalize data by number of iterations.
71
+ - `dwell_time`: Normalize data by dwell time.
72
+ - `sweep`: Normalize data by changing window size of sweep data.
73
+ win_config: Tuple of window size and step size for sweep data (default None, one window)
74
+ If the last window is smaller than the step size, it will be ignored.
75
+
76
+
77
+ Raises:
78
+ Exception: If data is not loaded before binning.
79
+ """
80
+ # reset binned data from previous binning
81
+ self.binned_data = {}
82
+
83
+ # set binning configurations
84
+ self.set_bin_configs(cust_bin_confs)
85
+
86
+ binned_data = self.bin(self.transformed_data, norm_modes, win_config=win_config)
87
+ self.add_binned_data(binned_data)
88
+
89
+ # print windows if win_config is given
90
+ if win_config is not None:
91
+ print(
92
+ f"The following {len(self.binned_data)} window(s) were"
93
+ f" created: {list(self.binned_data.keys())}"
94
+ )
95
+
96
+ def plot(
97
+ self,
98
+ proj_axes: list,
99
+ ranges=None,
100
+ norm_step_size: bool = False,
101
+ photon_energy: float = None,
102
+ width: int = 600,
103
+ height: int = 600,
104
+ ):
105
+ """
106
+ Plot loaded data as projection onto given axes. Projections are possible onto 1 or 2 axes.
107
+
108
+ Args:
109
+ proj_axes: List containing all axes onto which the projection is performed, e.g., [0,1].
110
+ ranges: List containing ranges for axes (e.g., [[50, 101], [0,50], None]), if None
111
+ entire range of axes is used (default entire range of each axis).
112
+ norm_step_size: Normalize data with step size before plotting (default False).
113
+ photon_energy: Photon energy to plot in binding energy, optional (default None).
114
+ width: Width of plot (default 600).
115
+ height: Height of plot (default 600).
116
+
117
+ Raises:
118
+ ValueError: An incorrect number of projection axes provided.
119
+ """
120
+
121
+ if self.bin_edges is None:
122
+ raise RuntimeError("Data not binned. Please bin data before plotting.")
123
+
124
+ if len(proj_axes) not in [1, 2]:
125
+ raise ValueError(f"A projection along {len(proj_axes)} axes is not possible.")
126
+
127
+ if ranges is None:
128
+ ranges = [None, None, None]
129
+
130
+ # concatenate all binned data into one array TODO show spectral evolution in plot
131
+ # data = np.sum(list(self.binned_data.values()), axis=0)
132
+
133
+ axes_values = get_axis_values(self.bin_edges, self.axes, proj_axes, photon_energy)
134
+ proj_data_wins = {}
135
+ for win_id, data in self.binned_data.items():
136
+ proj_data_wins[win_id] = project_data(
137
+ data, self.bin_edges, proj_axes, ranges, norm_step_size
138
+ )
139
+
140
+ self.fig = go.Figure(layout=go.Layout(width=width, height=height))
141
+
142
+ if len(proj_axes) == 2: # plot data in 2D as heatmap
143
+ plot_2d(
144
+ self.fig,
145
+ proj_data_wins,
146
+ self.bin_edges[proj_axes[0]],
147
+ self.bin_edges[proj_axes[1]],
148
+ self.axes,
149
+ proj_axes,
150
+ photon_energy,
151
+ height,
152
+ )
153
+ elif len(proj_axes) == 1: # plot data in 1D as line
154
+ plot_1d(
155
+ self.fig,
156
+ axes_values[0],
157
+ proj_data_wins,
158
+ self.axes,
159
+ proj_axes,
160
+ photon_energy,
161
+ height,
162
+ )
163
+
164
+ self.fig.show()
165
+
166
+ def load_counts(self):
167
+ """
168
+ Load counts of all measured events.
169
+ """
170
+ self.add_event_counts(self.count_events())
171
+
172
+ def plot_counts(self, iter_range: list = None, width: int = 600, height: int = 600):
173
+ """
174
+ Plot counts of all measured events over iterations in given range.
175
+
176
+ Args:
177
+ range: Range of iterations to plot (def+ault None, plot all).
178
+ width: Width of plot (default 600).
179
+ height: Height of plot (default 600).
180
+ """
181
+
182
+ iterations, counts = self.get_iter_counts(iter_range)
183
+
184
+ # create plot
185
+ self.fig = go.FigureWidget(layout=go.Layout(width=width, height=height))
186
+ display(self.fig)
187
+ plot_counts(self.fig, iterations, counts)
@@ -0,0 +1,58 @@
1
+ """
2
+ The artof_utils module provide static utility functions to be used in the artof package.
3
+ """
4
+
5
+ import os
6
+
7
+
8
+ def get_next_step(it: int, step: int, lens_steps: int):
9
+ """
10
+ Get the next step of a run
11
+
12
+ Args:
13
+ it: Current iteration.
14
+ step: Current step.
15
+ lens_steps: Total number of steps per iteration.
16
+
17
+ Returns:
18
+ Next iteration and step
19
+ """
20
+
21
+ if step == lens_steps - 1:
22
+ return it + 1, 0
23
+ return it, step + 1
24
+
25
+
26
+ def is_last_step(it: int, step: int, stop_iter: int, lens_steps: int):
27
+ """
28
+ Check if the current file is the last file of a run
29
+
30
+ Args:
31
+ it: Current iteration.
32
+ step: Current step in iteration.
33
+ lens_steps: Total number of steps.
34
+ stop_iter: Maximum number of iterations.
35
+
36
+ Returns:
37
+ Boolean value if the current file is the last file
38
+ """
39
+
40
+ return it == stop_iter - 1 and step == lens_steps - 1
41
+
42
+
43
+ def next_file_exists(path: str, it: int, step: int, lens_steps: int):
44
+ """
45
+ Check if the next file of a run exists
46
+
47
+ Args:
48
+ path: Path where data files are located.
49
+ it: Current iteration.
50
+ step: Current step.
51
+ lens_steps: Total number of steps.
52
+
53
+ Returns:
54
+ Boolean value if the next file exists
55
+ """
56
+
57
+ next_step = get_next_step(it, step, lens_steps)
58
+ return os.path.exists(f"{path}/{next_step[0]}_{next_step[1]}")