[0bf2c6f] | 1 | """ |
---|
[14e9eb3] | 2 | This module is a small tool to allow user to quickly |
---|
| 3 | determine the slit length value of data. |
---|
[0bf2c6f] | 4 | """ |
---|
| 5 | |
---|
| 6 | class SlitlengthCalculator(object): |
---|
| 7 | """ |
---|
[14e9eb3] | 8 | compute slit length from SAXSess beam profile (1st col. Q , 2nd col. I , |
---|
| 9 | and 3rd col. dI.: don't need the 3rd) |
---|
[0bf2c6f] | 10 | """ |
---|
| 11 | def __init__(self): |
---|
| 12 | |
---|
| 13 | # x data |
---|
| 14 | self.x = None |
---|
| 15 | # y data |
---|
| 16 | self.y = None |
---|
| 17 | #default slit length |
---|
| 18 | self.slit_length = 0.0 |
---|
| 19 | |
---|
| 20 | # The unit is unknown from SAXSess profile: |
---|
| 21 | # It seems 1/nm but it could be not fixed, |
---|
| 22 | # so users should be notified to determine the unit by themselves. |
---|
| 23 | self.slit_length_unit = "unknown" |
---|
| 24 | |
---|
| 25 | def set_data(self, x=None, y=None): |
---|
| 26 | """ |
---|
[69fee24] | 27 | Receive two vector x, y and prepare the slit calculator for |
---|
| 28 | computation. |
---|
| 29 | |
---|
| 30 | :param x: array |
---|
| 31 | :param y: array |
---|
[0bf2c6f] | 32 | """ |
---|
| 33 | self.x = x |
---|
| 34 | self.y = y |
---|
| 35 | |
---|
| 36 | def calculate_slit_length(self): |
---|
| 37 | """ |
---|
[14e9eb3] | 38 | Calculate slit length. |
---|
[69fee24] | 39 | |
---|
| 40 | :return: the slit length calculated value. |
---|
[0bf2c6f] | 41 | """ |
---|
| 42 | # None data do nothing |
---|
| 43 | if self.y == None or self.x == None: |
---|
| 44 | return |
---|
| 45 | # set local variable |
---|
| 46 | y = self.y |
---|
| 47 | x = self.x |
---|
| 48 | |
---|
| 49 | # find max y |
---|
| 50 | max_y = y.max() |
---|
| 51 | |
---|
| 52 | # initial values |
---|
| 53 | y_sum = 0.0 |
---|
| 54 | y_max = 0.0 |
---|
| 55 | ind = 0.0 |
---|
| 56 | |
---|
| 57 | # sum 10 or more y values until getting max_y, |
---|
| 58 | while (True): |
---|
| 59 | if ind >= 10 and y_max == max_y: |
---|
| 60 | break |
---|
| 61 | y_sum = y_sum + y[ind] |
---|
[d267aed] | 62 | if y[ind] > y_max: |
---|
| 63 | y_max = y[ind] |
---|
[0bf2c6f] | 64 | ind += 1 |
---|
| 65 | |
---|
| 66 | # find the average value/2 of the top values |
---|
| 67 | y_half = y_sum/(2.0*ind) |
---|
| 68 | |
---|
| 69 | # defaults |
---|
| 70 | y_half_d = 0.0 |
---|
| 71 | ind = 0.0 |
---|
| 72 | # find indices where it crosses y = y_half. |
---|
| 73 | while (True): |
---|
[afeb37a] | 74 | # no need to check when ind == 0 |
---|
| 75 | ind += 1 |
---|
| 76 | # y value and ind just after passed the spot of the half height |
---|
| 77 | y_half_d = y[ind] |
---|
| 78 | if y[ind] < y_half: |
---|
| 79 | break |
---|
| 80 | |
---|
| 81 | # y value and ind just before passed the spot of the half height |
---|
| 82 | y_half_u = y[ind-1] |
---|
[0bf2c6f] | 83 | |
---|
| 84 | # get corresponding x values |
---|
| 85 | x_half_d = x[ind] |
---|
| 86 | x_half_u = x[ind-1] |
---|
| 87 | |
---|
| 88 | # calculate x at y = y_half using linear interpolation |
---|
| 89 | if y_half_u == y_half_d: |
---|
| 90 | x_half = (x_half_d + x_half_u)/2.0 |
---|
| 91 | else: |
---|
[d267aed] | 92 | x_half = (x_half_u * (y_half - y_half_d) \ |
---|
| 93 | + x_half_d*(y_half_u-y_half)) \ |
---|
[afeb37a] | 94 | /(y_half_u - y_half_d) |
---|
[0bf2c6f] | 95 | |
---|
| 96 | # multiply by 2 due to the beam profile is for half beam |
---|
| 97 | slit_length = 2.0 * x_half |
---|
| 98 | |
---|
| 99 | # set slit_length |
---|
| 100 | self.slit_length = slit_length |
---|
| 101 | return self.slit_length |
---|
[14e9eb3] | 102 | |
---|
[0bf2c6f] | 103 | def get_slit_length_unit(self): |
---|
| 104 | """ |
---|
[69fee24] | 105 | :return: the slit length unit. |
---|
[0bf2c6f] | 106 | """ |
---|
| 107 | return self.slit_length_unit |
---|