示例#1
0
    def _reduce_single_angle(self, scale=1):
        """
        Reduce a single angle.
        """
        n_spectra = self.reflected_beam.n_spectra
        n_tpixels = np.size(self.reflected_beam.m_topandtail, 1)
        n_ypixels = np.size(self.reflected_beam.m_topandtail, 2)

        # calculate omega and two_theta depending on the mode.
        mode = self.reflected_beam.mode

        # we'll need the wavelengths to calculate Q.
        wavelengths = self.reflected_beam.m_lambda
        m_twotheta = np.zeros((n_spectra, n_tpixels, n_ypixels))

        detector_z_difference = (self.reflected_beam.detector_z -
                                 self.direct_beam.detector_z)

        beampos_z_difference = (self.reflected_beam.m_beampos -
                                self.direct_beam.m_beampos)

        Y_PIXEL_SPACING = self.reflected_beam.cat.y_pixels_per_mm[0]

        total_z_deflection = (detector_z_difference +
                              beampos_z_difference * Y_PIXEL_SPACING)

        if mode in ['FOC', 'POL', 'POLANAL', 'MT']:
            # omega_nom.shape = (N, )
            omega_nom = np.degrees(
                np.arctan(total_z_deflection / self.reflected_beam.detector_y)
                / 2.)
            '''
            Wavelength specific angle of incidence correction
            This involves:
            1) working out the trajectory of the neutrons through the
            collimation system.
            2) where those neutrons intersect the sample.
            3) working out the elevation of the neutrons when they hit the
            sample.
            4) correcting the angle of incidence.
            '''
            speeds = general.wavelength_velocity(wavelengths)
            collimation_distance = self.reflected_beam.cat.collimation_distance
            s2_sample_distance = (self.reflected_beam.cat.sample_distance -
                                  self.reflected_beam.cat.slit2_distance)

            # work out the trajectories of the neutrons for them to pass
            # through the collimation system.
            trajectories = find_trajectory(collimation_distance / 1000., 0,
                                           speeds)

            # work out where the beam hits the sample
            res = parabola_line_intersection_point(s2_sample_distance / 1000,
                                                   0, trajectories, speeds,
                                                   omega_nom[:, np.newaxis])
            intersect_x, intersect_y, x_prime, elevation = res

            # correct the angle of incidence with a wavelength dependent
            # elevation.
            omega_corrected = omega_nom[:, np.newaxis] - elevation

            m_twotheta += np.arange(n_ypixels * 1.)[np.newaxis, np.newaxis, :]
            m_twotheta -= self.direct_beam.m_beampos[:, np.newaxis, np.newaxis]
            m_twotheta *= Y_PIXEL_SPACING
            m_twotheta += detector_z_difference
            m_twotheta /= (self.reflected_beam.detector_y[:, np.newaxis,
                                                          np.newaxis])
            m_twotheta = np.arctan(m_twotheta)
            m_twotheta = np.degrees(m_twotheta)

            # you may be reflecting upside down, reverse the sign.
            upside_down = np.sign(omega_corrected[:, 0])
            m_twotheta *= upside_down[:, np.newaxis, np.newaxis]
            omega_corrected *= upside_down[:, np.newaxis]

        elif mode in ['SB', 'DB']:
            # the angle of incidence is half the two theta of the reflected
            # beam
            omega = np.arctan(
                total_z_deflection / self.reflected_beam.detector_y) / 2.

            # work out two theta for each of the detector pixels
            m_twotheta += np.arange(n_ypixels * 1.)[np.newaxis, np.newaxis, :]
            m_twotheta -= self.direct_beam.m_beampos[:, np.newaxis, np.newaxis]
            m_twotheta += detector_z_difference
            m_twotheta -= (
                self.reflected_beam.detector_y[:, np.newaxis, np.newaxis] *
                np.tan(omega[:, np.newaxis, np.newaxis]))

            m_twotheta /= (self.reflected_beam.detector_y[:, np.newaxis,
                                                          np.newaxis])
            m_twotheta = np.arctan(m_twotheta)
            m_twotheta += omega[:, np.newaxis, np.newaxis]

            # still in radians at this point
            # add an extra dimension, because omega_corrected needs to be the
            # angle of incidence for each wavelength. I.e. should be
            # broadcastable to (N, T)
            omega_corrected = np.degrees(omega)[:, np.newaxis]
            m_twotheta = np.degrees(m_twotheta)
        '''
        --Specular Reflectivity--
        Use the (constant wavelength) spectra that have already been integrated
        over 2theta (in processnexus) to calculate the specular reflectivity.
        Beware: this is because m_topandtail has already been divided through
        by monitor counts and error propagated (at the end of processnexus).
        Thus, the 2theta pixels are correlated to some degree. If we use the 2D
        plot to calculate reflectivity
        (sum {Iref_{2theta, lambda}}/I_direct_{lambda}) then the error bars in
        the reflectivity turn out much larger than they should be.
        '''
        ydata, ydata_sd = EP.EPdiv(self.reflected_beam.m_spec,
                                   self.reflected_beam.m_spec_sd,
                                   self.direct_beam.m_spec,
                                   self.direct_beam.m_spec_sd)

        # calculate the 1D Qz values.
        xdata = general.q(omega_corrected, wavelengths)
        xdata_sd = (self.reflected_beam.m_lambda_fwhm /
                    self.reflected_beam.m_lambda)**2
        xdata_sd += (self.reflected_beam.domega[:, np.newaxis] /
                     omega_corrected)**2
        xdata_sd = np.sqrt(xdata_sd) * xdata
        '''
        ---Offspecular reflectivity---
        normalise the counts in the reflected beam by the direct beam
        spectrum this gives a reflectivity. Also propagate the errors,
        leaving the fractional variance (dr/r)^2.
        --Note-- that adjacent y-pixels (same wavelength) are correlated in
        this treatment, so you can't just sum over them.
        i.e. (c_0 / d) + ... + c_n / d) != (c_0 + ... + c_n) / d
        '''
        m_ref, m_ref_sd = EP.EPdiv(
            self.reflected_beam.m_topandtail,
            self.reflected_beam.m_topandtail_sd,
            self.direct_beam.m_spec[:, :, np.newaxis],
            self.direct_beam.m_spec_sd[:, :, np.newaxis])

        # you may have had divide by zero's.
        m_ref = np.where(np.isinf(m_ref), 0, m_ref)
        m_ref_sd = np.where(np.isinf(m_ref_sd), 0, m_ref_sd)

        # calculate the Q values for the detector pixels.  Each pixel has
        # different 2theta and different wavelength, ASSUME that they have the
        # same angle of incidence
        qx, qy, qz = general.q2(omega_corrected[:, :, np.newaxis], m_twotheta,
                                0, wavelengths[:, :, np.newaxis])

        reduction = {}
        reduction['x'] = self.x = xdata
        reduction['x_err'] = self.x_err = xdata_sd
        reduction['y'] = self.y = ydata / scale
        reduction['y_err'] = self.y_err = ydata_sd / scale
        reduction['omega'] = omega_corrected
        reduction['m_twotheta'] = m_twotheta
        reduction['m_ref'] = self.m_ref = m_ref
        reduction['m_ref_err'] = self.m_ref_err = m_ref_sd
        reduction['qz'] = self.m_qz = qz
        reduction['qx'] = self.m_qx = qx
        reduction['nspectra'] = self.n_spectra = n_spectra
        reduction['start_time'] = self.reflected_beam.start_time
        reduction['datafile_number'] = self.datafile_number = (
            self.reflected_beam.datafile_number)

        fnames = []
        datasets = []
        datafilename = self.reflected_beam.datafilename
        datafilename = os.path.basename(datafilename.split('.nx.hdf')[0])

        for i in range(n_spectra):
            data_tup = self.data(scanpoint=i)
            datasets.append(ReflectDataset(data_tup))

        if self.save:
            for i, dataset in enumerate(datasets):
                fname = '{0}_{1}.dat'.format(datafilename, i)
                fnames.append(fname)
                with open(fname, 'wb') as f:
                    dataset.save(f)

                fname = '{0}_{1}.xml'.format(datafilename, i)
                with open(fname, 'wb') as f:
                    dataset.save_xml(f, start_time=reduction['start_time'][i])

        reduction['fname'] = fnames
        return datasets, deepcopy(reduction)
