ChessAnalysisPipeline 0.0.17.dev3__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.
Files changed (70) hide show
  1. CHAP/TaskManager.py +216 -0
  2. CHAP/__init__.py +27 -0
  3. CHAP/common/__init__.py +57 -0
  4. CHAP/common/models/__init__.py +8 -0
  5. CHAP/common/models/common.py +124 -0
  6. CHAP/common/models/integration.py +659 -0
  7. CHAP/common/models/map.py +1291 -0
  8. CHAP/common/processor.py +2869 -0
  9. CHAP/common/reader.py +658 -0
  10. CHAP/common/utils.py +110 -0
  11. CHAP/common/writer.py +730 -0
  12. CHAP/edd/__init__.py +23 -0
  13. CHAP/edd/models.py +876 -0
  14. CHAP/edd/processor.py +3069 -0
  15. CHAP/edd/reader.py +1023 -0
  16. CHAP/edd/select_material_params_gui.py +348 -0
  17. CHAP/edd/utils.py +1572 -0
  18. CHAP/edd/writer.py +26 -0
  19. CHAP/foxden/__init__.py +19 -0
  20. CHAP/foxden/models.py +71 -0
  21. CHAP/foxden/processor.py +124 -0
  22. CHAP/foxden/reader.py +224 -0
  23. CHAP/foxden/utils.py +80 -0
  24. CHAP/foxden/writer.py +168 -0
  25. CHAP/giwaxs/__init__.py +11 -0
  26. CHAP/giwaxs/models.py +491 -0
  27. CHAP/giwaxs/processor.py +776 -0
  28. CHAP/giwaxs/reader.py +8 -0
  29. CHAP/giwaxs/writer.py +8 -0
  30. CHAP/inference/__init__.py +7 -0
  31. CHAP/inference/processor.py +69 -0
  32. CHAP/inference/reader.py +8 -0
  33. CHAP/inference/writer.py +8 -0
  34. CHAP/models.py +227 -0
  35. CHAP/pipeline.py +479 -0
  36. CHAP/processor.py +125 -0
  37. CHAP/reader.py +124 -0
  38. CHAP/runner.py +277 -0
  39. CHAP/saxswaxs/__init__.py +7 -0
  40. CHAP/saxswaxs/processor.py +8 -0
  41. CHAP/saxswaxs/reader.py +8 -0
  42. CHAP/saxswaxs/writer.py +8 -0
  43. CHAP/server.py +125 -0
  44. CHAP/sin2psi/__init__.py +7 -0
  45. CHAP/sin2psi/processor.py +8 -0
  46. CHAP/sin2psi/reader.py +8 -0
  47. CHAP/sin2psi/writer.py +8 -0
  48. CHAP/tomo/__init__.py +15 -0
  49. CHAP/tomo/models.py +210 -0
  50. CHAP/tomo/processor.py +3862 -0
  51. CHAP/tomo/reader.py +9 -0
  52. CHAP/tomo/writer.py +59 -0
  53. CHAP/utils/__init__.py +6 -0
  54. CHAP/utils/converters.py +188 -0
  55. CHAP/utils/fit.py +2947 -0
  56. CHAP/utils/general.py +2655 -0
  57. CHAP/utils/material.py +274 -0
  58. CHAP/utils/models.py +595 -0
  59. CHAP/utils/parfile.py +224 -0
  60. CHAP/writer.py +122 -0
  61. MLaaS/__init__.py +0 -0
  62. MLaaS/ktrain.py +205 -0
  63. MLaaS/mnist_img.py +83 -0
  64. MLaaS/tfaas_client.py +371 -0
  65. chessanalysispipeline-0.0.17.dev3.dist-info/LICENSE +60 -0
  66. chessanalysispipeline-0.0.17.dev3.dist-info/METADATA +29 -0
  67. chessanalysispipeline-0.0.17.dev3.dist-info/RECORD +70 -0
  68. chessanalysispipeline-0.0.17.dev3.dist-info/WHEEL +5 -0
  69. chessanalysispipeline-0.0.17.dev3.dist-info/entry_points.txt +2 -0
  70. chessanalysispipeline-0.0.17.dev3.dist-info/top_level.txt +2 -0
