orGUI 1.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.
Files changed (83) hide show
  1. orGUI-1.0.1.dist-info/LICENSE +21 -0
  2. orGUI-1.0.1.dist-info/METADATA +147 -0
  3. orGUI-1.0.1.dist-info/RECORD +83 -0
  4. orGUI-1.0.1.dist-info/WHEEL +5 -0
  5. orGUI-1.0.1.dist-info/entry_points.txt +2 -0
  6. orGUI-1.0.1.dist-info/top_level.txt +1 -0
  7. orgui/__init__.py +36 -0
  8. orgui/app/ArrayTableDialog.py +433 -0
  9. orgui/app/QReflectionSelector.py +538 -0
  10. orgui/app/QScanSelector.py +692 -0
  11. orgui/app/QUBCalculator.py +1210 -0
  12. orgui/app/__init__.py +36 -0
  13. orgui/app/database.py +487 -0
  14. orgui/app/orGUI.py +2613 -0
  15. orgui/app/qutils.py +51 -0
  16. orgui/backend/__init__.py +32 -0
  17. orgui/backend/backends.py +157 -0
  18. orgui/backend/beamline/ID31DiffractLinTilt.py +77 -0
  19. orgui/backend/beamline/P212_tools.py +577 -0
  20. orgui/backend/beamline/__init__.py +36 -0
  21. orgui/backend/beamline/fio_reader.py +110 -0
  22. orgui/backend/beamline/id31_tools.py +651 -0
  23. orgui/backend/scans.py +95 -0
  24. orgui/backend/udefaults.py +163 -0
  25. orgui/backend/universalScanLoader.py +105 -0
  26. orgui/datautils/__init__.py +32 -0
  27. orgui/datautils/util.py +705 -0
  28. orgui/datautils/xrayutils/CTRcalc.py +3022 -0
  29. orgui/datautils/xrayutils/CTRopt.py +623 -0
  30. orgui/datautils/xrayutils/CTRplotutil.py +904 -0
  31. orgui/datautils/xrayutils/DetectorCalibration.py +685 -0
  32. orgui/datautils/xrayutils/HKLVlieg.py +1360 -0
  33. orgui/datautils/xrayutils/ReciprocalNavigation.py +401 -0
  34. orgui/datautils/xrayutils/_CTRcalc_accel.py +181 -0
  35. orgui/datautils/xrayutils/__init__.py +46 -0
  36. orgui/datautils/xrayutils/element_data.py +213 -0
  37. orgui/datautils/xrayutils/test/__init__.py +57 -0
  38. orgui/datautils/xrayutils/test/test_CTRcalc.py +152 -0
  39. orgui/datautils/xrayutils/test/test_DetectorCalibration.py +336 -0
  40. orgui/datautils/xrayutils/test/test_HKLcalc.py +88 -0
  41. orgui/datautils/xrayutils/unitcells/Fe3O4(100).bul +59 -0
  42. orgui/datautils/xrayutils/unitcells/Pt100.bul +7 -0
  43. orgui/datautils/xrayutils/unitcells/Pt100_small.bul +5 -0
  44. orgui/datautils/xrayutils/unitcells/Pt110.bul +5 -0
  45. orgui/datautils/xrayutils/unitcells/Pt111.bul +6 -0
  46. orgui/datautils/xrayutils/unitcells/Pt310.bul +13 -0
  47. orgui/datautils/xrayutils/unitcells/Pt3O4(100).bul +19 -0
  48. orgui/datautils/xrayutils/unitcells/PtO(001).bul +9 -0
  49. orgui/datautils/xrayutils/unitcells/PtO(010).bul +9 -0
  50. orgui/datautils/xrayutils/unitcells/PtO(100).bul +9 -0
  51. orgui/datautils/xrayutils/unitcells/__init__.py +67 -0
  52. orgui/datautils/xrayutils/unitcells/a-PtO2(0001).bul +6 -0
  53. orgui/main.py +101 -0
  54. orgui/resources/__init__.py +40 -0
  55. orgui/resources/icons/alpha.png +0 -0
  56. orgui/resources/icons/alpha.svg +67 -0
  57. orgui/resources/icons/diffractometer_v3.png +0 -0
  58. orgui/resources/icons/disable-image.png +0 -0
  59. orgui/resources/icons/disable-image.svg +68 -0
  60. orgui/resources/icons/document-nx-open.png +0 -0
  61. orgui/resources/icons/document-nx-open.svg +152 -0
  62. orgui/resources/icons/document-nx-save.png +0 -0
  63. orgui/resources/icons/document-nx-save.svg +73 -0
  64. orgui/resources/icons/logo.png +0 -0
  65. orgui/resources/icons/logo.svg +808 -0
  66. orgui/resources/icons/max_image.png +0 -0
  67. orgui/resources/icons/max_image.svg +77 -0
  68. orgui/resources/icons/max_image2.png +0 -0
  69. orgui/resources/icons/max_image2.svg +83 -0
  70. orgui/resources/icons/search-image.png +0 -0
  71. orgui/resources/icons/search-image.svg +94 -0
  72. orgui/resources/icons/search-reflection.png +0 -0
  73. orgui/resources/icons/search-reflection.svg +126 -0
  74. orgui/resources/icons/search.png +0 -0
  75. orgui/resources/icons/search.svg +91 -0
  76. orgui/resources/icons/select-image.png +0 -0
  77. orgui/resources/icons/select-image.svg +60 -0
  78. orgui/resources/icons/set-reflection.png +0 -0
  79. orgui/resources/icons/set-reflection.svg +91 -0
  80. orgui/resources/icons/sum_image.png +0 -0
  81. orgui/resources/icons/sum_image.svg +63 -0
  82. orgui/resources/icons/sum_image2.png +0 -0
  83. orgui/resources/icons/sum_image2.svg +75 -0