示例#2
0
    def _reduce_single_angle(self, scale=1):
        """
        Reduce a single angle.
        """
        n_spectra = self.reflected_beam.n_spectra
        n_tpixels = np.size(self.reflected_beam.m_topandtail, 1)
        n_xpixels = np.size(self.reflected_beam.m_topandtail, 2)

        # we'll need the wavelengths to calculate Q.
        wavelengths = self.reflected_beam.m_lambda
        m_twotheta = np.zeros((n_spectra, n_tpixels, n_xpixels))

        detrot_difference = (self.reflected_beam.detector_z -
                             self.direct_beam.detector_z)

        # difference in pixels between reflected position and direct beam
        # at the two different detrots.
        QZ_PIXEL_SPACING = self.reflected_beam.cat.qz_pixel_size[0]
        dy = self.reflected_beam.detector_y

        # convert that pixel difference to angle (in small angle approximation)
        # higher `som` leads to lower m_beampos. i.e. higher two theta
        # is at lower pixel values
        beampos_2theta_diff = -(self.reflected_beam.m_beampos -
                                self.direct_beam.m_beampos)
        beampos_2theta_diff *= QZ_PIXEL_SPACING / dy[0]
        beampos_2theta_diff = np.degrees(beampos_2theta_diff)

        total_2theta_deflection = detrot_difference + beampos_2theta_diff

        # omega_nom.shape = (N, )
        omega_nom = total_2theta_deflection / 2.0
        omega_corrected = omega_nom[:, np.newaxis]

        m_twotheta += np.arange(n_xpixels * 1.0)[np.newaxis, np.newaxis, :]
        m_twotheta -= self.direct_beam.m_beampos[:, np.newaxis, np.newaxis]
        # minus sign in following line because higher two theta is at lower
        # pixel values
        m_twotheta *= -QZ_PIXEL_SPACING / dy[:, np.newaxis, np.newaxis]
        m_twotheta = np.degrees(m_twotheta)
        m_twotheta += detrot_difference

        # you may be reflecting upside down, reverse the sign.
        upside_down = np.sign(omega_corrected[:, 0])
        m_twotheta *= upside_down[:, np.newaxis, np.newaxis]
        omega_corrected *= upside_down[:, np.newaxis]
        """
        --Specular Reflectivity--
        Use the (constant wavelength) spectra that have already been integrated
        over 2theta (in processnexus) to calculate the specular reflectivity.
        Beware: this is because m_topandtail has already been divided through
        by monitor counts and error propagated (at the end of processnexus).
        Thus, the 2theta pixels are correlated to some degree. If we use the 2D
        plot to calculate reflectivity
        (sum {Iref_{2theta, lambda}}/I_direct_{lambda}) then the error bars in
        the reflectivity turn out much larger than they should be.
        """
        ydata, ydata_sd = EP.EPdiv(
            self.reflected_beam.m_spec,
            self.reflected_beam.m_spec_sd,
            self.direct_beam.m_spec,
            self.direct_beam.m_spec_sd,
        )

        # calculate the 1D Qz values.
        xdata = general.q(omega_corrected, wavelengths)
        xdata_sd = (self.reflected_beam.m_lambda_fwhm /
                    self.reflected_beam.m_lambda)**2
        xdata_sd += (self.reflected_beam.domega[:, np.newaxis] /
                     omega_corrected)**2
        xdata_sd = np.sqrt(xdata_sd) * xdata
        """
        ---Offspecular reflectivity---
        normalise the counts in the reflected beam by the direct beam
        spectrum this gives a reflectivity. Also propagate the errors,
        leaving the fractional variance (dr/r)^2.
        --Note-- that adjacent y-pixels (same wavelength) are correlated in
        this treatment, so you can't just sum over them.
        i.e. (c_0 / d) + ... + c_n / d) != (c_0 + ... + c_n) / d
        """
        m_ref, m_ref_sd = EP.EPdiv(
            self.reflected_beam.m_topandtail,
            self.reflected_beam.m_topandtail_sd,
            self.direct_beam.m_spec[:, :, np.newaxis],
            self.direct_beam.m_spec_sd[:, :, np.newaxis],
        )

        # you may have had divide by zero's.
        m_ref = np.where(np.isinf(m_ref), 0, m_ref)
        m_ref_sd = np.where(np.isinf(m_ref_sd), 0, m_ref_sd)

        # calculate the Q values for the detector pixels.  Each pixel has
        # different 2theta and different wavelength, ASSUME that they have the
        # same angle of incidence
        qx, qy, qz = general.q2(
            omega_corrected[:, :, np.newaxis],
            m_twotheta,
            0,
            wavelengths[:, :, np.newaxis],
        )

        reduction = {}
        reduction["x"] = self.x = xdata
        reduction["x_err"] = self.x_err = xdata_sd
        reduction["y"] = self.y = ydata / scale
        reduction["y_err"] = self.y_err = ydata_sd / scale
        reduction["omega"] = omega_corrected
        reduction["m_twotheta"] = m_twotheta
        reduction["m_ref"] = self.m_ref = m_ref
        reduction["m_ref_err"] = self.m_ref_err = m_ref_sd
        reduction["qz"] = self.m_qz = qz
        reduction["qx"] = self.m_qx = qx
        reduction["nspectra"] = self.n_spectra = n_spectra
        reduction["start_time"] = self.reflected_beam.start_time
        reduction[
            "datafile_number"] = self.datafile_number = self.reflected_beam.datafile_number

        fnames = []
        datasets = []
        datafilename = self.reflected_beam.datafilename
        datafilename = os.path.basename(datafilename.split(".nx.hdf")[0])

        for i in range(n_spectra):
            data_tup = self.data(scanpoint=i)
            datasets.append(ReflectDataset(data_tup))

        if self.save:
            for i, dataset in enumerate(datasets):
                fname = "{0}_{1}.dat".format(datafilename, i)
                fnames.append(fname)
                with open(fname, "wb") as f:
                    dataset.save(f)

                fname = "{0}_{1}.xml".format(datafilename, i)
                with open(fname, "wb") as f:
                    dataset.save_xml(f, start_time=reduction["start_time"][i])

        reduction["fname"] = fnames
        return datasets, deepcopy(reduction)
