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/backend/scans.py ADDED
@@ -0,0 +1,95 @@
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
+
33
+ import numpy as np
34
+
35
+
36
+ class Scan():
37
+
38
+ def __init__(self,hdffilepath_orNode=None, scanno=None):
39
+ self.axisname = None # either "th" or "mu"
40
+ self.axis = None # value of either "th" or "mu"
41
+ self.th = 0. # or self.mu, depending on scanaxis
42
+ self.omega = 0. # = -1*th
43
+ self.title = "generic_scan"
44
+ # for mu-scan you must provide a value for omega/theta
45
+
46
+ def __len__(self):
47
+ raise NotImplementedError()
48
+
49
+ def get_raw_img(self, i):
50
+ raise NotImplementedError()
51
+
52
+
53
+
54
+ class h5_Image:
55
+
56
+ def __init__(self, data):
57
+
58
+ self.img = data
59
+ self.motors = dict()
60
+ self.counters = dict()
61
+
62
+
63
+ class SimulationScan(Scan):
64
+
65
+ def __init__(self, detshape, axismin, axismax, points, axis='th', fixed=0.):
66
+
67
+ self.shape = detshape
68
+ self.axisname = axis
69
+ self.axis = np.linspace(axismin,axismax,points)
70
+ if axis == 'th':
71
+ self.th = self.axis
72
+ self.omega = -1*self.th
73
+ self.mu = fixed
74
+ elif axis == 'mu':
75
+ self.mu = self.axis
76
+ self.th = fixed
77
+ self.omega = -1*self.th
78
+ else:
79
+ raise ValueError("%s is not an implemented scan axis." % axis)
80
+ self.nopoints = points
81
+
82
+ self.images = np.zeros((points,*detshape))
83
+ self.title = "sim ascan %s %s %s %s" % (self.axisname,axismin,axismax,points)
84
+
85
+ def __len__(self):
86
+ return self.nopoints
87
+
88
+ def get_raw_img(self, i):
89
+ return h5_Image(self.images[i])
90
+
91
+ def set_raw_img(self, i, data): #for intensity simulation in the future.
92
+ self.images[i] = data
93
+
94
+
95
+
@@ -0,0 +1,163 @@
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 numpy as np
33
+ from ..datautils.xrayutils import HKLVlieg
34
+ from ..datautils import util
35
+
36
+ def defaultU_GID(ubCalculator):
37
+ """Sets a default U matrix for Grazing incidence surface diffraction geometry.
38
+
39
+ Geometry:
40
+ L along z axis in alpha frame
41
+ K along x axis in alpha frame
42
+ for chi = 0°, phi = 0°, omega = 0° (omega = -theta)
43
+
44
+ Aligns crystal L axis along omega rotation axis.
45
+ Alpha tilts this rotation axis. Typically alpha is equal to the angle of incidence.
46
+
47
+ """
48
+ # Compute the two reflections' reciprical vectors in the
49
+ # cartesian crystal frame (hc = B @ hkl)
50
+ h1c = ubCalculator.lattice.reciprocalVectorCart([0.,0.,1.]).flatten() # for hkl = (0, 0, 1)
51
+ h2c = ubCalculator.lattice.reciprocalVectorCart([0.,1.,0.]).flatten() # for hkl = (0, 1, 0)
52
+
53
+ # Calculate the sample rotation matrices
54
+
55
+ chi1 = np.deg2rad(0.)
56
+ phi1 = np.deg2rad(0.)
57
+ omega1 = np.deg2rad(0.)
58
+
59
+ chi2 = np.deg2rad(0.)
60
+ phi2 = np.deg2rad(0.)
61
+ omega2 = np.deg2rad(0.)
62
+
63
+ # [ALPHA, DELTA, GAMMA, OMEGA, CHI, PHI]
64
+ pos1 = np.array([None, None, None, omega1, chi1, phi1])
65
+ pos2 = np.array([None, None, None, omega2, chi2, phi2])
66
+
67
+ _,_,_, OM1, CHI1, PHI1 = HKLVlieg.createVliegMatrices(pos1) # rotation matrices
68
+ _,_,_, OM2, CHI2, PHI2 = HKLVlieg.createVliegMatrices(pos2) # rotation matrices
69
+
70
+ # define reference directions in alpha frame
71
+
72
+ Qalp1 = np.array([0.,0.,1.]) * np.linalg.norm(h1c) # reference 1: z direction
73
+ Qalp2 = np.array([1.,0.,0.]) * np.linalg.norm(h2c) # reference 2: x direction
74
+
75
+ # Transform Qalp in Qphi
76
+ # hint: matrix inverse of rotation matrices is the transpose (T)
77
+ Qphi1 = PHI1.T @ CHI1.T @ OM1.T @ Qalp1
78
+ Qphi2 = PHI2.T @ CHI2.T @ OM2.T @ Qalp2
79
+
80
+ # 1: primary vector, 2: secondary vector
81
+
82
+ U, stats = HKLVlieg.UBCalculator.calc_U_from_vectors(Qphi1, Qphi2, h1c, h2c)
83
+
84
+ ubCalculator.setU(U)
85
+
86
+ return ubCalculator
87
+
88
+ def defaultU_TSD(ubCalculator):
89
+ """Sets a default U matrix for Transmission Surface Diffraction geometry.
90
+
91
+ Geometry:
92
+ L along y axis in laboratory frame (along beam direction) at omega = 0°
93
+ K along z axis in laboratory frame
94
+ for chi = 90°
95
+ phi = 0°
96
+ alpha = 0°
97
+
98
+ In TSD mode, the crystal L axis points towards the beam direction at one
99
+ specific omega value as described here:
100
+
101
+ Transmission Surface Diffraction for Operando Studies of Heterogeneous Interfaces
102
+ Finn Reikowski, Tim Wiegmann, Jochim Stettner, Jakub Drnec, Veijo Honkimäki, Fouad Maroun, Philippe Allongue, and Olaf M. Magnussen
103
+ The Journal of Physical Chemistry Letters 2017 8 (5), 1067-1071
104
+ DOI: 10.1021/acs.jpclett.7b00332
105
+
106
+ """
107
+ # Compute the two reflections' reciprical vectors in the
108
+ # cartesian crystal frame (hc = B @ hkl)
109
+ h1c = ubCalculator.lattice.reciprocalVectorCart([0.,0.,1.]).flatten() # for hkl = (0, 0, 1)
110
+ h2c = ubCalculator.lattice.reciprocalVectorCart([0.,1.,0.]).flatten() # for hkl = (0, 1, 0)
111
+
112
+ # Calculate the sample rotation matrices
113
+
114
+ chi1 = np.deg2rad(90.)
115
+ phi1 = np.deg2rad(0.)
116
+ omega1 = np.deg2rad(0.)
117
+ alpha1 = np.deg2rad(0.)
118
+
119
+ chi2 = np.deg2rad(90.)
120
+ phi2 = np.deg2rad(0.)
121
+ omega2 = np.deg2rad(0.)
122
+ alpha2 = np.deg2rad(0.)
123
+
124
+ # [ALPHA, DELTA, GAMMA, OMEGA, CHI, PHI]
125
+ pos1 = np.array([alpha1, None, None, omega1, chi1, phi1])
126
+ pos2 = np.array([alpha2, None, None, omega2, chi2, phi2])
127
+
128
+ A1,_,_, OM1, CHI1, PHI1 = HKLVlieg.createVliegMatrices(pos1) # rotation matrices
129
+ A2,_,_, OM2, CHI2, PHI2 = HKLVlieg.createVliegMatrices(pos2) # rotation matrices
130
+
131
+ # define reference directions in laboratory frame
132
+
133
+ Qlab1 = np.array([0.,1.,0.]) * np.linalg.norm(h1c) # reference 1: y direction
134
+ Qlab2 = np.array([0.,0.,1.]) * np.linalg.norm(h2c) # reference 2: z direction
135
+
136
+ # Transform Qlab in Qphi
137
+ # hint: matrix inverse of rotation matrices is the transpose (T)
138
+ Qphi1 = PHI1.T @ CHI1.T @ OM1.T @ A1.T @ Qlab1
139
+ Qphi2 = PHI2.T @ CHI2.T @ OM2.T @ A2.T @ Qlab2
140
+
141
+ # 1: primary vector, 2: secondary vector
142
+
143
+ U, stats = HKLVlieg.UBCalculator.calc_U_from_vectors(Qphi1, Qphi2, h1c, h2c)
144
+
145
+ ubCalculator.setU(U)
146
+
147
+ return ubCalculator
148
+
149
+ def manualU(ubCalculator):
150
+ U = np.array([[1., 0., 0.],
151
+ [0., 1., 0.],
152
+ [0., 0., 1.]])
153
+ # could also do something like
154
+ # U = util.z_rotation(np.deg2rad(45.))
155
+ ubCalculator.setU(U)
156
+ return ubCalculator
157
+
158
+
159
+ u_defaults = {
160
+ 'Grazing incidence' : defaultU_GID,
161
+ 'Transmission' : defaultU_TSD,
162
+ 'manual U' : manualU
163
+ }
@@ -0,0 +1,105 @@
1
+ # -*- coding: utf-8 -*-
2
+ # /*##########################################################################
3
+ #
4
+ # Copyright (c) 2024 Finn Schroeter
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__ = "Finn Schroeter"
26
+ __credits__ = ['Finn Schroeter']
27
+ __copyright__ = "Copyright 2024 Finn Schroeter"
28
+ __license__ = "MIT License"
29
+ __version__ = "1.0.0"
30
+
31
+ import re
32
+ import os
33
+ import fabio
34
+ import numpy as np
35
+
36
+ from .scans import h5_Image
37
+
38
+ class ImportImagesScan():
39
+
40
+ def __init__(self, imgpath):
41
+ self.filename = imgpath
42
+
43
+ self.inpath = self.find_files()
44
+
45
+ img_data = fabio.open(self.inpath[0] + self.inpath[1][0])
46
+ self.shape = (img_data.data.shape[0], img_data.data.shape[1])
47
+
48
+ self.FramesPerFile = img_data.nframes
49
+ if self.FramesPerFile > 1:
50
+ last_file = fabio.open(self.inpath[0] + self.inpath[1][-1])
51
+ self.FramesLastFile = last_file.nframes
52
+ else:
53
+ self.FramesLastFile = self.FramesPerFile
54
+
55
+ self.images = np.zeros((1,*self.shape))
56
+
57
+ self.axisname = ''
58
+ self.axis = [0]
59
+ self.th = 0
60
+ self.omega = 0
61
+ self.mu = 0
62
+
63
+ self.title = "manually loaded scan"
64
+
65
+ self.nopoints = (len(self.inpath[1])-1)*self.FramesPerFile + self.FramesLastFile
66
+
67
+
68
+ def find_files(self):
69
+ re_str = re.compile(r'_\d+' + os.path.splitext(self.filename)[1]) #define search string. It matches a file source with syntax name_0000i.extension -> may need to be adapted
70
+ selected_directory = os.path.dirname(os.path.abspath(self.filename))
71
+ filenames = ''.join(os.listdir(selected_directory))
72
+
73
+ found_scanfiles = re_str.findall(filenames) #list of found filenames (suffix only)
74
+ suffix = re_str.findall(self.filename)[0]
75
+ imagePrefix = self.filename.removesuffix(suffix)
76
+
77
+ #found_scannrs = [e[1:-4] for e in found_scanfiles] #only the scan numbers, eg. 00015
78
+
79
+ return [imagePrefix,found_scanfiles]
80
+
81
+ def set_axis(self,axismin,axismax,axis,fixedAxisValue):
82
+ self.axis = np.linspace(axismin,axismax,self.nopoints)
83
+ self.axisname = axis
84
+ if axis == 'th':
85
+ self.th = self.axis
86
+ self.omega = -1*self.th
87
+ self.mu = fixedAxisValue
88
+
89
+
90
+ def __len__(self):
91
+ return self.nopoints
92
+
93
+ def get_raw_img(self, i):
94
+ if self.FramesPerFile > 1:
95
+ index = i // self.FramesPerFile
96
+ frame = i % self.FramesPerFile
97
+ img_data = fabio.open(self.inpath[0] + self.inpath[1][index]).get_frame(frame)
98
+ else:
99
+ img_data = fabio.open(self.inpath[0] + self.inpath[1][i])
100
+
101
+ return h5_Image(img_data.data)
102
+
103
+ def set_raw_img(self, i, data): #for intensity simulation in the future.
104
+ self.images[i] = data
105
+
@@ -0,0 +1,32 @@
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
+ __all__ = ['util']