orgui/app/__init__.py ADDED
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2020-2024 Timo Fuchs
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+ __author__ = "Timo Fuchs"
26
+ __copyright__ = "Copyright 2020-2024 Timo Fuchs"
27
+ __license__ = "MIT License"
28
+ __version__ = "1.0.0"
29
+ __maintainer__ = "Timo Fuchs"
30
+ __email__ = "fuchs@physik.uni-kiel.de"
31
+
32
+ """Module descripiton
33
+
34
+ """
35
+
36
+ __all__ = ['orGUI','QReflectionSelector','QSpecScanSelector','QUBCalculator','database']
orgui/app/database.py ADDED
@@ -0,0 +1,487 @@
1
+ # -*- coding: utf-8 -*-
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2020-2024 Timo Fuchs
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+ # ###########################################################################*/
25
+ __author__ = "Timo Fuchs"
26
+ __copyright__ = "Copyright 2020-2024 Timo Fuchs"
27
+ __license__ = "MIT License"
28
+ __version__ = "1.0.0"
29
+ __maintainer__ = "Timo Fuchs"
30
+ __email__ = "fuchs@physik.uni-kiel.de"
31
+
32
+ import sys
33
+ import numpy as np
34
+ import silx.gui.hdf5
35
+ from silx.gui import icons
36
+ from silx.gui.data import DataViewerFrame
37
+ from silx.gui.hdf5.Hdf5TreeModel import Hdf5TreeModel
38
+ from silx.gui.data import DataViewerFrame
39
+ from silx.gui import qt
40
+ import tempfile
41
+ import silx.io.h5py_utils
42
+ from silx.io import nxdata
43
+ import silx.io.utils
44
+ import h5py
45
+
46
+ import datetime
47
+ import os
48
+ import traceback
49
+ import time
50
+
51
+ from ..datautils.xrayutils import unitcells
52
+ from ..datautils.xrayutils import HKLVlieg, CTRcalc
53
+ from ..datautils.xrayutils import DetectorCalibration
54
+
55
+ from silx.io.dictdump import dicttonx ,nxtodict
56
+
57
+
58
+ class ConfigData(qt.QObject):
59
+ def __init__(self, config=None):
60
+ self.detector = DetectorCalibration.Detector2D_SXRD()
61
+
62
+ pass
63
+
64
+ #@classmethod
65
+ def readConfig(self, filename):
66
+ config = configparser.ConfigParser()
67
+ config.read(configfile)
68
+
69
+ machine = config['Machine']
70
+ lattice = config['Lattice']
71
+ diffrac = config['Diffractometer']
72
+
73
+ self.azimuth = np.deg2rad(diffrac.getfloat('azimuthal_reference',0))
74
+ self.polaxis = np.deg2rad(diffrac.getfloat('polarization_axis',90))
75
+ self.polfactor = diffrac.getfloat('polarization_factor',0)
76
+
77
+ sdd = machine.getfloat('SDD',0.729) #m
78
+ E = machine.getfloat('E',78.0) #keV
79
+ pixelsize = machine.getfloat('pixelsize',172e-6) #m
80
+ cpx = machine.getfloat('cpx',731)
81
+ cpy = machine.getfloat('cpy',1587)
82
+ cp = [cpx,cpy]
83
+
84
+ self.mu = np.deg2rad(diffrac.getfloat('mu',0.05))
85
+ self.chi = np.deg2rad(diffrac.getfloat('chi',0.0))
86
+ self.phi = np.deg2rad(diffrac.getfloat('phi',0.0))
87
+
88
+
89
+ a1 = lattice.getfloat('a1',-1)
90
+ a2 = lattice.getfloat('a2',-1)
91
+ a3 = lattice.getfloat('a3',-1)
92
+ alpha1 = lattice.getfloat('alpha1',-1)
93
+ alpha2 = lattice.getfloat('alpha2',-1)
94
+ alpha3 = lattice.getfloat('alpha3',-1)
95
+ self.n = 1 - lattice.getfloat('refractionindex',0.0)
96
+
97
+ lat = np.array([a1,a2,a3])
98
+
99
+ latticeoverride = True
100
+ latangle = np.array([alpha1,alpha2,alpha3])
101
+ if np.any(lat < 0.) or np.any(latangle < 0):
102
+ latticeoverride = False
103
+ a1 = a2 = a3 = 1.
104
+ alpha1 = alpha2 = alpha3 = 90.
105
+
106
+
107
+ self.crystal = CTRcalc.UnitCell([a1,a2,a3],[alpha1,alpha2,alpha3])
108
+ self.crystal.addAtom('Pt',[0.,0.,0.],0.1,0.1,1.)
109
+ self.crystal.setEnergy(E*1e3)
110
+
111
+ self.ubCal = HKLVlieg.UBCalculator(self.crystal,E)
112
+ self.ubCal.defaultU()
113
+ self.angles = HKLVlieg.VliegAngles(self.ubCal)
114
+
115
+ if 'crystal' in lattice:
116
+ idx = self.crystalparams.crystalComboBox.findText(lattice['crystal'],qt.Qt.MatchFixedString)
117
+ if idx == -1:
118
+ qt.QMessageBox.warning(self,"Did not find crystal","Can not find crystal <%s> \nException occured during read of configfile %s,\nException:\n%s" % (unitcellsconfigfile,traceback.format_exc()))
119
+ else:
120
+ self.crystalparams.crystalComboBox.setCurrentIndex(idx)
121
+ self.crystalparams.onSwitchCrystal(idx)
122
+ #self.crystal = self.crystalparams.getCrystal()
123
+
124
+ if latticeoverride:
125
+ print('foo')
126
+ self.crystal.setLattice([a1,a2,a3],[alpha1,alpha2,alpha3])
127
+
128
+
129
+ if 'poni' in machine:
130
+ if machine['poni']:
131
+ self.detectorCal.load(machine['poni'])
132
+ self.ubCal.setLambda(self.detectorCal.get_wavelength()*1e10)
133
+
134
+ else:
135
+ self.detectorCal.setFit2D(sdd*1e3,cpx,cpy,pixelX=pixelsize*1e6, pixelY=pixelsize*1e6)
136
+ self.detectorCal.set_wavelength(self.ubCal.getLambda()*1e-10)
137
+ self.detectorCal.detector.shape = (2880,2880) # Perkin
138
+
139
+ else:
140
+ self.detectorCal.setFit2D(sdd*1e3,cpx,cpy,pixelX=pixelsize*1e6, pixelY=pixelsize*1e6)
141
+ self.detectorCal.set_wavelength(self.ubCal.getLambda()*1e-10)
142
+ self.detectorCal.detector.shape = (2880,2880)
143
+
144
+ self.detectorCal.setAzimuthalReference(self.azimuth)
145
+ self.detectorCal.setPolarization(self.polaxis,self.polfactor)
146
+
147
+ fit2dCal = self.detectorCal.getFit2D()
148
+
149
+ paramlist = [self.ubCal.getEnergy(),self.mu,fit2dCal['directDist']/1e3,
150
+ fit2dCal['pixelX']*1e-6,[fit2dCal['centerX'],fit2dCal['centerY']],self.polaxis
151
+ ,self.polfactor,self.azimuth,self.chi,self.phi]
152
+ self.crystalparams.setValues(self.crystal,self.n)
153
+ self.machineParams.setValues(paramlist)
154
+
155
+
156
+
157
+
158
+
159
+
160
+ class DataBase(qt.QMainWindow):
161
+
162
+ def __init__(self, plot, parent=None):
163
+ qt.QMainWindow.__init__(self, parent)
164
+ self.nxfile = None
165
+ self.filedialogdir = os.getcwd()
166
+ self.plot = plot
167
+
168
+ self.view = silx.gui.hdf5.Hdf5TreeView()
169
+ self.view.setSortingEnabled(True)
170
+
171
+ #self.view.addContextMenuCallback(self.nexus_treeview_callback)
172
+ #self.hdf5model = self.view.findHdf5TreeModel()
173
+
174
+ customModel = Hdf5TreeModel
175
+ customModel.NAME_COLUMN = 0
176
+ customModel.DESCRIPTION_COLUMN = 1
177
+ customModel.VALUE_COLUMN = 2
178
+ customModel.SHAPE_COLUMN = 3
179
+ customModel.TYPE_COLUMN = 4
180
+ customModel.NODE_COLUMN = 5
181
+ customModel.LINK_COLUMN = 6
182
+
183
+ self.hdf5model = customModel(self.view)
184
+ self.view.setModel(self.hdf5model)
185
+
186
+ self.dataviewer = DataViewerFrame.DataViewerFrame()
187
+ self.dataviewerDialog = qt.QDialog(self)
188
+ dvlayout = qt.QVBoxLayout()
189
+ dvlayout.addWidget(self.dataviewer)
190
+ self.dataviewerDialog.setLayout(dvlayout)
191
+ self.dataviewerDialog.setModal(False)
192
+
193
+ self.view.setExpandsOnDoubleClick(False)
194
+ self.hdf5model.setFileMoveEnabled(True)
195
+ #self.__treeModelSorted = silx.gui.hdf5.NexusSortFilterProxyModel(self.view)
196
+ #self.__treeModelSorted.setSourceModel(self.hdf5model)
197
+ #self.__treeModelSorted.sort(0, qt.Qt.AscendingOrder)
198
+ #self.__treeModelSorted.setSortCaseSensitivity(qt.Qt.CaseInsensitive)
199
+
200
+ #self.hdfTreeView.setModel(self.__treeModelSorted)
201
+
202
+ self.view.doubleClicked.connect(self._onNEXUSDoubleClicked)
203
+ self.view.addContextMenuCallback(self.nexus_treeview_callback)
204
+
205
+ self.temp_directory = tempfile.TemporaryDirectory(dir=os.path.join(os.getcwd()))
206
+ tempfilepath = os.path.join(self.temp_directory.name,"orgui_database.h5")
207
+ self.createNewDBFile(tempfilepath)
208
+ #self.add_nxdict(gauss)
209
+ #self.add_nxdict(gauss)
210
+ self.setCentralWidget(self.view)
211
+
212
+ toolbar = qt.QToolBar("Database toolbar",self)
213
+
214
+ loadDatabaseAct = toolbar.addAction(icons.getQIcon("document-open"),"Open orgui database")
215
+ loadDatabaseAct.triggered.connect(self.onOpenDatabase)
216
+
217
+ savenewact = toolbar.addAction(icons.getQIcon("layer-nx"),"Select orgui database location")
218
+ savenewact.triggered.connect(self.onSaveNewDBFile)
219
+
220
+ saveact = toolbar.addAction(icons.getQIcon("document-save"),"Save orgui database")
221
+ saveact.triggered.connect(self.onSaveDBFile)
222
+
223
+ self.addToolBar(toolbar)
224
+
225
+ def _onNEXUSDoubleClicked(self,index): # ToDo add try except with popup message!
226
+ nodes = list(self.view.selectedH5Nodes())
227
+ if len(nodes) > 0:
228
+ obj = nodes[0]
229
+ if obj.ntype is h5py.Dataset:
230
+ roi_node = self.get_roinode(obj.h5py_object)
231
+ if roi_node is not None:
232
+ self.plot_signal_callback(roi_node, obj)
233
+ return
234
+ self.plot_default(obj.h5py_object)
235
+
236
+ def plot_default(self, h5py_object):
237
+ try:
238
+ nxdat = nxdata.get_default(h5py_object)
239
+ #print(nxdat.axes, nxdat.signal, nxdat.title)
240
+ #print(nxdat.signal_name, nxdat.errors, nxdat.axes_names)
241
+ if nxdat is not None and len(nxdat.axes) == 1:
242
+ self.plot.addCurve(nxdat.axes[0], nxdat.signal, legend=nxdat.title, xlabel=nxdat.axes_names[0], ylabel=nxdat.signal_name, yerror=nxdat.errors)
243
+ except Exception as e:
244
+ traceback.print_exc()
245
+ print("Cannot plot data: %s" % e)
246
+
247
+ def get_roinode(self, obj):
248
+ if silx.io.utils.get_h5_class(obj) is None:
249
+ return None
250
+
251
+ while(obj.name != '/'):
252
+ meta = obj.attrs.get('orgui_meta', False)
253
+ if meta and meta == 'roi':
254
+ return obj
255
+ obj = obj.parent
256
+
257
+ def get_scannode(self, obj):
258
+ if silx.io.utils.get_h5_class(obj) is None:
259
+ return None
260
+
261
+ while(obj.name != '/'):
262
+ meta = obj.attrs.get('orgui_meta', False)
263
+ if meta and meta == 'scan':
264
+ return obj
265
+ obj = obj.parent
266
+
267
+ def nexus_treeview_callback(self,event):
268
+ objects = list(event.source().selectedH5Nodes())
269
+ obj = objects[0] # for single selection
270
+ menu = event.menu()
271
+ action = qt.QAction("Refresh", menu)
272
+ action.triggered.connect(lambda: self.hdf5model.synchronizeH5pyObject(obj))
273
+ menu.addAction(action)
274
+ action = qt.QAction("details", menu)
275
+ action.triggered.connect(lambda: self.view_data_callback(obj))
276
+ menu.addAction(action)
277
+
278
+ if obj.ntype is h5py.Dataset:
279
+ roi_node = self.get_roinode(obj.h5py_object)
280
+ if roi_node is not None:
281
+ action = qt.QAction("plot %s" % obj.name, menu)
282
+ action.triggered.connect(lambda: self.plot_signal_callback(roi_node, obj))
283
+ menu.addAction(action)
284
+
285
+ if obj.ntype is h5py.Group:
286
+ meta = obj.h5py_object.attrs.get('orgui_meta', False)
287
+ if meta and meta == 'roi':
288
+ action = qt.QAction("rename", menu)
289
+ action.triggered.connect(lambda: self.onRenameNode(obj.h5py_object))
290
+ menu.addAction(action)
291
+ menu.addSeparator()
292
+ action = qt.QAction("delete", menu)
293
+ action.triggered.connect(lambda: self.delete_node(obj.h5py_object))
294
+ menu.addAction(action)
295
+
296
+ if meta and meta == 'scan':
297
+ menu.addSeparator()
298
+ action = qt.QAction("delete", menu)
299
+ action.triggered.connect(lambda: self.onDeleteScan(obj.h5py_object))
300
+ menu.addAction(action)
301
+
302
+ """
303
+ if obj.ntype is h5py.File:
304
+ action = qt.QAction("remove", menu)
305
+ action.triggered.connect(lambda: self._onCloseFile())
306
+ menu.addAction(action)
307
+ """
308
+ def plot_signal_callback(self, roi_node, dataset):
309
+ try:
310
+ nxdat = nxdata.get_default(roi_node)
311
+ data = dataset.h5py_object[()]
312
+ #print(nxdat.axes, nxdat.signal, nxdat.title)
313
+ #print(nxdat.signal_name, nxdat.errors, nxdat.axes_names)
314
+ if nxdat is not None and len(nxdat.axes) == 1:
315
+ self.plot.addCurve(nxdat.axes[0], data, legend=nxdat.title + "_" + dataset.name, xlabel=nxdat.axes_names[0], ylabel=dataset.name)
316
+ except Exception as e:
317
+ traceback.print_exc()
318
+ print("Cannot plot data: %s" % e)
319
+
320
+
321
+
322
+ def view_data_callback(self,obj):
323
+ self.dataviewer.setData(obj)
324
+ self.dataviewerDialog.open()
325
+
326
+ def onSaveNewDBFile(self):
327
+ fileTypeDict = {'NEXUS Files (*.h5)': '.h5', 'All files (*)': '' }
328
+ fileTypeFilter = ""
329
+ for f in fileTypeDict:
330
+ fileTypeFilter += f + ";;"
331
+
332
+ filename, filetype = qt.QFileDialog.getSaveFileName(self,"Select database location",
333
+ self.filedialogdir,
334
+ fileTypeFilter[:-2])
335
+ if filename == '':
336
+ return
337
+
338
+ self.filedialogdir = os.path.splitext(filename)[0]
339
+ #filename += fileTypeDict[filetype]
340
+ self.saveNewDBFile(filename)
341
+
342
+ def onSaveDBFile(self):
343
+ fileTypeDict = {'NEXUS Files (*.h5)': '.h5', 'All files (*)': '' }
344
+ fileTypeFilter = ""
345
+ for f in fileTypeDict:
346
+ fileTypeFilter += f + ";;"
347
+
348
+ filename, filetype = qt.QFileDialog.getSaveFileName(self,"Save database",
349
+ self.filedialogdir,
350
+ fileTypeFilter[:-2])
351
+ if filename == '':
352
+ return
353
+
354
+ self.filedialogdir = os.path.splitext(filename)[0]
355
+ #filename += fileTypeDict[filetype]
356
+ self.saveDBFile(filename)
357
+
358
+ def onOpenDatabase(self):
359
+ fileTypeDict = {'NEXUS Files (*.h5)': '.h5', 'All files (*)': '' }
360
+ fileTypeFilter = ""
361
+ for f in fileTypeDict:
362
+ fileTypeFilter += f + ";;"
363
+
364
+ filename, filetype = qt.QFileDialog.getOpenFileName(self,"Save database",
365
+ self.filedialogdir,
366
+ fileTypeFilter[:-2])
367
+ if filename == '':
368
+ return
369
+
370
+ self.filedialogdir = os.path.splitext(filename)[0]
371
+ #filename += fileTypeDict[filetype]
372
+ try:
373
+ self.openDBFile(filename)
374
+ except:
375
+ msgbox = qt.QMessageBox(qt.QMessageBox.Critical,'Cannot open db file',
376
+ 'Cannot open db file %s.' % filename,
377
+ qt.QMessageBox.Ok, self)
378
+ msgbox.setDetailedText(traceback.format_exc())
379
+ clickedbutton = msgbox.exec()
380
+
381
+
382
+ def saveNewDBFile(self, filename):
383
+ alldata = nxtodict(self.nxfile)
384
+ self.createNewDBFile(filename, alldata)
385
+
386
+ def saveDBFile(self, filename):
387
+ alldata = nxtodict(self.nxfile)
388
+ dicttonx(alldata, filename)
389
+
390
+ def createNewDBFile(self, filename, datadict=None):
391
+ if self.nxfile is not None:
392
+ while(self.hdf5model.hasPendingOperations()):
393
+ qt.QApplication.processEvents()
394
+ time.sleep(0.01)
395
+ self.hdf5model.removeH5pyObject(self.nxfile)
396
+ self.nxfile.close()
397
+ self.nxfile = None
398
+ if hasattr(self, "temp_directory"):
399
+ del self.temp_directory
400
+
401
+ fileattrs = {"@NX_class": u"NXroot",
402
+ "@creator": u"orGUI version %s" % __version__,
403
+ "@file_name": str(os.path.basename(filename)),
404
+ "@file_time": datetime.datetime.utcnow().isoformat()}
405
+ if datadict is None:
406
+ datadict = fileattrs
407
+ else:
408
+ datadict.update(fileattrs)
409
+ try:
410
+ dicttonx(datadict, filename)
411
+ self.openDBFile(filename)
412
+ except:
413
+ msgbox = qt.QMessageBox(qt.QMessageBox.Critical,'Cannot create db file',
414
+ 'Cannot create file %s.' % filename,
415
+ qt.QMessageBox.Ok, self)
416
+ msgbox.setDetailedText(traceback.format_exc())
417
+ clickedbutton = msgbox.exec()
418
+
419
+ def openDBFile(self, filename):
420
+ if self.nxfile is not None:
421
+ self.hdf5model.removeH5pyObject(self.nxfile)
422
+ self.nxfile.close()
423
+ if hasattr(self, "temp_directory"):
424
+ del self.temp_directory
425
+ self.nxfile = silx.io.h5py_utils.File(filename,'a')
426
+ self._filepath = filename
427
+ while(self.hdf5model.hasPendingOperations()):
428
+ qt.QApplication.processEvents()
429
+ time.sleep(0.01)
430
+ self.hdf5model.insertH5pyObject(self.nxfile)
431
+ self.view.expandToDepth(0)
432
+
433
+ def add_nxdict(self, nxentry):
434
+ if self.nxfile is None:
435
+ raise Exception("No database file open.")
436
+ dicttonx(nxentry, self.nxfile, update_mode='add')
437
+ while(self.hdf5model.hasPendingOperations()):
438
+ qt.QApplication.processEvents()
439
+ time.sleep(0.01)
440
+ self.hdf5model.synchronizeH5pyObject(self.nxfile)
441
+ self.view.expandToDepth(0)
442
+
443
+ def onDeleteScan(self, obj):
444
+ btn = qt.QMessageBox.question(self,"Delete scan?","Are you sure that you want to delete %s from the orgui database?" % obj.name.split("/")[-1])
445
+ if btn == qt.QMessageBox.Yes:
446
+ self.delete_node(obj)
447
+
448
+ def delete_node(self, obj):
449
+ basename = obj.name.split("/")[-1]
450
+ objpar = obj.parent
451
+ del objpar[basename]
452
+ while(self.hdf5model.hasPendingOperations()):
453
+ qt.QApplication.processEvents()
454
+ time.sleep(0.01)
455
+ self.hdf5model.synchronizeH5pyObject(self.nxfile)
456
+ self.view.expandToDepth(0)
457
+
458
+ def onRenameNode(self, obj):
459
+ basename = obj.name.split("/")[-1]
460
+ newname, success = qt.QInputDialog.getText(self,"Rename NEXUS node",
461
+ "New name:", qt.QLineEdit.EchoMode.Normal,
462
+ basename)
463
+ if success and newname != '':
464
+ self.rename_node(obj, newname)
465
+
466
+ def rename_node(self, obj, newname):
467
+ basename = obj.name.split("/")[-1]
468
+ objpar = obj.parent
469
+ objpar.move(basename, newname)
470
+ while(self.hdf5model.hasPendingOperations()):
471
+ qt.QApplication.processEvents()
472
+ time.sleep(0.01)
473
+ self.hdf5model.synchronizeH5pyObject(self.nxfile)
474
+ self.view.expandToDepth(0)
475
+
476
+
477
+ def close(self):
478
+ if self.nxfile is not None:
479
+ self.hdf5model.removeH5pyObject(self.nxfile)
480
+ self.nxfile.close()
481
+ self.nxfile = None
482
+ if hasattr(self, "temp_directory"):
483
+ del self.temp_directory
484
+
485
+
486
+
487
+