示例#3
0
文件: reduce.py 项目: llimeht/refnx
    def _reduce_single_angle(self, scale=1):
        """
        Reduce a single angle.
        """
        n_spectra = self.reflected_beam.n_spectra
        n_tpixels = np.size(self.reflected_beam.m_topandtail, 1)
        n_ypixels = np.size(self.reflected_beam.m_topandtail, 2)

        # calculate omega and two_theta depending on the mode.
        mode = self.reflected_beam.mode

        # we'll need the wavelengths to calculate Q.
        wavelengths = self.reflected_beam.m_lambda
        m_twotheta = np.zeros((n_spectra, n_tpixels, n_ypixels))

        if mode in ['FOC', 'POL', 'POLANAL', 'MT']:
            detector_z_difference = (self.reflected_beam.detector_z -
                                     self.direct_beam.detector_z)
            beampos_z_difference = (self.reflected_beam.m_beampos
                                    - self.direct_beam.m_beampos)

            total_z_deflection = (detector_z_difference
                                  + beampos_z_difference * Y_PIXEL_SPACING)

            # omega_nom.shape = (N, )
            omega_nom = np.degrees(np.arctan(total_z_deflection
                                   / self.reflected_beam.detector_y) / 2.)

            '''
            Wavelength specific angle of incidence correction
            This involves:
            1) working out the trajectory of the neutrons through the
            collimation system.
            2) where those neutrons intersect the sample.
            3) working out the elevation of the neutrons when they hit the
            sample.
            4) correcting the angle of incidence.
            '''
            speeds = general.wavelength_velocity(wavelengths)
            collimation_distance = self.reflected_beam.cat.collimation_distance
            s2_sample_distance = (self.reflected_beam.cat.sample_distance
                                  - self.reflected_beam.cat.slit2_distance)

            # work out the trajectories of the neutrons for them to pass
            # through the collimation system.
            trajectories = pm.find_trajectory(collimation_distance / 1000.,
                                              0, speeds)
            
            # work out where the beam hits the sample
            res = pm.parabola_line_intersection_point(s2_sample_distance / 1000,
                                                      0,
                                                      trajectories,
                                                      speeds,
                                                      omega_nom[:, np.newaxis])
            intersect_x, intersect_y, x_prime, elevation = res

            # correct the angle of incidence with a wavelength dependent
            # elevation.
            omega_corrected = omega_nom[:, np.newaxis] - elevation

        elif mode == 'SB' or mode == 'DB':
            omega = self.reflected_beam.M_beampos + self.reflected_beam.detectorZ[:, np.newaxis]
            omega -= self.direct_beam.M_beampos + self.direct_beam.detectorZ
            omega /= 2 * self.reflected_beam.detectorY[:, np.newaxis, np.newaxis]
            omega = np.arctan(omega)

            m_twotheta += np.arange(n_ypixels * 1.)[np.newaxis, np.newaxis, :] * Y_PIXEL_SPACING
            m_twotheta += self.reflected_beam.detectorZ[:, np.newaxis, np.newaxis]
            m_twotheta -= self.direct_beam.M_beampos[:, :, np.newaxis] + self.direct_beam.detectorZ
            m_twotheta -= self.reflected_beam.detectorY[:, np.newaxis, np.newaxis] * np.tan(omega[:, :, np.newaxis])

            m_twotheta /= self.reflected_beam.detectorY[:, np.newaxis, np.newaxis]
            m_twotheta = np.arctan(m_twotheta)
            m_twotheta += omega[:, :, np.newaxis]

        '''
        --Specular Reflectivity--
        Use the (constant wavelength) spectra that have already been integrated
        over 2theta (in processnexus) to calculate the specular reflectivity.
        Beware: this is because m_topandtail has already been divided through
        by monitor counts and error propagated (at the end of processnexus).
        Thus, the 2theta pixels are correlated to some degree. If we use the 2D
        plot to calculate reflectivity
        (sum {Iref_{2theta, lambda}}/I_direct_{lambda}) then the error bars in
        the reflectivity turn out much larger than they should be.
        '''
        ydata, ydata_sd = EP.EPdiv(self.reflected_beam.m_spec,
                                   self.reflected_beam.m_spec_sd,
                                   self.direct_beam.m_spec,
                                   self.direct_beam.m_spec_sd)

        # calculate the 1D Qz values.
        xdata = general.q(omega_corrected, wavelengths)
        xdata_sd = (self.reflected_beam.m_lambda_fwhm
                    / self.reflected_beam.m_lambda) ** 2
        xdata_sd += (self.reflected_beam.domega[:, np.newaxis]
                     / omega_corrected) ** 2
        xdata_sd = np.sqrt(xdata_sd) * xdata

        '''
        ---Offspecular reflectivity---
        normalise the counts in the reflected beam by the direct beam
        spectrum this gives a reflectivity. Also propagate the errors,
        leaving the fractional variance (dr/r)^2.
        --Note-- that adjacent y-pixels (same wavelength) are correlated in this
        treatment, so you can't just sum over them.
        i.e. (c_0 / d) + ... + c_n / d) != (c_0 + ... + c_n) / d
        '''
        m_ref, m_ref_sd = EP.EPdiv(self.reflected_beam.m_topandtail,
                                   self.reflected_beam.m_topandtail_sd,
                                   self.direct_beam.m_spec[:, :, np.newaxis],
                                   self.direct_beam.m_spec_sd[:, :, np.newaxis])

        # you may have had divide by zero's.
        m_ref = np.where(np.isinf(m_ref), 0, m_ref)
        m_ref_sd = np.where(np.isinf(m_ref_sd), 0, m_ref_sd)

        # calculate the Q values for the detector pixels.  Each pixel has
        # different 2theta and different wavelength, ASSUME that they have the
        # same angle of incidence
        qx, qy, qz = general.q2(omega_corrected[:, :, np.newaxis],
                                m_twotheta,
                                0,
                                wavelengths[:, :, np.newaxis])

        reduction = {}
        reduction['xdata'] = self.xdata = xdata
        reduction['xdata_sd'] = self.xdata_sd = xdata_sd
        reduction['ydata'] = self.ydata = ydata
        reduction['ydata_sd'] = self.ydata_sd = ydata_sd
        reduction['m_ref'] = self.m_ref = m_ref
        reduction['m_ref_sd'] = self.m_ref_sd = m_ref_sd
        reduction['qz'] = self.m_qz = qz
        reduction['qy'] = self.m_qy = qy
        reduction['nspectra'] = self.n_spectra = n_spectra
        reduction['datafile_number'] = self.datafile_number = (
            self.reflected_beam.datafile_number)

        fnames = []
        if self.save:
            for i in range(n_spectra):
                data_tup = self.data(scanpoint=i)
                dataset = ReflectDataset(data_tup)
                fname = 'PLP{0:07d}_{1}.dat'.format(self.datafile_number, i)
                fnames.append(fname)
                with open(fname, 'wb') as f:
                    dataset.save(f)
                fname = 'PLP{0:07d}_{1}.xml'.format(self.datafile_number, i)
                with open(fname, 'wb') as f:
                    dataset.save_xml(f)

        reduction['fname'] = fnames
        return deepcopy(reduction)
