def calc_EQ_Jacobian_dgs(*args): """ This function calculates the area of a polygon for use in the application of the Jacobian for DGS S(Q,E) data. @param args: A list of parameters used to calculate the area The following is a list of the arguments needed in their expected order 1. E_1 2. Q_1 3. E_2 4. Q_2 5. E_3 6. Q_3 7. E_4 8. Q_4 @type args: C{list} @return: The polygon areas @rtype: (C{nessi_list.NessiList}, C{nessi_list.NessiList}) """ import nessi_list import utils # Settle out the arguments to sensible names E1 = args[0] Q1 = args[1] E2 = args[2] Q2 = args[3] E3 = args[4] Q3 = args[5] E4 = args[6] Q4 = args[7] poly_size = 4 area = nessi_list.NessiList(len(E1)) area_err2 = nessi_list.NessiList(len(E1)) import itertools xvals = [xvals for xvals in itertools.izip(E1, E2, E3, E4, E1, E2)] yvals = [yvals for yvals in itertools.izip(Q1, Q2, Q3, Q4, Q1, Q2)] for x, y, i in itertools.izip(xvals, yvals, itertools.count()): xn = nessi_list.NessiList() xn.extend(x) yn = nessi_list.NessiList() yn.extend(y) area[i] = utils.calc_area_2D_polygon(xn, yn, poly_size) return (area, area_err2)
def ref_beamdiv_correct(attrs, pix_id, epsilon, cpix, **kwargs): """ @param attrs: The attribute list of a C{SOM.SOM} @type attrs: C{SOM.AttributeList} @param pix_id: The pixel ID for which the correction will be calculated @type pix_id: C{tuple} @param epsilon: The pixel spatial resolution in units of meters @type epsilon: C{float} @param cpix: The center pixel for the calculation @type cpix: C{float} @param kwargs: A list of keyword arguments that the function accepts: @kwarg det_secondary: The main sample to detector flightpath in meters. @type det_secondary: C{float} @kwarg pix_width: The width of a pixel in the high resolution direction @type pix_width: C{float} @return: The beam divergence correction to the scattering angle @type: float @raise RuntimeError: If the instrument name is not recognized. """ # Set instrument specific strings inst_name = attrs["instrument_name"] if inst_name == "REF_L": first_slit_size = "data-slit1_size" last_slit_size = "data-slit2_size" last_slit_dist = "data-slit2_distance" slit_dist = "data-slit12_distance" elif inst_name == "REF_M": first_slit_size = "data-slit1_size" last_slit_size = "data-slit3_size" last_slit_dist = "data-slit3_distance" slit_dist = "data-slit13_distance" else: raise RuntimeError("Do not know how to handle instrument %s" \ % inst_name) # Get sorting direction, y is True, x is False y_sort = attrs["ref_sort"] # Get keyword arguments det_secondary = kwargs.get("det_secondary") pix_width = kwargs.get("pix_width") # Check keyword arguments if det_secondary is None: det_secondary = attrs.instrument.get_det_secondary()[0] # This is currently set to the same number for both REF_L and REF_M if epsilon is None: epsilon = 0.5 * 1.3 * 1.0e-3 # Set the center pixel to something if cpix is None: cpix = 133.5 gamma_plus = math.atan2(0.5 * (attrs[first_slit_size][0] + \ attrs[last_slit_size][0]), attrs[slit_dist][0]) gamma_minus = math.atan2(0.5 * (attrs[first_slit_size][0] - \ attrs[last_slit_size][0]), attrs[slit_dist][0]) half_last_aperture = 0.5 * attrs[last_slit_size][0] neg_half_last_aperture = -1.0 * half_last_aperture last_slit_to_det = attrs[last_slit_dist][0] + det_secondary dist_last_aper_det_sin_gamma_plus = last_slit_to_det * math.sin(gamma_plus) dist_last_aper_det_sin_gamma_minus = last_slit_to_det * \ math.sin(gamma_minus) # Set the delta theta coordinates of the acceptance polygon accept_poly_x = nessi_list.NessiList() accept_poly_x.append(-1.0 * gamma_minus) accept_poly_x.append(gamma_plus) accept_poly_x.append(gamma_plus) accept_poly_x.append(gamma_minus) accept_poly_x.append(-1.0 * gamma_plus) accept_poly_x.append(-1.0 * gamma_plus) accept_poly_x.append(accept_poly_x[0]) # Set the z coordinates of the acceptance polygon accept_poly_y = nessi_list.NessiList() accept_poly_y.append(half_last_aperture - \ dist_last_aper_det_sin_gamma_minus + epsilon) accept_poly_y.append(half_last_aperture + \ dist_last_aper_det_sin_gamma_plus + epsilon) accept_poly_y.append(half_last_aperture + \ dist_last_aper_det_sin_gamma_plus - epsilon) accept_poly_y.append(neg_half_last_aperture + \ dist_last_aper_det_sin_gamma_minus - epsilon) accept_poly_y.append(neg_half_last_aperture - \ dist_last_aper_det_sin_gamma_plus - epsilon) accept_poly_y.append(neg_half_last_aperture - \ dist_last_aper_det_sin_gamma_plus + epsilon) accept_poly_y.append(accept_poly_y[0]) if y_sort: cur_index = pix_id[1][1] if pix_width is None: cur_offset = attrs.instrument.get_y_pix_offset(pix_id) next_id = (pix_id[0], (pix_id[1][0], pix_id[1][1]+1)) next_offset = attrs.instrument.get_y_pix_offset(next_id) else: cur_index = pix_id[1][0] if pix_width is None: cur_offset = attrs.instrument.get_x_pix_offset(pix_id) next_id = (pix_id[0], (pix_id[1][0]+1, pix_id[1][1])) next_offset = attrs.instrument.get_x_pix_offset(next_id) if pix_width is None: pix_width = math.fabs(next_offset - cur_offset) # Set the z band for the pixel xMinus = (cur_index - cpix - 0.5) * pix_width xPlus = (cur_index - cpix + 0.5) * pix_width # Calculate the intersection yLeftCross = -1 yRightCross = -1 xI = accept_poly_x[0] yI = accept_poly_y[0] int_poly_x = nessi_list.NessiList() int_poly_y = nessi_list.NessiList() for i in xrange(len(accept_poly_x)): xF = accept_poly_y[i] yF = accept_poly_x[i] if xI < xF: if xI < xMinus and xF >= xMinus: yLeftCross = yI + (yF - yI) * (xMinus - xI) / (xF - xI) int_poly_x.append(yLeftCross) int_poly_y.append(xMinus) if xI < xPlus and xF >= xPlus: yRightCross = yI + (yF - yI) * (xPlus - xI) / (xF - xI); int_poly_x.append(yRightCross) int_poly_y.append(xPlus) else: if xF < xPlus and xI >= xPlus: yRightCross = yI + (yF - yI) * (xPlus - xI) / (xF - xI); int_poly_x.append(yRightCross) int_poly_y.append(xPlus) if xF < xMinus and xI >= xMinus: yLeftCross = yI + (yF - yI) * (xMinus - xI) / (xF - xI); int_poly_x.append(yLeftCross) int_poly_y.append(xMinus) # This catches points on the polygon inside the range of interest if xF >= xMinus and xF < xPlus: int_poly_x.append(yF) int_poly_y.append(xF) xI = xF yI = yF if len(int_poly_x) > 2: int_poly_x.append(int_poly_x[0]) int_poly_y.append(int_poly_y[0]) int_poly_x.append(int_poly_x[1]) int_poly_y.append(int_poly_y[1]) else: # Intersection polygon is NULL, point or line, so has no area # Therefore there is no angle correction return None # Calculate intersection polygon aread import utils area = utils.calc_area_2D_polygon(int_poly_x, int_poly_y, len(int_poly_x) - 2, True) return __calc_center_of_mass(int_poly_x, int_poly_y, area)