mlgidbase 0.0.1__py3-none-any.whl
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.
- docs/conf.py +30 -0
- mlgidbase/__init__.py +7 -0
- mlgidbase/main.py +491 -0
- mlgidbase/mlgiddetect_functions.py +379 -0
- mlgidbase/mlgidmatch_functions.py +551 -0
- mlgidbase/nexus_operations.py +65 -0
- mlgidbase/peak_operations.py +244 -0
- mlgidbase/pygid_functions.py +356 -0
- mlgidbase/pygidfit_functions.py +241 -0
- mlgidbase/visualization.py +863 -0
- mlgidbase/widgets.py +43 -0
- mlgidbase-0.0.1.dist-info/METADATA +106 -0
- mlgidbase-0.0.1.dist-info/RECORD +18 -0
- mlgidbase-0.0.1.dist-info/WHEEL +5 -0
- mlgidbase-0.0.1.dist-info/licenses/LICENSE +21 -0
- mlgidbase-0.0.1.dist-info/top_level.txt +3 -0
- tests/__init__.py +0 -0
- tests/test_mlgidbase.py +185 -0
docs/conf.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
sys.path.insert(0, os.path.abspath('..'))
|
|
4
|
+
|
|
5
|
+
project = 'mlgidBASE'
|
|
6
|
+
author = 'Ainur Abukaev'
|
|
7
|
+
release = '0.1.0'
|
|
8
|
+
|
|
9
|
+
extensions = [
|
|
10
|
+
'sphinx.ext.autodoc',
|
|
11
|
+
'sphinx.ext.napoleon',
|
|
12
|
+
'nbsphinx',
|
|
13
|
+
'myst_nb',
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
templates_path = ['_templates']
|
|
17
|
+
exclude_patterns = ['_build', '**.ipynb_checkpoints']
|
|
18
|
+
|
|
19
|
+
html_theme = 'sphinx_rtd_theme'
|
|
20
|
+
html_static_path = ['_static']
|
|
21
|
+
|
|
22
|
+
tutorial_dir = os.path.join(os.path.dirname(__file__), 'tutorials')
|
|
23
|
+
tutorials = sorted(f for f in os.listdir(tutorial_dir) if f.endswith('.ipynb'))
|
|
24
|
+
tutorial_names = [os.path.splitext(f)[0] for f in tutorials]
|
|
25
|
+
|
|
26
|
+
toctree_path = os.path.join(os.path.dirname(__file__), 'tutorials_toctree.rst')
|
|
27
|
+
with open(toctree_path, 'w', encoding='utf-8') as f:
|
|
28
|
+
f.write("Tutorials\n=========\n\n.. toctree::\n :maxdepth: 2\n\n")
|
|
29
|
+
for name in tutorial_names:
|
|
30
|
+
f.write(f" tutorials/{name}\n")
|
mlgidbase/__init__.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# from .expparams import ExpParams
|
|
2
|
+
# from .dataloader import DataLoader
|
|
3
|
+
# from .datasaver import DataSaver, ExpMetadata, SampleMetadata
|
|
4
|
+
# from .coordmaps import CoordMaps
|
|
5
|
+
# from .conversion import Conversion
|
|
6
|
+
from .main import mlgidBASE
|
|
7
|
+
__version__ = "0.0.1"
|
mlgidbase/main.py
ADDED
|
@@ -0,0 +1,491 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Any, Optional
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from .pygid_functions import (get_nexus, save_pipeline, det2pol_gid_pygid, det2q_gid_pygid)
|
|
6
|
+
from .mlgiddetect_functions import _run_detection
|
|
7
|
+
from .pygidfit_functions import _run_fitting
|
|
8
|
+
from .mlgidmatch_functions import _run_matching
|
|
9
|
+
from .visualization import get_plot_params, _plot_analysis_results
|
|
10
|
+
from .peak_operations import _delete_peak, _add_peak, _draw_box
|
|
11
|
+
from .nexus_operations import _get_detected_peaks, _get_fitted_peaks, _get_matched_peaks
|
|
12
|
+
from mlgidmatch.preprocess.cif_preprocess import CifPattern
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class mlgidBASE:
|
|
16
|
+
"""
|
|
17
|
+
High-level pipeline for GID data analysis including detection, fitting, and matching.
|
|
18
|
+
|
|
19
|
+
This class provides a unified interface to process grazing-incidence diffraction (GID)
|
|
20
|
+
data either from a NeXus file or directly from a `pygid.Conversion` object. It integrates
|
|
21
|
+
three main stages:
|
|
22
|
+
|
|
23
|
+
1. Peak detection (mlgiddetect)
|
|
24
|
+
2. Peak fitting (pygidfit)
|
|
25
|
+
3. Structure matching (mlgidmatch)
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
filename : str, optional
|
|
30
|
+
Path to a NeXus file containing GID data. Mutually exclusive with `pygid_conversion`.
|
|
31
|
+
pygid_conversion : object, optional
|
|
32
|
+
Precomputed `pygid.Conversion` instance. Mutually exclusive with `filename`.
|
|
33
|
+
imp_detect : object, optional
|
|
34
|
+
Preloaded inference model for peak detection.
|
|
35
|
+
config_detect : object or str, optional
|
|
36
|
+
Detection configuration or path to configuration file.
|
|
37
|
+
cif_prepr : CifPattern, optional
|
|
38
|
+
Preprocessed CIF patterns used for matching.
|
|
39
|
+
path_to_save : str, default "result.h5"
|
|
40
|
+
Output file path for saving results.
|
|
41
|
+
overwrite_file : bool, default True
|
|
42
|
+
Whether to overwrite the output file if it exists.
|
|
43
|
+
h5_group : str, default "entry_0000"
|
|
44
|
+
Target HDF5 group for saving results.
|
|
45
|
+
overwrite_group : bool, default False
|
|
46
|
+
Whether to overwrite an existing group in the HDF5 file.
|
|
47
|
+
smpl_metadata : Any, optional
|
|
48
|
+
Sample metadata to store in output.
|
|
49
|
+
exp_metadata : Any, optional
|
|
50
|
+
Experimental metadata to store in output.
|
|
51
|
+
plot_params : dict, optional
|
|
52
|
+
Matplotlib configuration parameters for plotting.
|
|
53
|
+
|
|
54
|
+
Attributes
|
|
55
|
+
----------
|
|
56
|
+
from_nexus : bool
|
|
57
|
+
Indicates whether data source is a NeXus file.
|
|
58
|
+
nexus : object
|
|
59
|
+
Loaded NeXus file handler.
|
|
60
|
+
entry_dict : dict
|
|
61
|
+
Structure of entries in the NeXus file.
|
|
62
|
+
img_container_detect_list : list
|
|
63
|
+
Results of detection stage.
|
|
64
|
+
img_container_fit_list : list
|
|
65
|
+
Results of fitting stage.
|
|
66
|
+
container_match_list : list
|
|
67
|
+
Results of matching stage.
|
|
68
|
+
logger : logging.Logger
|
|
69
|
+
Logger instance for pipeline messages.
|
|
70
|
+
|
|
71
|
+
Notes
|
|
72
|
+
-----
|
|
73
|
+
Exactly one of `filename` or `pygid_conversion` must be provided.
|
|
74
|
+
|
|
75
|
+
Workflow
|
|
76
|
+
--------
|
|
77
|
+
Typical usage:
|
|
78
|
+
|
|
79
|
+
>>> analysis = mlgidBASE(filename="data.h5")
|
|
80
|
+
>>> analysis.run_detection()
|
|
81
|
+
>>> analysis.run_fitting()
|
|
82
|
+
>>> analysis.run_matching()
|
|
83
|
+
>>> analysis.save_result()
|
|
84
|
+
|
|
85
|
+
The pipeline can also operate fully in-memory using a `pygid.Conversion` object.
|
|
86
|
+
|
|
87
|
+
"""
|
|
88
|
+
def __init__(
|
|
89
|
+
self,
|
|
90
|
+
*,
|
|
91
|
+
filename: Optional[str] = None,
|
|
92
|
+
pygid_conversion: Optional[Any] = None,
|
|
93
|
+
imp_detect: Optional[Any] = None,
|
|
94
|
+
config_detect: Optional[Any] = None,
|
|
95
|
+
cif_prepr: Optional[CifPattern] = None,
|
|
96
|
+
path_to_save: str = "result.h5",
|
|
97
|
+
overwrite_file: bool = True,
|
|
98
|
+
h5_group: str = "entry_0000",
|
|
99
|
+
overwrite_group: bool = False,
|
|
100
|
+
smpl_metadata: Any = None,
|
|
101
|
+
exp_metadata: Any = None,
|
|
102
|
+
plot_params: Any = None
|
|
103
|
+
):
|
|
104
|
+
self.filename = filename
|
|
105
|
+
self.pygid_conversion = pygid_conversion
|
|
106
|
+
|
|
107
|
+
self.imp_detect = imp_detect
|
|
108
|
+
self.config_detect = config_detect
|
|
109
|
+
|
|
110
|
+
self.cif_prepr = cif_prepr
|
|
111
|
+
|
|
112
|
+
self.path_to_save = path_to_save
|
|
113
|
+
self.overwrite_file = overwrite_file
|
|
114
|
+
self.h5_group = h5_group
|
|
115
|
+
self.overwrite_group = overwrite_group
|
|
116
|
+
self.smpl_metadata = smpl_metadata
|
|
117
|
+
self.exp_metadata = exp_metadata
|
|
118
|
+
|
|
119
|
+
self.from_nexus: Optional[bool] = None
|
|
120
|
+
self.nexus: Any = None
|
|
121
|
+
self.entry_dict: Any = None
|
|
122
|
+
|
|
123
|
+
self.img_container_detect_list = None
|
|
124
|
+
self.img_container_fit_list = None
|
|
125
|
+
self.container_match_list = None
|
|
126
|
+
|
|
127
|
+
self.logger = logging.getLogger(self.__class__.__name__)
|
|
128
|
+
self.logger.setLevel(logging.INFO)
|
|
129
|
+
|
|
130
|
+
self._initialize_source()
|
|
131
|
+
self.plot_params = get_plot_params()
|
|
132
|
+
|
|
133
|
+
def _validate_input(self) -> None:
|
|
134
|
+
"""
|
|
135
|
+
Validate that the source data is correctly specified.
|
|
136
|
+
|
|
137
|
+
Raises
|
|
138
|
+
------
|
|
139
|
+
AttributeError
|
|
140
|
+
If neither `pygid_conversion` nor `filename` is provided, or if both are provided.
|
|
141
|
+
"""
|
|
142
|
+
if self.pygid_conversion is None and self.filename is None:
|
|
143
|
+
raise AttributeError(
|
|
144
|
+
"Need to specify either pygid.Conversion instance or Nexus filename"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
if self.pygid_conversion is not None and self.filename is not None:
|
|
148
|
+
raise AttributeError(
|
|
149
|
+
"Need to specify either pygid.Conversion instance or Nexus filename"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
def _initialize_source(self) -> None:
|
|
153
|
+
"""
|
|
154
|
+
Initialize the data source and precompute key arrays.
|
|
155
|
+
|
|
156
|
+
Sets attributes for:
|
|
157
|
+
- GID reciprocal space arrays (`q_abs`, `chi`, `q_xy`, `q_z`)
|
|
158
|
+
- Polar images (`img_pol`)
|
|
159
|
+
- NeXus file handler and entry dictionary if reading from file.
|
|
160
|
+
|
|
161
|
+
Notes
|
|
162
|
+
-----
|
|
163
|
+
Only one source should be provided: `pygid_conversion` or `filename`.
|
|
164
|
+
"""
|
|
165
|
+
self._validate_input()
|
|
166
|
+
if self.pygid_conversion is not None:
|
|
167
|
+
# check_valid_conversion(self.pygid_conversion)
|
|
168
|
+
self.from_nexus = False
|
|
169
|
+
dq_init = float(self.pygid_conversion.matrix[0].dq)
|
|
170
|
+
self.q_abs, self.chi, self.img_pol = det2pol_gid_pygid(self.pygid_conversion)
|
|
171
|
+
det2q_gid_pygid(self.pygid_conversion, dq_init)
|
|
172
|
+
self.q_xy = self.pygid_conversion.matrix[0].q_xy
|
|
173
|
+
self.q_z = self.pygid_conversion.matrix[0].q_z
|
|
174
|
+
if self.filename is not None:
|
|
175
|
+
self.nexus = get_nexus(self.filename)
|
|
176
|
+
self.entry_dict = self.nexus.entry_dict
|
|
177
|
+
self.from_nexus = True
|
|
178
|
+
|
|
179
|
+
def run_detection(self, entry=None, frame_num=None, config_detect=None, model_type=None):
|
|
180
|
+
"""
|
|
181
|
+
Run peak detection on the dataset.
|
|
182
|
+
|
|
183
|
+
Parameters
|
|
184
|
+
----------
|
|
185
|
+
entry : str, optional
|
|
186
|
+
Entry name in the NeXus file. Defaults to all entries.
|
|
187
|
+
frame_num : int, optional
|
|
188
|
+
Frame index to process. Defaults to all frames.
|
|
189
|
+
config_detect : Config or str, optional
|
|
190
|
+
Detection configuration object or path to configuration file.
|
|
191
|
+
model_type : str, optional
|
|
192
|
+
Type of detection model to use (e.g., 'faster_rcnn', 'dino').
|
|
193
|
+
"""
|
|
194
|
+
_run_detection(self, entry, frame_num, config_detect, model_type)
|
|
195
|
+
|
|
196
|
+
def run_fitting(self, entry=None, frame_num=None, crit_angle=0,
|
|
197
|
+
clustering_distance_peaks=10, clustering_distance_rings=10,
|
|
198
|
+
clustering_extend=2, theta_fixed = True, use_pool=False, debug=False):
|
|
199
|
+
"""
|
|
200
|
+
Fit detected peaks to clusters for structural analysis.
|
|
201
|
+
|
|
202
|
+
Parameters
|
|
203
|
+
----------
|
|
204
|
+
entry : str, optional
|
|
205
|
+
Entry name in the NeXus file. Defaults to all entries.
|
|
206
|
+
frame_num : int, optional
|
|
207
|
+
Frame index to process. Defaults to all frames.
|
|
208
|
+
crit_angle : float, default 0
|
|
209
|
+
Maximum allowed misorientation angle between peaks.
|
|
210
|
+
clustering_distance_peaks : float, default 10
|
|
211
|
+
Distance threshold for peak clustering.
|
|
212
|
+
clustering_distance_rings : float, default 10
|
|
213
|
+
Distance threshold for ring clustering.
|
|
214
|
+
clustering_extend : int, default 2
|
|
215
|
+
Number of neighboring peaks to include in cluster expansion.
|
|
216
|
+
theta_fixed : bool, default True
|
|
217
|
+
Whether the polar angle theta is fixed during clustering.
|
|
218
|
+
use_pool : bool, default False
|
|
219
|
+
Whether to use multiprocessing for fitting.
|
|
220
|
+
debug : bool, default False
|
|
221
|
+
Whether to print debugging information.
|
|
222
|
+
"""
|
|
223
|
+
_run_fitting(self, entry=entry, frame_num=frame_num, crit_angle=crit_angle,
|
|
224
|
+
clustering_distance_peaks=clustering_distance_peaks,
|
|
225
|
+
clustering_distance_rings=clustering_distance_rings,
|
|
226
|
+
clustering_extend=clustering_extend,
|
|
227
|
+
theta_fixed = theta_fixed, use_pool=use_pool,
|
|
228
|
+
debug=debug)
|
|
229
|
+
|
|
230
|
+
def run_matching(self, entry=None, frame_num=None, cif_prepr=None,
|
|
231
|
+
probability_threshold=0.5, peaks_type='segments', device=None, intensity_threshold=0,
|
|
232
|
+
threshold=None):
|
|
233
|
+
"""
|
|
234
|
+
Match fitted peaks to preprocessed CIF patterns.
|
|
235
|
+
|
|
236
|
+
Parameters
|
|
237
|
+
----------
|
|
238
|
+
entry : str, optional
|
|
239
|
+
Entry name in the NeXus file. Defaults to all entries.
|
|
240
|
+
frame_num : int, optional
|
|
241
|
+
Frame index to process. Defaults to all frames.
|
|
242
|
+
cif_prepr : CifPattern, optional
|
|
243
|
+
Preprocessed CIF patterns for matching.
|
|
244
|
+
probability_threshold : float, default 0.5
|
|
245
|
+
Minimum probability threshold for a match.
|
|
246
|
+
peaks_type : {'segments', 'rings'}, default 'segments'
|
|
247
|
+
Type of peaks to match.
|
|
248
|
+
device : str, optional
|
|
249
|
+
Device to use for matching ('cpu' or 'cuda').
|
|
250
|
+
intensity_threshold : float, default 0
|
|
251
|
+
Minimum peak intensity to consider.
|
|
252
|
+
threshold : float, optional
|
|
253
|
+
Alternative threshold value for matching probability.
|
|
254
|
+
"""
|
|
255
|
+
_run_matching(self, entry=entry, frame_num=frame_num, cif_prepr=cif_prepr,
|
|
256
|
+
probability_threshold=probability_threshold, peaks_type=peaks_type,
|
|
257
|
+
device=device, intensity_threshold=intensity_threshold,
|
|
258
|
+
threshold=threshold)
|
|
259
|
+
|
|
260
|
+
def save_result(self, path_to_save = 'result.h5', overwrite_file = True, h5_group = 'entry_0000',
|
|
261
|
+
overwrite_group = False, smpl_metadata = None, exp_metadata = None,
|
|
262
|
+
save_polar = False, h5_group_polar = 'entry_polar_0000'):
|
|
263
|
+
"""
|
|
264
|
+
Save the full analysis pipeline results to an HDF5 file.
|
|
265
|
+
|
|
266
|
+
Parameters
|
|
267
|
+
----------
|
|
268
|
+
path_to_save : str, default 'result.h5'
|
|
269
|
+
Path of the output file.
|
|
270
|
+
overwrite_file : bool, default True
|
|
271
|
+
Whether to overwrite an existing file.
|
|
272
|
+
h5_group : str, default 'entry_0000'
|
|
273
|
+
HDF5 group for the main results.
|
|
274
|
+
overwrite_group : bool, default False
|
|
275
|
+
Whether to overwrite an existing HDF5 group.
|
|
276
|
+
smpl_metadata : dict or object, optional
|
|
277
|
+
Sample metadata to include in the saved file.
|
|
278
|
+
exp_metadata : dict or object, optional
|
|
279
|
+
Experimental metadata to include in the saved file.
|
|
280
|
+
save_polar : bool, default False
|
|
281
|
+
Whether to save polar images in a separate HDF5 group.
|
|
282
|
+
h5_group_polar : str, default 'entry_polar_0000'
|
|
283
|
+
HDF5 group name for polar images if `save_polar=True`.
|
|
284
|
+
"""
|
|
285
|
+
save_pipeline(self.pygid_conversion, self.img_container_detect_list,
|
|
286
|
+
self.img_container_fit_list, self.container_match_list,
|
|
287
|
+
path_to_save, overwrite_file, h5_group, overwrite_group,
|
|
288
|
+
smpl_metadata, exp_metadata)
|
|
289
|
+
if save_polar:
|
|
290
|
+
self.pygid_conversion.img_gid_pol = self.img_pol
|
|
291
|
+
self.pygid_conversion.matrix[0].ang_gid_pol = self.chi
|
|
292
|
+
self.pygid_conversion.matrix[0].q_gid_pol = self.q_abs
|
|
293
|
+
save_pipeline(self.pygid_conversion, None,
|
|
294
|
+
None, None,
|
|
295
|
+
path_to_save, False, h5_group_polar, overwrite_group,
|
|
296
|
+
smpl_metadata, exp_metadata)
|
|
297
|
+
|
|
298
|
+
def set_plot_defaults(self, font_size=14, axes_titlesize=14, axes_labelsize=18, grid=False, grid_color='gray',
|
|
299
|
+
grid_linestyle='--', grid_linewidth=0.5, xtick_labelsize=14, ytick_labelsize=14,
|
|
300
|
+
legend_fontsize=12, legend_loc='best', legend_frameon=True, legend_borderpad=1.0,
|
|
301
|
+
legend_borderaxespad=1.0, figure_titlesize=16, figsize=(6.4, 4.8), axes_linewidth=0.5,
|
|
302
|
+
savefig_dpi=600, savefig_transparent=False, savefig_bbox_inches=None,
|
|
303
|
+
savefig_pad_inches=0.1, line_linewidth=2, line_color='blue', line_linestyle='-',
|
|
304
|
+
line_marker=None, scatter_marker='o', scatter_edgecolors='black',
|
|
305
|
+
cmap='inferno'):
|
|
306
|
+
"""
|
|
307
|
+
Sets the default settings for various parts of a Matplotlib plot, including font sizes, gridlines,
|
|
308
|
+
legend, figure properties, and line styles. The function configures the default style for future
|
|
309
|
+
plots created with Matplotlib.
|
|
310
|
+
|
|
311
|
+
Parameters:
|
|
312
|
+
- font_size (int): Default font size for text elements (e.g., title, labels, ticks).
|
|
313
|
+
- axes_titlesize (int): Font size for axes titles.
|
|
314
|
+
- axes_labelsize (int): Font size for axes labels (x and y).
|
|
315
|
+
- grid (bool): Whether or not to display gridlines (True/False).
|
|
316
|
+
- grid_color (str): Color of the gridlines (e.g., 'gray', 'black').
|
|
317
|
+
- grid_linestyle (str): Line style of the gridlines (e.g., '--', '-', ':').
|
|
318
|
+
- grid_linewidth (float): Width of the gridlines.
|
|
319
|
+
- xtick_labelsize (int): Font size for x-axis tick labels.
|
|
320
|
+
- ytick_labelsize (int): Font size for y-axis tick labels.
|
|
321
|
+
- legend_fontsize (int): Font size for the legend text.
|
|
322
|
+
- legend_loc (str): Location of the legend (e.g., 'best', 'upper right', 'lower left').
|
|
323
|
+
- legend_frameon (bool): Whether to display a frame around the legend.
|
|
324
|
+
- legend_borderpad (float): Padding between the legend's content and the legend's frame.
|
|
325
|
+
- legend_borderaxespad (float): Padding between the legend and axes.
|
|
326
|
+
- figure_titlesize (int): Font size for the figure title.
|
|
327
|
+
- figsize (tuple): Size of the figure in inches (e.g., (6, 6)).
|
|
328
|
+
- savefig_dpi (int): DPI for saving the figure (higher DPI means better quality).
|
|
329
|
+
- savefig_transparent (bool): Whether the saved figure should have a transparent background.
|
|
330
|
+
- savefig_bbox_inches (str): Defines what part of the plot to save (e.g., 'tight' to crop extra whitespace).
|
|
331
|
+
- savefig_pad_inches (float): Padding added around the figure when saving.
|
|
332
|
+
- line_linewidth (float): Line width for plot lines.
|
|
333
|
+
- line_color (str): Color of the plot lines (e.g., 'blue', 'red').
|
|
334
|
+
- line_linestyle (str): Line style (e.g., '-', '--', ':').
|
|
335
|
+
- line_marker (str): Marker style for plot lines (e.g., 'o', 'x').
|
|
336
|
+
- scatter_marker (str): Marker style for scatter plots (e.g., 'o', 'x').
|
|
337
|
+
- scatter_edgecolors (str): Color for the edges of scatter plot markers (e.g., 'black').
|
|
338
|
+
- cmap (str): Image colormap
|
|
339
|
+
"""
|
|
340
|
+
self.plot_params.update(get_plot_params(font_size, axes_titlesize, axes_labelsize, grid, grid_color,
|
|
341
|
+
grid_linestyle, grid_linewidth, xtick_labelsize,
|
|
342
|
+
ytick_labelsize,
|
|
343
|
+
legend_fontsize, legend_loc, legend_frameon, legend_borderpad,
|
|
344
|
+
legend_borderaxespad, figure_titlesize, figsize,
|
|
345
|
+
axes_linewidth,
|
|
346
|
+
savefig_dpi, savefig_transparent, savefig_bbox_inches,
|
|
347
|
+
savefig_pad_inches, line_linewidth, line_color, line_linestyle,
|
|
348
|
+
line_marker, scatter_marker, scatter_edgecolors,
|
|
349
|
+
cmap))
|
|
350
|
+
|
|
351
|
+
def plot_analysis_results(self,
|
|
352
|
+
detected_params={'line_width': 0.5,
|
|
353
|
+
'line_style': "--",
|
|
354
|
+
'line_color': "black",
|
|
355
|
+
'plot_id': True,
|
|
356
|
+
'text_color': 'white',
|
|
357
|
+
'text_size': 8,
|
|
358
|
+
'plot': False},
|
|
359
|
+
fitted_params={'plot_segments': True,
|
|
360
|
+
'marker': 'o',
|
|
361
|
+
'marker_size': 50,
|
|
362
|
+
'marker_facecolor': "none",
|
|
363
|
+
'marker_edgecolor': "bone",
|
|
364
|
+
'plot_rings': True,
|
|
365
|
+
'line_width': 1,
|
|
366
|
+
'line_style': "--",
|
|
367
|
+
'line_color': "bone",
|
|
368
|
+
'plot_id': False,
|
|
369
|
+
'text_color': 'white',
|
|
370
|
+
'text_size': 8,
|
|
371
|
+
'plot': False},
|
|
372
|
+
matched_params={
|
|
373
|
+
'solution': None,
|
|
374
|
+
'plot_segments': True,
|
|
375
|
+
'marker': ['o', 'o', 'o'],
|
|
376
|
+
'marker_size': [50, 50, 50],
|
|
377
|
+
'marker_facecolor': ["none", "none", "none"],
|
|
378
|
+
'marker_edgecolor': ["bone", 'blue', 'green'],
|
|
379
|
+
'plot_rings': True,
|
|
380
|
+
'line_width': [1, 1, 1],
|
|
381
|
+
'line_style': ["--", "--", "--"],
|
|
382
|
+
'line_color': ["bone", 'blue', 'green'],
|
|
383
|
+
'plot_id': False,
|
|
384
|
+
'text_color': 'white',
|
|
385
|
+
'text_size': 8,
|
|
386
|
+
'legend': True,
|
|
387
|
+
'plot': False,},
|
|
388
|
+
frame_num=None, entry=None,
|
|
389
|
+
return_result=False, plot_result=True,
|
|
390
|
+
clims=None, xlim=(None, None), ylim=(None, None),
|
|
391
|
+
save_fig=False, path_to_save_fig="img.png"):
|
|
392
|
+
"""
|
|
393
|
+
Visualize the results of detection, fitting, and matching stages.
|
|
394
|
+
|
|
395
|
+
Parameters
|
|
396
|
+
----------
|
|
397
|
+
detected_params : dict, optional
|
|
398
|
+
Plotting options for detected peaks.
|
|
399
|
+
fitted_params : dict, optional
|
|
400
|
+
Plotting options for fitted peaks and clusters.
|
|
401
|
+
matched_params : dict, optional
|
|
402
|
+
Plotting options for matched peaks to CIF patterns.
|
|
403
|
+
frame_num : int, optional
|
|
404
|
+
Frame index to plot. Defaults to all frames.
|
|
405
|
+
entry : str, optional
|
|
406
|
+
Entry name in the NeXus file.
|
|
407
|
+
return_result : bool, default False
|
|
408
|
+
Whether to return the matplotlib figure object.
|
|
409
|
+
plot_result : bool, default True
|
|
410
|
+
Whether to display the plot interactively.
|
|
411
|
+
clims : tuple, optional
|
|
412
|
+
Color limits for the plot.
|
|
413
|
+
xlim : tuple, default (None, None)
|
|
414
|
+
X-axis limits.
|
|
415
|
+
ylim : tuple, default (None, None)
|
|
416
|
+
Y-axis limits.
|
|
417
|
+
save_fig : bool, default False
|
|
418
|
+
Whether to save the figure to a file.
|
|
419
|
+
path_to_save_fig : str, default 'img.png'
|
|
420
|
+
Path to save the figure if `save_fig=True`.
|
|
421
|
+
"""
|
|
422
|
+
_plot_analysis_results(self,
|
|
423
|
+
detected_params=detected_params,
|
|
424
|
+
fitted_params=fitted_params,
|
|
425
|
+
matched_params=matched_params,
|
|
426
|
+
frame_num=frame_num, entry=entry,
|
|
427
|
+
return_result=return_result, plot_result=plot_result,
|
|
428
|
+
clims=clims, xlim=xlim, ylim=ylim,
|
|
429
|
+
save_fig=save_fig, path_to_save_fig=path_to_save_fig)
|
|
430
|
+
|
|
431
|
+
def check_valid_data(self, detected_params, fitted_params, matched_params):
|
|
432
|
+
"""
|
|
433
|
+
Check that the pipeline has valid data for plotting.
|
|
434
|
+
|
|
435
|
+
This function disables plotting for stages that were not run
|
|
436
|
+
and provides informative logger messages.
|
|
437
|
+
|
|
438
|
+
Parameters
|
|
439
|
+
----------
|
|
440
|
+
detected_params : dict
|
|
441
|
+
Plotting configuration for detection stage.
|
|
442
|
+
fitted_params : dict
|
|
443
|
+
Plotting configuration for fitting stage.
|
|
444
|
+
matched_params : dict
|
|
445
|
+
Plotting configuration for matching stage.
|
|
446
|
+
|
|
447
|
+
Raises
|
|
448
|
+
------
|
|
449
|
+
ValueError
|
|
450
|
+
If required data for plotting (`img_gid_q`) is missing.
|
|
451
|
+
"""
|
|
452
|
+
if self.img_container_detect_list is None and detected_params.get('plot', True):
|
|
453
|
+
self.logger.info("No detected peaks. Use run_detection() first.")
|
|
454
|
+
detected_params['plot'] = False
|
|
455
|
+
fitted_params['plot'] = False
|
|
456
|
+
matched_params['plot'] = False
|
|
457
|
+
if self.img_container_fit_list is None and fitted_params.get('plot', True):
|
|
458
|
+
self.logger.info("No fitted peaks. Use run_fitting() first.")
|
|
459
|
+
fitted_params['plot'] = False
|
|
460
|
+
matched_params['plot'] = False
|
|
461
|
+
if self.container_match_list is None and matched_params.get('plot', True):
|
|
462
|
+
self.logger.info("No matched peaks. Use run_matching() first.")
|
|
463
|
+
matched_params['plot'] = False
|
|
464
|
+
if not hasattr(self.pygid_conversion, 'img_gid_q'):
|
|
465
|
+
raise ValueError("img_gid_q is not available in pygid.Conversion."
|
|
466
|
+
"Use plotting before saving.")
|
|
467
|
+
def delete_peak(self, entry=None, frame_num=None, peak_id = None):
|
|
468
|
+
_delete_peak(self, entry=entry, frame_num=frame_num, peak_id=peak_id)
|
|
469
|
+
|
|
470
|
+
def get_detected_peaks(self, entry=None, frame_num=None):
|
|
471
|
+
return _get_detected_peaks(self.nexus, entry=entry, frame_num=frame_num)
|
|
472
|
+
|
|
473
|
+
def get_fitted_peaks(self, entry=None, frame_num=None):
|
|
474
|
+
return _get_fitted_peaks(self.nexus, entry=entry, frame_num=frame_num)
|
|
475
|
+
|
|
476
|
+
def get_matched_peaks(self, entry=None, frame_num=None):
|
|
477
|
+
return _get_matched_peaks(self.nexus, entry=entry, frame_num=frame_num)
|
|
478
|
+
|
|
479
|
+
def add_peak(self, entry=None, frame_num=None,
|
|
480
|
+
angle=None, angle_width = None,
|
|
481
|
+
radius = None, radius_width = None,
|
|
482
|
+
q_xy = None, q_z = None,
|
|
483
|
+
dq_xy = None, dq_z = None,):
|
|
484
|
+
_add_peak(self, entry=entry, frame_num=frame_num,
|
|
485
|
+
angle=angle, angle_width=angle_width,
|
|
486
|
+
radius=radius, radius_width=radius_width,
|
|
487
|
+
q_xy=q_xy, q_z=q_z,
|
|
488
|
+
dq_xy=dq_xy, dq_z=dq_z,
|
|
489
|
+
)
|
|
490
|
+
def draw_box(self, entry=None, frame_num=None):
|
|
491
|
+
_draw_box(self, entry=entry, frame_num=frame_num)
|