示例#4
0
def reduce_xrdml(f, bkg=None, scale=None, sample_length=None):
    """
    Reduces a Panalytical XRDML file

    Parameters
    ----------
    f: file-like object or string
        The specular reflectivity (XRDML) file of interest
    bkg: list
        A list of file-like objects or strings that contain background
        measurements. The background is assumed to have the same number of
        points as the specular reflectivity curve.  The backgrounds are
        averaged and subtracted from the specular reflectivity
    scale: float, None
        The direct beam intensity (cps). If `scale is None` then the dataset
        is scaled by the point with maximum intensity below Q = 0.0318 (Q_crit
        for Si at 8.048 keV).
    sample_length: None or float
        If None then no footprint correction is done. Otherwise the transverse
        footprint of the sample (mm).

    Returns
    -------
    dataset: refnx.dataset.ReflectDataset
        The specular reflectivity as a function of momentum transfer, Q.
    """

    spec = parse_xrdml_file(f)

    reflectivity = spec["intensities"] / spec["count_time"]
    reflectivity_s = np.sqrt(reflectivity) / spec["count_time"]

    # do the background subtraction
    if bkg is not None:
        bkgds = [parse_xrdml_file(fi) for fi in bkg]

        bkgd_refs = np.r_[[bkgd["intensities"] for bkgd in bkgds]]
        bkgd_refs_s = np.r_[[
            np.sqrt(bkgd["intensities"]) / bkgd["count_time"] for bkgd in bkgds
        ]]
        bkgd_refs_var = bkgd_refs_s**2
        weights = 1.0 / bkgd_refs_var
        numerator = np.sum(bkgd_refs * weights, axis=0)
        denominator = np.sum(weights, axis=0)

        total_bkgd = numerator / denominator
        total_bkgd_s = np.sqrt(1 / denominator)

        reflectivity, reflectivity_s = EP.EPsub(reflectivity, reflectivity_s,
                                                total_bkgd, total_bkgd_s)

    # work out the Q values
    qx, qy, qz = general.q2(
        spec["omega"],
        spec["twotheta"],
        np.zeros_like(spec["omega"]),
        spec["wavelength"],
    )

    # do a footprint correction
    if sample_length is not None:
        footprint_correction = general.beamfrac(
            np.array([XRR_BEAMWIDTH_SD]) * 2.35,
            np.array([sample_length]),
            spec["omega"],
        )
        reflectivity /= footprint_correction
        reflectivity_s /= footprint_correction

    # divide by the direct beam intensity
    # assumes that the direct beam intensity is enormous, so the counting
    # uncertainties in the scale factor are negligible.
    if scale is None:
        # no scale factor was specifed, so normalise by highest intensity point
        # below Qc for Silicon at 8.048 keV
        below_qc = qz[qz < 0.0318]
        if len(below_qc):
            scale = np.max(reflectivity[qz < 0.0318])

    reflectivity /= scale
    reflectivity_s /= scale

    d = ReflectDataset(data=(qz, reflectivity, reflectivity_s))

    return d
