14
14
TTH_GRID [- 1 ] = 180.00
15
15
CVE_METHODS = ["brute_force" , "polynomial_interpolation" ]
16
16
17
- # pre -computed datasets for polynomial interpolation (fast calculation)
17
+ # Pre -computed datasets for polynomial interpolation (fast calculation)
18
18
MUD_LIST = [0.5 , 1 , 2 , 3 , 4 , 5 , 6 ]
19
19
CWD = Path (__file__ ).parent .resolve ()
20
20
MULS = np .loadtxt (CWD / "data" / "inverse_cve.xy" )
@@ -32,91 +32,43 @@ def __init__(self, radius=1, n_points_on_diameter=N_POINTS_ON_DIAMETER, mu=None)
32
32
self ._get_grid_points ()
33
33
34
34
def _get_grid_points (self ):
35
- """
36
- given a radius and a grid size, return a grid of points to uniformly sample that circle
37
- """
35
+ """Given a radius and a grid size, return a grid of points to uniformly sample that circle."""
38
36
xs = np .linspace (- self .radius , self .radius , self .npoints )
39
37
ys = np .linspace (- self .radius , self .radius , self .npoints )
40
38
self .grid = {(x , y ) for x in xs for y in ys if x ** 2 + y ** 2 <= self .radius ** 2 }
41
39
self .total_points_in_grid = len (self .grid )
42
40
43
- def set_distances_at_angle (self , angle ):
44
- """
45
- given an angle, set the distances from the grid points to the entry and exit coordinates
46
-
47
- Parameters
48
- ----------
49
- angle float
50
- the angle in degrees
51
-
52
- Returns
53
- -------
54
- the list of distances containing total distance, primary distance and secondary distance
55
-
56
- """
57
- self .primary_distances , self .secondary_distances , self .distances = [], [], []
58
- for coord in self .grid :
59
- distance , primary , secondary = self .get_path_length (coord , angle )
60
- self .distances .append (distance )
61
- self .primary_distances .append (primary )
62
- self .secondary_distances .append (secondary )
63
-
64
- def set_muls_at_angle (self , angle ):
65
- """
66
- compute muls = exp(-mu*distance) for a given angle
67
-
68
- Parameters
69
- ----------
70
- angle float
71
- the angle in degrees
72
-
73
- Returns
74
- -------
75
- an array of floats containing the muls corresponding to each angle
76
-
77
- """
78
- mu = self .mu
79
- self .muls = []
80
- if len (self .distances ) == 0 :
81
- self .set_distances_at_angle (angle )
82
- for distance in self .distances :
83
- self .muls .append (np .exp (- mu * distance ))
84
-
85
41
def _get_entry_exit_coordinates (self , coordinate , angle ):
86
- """
87
- get the coordinates where the beam enters and leaves the circle for a given angle and grid point
88
-
89
- Parameters
90
- ----------
91
- grid_point tuple of floats
92
- the coordinates of the grid point
93
-
94
- angle float
95
- the angle in degrees
42
+ """Get the coordinates where the beam enters and leaves the circle for a given angle and grid point.
96
43
97
- radius float
98
- the radius of the circle in units of inverse mu
99
-
100
- it is calculated in the following way:
44
+ It is calculated in the following way:
101
45
For the entry coordinate, the y-component will be the y of the grid point and the x-component will be minus
102
46
the value of x on the circle at the height of this y.
103
47
104
48
For the exit coordinate:
105
- Find the line y = ax + b that passes through grid_point at angle angle
106
- The circle is x^2 + y^2 = r^2
49
+ Find the line y = ax + b that passes through grid_point at angle.
50
+ The circle is x^2 + y^2 = r^2.
107
51
The exit point is where these are simultaneous equations
108
52
x^2 + y^2 = r^2 & y = ax + b
109
53
x^2 + (ax+b)^2 = r^2
110
54
=> x^2 + a^2x^2 + 2abx + b^2 - r^2 = 0
111
55
=> (1+a^2) x^2 + 2abx + (b^2 - r^2) = 0
112
56
to find x_exit we find the roots of these equations and pick the root that is above y-grid
113
- then we get y_exit from y_exit = a*x_exit + b
57
+ then we get y_exit from y_exit = a*x_exit + b.
58
+
59
+ Parameters
60
+ ----------
61
+ coordinate : tuple of floats
62
+ The coordinates of the grid point.
63
+
64
+ angle : float
65
+ The angle in degrees.
114
66
115
67
Returns
116
68
-------
117
- (1) the coordinate of the entry point and (2) of the exit point of a beam entering horizontally
118
- impinging on a coordinate point that lies in the circle and then exiting at some angle, angle.
119
-
69
+ (entry_point, exit_point): tuple of floats
70
+ (1) The coordinate of the entry point and (2) of the exit point of a beam entering horizontally
71
+ impinging on a coordinate point that lies in the circle and then exiting at some angle, angle.
120
72
"""
121
73
epsilon = 1e-7 # precision close to 90
122
74
angle = math .radians (angle )
@@ -140,28 +92,22 @@ def _get_entry_exit_coordinates(self, coordinate, angle):
140
92
141
93
return entry_point , exit_point
142
94
143
- def get_path_length (self , grid_point , angle ):
144
- """
145
- return the path length
146
-
147
- This is the pathlength of a horizontal line entering the circle at the
148
- same height to the grid point then exiting at angle angle
95
+ def _get_path_length (self , grid_point , angle ):
96
+ """Return the path length of a horizontal line entering the circle at the
97
+ same height to the grid point then exiting at angle.
149
98
150
99
Parameters
151
100
----------
152
- grid_point double of floats
153
- the coordinate inside the circle
101
+ grid_point : double of floats
102
+ The coordinate inside the circle.
154
103
155
- angle float
156
- the angle of the output beam
157
-
158
- radius
159
- the radius of the circle
104
+ angle : float
105
+ The angle of the output beam in degrees.
160
106
161
107
Returns
162
108
-------
163
- floats total distance, primary distance and secondary distance
164
-
109
+ ( total distance, primary distance, secondary distance): tuple of floats
110
+ The tuple containing three floats, which are the total distance, entry distance and exit distance.
165
111
"""
166
112
167
113
# move angle a tad above zero if it is zero to avoid it having the wrong sign due to some rounding error
@@ -174,13 +120,41 @@ def get_path_length(self, grid_point, angle):
174
120
total_distance = primary_distance + secondary_distance
175
121
return total_distance , primary_distance , secondary_distance
176
122
123
+ def set_distances_at_angle (self , angle ):
124
+ """Given an angle, set the distances from the grid points to the entry and exit coordinates.
177
125
178
- def _cve_brute_force (diffraction_data , mud ):
179
- """
180
- compute cve for the given mud on a global grid using the brute-force method
181
- assume mu=mud/2, given that the same mu*D yields the same cve and D/2=1
182
- """
126
+ Parameters
127
+ ----------
128
+ angle : float
129
+ The angle of the output beam in degrees.
130
+ """
131
+ self .primary_distances , self .secondary_distances , self .distances = [], [], []
132
+ for coord in self .grid :
133
+ distance , primary , secondary = self ._get_path_length (coord , angle )
134
+ self .distances .append (distance )
135
+ self .primary_distances .append (primary )
136
+ self .secondary_distances .append (secondary )
137
+
138
+ def set_muls_at_angle (self , angle ):
139
+ """Compute muls = exp(-mu*distance) for a given angle.
183
140
141
+ Parameters
142
+ ----------
143
+ angle : float
144
+ The angle of the output beam in degrees.
145
+ """
146
+ mu = self .mu
147
+ self .muls = []
148
+ if len (self .distances ) == 0 :
149
+ self .set_distances_at_angle (angle )
150
+ for distance in self .distances :
151
+ self .muls .append (np .exp (- mu * distance ))
152
+
153
+
154
+ def _cve_brute_force (input_pattern , mud ):
155
+ """Compute cve for the given mud on a global grid using the brute-force method.
156
+ Assume mu=mud/2, given that the same mu*D yields the same cve and D/2=1.
157
+ """
184
158
mu_sample_invmm = mud / 2
185
159
abs_correction = Gridded_circle (mu = mu_sample_invmm )
186
160
distances , muls = [], []
@@ -197,19 +171,18 @@ def _cve_brute_force(diffraction_data, mud):
197
171
xarray = TTH_GRID ,
198
172
yarray = cve ,
199
173
xtype = "tth" ,
200
- wavelength = diffraction_data .wavelength ,
174
+ wavelength = input_pattern .wavelength ,
201
175
scat_quantity = "cve" ,
202
- name = f"absorption correction, cve, for { diffraction_data .name } " ,
203
- metadata = diffraction_data .metadata ,
176
+ name = f"absorption correction, cve, for { input_pattern .name } " ,
177
+ metadata = input_pattern .metadata ,
204
178
)
205
179
return cve_do
206
180
207
181
208
- def _cve_polynomial_interpolation (diffraction_data , mud ):
209
- """
210
- compute cve using polynomial interpolation method, raise an error if mu*D is out of the range (0.5 to 6)
182
+ def _cve_polynomial_interpolation (input_pattern , mud ):
183
+ """Compute cve using polynomial interpolation method,
184
+ raise an error if the mu*D value is out of the range (0.5 to 6).
211
185
"""
212
-
213
186
if mud > 6 or mud < 0.5 :
214
187
raise ValueError (
215
188
f"mu*D is out of the acceptable range (0.5 to 6) for polynomial interpolation. "
@@ -225,18 +198,16 @@ def _cve_polynomial_interpolation(diffraction_data, mud):
225
198
xarray = TTH_GRID ,
226
199
yarray = cve ,
227
200
xtype = "tth" ,
228
- wavelength = diffraction_data .wavelength ,
201
+ wavelength = input_pattern .wavelength ,
229
202
scat_quantity = "cve" ,
230
- name = f"absorption correction, cve, for { diffraction_data .name } " ,
231
- metadata = diffraction_data .metadata ,
203
+ name = f"absorption correction, cve, for { input_pattern .name } " ,
204
+ metadata = input_pattern .metadata ,
232
205
)
233
206
return cve_do
234
207
235
208
236
209
def _cve_method (method ):
237
- """
238
- retrieve the cve computation function for the given method
239
- """
210
+ """Retrieve the cve computation function for the given method."""
240
211
methods = {
241
212
"brute_force" : _cve_brute_force ,
242
213
"polynomial_interpolation" : _cve_polynomial_interpolation ,
@@ -246,60 +217,57 @@ def _cve_method(method):
246
217
return methods [method ]
247
218
248
219
249
- def compute_cve (diffraction_data , mud , method = "polynomial_interpolation" , xtype = "tth" ):
250
- f"""
251
- compute and interpolate the cve for the given diffraction data and mud using the selected method
220
+ def compute_cve (input_pattern , mud , method = "polynomial_interpolation" , xtype = "tth" ):
221
+ f"""Compute and interpolate the cve for the given input diffraction data and mu*D using the selected method.
252
222
253
223
Parameters
254
224
----------
255
- diffraction_data Diffraction_object
256
- the diffraction pattern
257
- mud float
258
- the mu*D of the diffraction object, where D is the diameter of the circle
259
- xtype str
260
- the quantity on the independent variable axis, allowed values are { * XQUANTITIES , }
261
- method str
262
- the method used to calculate cve, must be one of { * CVE_METHODS , }
225
+ input_pattern : DiffractionObject
226
+ The input diffraction object to which the cve will be applied.
227
+ mud : float
228
+ The mu*D value of the diffraction object, where D is the diameter of the circle.
229
+ xtype : str
230
+ The quantity on the independent variable axis, allowed values are { * XQUANTITIES , } .
231
+ method : str
232
+ The method used to calculate cve, must be one of { * CVE_METHODS , } .
263
233
264
234
Returns
265
235
-------
266
- the diffraction object with cve curves
236
+ cve_do: DiffractionObject
237
+ The diffraction object that contains the cve to be applied.
267
238
"""
268
-
269
239
cve_function = _cve_method (method )
270
- cve_do_on_global_grid = cve_function (diffraction_data , mud )
271
- orig_grid = diffraction_data .on_xtype (xtype )[0 ]
240
+ cve_do_on_global_grid = cve_function (input_pattern , mud )
241
+ orig_grid = input_pattern .on_xtype (xtype )[0 ]
272
242
global_xtype = cve_do_on_global_grid .on_xtype (xtype )[0 ]
273
243
cve_on_global_xtype = cve_do_on_global_grid .on_xtype (xtype )[1 ]
274
244
newcve = np .interp (orig_grid , global_xtype , cve_on_global_xtype )
275
245
cve_do = DiffractionObject (
276
246
xarray = orig_grid ,
277
247
yarray = newcve ,
278
248
xtype = xtype ,
279
- wavelength = diffraction_data .wavelength ,
249
+ wavelength = input_pattern .wavelength ,
280
250
scat_quantity = "cve" ,
281
- name = f"absorption correction, cve, for { diffraction_data .name } " ,
282
- metadata = diffraction_data .metadata ,
251
+ name = f"absorption correction, cve, for { input_pattern .name } " ,
252
+ metadata = input_pattern .metadata ,
283
253
)
284
254
return cve_do
285
255
286
256
287
- def apply_corr (diffraction_pattern , absorption_correction ):
288
- """
289
- Apply absorption correction to the given diffraction object modo with the correction diffraction object abdo
257
+ def apply_corr (input_pattern , absorption_correction ):
258
+ """Apply absorption correction to the given diffraction object with the correction diffraction object.
290
259
291
260
Parameters
292
261
----------
293
- diffraction_pattern Diffraction_object
294
- the input diffraction object to which the cve will be applied
295
- absorption_correction Diffraction_object
296
- the diffraction object that contains the cve to be applied
262
+ input_pattern : DiffractionObject
263
+ The input diffraction object to which the cve will be applied.
264
+ absorption_correction : DiffractionObject
265
+ The diffraction object that contains the cve to be applied.
297
266
298
267
Returns
299
268
-------
300
- a corrected diffraction object with the correction applied through multiplication
301
-
269
+ corrected_pattern: DiffractionObject
270
+ The corrected diffraction object with the correction applied through multiplication.
302
271
"""
303
-
304
- corrected_pattern = diffraction_pattern * absorption_correction
272
+ corrected_pattern = input_pattern * absorption_correction
305
273
return corrected_pattern
0 commit comments