1 | """ |
---|
2 | This software was developed by the University of Tennessee as part of the |
---|
3 | Distributed Data Analysis of Neutron Scattering Experiments (DANSE) |
---|
4 | project funded by the US National Science Foundation. |
---|
5 | |
---|
6 | See the license text in license.txt |
---|
7 | |
---|
8 | copyright 2008, 2009, University of Tennessee |
---|
9 | """ |
---|
10 | from numpy import * |
---|
11 | |
---|
12 | class SlitlengthCalculator(object): |
---|
13 | """ |
---|
14 | compute slit length from SAXSess beam profile (1st col. Q , 2nd col. I , and 3rd col. dI.: don't need the 3rd) |
---|
15 | @object: data where are data.y and data.x |
---|
16 | """ |
---|
17 | def __init__(self): |
---|
18 | |
---|
19 | # x data |
---|
20 | self.x = None |
---|
21 | # y data |
---|
22 | self.y = None |
---|
23 | #default slit length |
---|
24 | self.slit_length = 0.0 |
---|
25 | |
---|
26 | # The unit is unknown from SAXSess profile: |
---|
27 | # It seems 1/nm but it could be not fixed, |
---|
28 | # so users should be notified to determine the unit by themselves. |
---|
29 | self.slit_length_unit = "unknown" |
---|
30 | |
---|
31 | def set_data(self, x=None, y=None): |
---|
32 | """ |
---|
33 | set data |
---|
34 | @ Param x, y: x array and y array |
---|
35 | """ |
---|
36 | self.x = x |
---|
37 | self.y = y |
---|
38 | |
---|
39 | |
---|
40 | def calculate_slit_length(self): |
---|
41 | """ |
---|
42 | Calculate slit length using 10 max point |
---|
43 | ToDo: Near future, it should be re-factored in better method. |
---|
44 | """ |
---|
45 | # None data do nothing |
---|
46 | if self.y == None or self.x == None: |
---|
47 | return |
---|
48 | |
---|
49 | # set local variable |
---|
50 | y = self.y |
---|
51 | x = self.x |
---|
52 | |
---|
53 | # find max y |
---|
54 | max_y = y.max() |
---|
55 | |
---|
56 | # initial values |
---|
57 | y_sum = 0.0 |
---|
58 | y_max = 0.0 |
---|
59 | ind = 0.0 |
---|
60 | |
---|
61 | # sum 10 or more y values until getting max_y, |
---|
62 | while (True): |
---|
63 | if ind >= 10 and y_max == max_y: |
---|
64 | break |
---|
65 | y_sum = y_sum + y[ind] |
---|
66 | if y[ind] > y_max: y_max = y[ind] |
---|
67 | ind += 1 |
---|
68 | |
---|
69 | # find the average value/2 of the top values |
---|
70 | y_half = y_sum/(2.0*ind) |
---|
71 | |
---|
72 | # defaults |
---|
73 | y_half_d = 0.0 |
---|
74 | ind = 0.0 |
---|
75 | # find indices where it crosses y = y_half. |
---|
76 | while (True): |
---|
77 | ind += 1 # no need to check when ind == 0 |
---|
78 | y_half_d = y[ind] # y value and ind just after passed the spot of the half height |
---|
79 | if y[ind] < y_half: break |
---|
80 | |
---|
81 | y_half_u = y[ind-1] # y value and ind just before passed the spot of the half height |
---|
82 | |
---|
83 | # get corresponding x values |
---|
84 | x_half_d = x[ind] |
---|
85 | x_half_u = x[ind-1] |
---|
86 | |
---|
87 | # calculate x at y = y_half using linear interpolation |
---|
88 | if y_half_u == y_half_d: |
---|
89 | x_half = (x_half_d + x_half_u)/2.0 |
---|
90 | else: |
---|
91 | x_half = (x_half_u * (y_half - y_half_d) + x_half_d*(y_half_u-y_half))/(y_half_u - y_half_d) |
---|
92 | |
---|
93 | # multiply by 2 due to the beam profile is for half beam |
---|
94 | slit_length = 2.0 * x_half |
---|
95 | |
---|
96 | # set slit_length |
---|
97 | self.slit_length = slit_length |
---|
98 | |
---|
99 | def get_slit_length(self): |
---|
100 | """ |
---|
101 | Calculate and return the slit length |
---|
102 | """ |
---|
103 | self.calculate_slit_length() |
---|
104 | return self.slit_length |
---|
105 | |
---|
106 | def get_slit_length_unit(self): |
---|
107 | """ |
---|
108 | return the slit length unit |
---|
109 | """ |
---|
110 | return self.slit_length_unit |
---|