示例#5
0
def process_offspec(f):
    """
    Process a 2D XRDML file and return qx, qz, intensity, dintensity

    Parameters
    ----------
    f: str or file-like

    Returns
    -------
    qx, qz, intensity, dintensity
    """

    x = et.parse(f)
    root = x.getroot()
    ns = {"xrdml": "http://www.xrdml.com/XRDMeasurement/1.0"}
    query = {
        "intensities": ".//xrdml:intensities",
        "twotheta_start": ".//xrdml:positions[@axis='2Theta']"
        "/xrdml:startPosition",
        "twotheta_end": ".//xrdml:positions[@axis='2Theta']"
        "/xrdml:endPosition",
        "omega_start": ".//xrdml:positions[@axis='Omega']"
        "/xrdml:startPosition",
        "omega_end": ".//xrdml:positions[@axis='Omega']"
        "/xrdml:endPosition",
        "cnt_time": ".//xrdml:commonCountingTime",
        "kAlpha1": ".//xrdml:kAlpha1",
        "kAlpha2": ".//xrdml:kAlpha2",
        "ratio": ".//xrdml:ratioKAlpha2KAlpha1",
    }

    res = {key: root.findall(value, ns) for key, value in query.items()}

    kAlpha1 = float(res["kAlpha1"][0].text)
    kAlpha2 = float(res["kAlpha2"][0].text)
    ratio = float(res["ratio"][0].text)
    wavelength = (kAlpha1 + ratio * kAlpha2) / (1 + ratio)

    intensity = [
        np.fromstring(ints.text, sep=" ") for ints in res["intensities"]
    ]
    twotheta_starts = np.array(
        [np.fromstring(ints.text, sep=" ") for ints in res["twotheta_start"]])
    twotheta_ends = np.array(
        [np.fromstring(ints.text, sep=" ") for ints in res["twotheta_end"]])
    omega_starts = np.array(
        [np.fromstring(ints.text, sep=" ") for ints in res["omega_start"]])
    omega_ends = np.array(
        [np.fromstring(ints.text, sep=" ") for ints in res["omega_end"]])
    cnt_time = np.array(
        [np.fromstring(ints.text, sep=" ") for ints in res["cnt_time"]])

    intensity = np.array(intensity)
    dintensity = np.sqrt(intensity) / cnt_time
    intensity /= cnt_time

    omegas = []
    two_thetas = []

    for i in range(len(intensity)):
        omega = np.linspace(omega_starts[i], omega_ends[i],
                            np.size(intensity, 1))
        omegas.append(omega)
        two_theta = np.linspace(twotheta_starts[i], twotheta_ends[i],
                                np.size(intensity, 1))
        two_thetas.append(two_theta)

    omega = np.array(omegas)
    twotheta = np.array(two_thetas)
    qx, qy, qz = general.q2(omega, twotheta, 0, wavelength)

    return qx, qz, intensity, dintensity