@@ -0,0 +1,348 @@
1
+ # Third party modules
2
+ from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
3
+ import matplotlib.pyplot as plt
4
+ import numpy as np
5
+ import tkinter as tk
6
+ from tkinter import messagebox
7
+
8
+ class MaterialParamSelector:
9
+ def __init__(
10
+ self, root, x, y, tth, preselected_materials, label, on_complete):
11
+
12
+ self.root = root
13
+ self.root.title('Material Parameter Selection')
14
+ self.on_complete = on_complete # Completion callback
15
+
16
+ # Reference data
17
+ self.ref_data_x = x
18
+ self.ref_data_y = y
19
+ self.ref_data_label = label
20
+ self.tth = tth
21
+
22
+ # Materials
23
+ self.materials = []
24
+ self.selected_material = None
25
+
26
+ # Create plot
27
+ self.figure, self.ax = plt.subplots()
28
+ self.legend_handles = []
29
+ self.canvas = FigureCanvasTkAgg(self.figure, self.root)
30
+ self.canvas.get_tk_widget().grid(row=0, column=0, rowspan=12)
31
+
32
+ # Widgets for material list and parameters
33
+ self.material_listbox = tk.Listbox(root, height=5)
34
+ self.material_listbox.grid(row=0, column=1, rowspan=2)
35
+ self.material_listbox.bind(
36
+ '<<ListboxSelect>>', self.on_material_select)
37
+
38
+ self.add_material_button = tk.Button(
39
+ root, text='Add Material', command=self.add_material)
40
+ self.add_material_button.grid(row=0, column=2)
41
+
42
+ self.remove_material_button = tk.Button(
43
+ root, text='Remove Material', command=self.remove_material)
44
+ self.remove_material_button.grid(row=1, column=2)
45
+
46
+ # Parameter fields
47
+ self.fields = {}
48
+ for i, field in enumerate(
49
+ ['Material Name', 'Space Group',
50
+ 'a', 'b', 'c', 'alpha', 'beta', 'gamma']):
51
+ if i > 1:
52
+ units = 'Angstroms' if i < 5 else 'degrees'
53
+ text = f'{field} ({units})'
54
+ else:
55
+ text = field
56
+ tk.Label(root, text=text).grid(row=i+2, column=1)
57
+ entry = tk.Entry(root)
58
+ entry.grid(row=i+2, column=2)
59
+ self.fields[field] = entry
60
+
61
+ self.update_button = tk.Button(
62
+ root, text='Update Material Properties',
63
+ command=self.update_material)
64
+ self.update_button.grid(row=11, column=1, columnspan=2)
65
+ self.update_button = tk.Button(
66
+ root, text='Update Material Properties',
67
+ command=self.update_material)
68
+ self.update_button.grid(row=11, column=1, columnspan=2)
69
+
70
+ self.confirm_button = tk.Button(
71
+ root, text='Confirm\nAll\nSelected\nMaterial\nProperties',
72
+ command=self.on_close)
73
+ self.confirm_button.grid(row=0, column=3, rowspan=12)
74
+
75
+ # Initial Material Data
76
+ if not preselected_materials:
77
+ self.materials = [None]
78
+ self.add_material(None)
79
+ else:
80
+ for material in preselected_materials:
81
+ self.add_material(material)
82
+ self.selected_material = 0
83
+
84
+ # Overwrite the root window's close action to call `self.on_close`
85
+ self.root.protocol('WM_DELETE_WINDOW', self.on_close)
86
+
87
+ def plot_reference_data(self):
88
+ # Plot reference data as a simple sine wave for illustration
89
+ handle = self.ax.plot(
90
+ self.ref_data_x, self.ref_data_y, label=self.ref_data_label)
91
+ self.legend_handles = handle
92
+ self.ax.legend(handles=self.legend_handles)
93
+ self.ax.set_xlabel('Energy (keV)')
94
+ self.ax.set_ylabel('Intensity (a.u)')
95
+ self.canvas.draw()
96
+
97
+ def add_material(self, new_material=None):
98
+ # Local modules
99
+ from CHAP.edd.models import MaterialConfig
100
+
101
+ if new_material is None:
102
+ new_material = MaterialConfig(
103
+ material_name='Ti64',
104
+ sgnum=194,
105
+ lattice_parameters=[2.9217, 4.66027]
106
+ )
107
+ self.materials.append(new_material)
108
+ self.material_listbox.insert(tk.END, new_material.material_name)
109
+ self.material_listbox.select_set(tk.END)
110
+ self.on_material_select(None)
111
+ self.update_plot()
112
+
113
+ def remove_material(self):
114
+ if self.selected_material is not None:
115
+ self.materials.pop(self.selected_material)
116
+ self.material_listbox.delete(self.selected_material)
117
+ self.selected_material = None
118
+ self.clear_fields()
119
+ self.update_plot()
120
+
121
+ def update_material(self):
122
+ # Local modules
123
+ from CHAP.edd.utils import make_material
124
+ # from CHAP.utils.material import Material
125
+
126
+ if self.selected_material is None:
127
+ return
128
+
129
+ material = self.materials[self.selected_material]
130
+ try:
131
+ # Retrieve values from fields
132
+ name = self.fields['Material Name'].get()
133
+ sgnum = int(self.fields['Space Group'].get())
134
+ lattice_parameters = [
135
+ float(self.fields[param].get())
136
+ for param in ('a', 'b', 'c', 'alpha', 'beta', 'gamma')
137
+ ]
138
+ # Make a hexrd material from those values so we can
139
+ # propagate any other updates required by the material's
140
+ # symmetries
141
+ _material = make_material(name, sgnum, lattice_parameters)
142
+ # _material = Material.make_material(
143
+ # name, sgnum=sgnum,
144
+ # lattice_parameters_angstroms=lattice_parameters,
145
+ # pos=['4a', '8c'])
146
+ # #pos=[(0,0,0), (1/4, 1/4, 1/4), (3/4, 3/4, 3/4)])
147
+ self.material_name, sgnum=self.sgnum,
148
+ lattice_parameters_angstroms=self.lattice_parameters)
149
+ material.material_name = name
150
+ material.sgnum = _material.sgnum
151
+ material.lattice_parameters = [
152
+ _material.latticeParameters[i].value for i in range(6)
153
+ ]
154
+ material._material = _material
155
+ # If the updated field forces other field(s) to get new
156
+ # values (because of space group symmetries), propagate
157
+ # those new values to the gui entries too.
158
+ for key, entry in self.fields.items():
159
+ if key == 'Material Name':
160
+ continue
161
+ entry.delete(0, tk.END)
162
+ self.fields['Space Group'].insert(0, str(material.sgnum))
163
+ for i, key in enumerate(('a', 'b', 'c', 'alpha', 'beta', 'gamma')):
164
+ self.fields[key].insert(
165
+ 0, str(_material.latticeParameters[i].value))
166
+
167
+ # Update the listbox name display
168
+ self.material_listbox.delete(self.selected_material)
169
+ self.material_listbox.insert(
170
+ self.selected_material, material.material_name)
171
+ self.update_plot()
172
+ except ValueError:
173
+ messagebox.showerror(
174
+ 'Invalid input',
175
+ 'Please enter valid numbers for lattice parameters.')
176
+
177
+ def on_material_select(self, event):
178
+ if len(self.material_listbox.curselection()) == 0:
179
+ # Listbox item deselection event can be ignored
180
+ return
181
+ # Update the selected material index
182
+ self.selected_material = self.material_listbox.curselection()[0]
183
+ material = self.materials[self.selected_material]
184
+ self.clear_fields()
185
+ self.fields['Material Name'].insert(0, material.material_name)
186
+ self.fields['Space Group'].insert(0, str(material.sgnum))
187
+ for i, key in enumerate(('a', 'b', 'c', 'alpha', 'beta', 'gamma')):
188
+ self.fields[key].insert(
189
+ 0, str(material._material.latticeParameters[i].value))
190
+
191
+ def clear_fields(self):
192
+ for entry in self.fields.values():
193
+ entry.delete(0, tk.END)
194
+
195
+ def update_plot(self):
196
+ # Local modules
197
+ from CHAP.edd.utils import (
198
+ get_unique_hkls_ds,
199
+ get_peak_locations,
200
+ )
201
+
202
+ self.ax.cla()
203
+ self.legend_handles = []
204
+ self.plot_reference_data() # Re-plot reference data
205
+
206
+ # Plot each material's hkl peak locations
207
+ for i, material in enumerate(self.materials):
208
+ hkls, ds = get_unique_hkls_ds([material])
209
+ E0s = get_peak_locations(ds, self.tth)
210
+ for hkl, E0 in zip(hkls, E0s):
211
+ if E0 < min(self.ref_data_x) or E0 > max(self.ref_data_x):
212
+ continue
213
+ line = self.ax.axvline(
214
+ E0, c=f'C{i+1}', ls='--', lw=1,
215
+ label=material.material_name)
216
+ self.ax.text(E0, 1, str(hkl)[1:-1], c=f'C{i+1}',
217
+ ha='right', va='top', rotation=90,
218
+ transform=self.ax.get_xaxis_transform())
219
+ self.legend_handles.append(line)
220
+ self.ax.legend(handles=self.legend_handles)
221
+ self.canvas.draw()
222
+
223
+ def on_close(self):
224
+ """Handle closing the GUI and triggering the on_complete
225
+ callback."""
226
+ if self.on_complete:
227
+ self.on_complete(self.materials, self.figure)
228
+ self.root.destroy() # Close the tkinter root window
229
+ plt.close()
230
+
231
+ def run_material_selector(
232
+ x, y, tth, preselected_materials=None, label='Reference Data',
233
+ on_complete=None, interactive=False):
234
+ """Run the MaterialParamSelector tkinter application.
235
+
236
+ :param x: MCA channel energies.
237
+ :type x: np.ndarray
238
+ :param y: MCA intensities.
239
+ :type y: np.ndarray
240
+ :param tth: The (calibrated) 2&theta; angle.
241
+ :type tth: float
242
+ :param preselected_materials: Materials to get HKLs and lattice
243
+ spacings for.
244
+ :type preselected_materials: list[hexrd.material.Material], optional
245
+ :param label: Legend label for the 1D plot of reference MCA data
246
+ from the parameters `x`, `y`, defaults to `"Reference Data"`.
247
+ :type label: str, optional
248
+ :param on_complete: Callback function to handle completion of the
249
+ material selection, defaults to `None`.
250
+ :type on_complete: Callable, optional
251
+ :param interactive: Show the plot and allow user interactions with
252
+ the matplotlib figure, defaults to `False`.
253
+ :type interactive: bool, optional
254
+ :return: The selected materials for the strain analyses.
255
+ :rtype: list[CHAP.edd.models.MaterialConfig]
256
+ """
257
+ # Initialize the main application window
258
+ root = tk.Tk()
259
+
260
+ # Create the material parameter selection GUI within the main
261
+ # window
262
+ # This GUI allows the user to adjust and visualize lattice
263
+ # parameters and space group
264
+ app = MaterialParamSelector(
265
+ root, x, y, tth, preselected_materials, label, on_complete)
266
+
267
+ if interactive:
268
+ # If interactive mode is enabled, start the GUI event loop to
269
+ # allow user interaction
270
+ root.mainloop()
271
+ else:
272
+ # If not in interactive mode, immediately close the
273
+ # application
274
+ app.on_close()
275
+
276
+ def select_material_params(
277
+ x, y, tth, preselected_materials=None, label='Reference Data',
278
+ interactive=False, return_buf=False):
279
+ """Interactively adjust the lattice parameters and space group for
280
+ a list of materials. It is possible to add / remove materials from
281
+ the list.
282
+
283
+ :param x: MCA channel energies.
284
+ :type x: np.ndarray
285
+ :param y: MCA intensities.
286
+ :type y: np.ndarray
287
+ :param tth: The (calibrated) 2&theta angle.
288
+ :type tth: float
289
+ :param preselected_materials: Materials to get HKLs and
290
+ lattice spacings for.
291
+ :type preselected_materials: list[hexrd.material.Material],
292
+ optional
293
+ :param label: Legend label for the 1D plot of reference MCA data
294
+ from the parameters `x`, `y`, defaults to `"Reference Data"`.
295
+ :type label: str, optional
296
+ :param interactive: Show the plot and allow user interactions with
297
+ the matplotlib figure, defaults to `False`.
298
+ :type interactive: bool, optional
299
+ :param return_buf: Return an in-memory object as a byte stream
300
+ represention of the Matplotlib figure, defaults to `False`.
301
+ :type return_buf: bool, optional
302
+ :return: The selected materials for the strain analyses and a byte
303
+ stream represention of the Matplotlib figure if return_buf is
304
+ `True` (`None` otherwise).
305
+ :rtype: list[CHAP.edd.models.MaterialConfig],
306
+ Union[io.BytesIO, None]
307
+ """
308
+ # Local modules
309
+ from CHAP.utils.general import fig_to_iobuf
310
+
311
+ # Run the MaterialParamSelector with the callback function to
312
+ # handle the materials data and, if requested, the output figure
313
+ materials = None
314
+ figure = None
315
+ def on_complete(_materials, _figure):
316
+ nonlocal materials, figure
317
+ materials = _materials
318
+ figure = _figure
319
+
320
+ run_material_selector(
321
+ x, y, tth, preselected_materials, label, on_complete, interactive)
322
+
323
+ if return_buf:
324
+ buf = fig_to_iobuf(figure)
325
+ else:
326
+ buf = None
327
+
328
+ return materials, buf
329
+
330
+
331
+ if __name__ == '__main__':
332
+ # Local modules
333
+ from CHAP.edd.models import MaterialConfig
334
+
335
+ xx = np.linspace(40, 100, 100)
336
+ yy = np.sin(xx)
337
+ ttth = 5
338
+ ppreselected_materials = [
339
+ MaterialConfig(
340
+ material_name='Ti64_orig',
341
+ sgnum=194,
342
+ lattice_parameters=[2.9217, 4.66027]
343
+ )
344
+ ]
345
+ mmaterials = select_material_params(
346
+ xx, yy, ttth, preselected_materials=ppreselected_materials,
347
+ interactive=True)
348
+ print(f'Returned materials: {mmaterials}')