示例#6
0
 def test_q2(self):
     qx, qy, qz = general.q2(1., 2., 0., 2.)
     assert_almost_equal(qz, 0.1096567037)
示例#7
0
文件: xray.py 项目: tjmurdoch/refnx
def reduce_xrdml(f, bkg=None, scale=1, sample_length=None):
    """
    Reduces a Panalytical XRDML file

    Parameters
    ----------
    f: file-like object or string
        The specular reflectivity (XRDML) file of interest
    bkg: list
        A list of file-like objects or strings that contain background
        measurements. The background is assumed to have the same number of
        points as the specular reflectivity curve.  The backgrounds are
        averaged and subtracted from the specular reflectivity
    scale: float
        The direct beam intensity (cps)
    sample_length: None or float
        If None then no footprint correction is done. Otherwise the transverse
        footprint of the sample (mm).

    Returns
    -------
    specular_q, specular_r, specular_dr: np.ndarray
        The specular reflectivity as a function of momentum transfer, Q.
    """

    spec = parse_xrdml_file(f)

    reflectivity = spec['intensities'] / spec['count_time']
    reflectivity_s = np.sqrt(reflectivity) / spec['count_time']

    # do the background subtraction
    if bkg is not None:
        bkgds = [parse_xrdml_file(fi) for fi in bkg]

        bkgd_refs = np.r_[[bkgd['intensities'] for bkgd in bkgds]]
        bkgd_refs_s = np.r_[[np.sqrt(bkgd['intensities']) / bkgd['count_time']
                             for bkgd in bkgds]]
        bkgd_refs_var = bkgd_refs_s ** 2
        weights = 1. / bkgd_refs_var
        numerator = np.sum(bkgd_refs * weights, axis=0)
        denominator = np.sum(weights, axis=0)

        total_bkgd = numerator / denominator
        total_bkgd_s = np.sqrt(1 / denominator)

        reflectivity, reflectivity_s = EP.EPsub(reflectivity,
                                                reflectivity_s,
                                                total_bkgd,
                                                total_bkgd_s)

    # work out the Q values
    qx, qy, qz = general.q2(spec['omega'],
                            spec['twotheta'],
                            np.zeros_like(spec['omega']),
                            spec['wavelength'])

    # do a footprint correction
    if sample_length is not None:
        footprint_correction = general.beamfrac(np.array([XRR_BEAMWIDTH_SD]) *
                                                2.35,
                                                np.array([sample_length]),
                                                spec['omega'])
        reflectivity /= footprint_correction
        reflectivity_s /= footprint_correction

    # divide by the direct beam intensity
    # assumes that the direct beam intensity is enormous, so the counting
    # uncertainties in the scale factor are negligible.
    reflectivity /= scale
    reflectivity_s /= scale

    return qz, reflectivity, reflectivity_s
示例#8
0
def process_offspec(f):
    """
    Process a 2D XRDML file and return qx, qz, intensity, dintensity

    Parameters
    ----------
    f: str or file-like

    Returns
    -------
    qx, qz, intensity, dintensity
    """

    x = et.parse(f)
    root = x.getroot()
    ns = {'xrdml': 'http://www.xrdml.com/XRDMeasurement/1.0'}
    query = {
        'intensities': './/xrdml:intensities',
        'twotheta_start': './/xrdml:positions[@axis=\'2Theta\']'
        '/xrdml:startPosition',
        'twotheta_end': './/xrdml:positions[@axis=\'2Theta\']'
        '/xrdml:endPosition',
        'omega_start': './/xrdml:positions[@axis=\'Omega\']'
        '/xrdml:startPosition',
        'omega_end': './/xrdml:positions[@axis=\'Omega\']'
        '/xrdml:endPosition',
        'cnt_time': './/xrdml:commonCountingTime',
        'kAlpha1': './/xrdml:kAlpha1',
        'kAlpha2': './/xrdml:kAlpha2',
        'ratio': './/xrdml:ratioKAlpha2KAlpha1'
    }

    res = {key: root.findall(value, ns) for key, value in query.items()}

    kAlpha1 = float(res['kAlpha1'][0].text)
    kAlpha2 = float(res['kAlpha2'][0].text)
    ratio = float(res['ratio'][0].text)
    wavelength = (kAlpha1 + ratio * kAlpha2) / (1 + ratio)

    intensity = [
        np.fromstring(ints.text, sep=' ') for ints in res['intensities']
    ]
    twotheta_starts = np.array(
        [np.fromstring(ints.text, sep=' ') for ints in res['twotheta_start']])
    twotheta_ends = np.array(
        [np.fromstring(ints.text, sep=' ') for ints in res['twotheta_end']])
    omega_starts = np.array(
        [np.fromstring(ints.text, sep=' ') for ints in res['omega_start']])
    omega_ends = np.array(
        [np.fromstring(ints.text, sep=' ') for ints in res['omega_end']])
    cnt_time = np.array(
        [np.fromstring(ints.text, sep=' ') for ints in res['cnt_time']])

    intensity = np.array(intensity)
    dintensity = np.sqrt(intensity) / cnt_time
    intensity /= cnt_time

    omegas = []
    two_thetas = []

    for i in range(len(intensity)):
        omega = np.linspace(omega_starts[i], omega_ends[i],
                            np.size(intensity, 1))
        omegas.append(omega)
        two_theta = np.linspace(twotheta_starts[i], twotheta_ends[i],
                                np.size(intensity, 1))
        two_thetas.append(two_theta)

    omega = np.array(omegas)
    twotheta = np.array(two_thetas)
    qx, qy, qz = general.q2(omega, twotheta, 0, wavelength)

    return qx, qz, intensity, dintensity
示例#9
0
def reduce_xrdml(f, bkg=None, scale=1, sample_length=None):
    """
    Reduces a Panalytical XRDML file

    Parameters
    ----------
    f: file-like object or string
        The specular reflectivity (XRDML) file of interest
    bkg: list
        A list of file-like objects or strings that contain background
        measurements. The background is assumed to have the same number of
        points as the specular reflectivity curve.  The backgrounds are
        averaged and subtracted from the specular reflectivity
    scale: float
        The direct beam intensity (cps)
    sample_length: None or float
        If None then no footprint correction is done. Otherwise the transverse
        footprint of the sample (mm).

    Returns
    -------
    specular_q, specular_r, specular_dr: np.ndarray
        The specular reflectivity as a function of momentum transfer, Q.
    """

    spec = parse_xrdml_file(f)

    reflectivity = spec['intensities'] / spec['count_time']
    reflectivity_s = np.sqrt(reflectivity) / spec['count_time']

    # do the background subtraction
    if bkg is not None:
        bkgds = [parse_xrdml_file(fi) for fi in bkg]

        bkgd_refs = np.r_[[bkgd['intensities'] for bkgd in bkgds]]
        bkgd_refs_s = np.r_[[
            np.sqrt(bkgd['intensities']) / bkgd['count_time'] for bkgd in bkgds
        ]]
        bkgd_refs_var = bkgd_refs_s**2
        weights = 1. / bkgd_refs_var
        numerator = np.sum(bkgd_refs * weights, axis=0)
        denominator = np.sum(weights, axis=0)

        total_bkgd = numerator / denominator
        total_bkgd_s = np.sqrt(1 / denominator)

        reflectivity, reflectivity_s = EP.EPsub(reflectivity, reflectivity_s,
                                                total_bkgd, total_bkgd_s)

    # work out the Q values
    qx, qy, qz = general.q2(spec['omega'], spec['twotheta'],
                            np.zeros_like(spec['omega']), spec['wavelength'])

    # do a footprint correction
    if sample_length is not None:
        footprint_correction = general.beamfrac(
            np.array([XRR_BEAMWIDTH_SD]) * 2.35, np.array([sample_length]),
            spec['omega'])
        reflectivity /= footprint_correction
        reflectivity_s /= footprint_correction

    # divide by the direct beam intensity
    # assumes that the direct beam intensity is enormous, so the counting
    # uncertainties in the scale factor are negligible.
    reflectivity /= scale
    reflectivity_s /= scale

    return qz, reflectivity, reflectivity_s
示例#10
0
 def test_q2(self):
     qx, qy, qz = general.q2(1., 2., 0., 2.)
     assert_almost_equal(qz, 0.1096567037)