Example #1
0
def Save(nxs_filename, recording_dir, fast, working_dir, verbose):
    '''
    Use the PyNexus library to convert the Nexus file into a .dat file.

    Parameters
    ----------
    nxs_filename : str
        nexus filename
    recording_dir : str
        directory where the nexus file is stored
    fast : bool
        triger fast extract of the nexus file
    working_dir : str
        directory where the treated files will be stored
    verbose : bool
        verbose mode
    '''
    savename = working_dir + nxs_filename[:nxs_filename.rfind('.nxs')]

    # We assume extraction was already checked with Extract
    nxs_path = recording_dir + nxs_filename
    nexus = PN.PyNexusFile(nxs_path, fast=fast)

    # Get stamps and Data
    stamps, data = nexus.extractData()

    f = io.StringIO()
    # Avoid printing sensors in the notebook
    with redirect_stdout(f):
        old_nexus_filename = nexus.filename
        # Save in working dir
        nexus.filename = working_dir + nxs_filename
        nexus.savePointExtractedData((stamps, data))
        nexus.saveOneDExtractedData((stamps, data))
        nexus.filename = old_nexus_filename
    out = f.getvalue()

    nexus.close()

    if verbose:
        print('\t. 0D data saved in:')
        print('\t%s.dat' % savename)
        print('\t. Spectrum(s) saved in:')
        print('\t%s_fluospectrum*.mat' % savename)
Example #2
0
def Extract(nxs_filename, recording_dir, xLabel, yLabel, show_data_stamps,
            verbose):
    '''
    Extract the sensors.

    Parameters
    ----------
    nxs_filename : str
        nexus filename
    recording_dir : str
        directory where the nexus file is stored
    xLabel : str
        exact name of the x sensor, as it appears in the data stamps
    yLabel : str
        exact name of the y sensor, as it appears in the data stamps        
    show_data_stamps : bool, optional
        print the list of sensors from the nexus file
    verbose : bool, optional
        verbose mode

    Returns
    -------
    array_like
        xData, an array containing the list of x values
    array_like
        yData, an array containing the list of y values

    Raises
    ------
    SystemExit('Nexus not found')
        when Nexus file not found
    SystemExit('Sensor not found')
        when sensor not found
    '''

    nxs_path = recording_dir + nxs_filename

    if not os.path.isfile(nxs_path):
        print(PN._RED + 'Scan %s seems not to exist in recording directory' %
              (nxs_filename) + PN._RESET)
        print(('\t\t recording directory : ' + recording_dir))
        sys.exit('Nexus not found')

    else:
        if verbose: print(PN._BLUE + " - Open Nexus Data File :" + PN._RESET)
        if verbose: print('\t' + nxs_path)
        try:
            nexus = PN.PyNexusFile(nxs_path, fast=True)
        except:
            print(PN._RED,
                  '\t Nexus file seems not to exist or is not correct',
                  PN._RESET)
            sys.exit('Nexus not found')

        nbpts = np.int(nexus.get_nbpts())
        if verbose: print("\t. Number of data points: ", nbpts)

        # Get stamps and Data
        stamps0D, data0D = nexus.extractData('0D')
        nexus.close()

        # Explore stamps
        if show_data_stamps: print("\t. Available Counters:")
        for i in range(len(stamps0D)):
            if stamps0D[i][1] is not None:
                if show_data_stamps:
                    print("\t\t", i, ' -------> ', stamps0D[i][1])
            else:
                if show_data_stamps:
                    print("\t\t", i, ' -------> ', stamps0D[i][0])

        sensor_list = [
            stamps0D[i][0] if stamps0D[i][1] == None else stamps0D[i][1]
            for i in range(len(stamps0D))
        ]

        if xLabel in sensor_list:
            xArg = sensor_list.index(xLabel)
        else:
            print(PN._RED, '\t Sensor %s is not in the sensor list' % (xLabel),
                  PN._RESET)
            sys.exit('Sensor not found')

        if yLabel in sensor_list:
            yArg = sensor_list.index(yLabel)
        else:
            print(PN._RED, '\t Sensor %s is not in the sensor list' % (yLabel),
                  PN._RESET)
            sys.exit('Sensor not found')

        # Find positions of non Nan values based on data0D[xArg]
        args = ~np.isnan(data0D[xArg])

        # Take only the non NaN values
        xData = data0D[xArg][args]
        yData = data0D[yArg][args]

        return xData, yData
Example #3
0
def Extract(nxs_filename, recording_dir, fast, show_data_stamps, verbose):
    '''
    Extract the isotherm.

    Parameters
    ----------
    nxs_filename : str
        nexus filename
    recording_dir : str
        directory where the nexus file is stored
    fast : bool
        triger fast extract of the nexus file
    show_data_stamps : bool
        print the list of sensors from the nexus file
    verbose : bool
        verbose mode

    Returns
    -------
    array_like
        area, an array containing the list of area values
    array_like
        pressure, an array containing the list of pressure values 
    array_like
        time, an array containing the list of time values      

    Raises
    ------
    SystemExit('Nexus not found')
        when Nexus file not found
    '''

    nxs_path = recording_dir + nxs_filename

    if not os.path.isfile(nxs_path):
        print(PN._RED + 'Scan %s seems not to exist in recording directory' %
              (nxs_filename) + PN._RESET)
        print(('\t\t recording directory : ' + recording_dir))
        sys.exit('Nexus not found')

    else:
        column_pi = None
        column_area = None
        column_time = None
        if verbose: print(PN._BLUE + " - Open Nexus Data File :" + PN._RESET)
        if verbose: print('\t' + nxs_path)
        try:
            nexus = PN.PyNexusFile(nxs_path, fast=fast)
        except:
            print(PN._RED,
                  '\t Nexus file seems not to exist or is not correct',
                  PN._RESET)
            sys.exit('Nexus not found')

        nbpts = np.int(nexus.get_nbpts())
        if verbose: print("\t. Number of data points: ", nbpts)

        # Get stamps and Data
        stamps, data = nexus.extractData('0D')
        nexus.close()

        # Explore stamps
        if show_data_stamps: print("\t. Available Counters:")
        for i in range(len(stamps)):
            if stamps[i][1] is not None:
                if show_data_stamps:
                    print("\t\t", i, ' -------> ', stamps[i][1])
            else:
                if show_data_stamps:
                    print("\t\t", i, ' -------> ', stamps[i][0])

        # Find columns
        for i in range(len(stamps)):
            if stamps[i][1] is not None:
                if stamps[i][1].lower() == 'surfacepressure':
                    column_pi = i
                if stamps[i][1].lower() == 'areapermolecule':
                    column_area = i
            if stamps[i][0].find('sensorsRelTimestamps') > -1:
                column_time = i

        if column_time is not None:
            if column_area is not None:
                if column_pi is not None:
                    cont = True
        if cont:
            if verbose:
                print('\t. Area per molecule found column %d' % (column_area))
                print('\t. Surface pressure per molecule found column %d' %
                      (column_pi))
                print('\t. Time per molecule found column %d' % (column_time))

                # Find positions of non Nan values based on data[0]
                args = ~np.isnan(data[0])

                # Get first and last position of the non NaN values
                print('\t. Valid data between points %d and %d' %
                      (np.argmax(args), len(args) - np.argmax(args[::-1]) - 1))

        area = data[column_area]
        pressure = data[column_pi]
        time = data[column_time]

        return area, pressure, time
Example #4
0
def Extract_channel0(nxs_filename='SIRIUS_test.nxs',
                     recording_dir='',
                     binsize=10,
                     logx=False,
                     logy=False,
                     logz=False,
                     nblevels=50,
                     cmap='jet',
                     show_data_stamps=True,
                     verbose=True):
    '''
    Extract the channel of the Vineyard's peak.

    Parameters
    ----------
    nxs_filename : str
        nexus filename
    recording_dir : str
        directory where the nexus file is stored
    binsize : int, optional
        size in pixels of the vertical binning (along qz)
    logx : bool, optional
        log on the x axis of the integrated profile
    logy : bool, optional
        log on the y axis of the integrated profile
    logz : bool, optional
        log on the image
    nblevels : int, optional
        number of color levels for the image display
    cmap : str, optional
        colormap of the image
    show_data_stamps : bool, optional
        print the list of sensors from the nexus file
    verbose : bool, optional
        verbose mode


    Returns
    -------
    int
        channel0, the vertical channel corresponding to the Vineyard's peak

    Raises
    ------
    SystemExit('Nexus not found')
        when Nexus file is not found
    SystemExit('Pilatus not found')
        when Pilatus is not found
    SystemExit('No sensor found')
        when delta and qxy are not found
    SystemExit('gamma not found')
        when gamma not found and computeqz is True
    '''

    nxs_path = recording_dir + nxs_filename

    if not os.path.isfile(nxs_path):
        print(PN._RED + 'Scan %s seems not to exist in recording directory' %
              (nxs_filename) + PN._RESET)
        print(('\t\t recording directory : ' + recording_dir))
        sys.exit('Nexus not found')

    else:

        # Extract sensors from the Pilatus
        column_z = None
        column_qxy = None
        column_delta = None
        column_pi = None
        column_area = None
        column_gamma = None

        if verbose: print(PN._BLUE + " - Open Nexus Data File :" + PN._RESET)
        if verbose: print('\t' + nxs_path)
        try:
            nexus = PN.PyNexusFile(nxs_path, fast=True)
        except:
            print(PN._RED,
                  '\t Nexus file seems not to exist or is not correct',
                  PN._RESET)
            sys.exit('Nexus not found')

        nbpts = np.int(nexus.get_nbpts())
        if verbose: print("\t. Number of data points: ", nbpts)

        # Get stamps
        stamps = nexus.extractStamps()
        if show_data_stamps: print("\t. Available Counters:")
        for i in range(len(stamps)):
            if stamps[i][1] is not None:
                if show_data_stamps:
                    print("\t\t", i, ' -------> ', stamps[i][1])
                if stamps[i][1].lower() == 'pilatus':
                    column_z = i
            else:
                if show_data_stamps:
                    print("\t\t", i, ' -------> ', stamps[i][0])

        # Extract 0D data
        stamps0D, data = nexus.extractData('0D')

        # Find columns
        for i in range(len(stamps0D)):
            if stamps0D[i][1] is not None:
                if stamps0D[i][1].lower() == 'delta':
                    column_delta = i
                if stamps0D[i][1].lower() == 'qxy':
                    column_qxy = i
                if stamps0D[i][1].lower() == 'surfacepressure':
                    column_pi = i
                if stamps0D[i][1].lower() == 'areapermolecule':
                    column_area = i
                if stamps0D[i][1].lower() == 'gamma':
                    column_gamma = i

        # Check that Pilatus data are present (images)
        if column_z is not None:
            if verbose:
                print('\t. Pilatus data found, (column %d, alias %s)' %
                      (column_z, stamps[column_z][1]))
        else:
            print(PN._RED, '\t. No pilatus data found', PN._RESET)
            nexus.close()
            sys.exit('Pilatus not found')

        # Check what is the x input (qxy or delta)
        if column_qxy is None:
            if column_delta is None:
                print(PN._RED,
                      '\t. No usual actuator for GIXD found, stop here',
                      PN._RESET)
                sys.exit('No sensor found')
            else:
                column_x = column_delta
                if verbose:
                    print('\t. delta data found, (column %d, alias %s)' %
                          (column_x, stamps[column_x][1]))
        else:
            column_x = column_qxy
            if verbose:
                print('\t. qxy data found, (column %d, alias %s)' %
                      (column_x, stamps[column_x][1]))

        # Find positions of non Nan values based on data[0]
        args = ~np.isnan(data[0])

        # Get first and last position of the non NaN values
        if verbose:
            print('\t. Valid data between points %d and %d' %
                  (np.argmax(args), len(args) - np.argmax(args[::-1]) - 1))

        # Compute and print mean values
        if column_pi is not None:
            mean_pi = data[column_pi][args].mean()
            if verbose:
                print(
                    '\t. Surface pressure data found, mean value %3.4g ± %3.4g mN/m'
                    % (mean_pi, data[column_pi][args].std()))
        else:
            print('\t. No surface pressure data found')
            mean_pi = None

        if column_area is not None:
            mean_area = data[column_area][args].mean()
            if verbose:
                print(
                    '\t. Area per molecule data found, mean value %3.4g ± %3.4g nm2 per molecule'
                    % (mean_area, data[column_area][args].std()))
        else:
            print('\t. No area per molecule data found')
            mean_area = None

        if column_gamma is not None:
            mean_gamma = data[column_gamma][args].mean()
            if verbose:
                print('\t. Gamma motor data found, mean value %3.4g deg' %
                      (mean_gamma))
        else:
            print('\t. No gamma motor data found')
            mean_gamma = None
            if computeqz:
                print(
                    '\t. gamma is required to compute qz. Add gamma to the sensors.'
                )
                nexus.close()
                sys.exit('gamma not found')

        # Load images
        stamps, images = nexus.extractData('2D')

        # Get positions of the dead pixels
        dead_pixels = Check_dead_pixels.get_dead_pixels()

        daty = []
        datyTop = []
        datyBottom = []
        datyFirstQuarter = []
        mat = []

        # Loop over all the non Nan values
        for i in np.arange(len(args))[args]:
            sys.stdout.write(
                'Treat image %d/%d                                                                 \r'
                % (i + 1, nbpts))
            sys.stdout.flush()

            image = images[0][i]

            for ii, jj in dead_pixels:
                image[ii, jj] = 0.0

            # Keep only the ROI corresponding to the Soller
            ROI = [510, 350, 130, 692]
            image = image[ROI[1]:ROI[1] + ROI[3], ROI[0]:ROI[0] + ROI[2]]

            # Replace the intensity of the dead zones with a value of 0
            image = np.where(image < 0., 0., image)

            # Rod (integration along the horizontal axis)
            rod = image.sum(axis=1)

            # Final image with rods stacked (dim: nb_angle x vertical_dim_ROI)
            mat.append(rod)

            # Integrated rods
            daty.append(rod.sum())

            # Integrate the rod on different parts of the detector only
            datyTop.append(rod[0:np.int(ROI[3] / 2)].sum())
            datyBottom.append(rod[np.int(ROI[3] / 2):ROI[3]].sum())
            datyFirstQuarter.append(rod[np.int(3 * ROI[3] / 4):ROI[3]].sum())

            sys.stdout.write(
                '                                                                                  \r'
            )
            sys.stdout.flush()

        # Convert in numpy array
        daty = np.array(daty)
        datyTop = np.array(datyTop)
        datyBottom = np.array(datyBottom)
        datyFirstQuarter = np.array(datyFirstQuarter)
        mat = np.array(mat)

        # Extract x values (qxy or delta)
        x = data[column_x]
        x = x[args]

        # Bin the matrix, return binned vertical channels and binned matrix
        ch_binned, mat_binned = Groupe(mat, binsize=binsize)

        # Create Graph
        # The graph has to be splitted into two parts for good rendering in PDF
        fig = plt.figure(1, figsize=(12, 5))
        fig.subplots_adjust(hspace=0.4, wspace=0.4, bottom=0.16)
        ax1 = fig.add_subplot(121)
        ax2 = fig.add_subplot(122)

        # Plot the integrated spectra
        error = np.sqrt(daty)

        if (not logx) and (not logy):
            ax1.errorbar(x, daty, yerr=error, fmt='ro', label="full")
            ax1.plot(x, datyTop, 'k-', label='top')
            ax1.plot(x, datyBottom, 'b-', label='bottom')
            ax1.plot(x, datyFirstQuarter, 'r-', label='bottom quarter')
            ax1.legend()
        elif logx and (not logy):
            ax1.semilogx(x, daty, 'ro')
        elif (not logx) and (logy):
            ax1.semilogy(x, daty, 'ro')
        elif logx and (logy):
            ax1.loglog(x, daty, 'ro')
        ax1.set_xlabel(stamps0D[column_x][1] + ' (' + stamps0D[column_x][2] +
                       ')',
                       labelpad=13,
                       fontsize='large')
        ax1.set_ylabel("Qz integrated intensity",
                       labelpad=13,
                       fontsize='large')

        # Plot the matrix
        if logz:
            ax2.contourf(x, ch_binned, np.log(mat_binned.transpose()))
        else:
            zmax = mat_binned.max()
            zmin = mat_binned.min()
            ax2.contourf(x,
                         ch_binned, (mat_binned.transpose()),
                         levels=np.linspace(zmin, zmax, nblevels),
                         cmap=cmap)

        ax2.set_ylabel(r'$vertical\ channels$', fontsize='large')
        ax2.set_xlabel(stamps0D[column_x][1] + ' (' + stamps0D[column_x][2] +
                       ')',
                       labelpad=13,
                       fontsize='large')

        if column_pi is not None:
            fig.text(.04,
                     .05,
                     r'$\pi = %3.4gmN.m^{-1}$' % (mean_pi),
                     fontsize='large',
                     color='red')
        if column_gamma is not None:
            fig.text(.96,
                     .05,
                     r'$\gamma = %3.4g deg$' % (mean_gamma),
                     fontsize='large',
                     color='red',
                     horizontalalignment='right')

        rod = mat.sum(axis=0)
        fig.suptitle(nxs_filename[nxs_filename.rfind('/') + 1:],
                     fontsize='x-large')
        plt.show()

        fig = plt.figure(1, figsize=(12, 8))
        ax3 = fig.add_axes([0.125, 0.13, 0.775, 0.37])
        ax3.plot(rod)

        # Extract the channel of the Vineyard peak
        channel0 = rod.argmax()

        ax3.text(channel0 * 0.95,
                 rod[channel0],
                 'Channel of Vineyard Peak ($\mathregular{\\theta_c}$): %d' %
                 (int(channel0)),
                 fontsize='x-large',
                 horizontalalignment='right',
                 color='red')
        plt.plot((channel0, channel0),
                 (rod[channel0] * 1.1, rod[channel0] * 1.3),
                 'r-',
                 lw=2)
        ax3.set_xlabel('channels', fontsize='large')
        ax3.set_ylabel('Q$\mathregular{_{xy}}$ - Integrated Intensity',
                       fontsize='large')
        plt.show()

        print(PN._RED, 'Data not saved. To save data, run a GIXD on the scan.',
              PN._RESET)
        print(PN._RED, 'Channel0: %g' % channel0, PN._RESET)

    return channel0
Example #5
0
def Save(x, daty, datyTop, datyBottom, datyFirstQuarter, mat, moytocreate,
         mean_gamma, column_x, channel0, thetazfactor, wavelength, thetac,
         nxs_filename, recording_dir, working_dir, computeqz, verbose):
    '''
    Save GIXD data.
    XXX_1D.mat: each line corresponds to a position of delta.
                It is the matrix corresponding to the image displayed.
    XXX_1D.dat: each line corresponds to a position of delta.
                It contains the value of each sensor, and integration along qz:
                - QzIntegrated : over the whole detector,
                - QzIntegratedTop : over its top half,
                - QzIntegratedBottom : over its bottom half,
                - QzIntegratedBottomQuarter : over its bottom quarter.
    Binned data:
        - XXX_1D.matNN : binning of the matrix, with NN the number of points per bin.
        - XXX_1D_qz.datNN : to convert bin number to qz in XXX_1D.matNN.
        - XXX_1D.moyNN : a more convenient way to represent the binned matrices
                         with a 3 columns (qxy, qz, intensity) display.

    Parameters
    ----------
    x : array_like
        either qxy (nm^-1) or delta (deg) values
    daty : array_like
        rods integrated over the whole vertical axis of the detector            
    datyTop : array_like
        rods integrated over the top half vertical axis of the detector            
    datyBottom : array_like
        rods integrated over the bottom half vertical axis of the detector     
    datyFirstQuarter : array_like
        rods integrated over the bottom quarter vertical axis of the detector                        
    mat : array_like
        Original matrix corresponding to the GIXD image
    moytocreate : array_like, optional
        binsizes to be saved    
    mean_gamma : float or None
        the average of gamma (deg) over the scan     
    column_x : int
        the column corresponding to the x values in stamps0D
    channel0 : float
        vertical channel corresponding to the Vineyard's peak
    thetazfactor : float
        factor for conversion from channel to radian in the vertical direction (rad/channel)
    wavelength : float
        wavelength in nm
    thetac : float
        critical angle in rad  
    nxs_filename : str
        nexus filename        
    recording_dir : str
        directory where the nexus file is stored
    working_dir : str, optional
        directory where the treated files will be stored            
    computeqz : bool
        switch from pixels to qz in the vertical direction
    verbose : bool, optional
        verbose mode            
    '''

    # Extract 0D data
    nxs_path = recording_dir + nxs_filename
    nexus = PN.PyNexusFile(nxs_path)
    stamps0D, data = nexus.extractData('0D')
    nbpts = np.int(nexus.get_nbpts())

    # Find positions of non Nan values based on data[0]
    args = ~np.isnan(data[0])

    # Create Save Name
    savename = working_dir + nxs_filename[:nxs_filename.rfind('.nxs')] + '_1D'

    # Save the original matrix
    np.savetxt(savename + '.mat', mat)
    if verbose: print('\t. Original, non binned, matrix saved in:')
    if verbose: print("\t", savename + '.mat')

    # Take care of scalar data
    tosave = np.zeros((daty.shape[0], 4), float)
    tosave[:, 0] = daty
    tosave[:, 1] = datyTop
    tosave[:, 2] = datyBottom
    tosave[:, 3] = datyFirstQuarter

    # Concatenate scalar data
    data = np.array(data).transpose()
    data = data[args, :]
    data_tosave = np.concatenate((data, tosave), axis=1)

    f = open(savename + '.dat', "w")

    # Create and save header
    s = ""
    for i in range(len(stamps0D)):
        if stamps0D[i][1] is not None:
            s = s + stamps0D[i][1] + '\t'
        else:
            s = s + stamps0D[i][0] + '\t'
    s = s + 'QzIntegrated \t QzIntegratedTop \t QzIntegratedBottom \tQzIntegratedBottomQuarter\n'
    f.write(s)

    # Save data
    for i in range(data_tosave.shape[0]):
        s = ""
        for j in range(data_tosave.shape[1]):
            s = s + str(data_tosave[i, j]) + '\t'
        f.write(s + '\n')
    f.close()

    if verbose: print('\t. Scalar data saved in:')
    if verbose: print("\t", savename + '.dat')

    # Save as moy
    for binsize in moytocreate:

        # Bin the matrix
        ch_binned, mat_binned = Groupe(mat, binsize=binsize)

        # Extract y values (qz or vertical channels)
        if computeqz:
            # Compute and return qz
            thetaz = thetac + (mean_gamma * np.pi /
                               180.0) + (channel0 - ch_binned) * thetazfactor
            y = 2.0 * np.pi * np.sin(thetaz) / wavelength
        else:
            # Return the vertical channels
            y = ch_binned

        # Create the moy images
        moy = np.zeros((nbpts * y.shape[0], 3), float)
        index = 0
        for i in range(data.shape[0]):
            for j in range(y.shape[0]):
                moy[index, 0] = x[i]
                moy[index, 1] = y[j]
                moy[index, 2] = mat_binned[i, j]
                index = index + 1

        f = open(savename + '.moy' + str(binsize), 'w')
        f.write(stamps0D[column_x][1] + '\t' + 'Qz \t Intensity\n')
        for i in range(moy.shape[0]):
            f.write(
                str(moy[i, 0]) + '\t' + str(moy[i, 1]) + '\t' +
                str(moy[i, 2]) + '\n')
        f.close()

        # Save the matrix
        np.savetxt(savename + '.mat' + str(binsize), mat_binned)

        # Save the Qz
        if computeqz:
            np.savetxt(savename + '_qz.dat' + str(binsize), y)
            if verbose: print('\t. qz values saved in:')
            if verbose: print('\t' + savename + '_qz.dat' + str(binsize))

        if verbose:
            print('\t. Binned matrix saved in:')
            print("\t", savename + '.mat' + str(binsize))

            print('\t. XYZ data saved in:')
            print("\t", savename + '.moy' + str(binsize))

    plt.show()
Example #6
0
def Extract(nxs_filename, recording_dir, channel0, thetazfactor, wavelength,
            thetac, binsize, computeqz, show_data_stamps, verbose):
    '''
    Extract the nexus scan and return useful quantities for GIXD.

    Parameters
    ----------
    nxs_filename : str
        nexus filename
    recording_dir : str
        directory where the nexus file is stored
    channel0 : float
        vertical channel corresponding to the Vineyard's peak
    thetazfactor : float
        factor for conversion from channel to radian in the vertical direction (rad/channel)
    wavelength : float
        wavelength in nm
    thetac : float
        critical angle in rad
    binsize : int
        size in pixels of the vertical binning (along qz)
    computeqz : bool
        switch from pixels to qz in the vertical direction
    show_data_stamps : bool
        print the list of sensors from the nexus file
    verbose : bool
        verbose mode


    Returns
    -------
    array_like
        x, an array containing either qxy (nm^-1) values, if qxy is available in the list of sensors,
        or delta (deg) if not
    array_like
        y, an array containing either qz (nm^-1) values, if computeqz is True,
        or vertical channels if not        
    str
        xlabel, indicating whether x corresponds to qxy or delta (useful for plot)            
    str
        ylabel, indicating whether y corresponds to qz or channels (useful for plot)           
    int
        column_x, the column corresponding to the x values in stamps0D (useful for save)            
    array_like
        daty, rods integrated over the whole vertical axis of the detector            
    array_like
        datyTop, rods integrated over the top half vertical axis of the detector            
    array_like
        datyBottom, rods integrated over the bottom half vertical axis of the detector     
    array_like
        datyFirstQuarter, rods integrated over the bottom quarter vertical axis of the detector                        
    array_like
        mat, each line corresponds to a position of delta.
        It is the matrix corresponding to the image displayed in plot            
    array_like
        mat_binned, original matrix after binning            
    array_like
        ch_binned, array of channels after binning            
    float or None
        mean_pi, the average of the surface pressure (mN/m) over the scan (None if pressure not found)            
    float or None
        mean_area, the average of the area per molecule (nm^2) over the scan (None if area not found)        
    float or None
        mean_gamma, the average of gamma (deg) over the scan (None if gamma not found)


    Raises
    ------
    SystemExit('Nexus not found')
        when Nexus file not found
    SystemExit('Pilatus not found')
        when Pilatus is not found
    SystemExit('No sensor found')
        when delta and qxy are not found
    SystemExit('gamma not found')
        when gamma not found and computeqz is True
    '''

    nxs_path = recording_dir + nxs_filename

    if not os.path.isfile(nxs_path):
        print(PN._RED + 'Scan %s seems not to exist in recording directory' %
              (nxs_filename) + PN._RESET)
        print(('\t\t recording directory : ' + recording_dir))
        sys.exit('Nexus not found')

    else:

        # Extract sensors from the Pilatus
        column_z = None
        column_qxy = None
        column_delta = None
        column_pi = None
        column_area = None
        column_gamma = None

        if verbose: print(PN._BLUE + " - Open Nexus Data File :" + PN._RESET)
        if verbose: print('\t' + nxs_path)
        try:
            nexus = PN.PyNexusFile(nxs_path, fast=True)
        except:
            print(PN._RED,
                  '\t Nexus file seems not to exist or is not correct',
                  PN._RESET)
            sys.exit('Nexus not found')

        nbpts = np.int(nexus.get_nbpts())
        if verbose: print("\t. Number of data points: ", nbpts)

        # Get stamps
        stamps = nexus.extractStamps()
        if show_data_stamps: print("\t. Available Counters:")
        for i in range(len(stamps)):
            if stamps[i][1] is not None:
                if show_data_stamps:
                    print("\t\t", i, ' -------> ', stamps[i][1])
                if stamps[i][1].lower() == 'pilatus':
                    column_z = i
            else:
                if show_data_stamps:
                    print("\t\t", i, ' -------> ', stamps[i][0])

        # Extract 0D data
        stamps0D, data = nexus.extractData('0D')

        # Find columns
        for i in range(len(stamps0D)):
            if stamps0D[i][1] is not None:
                if stamps0D[i][1].lower() == 'delta':
                    column_delta = i
                if stamps0D[i][1].lower() == 'qxy':
                    column_qxy = i
                if stamps0D[i][1].lower() == 'surfacepressure':
                    column_pi = i
                if stamps0D[i][1].lower() == 'areapermolecule':
                    column_area = i
                if stamps0D[i][1].lower() == 'gamma':
                    column_gamma = i

        # Check that Pilatus data are present (images)
        if column_z is not None:
            if verbose:
                print('\t. Pilatus data found, (column %d, alias %s)' %
                      (column_z, stamps[column_z][1]))
        else:
            print(PN._RED, '\t. No pilatus data found', PN._RESET)
            nexus.close()
            sys.exit('Pilatus not found')

        # Check what is the x input (qxy or delta)
        if column_qxy is None:
            if column_delta is None:
                print(PN._RED,
                      '\t. No usual actuator for GIXD found, stop here',
                      PN._RESET)
                sys.exit('No sensor found')
            else:
                column_x = column_delta
                if verbose:
                    print('\t. delta data found, (column %d, alias %s)' %
                          (column_x, stamps[column_x][1]))
        else:
            column_x = column_qxy
            if verbose:
                print('\t. qxy data found, (column %d, alias %s)' %
                      (column_x, stamps[column_x][1]))

        # Find positions of non Nan values based on data[0]
        args = ~np.isnan(data[0])

        # Get first and last position of the non NaN values
        if verbose:
            print('\t. Valid data between points %d and %d' %
                  (np.argmax(args), len(args) - np.argmax(args[::-1]) - 1))

        # Compute and print mean values
        if column_pi is not None:
            mean_pi = data[column_pi][args].mean()
            if verbose:
                print(
                    '\t. Surface pressure data found, mean value %3.4g ± %3.4g mN/m'
                    % (mean_pi, data[column_pi][args].std()))
        else:
            print('\t. No surface pressure data found')
            mean_pi = None

        if column_area is not None:
            mean_area = data[column_area][args].mean()
            if verbose:
                print(
                    '\t. Area per molecule data found, mean value %3.4g ± %3.4g nm2 per molecule'
                    % (mean_area, data[column_area][args].std()))
        else:
            print('\t. No area per molecule data found')
            mean_area = None

        if column_gamma is not None:
            mean_gamma = data[column_gamma][args].mean()
            if verbose:
                print('\t. Gamma motor data found, mean value %3.4g deg' %
                      (mean_gamma))
        else:
            print('\t. No gamma motor data found')
            mean_gamma = None
            if computeqz:
                print(
                    '\t. gamma is required to compute qz. Add gamma to the sensors.'
                )
                nexus.close()
                sys.exit('gamma not found')

        # Load images
        stamps, images = nexus.extractData('2D')
        nexus.close()

        # Get positions of the dead pixels
        dead_pixels = Check_dead_pixels.get_dead_pixels()

        daty = []
        datyTop = []
        datyBottom = []
        datyFirstQuarter = []
        mat = []

        # Loop over all the non Nan values
        for i in np.arange(len(args))[args]:
            sys.stdout.write(
                'Treat image %d/%d                                                                 \r'
                % (i + 1, nbpts))
            sys.stdout.flush()

            image = images[0][i]

            for ii, jj in dead_pixels:
                image[ii, jj] = 0.0

            # Keep only the ROI corresponding to the Soller
            ROI = [510, 350, 130, 692]
            image = image[ROI[1]:ROI[1] + ROI[3], ROI[0]:ROI[0] + ROI[2]]

            # Replace the intensity of the dead zones with a value of 0
            image = np.where(image < 0., 0., image)

            # Rod (integration along the horizontal axis)
            rod = image.sum(axis=1)

            # Final image with rods stacked (dim: nb_angle x vertical_dim_ROI)
            mat.append(rod)

            # Integrated rods
            daty.append(rod.sum())

            # Integrate the rod on different parts of the detector only
            datyTop.append(rod[0:np.int(ROI[3] / 2)].sum())
            datyBottom.append(rod[np.int(ROI[3] / 2):ROI[3]].sum())
            datyFirstQuarter.append(rod[np.int(3 * ROI[3] / 4):ROI[3]].sum())

            sys.stdout.write(
                '                                                                                  \r'
            )
            sys.stdout.flush()

        # Convert in numpy array
        daty = np.array(daty)
        datyTop = np.array(datyTop)
        datyBottom = np.array(datyBottom)
        datyFirstQuarter = np.array(datyFirstQuarter)
        mat = np.array(mat)

        # Extract x values (qxy or delta)
        x = data[column_x]
        x = x[args]

        # Bin the matrix, return binned vertical channels and binned matrix
        ch_binned, mat_binned = Groupe(mat, binsize=binsize)

        # Extract y values (qz or vertical channels)
        if computeqz == True:
            # Compute and return qz
            thetaz = thetac + (mean_gamma * np.pi /
                               180.0) + (channel0 - ch_binned) * thetazfactor
            y = 2.0 * np.pi * np.sin(thetaz) / wavelength
        else:
            # Return the vertical channels
            y = ch_binned

        # Nature and unit of the axis
        if column_qxy is None:
            # x axis corresponds to delta
            xlabel = str(stamps0D[column_x][1])
        else:
            # x axis corresponds to qxy
            xlabel = str(stamps0D[column_x][1] + ' (' + stamps0D[column_x][2] +
                         ')')

        if computeqz:
            ylabel = 'qz (nm-1)'
        else:
            ylabel = r'$vertical\ channels$'

        return x, y, xlabel, ylabel, column_x,\
               daty, datyTop, datyBottom, datyFirstQuarter,\
               mat, mat_binned, ch_binned, \
               mean_pi, mean_area, mean_gamma
Example #7
0
def Extract(nxs_filename, recording_dir, show_data_stamps, verbose):
    '''
    Extract the Pilatus images from the scan and return the sum.

    Parameters
    ----------
    nxs_filename : str
        nexus filename
    recording_dir : str
        directory where the nexus file is stored
    show_data_stamps : bool
        print the list of sensors from the nexus file
    verbose : bool
        verbose mode


    Returns
    -------
    array_like
        images_sum, the Pilatus image integrated over the scan (usually time).
    array_like
        integrated_x, an array containing the profile integrated along the horizontal axis  
    array_like
        integrated_y, an array containing the profile integrated along the vertical axis        


    Raises
    ------
    SystemExit('Nexus not found')
        when Nexus file not found
    SystemExit('Pilatus not found')
        when Pilatus is not found
    '''

    nxs_path = recording_dir + nxs_filename

    if not os.path.isfile(nxs_path):
        print(PN._RED + 'Scan %s seems not to exist in recording directory' %
              (nxs_filename) + PN._RESET)
        print(('\t\t recording directory : ' + recording_dir))
        sys.exit('Nexus not found')

    else:

        i_pilatus = None

        if verbose: print(PN._BLUE + " - Open Nexus Data File :" + PN._RESET)
        if verbose: print('\t' + nxs_path)

        try:
            nexus = PN.PyNexusFile(nxs_path, fast=True)
        except:
            print(PN._RED,
                  '\t Nexus file seems not to exist or is not correct',
                  PN._RESET)
            sys.exit('Nexus not found')

        nbpts = np.int(nexus.get_nbpts())
        if verbose: print("\t. Number of data points: ", nbpts)

        # Get stamps
        stamps = nexus.extractStamps()
        if show_data_stamps: print("\t. Available Counters:")
        for i in range(len(stamps)):
            if stamps[i][1] is not None:
                if show_data_stamps:
                    print("\t\t", i, ' -------> ', stamps[i][1])
                if stamps[i][1].lower() == 'pilatus':
                    i_pilatus = i
            else:
                if show_data_stamps:
                    print("\t\t", i, ' -------> ', stamps[i][0])

        # Check that Pilatus data are present (images)
        if i_pilatus is not None:
            if verbose:
                print('\t. Pilatus data found, (column %d, alias %s)' %
                      (i_pilatus, stamps[i_pilatus][1]))
        else:
            print(PN._RED, '\t. No pilatus data found', PN._RESET)
            nexus.close()
            sys.exit('Pilatus not found')

        images = np.zeros([nbpts, 1043, 981])

        for i in range(nbpts):
            sys.stdout.write(
                'Treat image %d/%d                                                                 \r'
                % (i + 1, nbpts))
            sys.stdout.flush()

            #Extract the images from the nexus file
            stamp, image = nexus.extract_one_data_point(stamps[i_pilatus][0],
                                                        i,
                                                        verbose=False)

            # Get positions of the dead pixels
            dead_pixels = Check_dead_pixels.get_dead_pixels()

            #Remove the dead pixels
            for ii, jj in dead_pixels:
                image[ii, jj] = 0.0

            images[i, :] = image

            sys.stdout.write(
                '                                                                                  \r'
            )
            sys.stdout.flush()

        nexus.close()

        # Sum the images over time
        images_sum = images.sum(axis=0)

        # Replace dead zones with an intensity of -2.
        images_sum = np.where(images_sum < 0., -2., images_sum)

        # Integrate over the horizontal axis
        # Put the dead zones to 0. for the integration
        integrated_x = np.where(images_sum > 0, images_sum, 0.).sum(axis=1)

        # Integrate over the vertical axis
        # Put the dead zones to 0. for the integration
        integrated_y = np.where(images_sum > 0, images_sum, 0.).sum(axis=0)

        return images_sum, integrated_x, integrated_y
Example #8
0
def Extract(nxs_filename, recording_dir, list_elems, logz, first_channel,
            last_channel, gain, eV0, fast, show_data_stamps, verbose):
    '''
    Extract the nexus scan and return useful quantities for XRF.

    Parameters
    ----------
    nxs_filename : str
        nexus filename
    recording_dir : str
        directory where the nexus file is stored
    list_elems : array_like   
        an array with the elements to extract, for ex. list_elems = [1, 2, 3]
    logz : bool
        log on the plots
    first_channel : int, optional
        the spectrums will be extracted between first_channel and last_channel
    last_channel : int
        the spectrums will be extracted between first_channel and last_channel
    gain : float
        channels are converted to eVs following eVs = gain*channel+eV0
    ev0 : float
        channels are converted to eVs following eVs = gain*channel+eV0
    fast : bool, optional
        triger fast extract of the nexus file
    show_data_stamps : bool, optional
        print the list of sensors from the nexus file
    verbose : bool, optional
        verbose mode


    Returns
    -------
    array_like
        channels, an array containing the channels
    array_like
        eVs, an array containing the channels converted to eVs
    array_like
        spectrums, an array containing the spectrums
    int
        first_non_zero_spectrum, index of the first scan extracted
    int
        last_non_zero_spectrum, index of the last scan extracted

    Raises
    ------
    SystemExit('Nexus not found')
        when Nexus file is not found
    SystemExit('ICR not found')
        when no ICR is found (most likely because the wrong elements were given)
    '''
    nxs_path = recording_dir + nxs_filename

    if not os.path.isfile(nxs_path):
        print(PN._RED + 'Scan %s seems not to exist in recording directory' %
              (nxs_filename) + PN._RESET)
        print('\t\t recording directory: %s' % recording_dir)
        sys.exit('Nexus not found')

    else:

        if verbose: print(PN._BLUE + " - Open Nexus Data File :" + PN._RESET)
        if verbose: print('\t%s' % nxs_path)
        try:
            nexus = PN.PyNexusFile(nxs_path, fast=fast)
        except:
            print(PN._RED +
                  '\t Nexus file seems not to exist or is not correct' +
                  PN._RESET)
            sys.exit('Nexus not found')

        nbpts = np.int(nexus.get_nbpts())
        if verbose: print("\t. Number of data points: %s" % nbpts)

        # Get stamps
        stamps, data = nexus.extractData()

        nexus.close()

        if show_data_stamps: print("\t. Available Counters:")
        for i in range(len(stamps)):
            if stamps[i][1] is not None:
                if show_data_stamps:
                    print("\t\t%s  -------> %s" % (i, stamps[i][1]))
                if stamps[i][1].lower() == 'pilatus':
                    columnz = i
            else:
                if show_data_stamps:
                    print("\t\t%s  -------> %s" % (i, stamps[i][0]))

    def extract_and_correct(ind_spectrum):
        """Extract the requested fluospectrum from the nexus file and correct it with ICR/OCR"""

        is_icr_found = False
        is_ocr_found = False
        for i in range(len(stamps)):
            if (stamps[i][1] != None
                    and stamps[i][1].lower() == "fluoicr0" + ind_spectrum):
                fluoicr = data[i]
                is_icr_found = True
            if (stamps[i][1] != None
                    and stamps[i][1].lower() == "fluoocr0" + ind_spectrum):
                fluoocr = data[i]
                is_ocr_found = True
            if (stamps[i][1] != None and stamps[i][1].lower()
                    == "fluospectrum0" + ind_spectrum):
                fluospectrum = data[i]
            if (stamps[i][1] == None
                    and stamps[i][0].lower() == "integration_time"):
                integration_time = data[i]

        if is_icr_found:
            ICR = fluoicr
            if is_ocr_found:
                OCR = fluoocr
            else:
                print(
                    PN._RED +
                    "OCR not found in data. Taking OCR = spectrum_intensity/counting_time."
                    + PN._RESET)
                OCR = np.array([
                    np.sum(fluospectrum[n]) / integration_time[n]
                    for n in range(len(fluospectrum))
                ])

            ratio = np.array([
                ICR[n] / OCR[n] if (~np.isclose(OCR[n], 0.) & ~np.isnan(OCR[n])
                                    & ~np.isnan(ICR[n])) else 0.
                for n in range(len(ICR))
            ])
            spectrums_corr = np.array(
                [fluospectrum[n] * ratio[n] for n in range(len(ratio))])
            return spectrums_corr

        else:
            print(
                PN._RED +
                "ICR not found in data. Check if the box \'Elements\' is right."
                + PN._RESET)
            print(
                PN._RED +
                "Try to put 4 in the box \'Elements\' for the single-element detector."
                + PN._RESET)
            print(
                PN._RED +
                "Try to put 0, 1, 2, 3 in the box \'Elements\' for the four-elements detector."
                + PN._RESET)
            sys.exit('ICR not found.')

    # Correct each chosen element with ICR/OCR and sum them
    allspectrums_corr = np.zeros((nbpts, 2048))

    for i in list_elems:
        allspectrums_corr += extract_and_correct(str(i))

    ind_non_zero_spectrums = np.where(
        np.sum(allspectrums_corr, axis=1) > 10.)[0]
    list_ranges = np.split(
        ind_non_zero_spectrums,
        np.where(np.diff(ind_non_zero_spectrums) != 1)[0] + 1)
    first_non_zero_spectrum = ind_non_zero_spectrums[0]
    last_non_zero_spectrum = ind_non_zero_spectrums[-1]

    channels = np.arange(int(first_channel), int(last_channel + 1))
    eVs = channels * gain + eV0
    spectrums = allspectrums_corr[0:last_non_zero_spectrum + 1,
                                  int(first_channel):int(last_channel + 1)]

    return channels, eVs, spectrums, first_non_zero_spectrum, last_non_zero_spectrum
Example #9
0
def extract_direct(nxs_filename, ROIx0, ROIy0, ROIsizex, ROIsizey,
                   recording_dir, verbose):
    '''
    Extract the nexus scan of the direct beam and companion files and return the value of the direct.

    Parameters
    ----------
    nxs_filename : str
        nexus filename
    ROIx0 : int
        x0 of the integrated ROI (for the direct and the XRR scans)       
    ROIy0 : int
        y0 of the integrated ROI (for the direct and the XRR scans)        
    ROIsizex : int
        sizex of the integrated ROI (for the direct and the XRR scans)
    ROIsizey : int
        sizey of the integrated ROI (for the direct and the XRR scans)   
    recording_dir : str
        directory where the nexus file is stored        
    verbose : bool
        verbose mode    

    Returns
    -------
    
    float
        direct, value of the direct

    Raises
    ------
    SystemExit('direct_gains.dat not found')
        when XXX_direct_gains.dat file not found
    SystemExit('Sensor not found')
        when a particular sensor is not found in the nxs
    '''    
    file_path = recording_dir+nxs_filename[:-4]+'_direct_gains.dat'

    import os
    import sys
    if not os.path.isfile(file_path):
        print(PN._RED+'The file %s seems not to exist in recording directory'%
              (nxs_filename[:-4]+'_direct_gains.dat')+PN._RESET)
        print('\t\t recording directory: %s'%recording_dir)
        sys.exit('direct_gains.dat not found')

    else:
        
        file = nxs_filename[:-4]+'_direct_gains.dat'

        #########################
        # Extraction of the gains
        gain1 = np.array([])
        gain2 = np.array([])
        gain3 = np.array([])
        gain4 = np.array([])
        gain5 = np.array([])
        gain6 = np.array([])


        if verbose: print('Extracting I0 for different gains from file %s'%file)

        gain1_temp =  np.genfromtxt(recording_dir+file)[0]
        gain2_temp =  np.genfromtxt(recording_dir+file)[1]
        gain3_temp =  np.genfromtxt(recording_dir+file)[2]
        gain4_temp =  np.genfromtxt(recording_dir+file)[3]
        gain5_temp =  np.genfromtxt(recording_dir+file)[4]
        gain6_temp =  np.genfromtxt(recording_dir+file)[5]

        gain1 = np.append(gain1, gain1_temp)
        gain2 = np.append(gain2, gain2_temp)
        gain3 = np.append(gain3, gain3_temp)
        gain4 = np.append(gain4, gain4_temp)
        gain5 = np.append(gain5, gain5_temp)
        gain6 = np.append(gain6, gain6_temp)

        gains = [gain1, gain2, gain3, gain4, gain5, gain6]

        # Identify saturated values
        g1s = np.where(gain1<9.9, gain1, -1) 
        g2s = np.where(gain2<9.9, gain2, -1) 
        g3s = np.where(gain3<9.9, gain3, -1) 
        g4s = np.where(gain4<9.9, gain4, -1) 
        g5s = np.where(gain5<9.9, gain5, -1) 
        g6s = np.where(gain6<9.9, gain6, -1) 

        # Construct the final curve
        g_temp = np.where(g6s<0, g5s/1e4, g6s/1e5)
        g_temp = np.where(g_temp<0, g4s/1e3, g_temp)
        g_temp = np.where(g_temp<0, g3s/1e2, g_temp)
        g_temp = np.where(g_temp<0, g2s/1e1, g_temp)
        
        I0 = np.where(g_temp<0, g1s, g_temp)[0]


        #########################
        # Extraction of direct

        # Extract the sum of all images
        image, _, _ =PilatusSum.Extract(nxs_filename, recording_dir,
                                        show_data_stamps=False, verbose=verbose)

        # Extract the ROI containing reflected beams
        # Full image: ROI = [0, 0, 981, 1043]
        ROI = [ROIx0, ROIy0, ROIsizex, ROIsizey]

        #Apply the ROI
        image_ROI = image[ROI[1]:ROI[1]+ROI[3], ROI[0]:ROI[0]+ROI[2]]

        # Extract info from nexus file
        nexus = PN.PyNexusFile(recording_dir+nxs_filename, fast=True)
        nbpts=int(nexus.get_nbpts())
        stamps0D, data0D = nexus.extractData("0D")
        sensor_list = [stamps0D[i][0] if stamps0D[i][1]== None else stamps0D[i][1] for i in range(len(stamps0D))]
       
        if 'integration_time' in sensor_list:
            integration_timeArg = sensor_list.index('integration_time')
        else:
            print(PN._RED+'\t Sensor %s is not in the sensor list'%('integration_time')+PN._RESET)
            sys.exit('Sensor not found')  

        integration_time = np.mean(data0D[integration_timeArg])

        # Sum the ROI and normalize with the integration time, the number of images
        image_ROI_sum = image_ROI.sum(axis=0).sum(axis=0)  
        direct =  image_ROI_sum/integration_time/I0/nbpts
        
        return direct
Example #10
0
def Extract(nxs_filename, ROIx0, ROIy0, ROIsizex, ROIsizey,
            m4pitch0, wavelength, direct,
            recording_dir, verbose):
    '''
    Extract the nexus scan and companion files and return useful quantities for XRR.

    Parameters
    ----------
    nxs_filename : str
        nexus filename
    ROIx0 : int
        x0 of the integrated ROI (for the direct and the XRR scans)       
    ROIy0 : int
        y0 of the integrated ROI (for the direct and the XRR scans)        
    ROIsizex : int
        sizex of the integrated ROI (for the direct and the XRR scans)
    ROIsizey : int
        sizey of the integrated ROI (for the direct and the XRR scans)        
    m4pitch0 : float
        value of m4pitch0 (m4pitch aligned with the beam) in deg               
    wavelength : float
        wavelength in nm        
    direct : float
        value of the normalisation
    working_dir : str
        directory where the treated files will be stored
    verbose : bool
        verbose mode    

    Returns
    -------
    
    array_like
        m4pitch, an array containing the list of m4pitch 
    array_like
        theta, an array containing the list of theta (i.e. 2.*theta/2.) 
    array_like
        qz, an array containing the list of qz
    array_like
        gains, an array of arrays, each containing the list of intensities for a specific gain of the chamber
    array_like
        I0, an array containing the intensities of the chamber normalized by its gain
    array_like
        I, an array containing the values of the integrated ROI on the XRR scans
    array_like
        Inorm, an array containing the values I normalized by I0 and the direct (i.e. the reflectivity)       

    Raises
    ------
    SystemExit('XRR_files.dat not found')
        when XXX_XRR_files.dat file not found
    SystemExit('Sensor not found')
        when a particular sensor is not found in the nxs
    SystemExit('direct_gains.dat not found')
        when XXX_direct_gains.dat file not found
    '''
    
    
    # Extract the intensity of the ionization chamber for the different gains
    # The nxs_filename should be the first XRR, with a companion file XXX_XRR_files.dat
    files_path = recording_dir+nxs_filename[:-4]+'_XRR_files.dat'

    if not os.path.isfile(files_path):
        print(PN._RED+'The file %s seems not to exist in recording directory'%
              (nxs_filename[:-4]+'_XRR_files.dat')+PN._RESET)
        print('\t\t recording directory: %s'%recording_dir)
        sys.exit('XRR_files.dat not found')
        
    else:

        file_list = np.genfromtxt(recording_dir+nxs_filename[:-4]+'_XRR_files.dat',dtype='U')
        
        #########################
        # Extraction of the gains
        gain1 = np.array([])
        gain2 = np.array([])
        gain3 = np.array([])
        gain4 = np.array([])
        gain5 = np.array([])
        gain6 = np.array([])

        for file in file_list:
            
            file += '_XRR_gains.dat'
            
            if verbose: print('Extracting I0 for different gains from file %s'%file)
            
            gain1_temp =  np.genfromtxt(recording_dir+file)[1]
            gain2_temp =  np.genfromtxt(recording_dir+file)[2]
            gain3_temp =  np.genfromtxt(recording_dir+file)[3]
            gain4_temp =  np.genfromtxt(recording_dir+file)[4]
            gain5_temp =  np.genfromtxt(recording_dir+file)[5]
            gain6_temp =  np.genfromtxt(recording_dir+file)[6]

            gain1 = np.append(gain1, gain1_temp)
            gain2 = np.append(gain2, gain2_temp)
            gain3 = np.append(gain3, gain3_temp)
            gain4 = np.append(gain4, gain4_temp)
            gain5 = np.append(gain5, gain5_temp)
            gain6 = np.append(gain6, gain6_temp)

        gains = [gain1, gain2, gain3, gain4, gain5, gain6]
        
        # Identify saturated values
        g1s = np.where(gain1<9.9, gain1, -1) 
        g2s = np.where(gain2<9.9, gain2, -1) 
        g3s = np.where(gain3<9.9, gain3, -1) 
        g4s = np.where(gain4<9.9, gain4, -1) 
        g5s = np.where(gain5<9.9, gain5, -1) 
        g6s = np.where(gain6<9.9, gain6, -1) 

        # Construct the final curve
        g_temp = np.where(g6s<0, g5s/1e4, g6s/1e5)
        g_temp = np.where(g_temp<0, g4s/1e3, g_temp)
        g_temp = np.where(g_temp<0, g3s/1e2, g_temp)
        g_temp = np.where(g_temp<0, g2s/1e1, g_temp)
        I0 = np.where(g_temp<0, g1s, g_temp)


        I = np.array([])
        m4pitch = np.array([])

        #########################
        # Extraction of XRR
        
        for file in file_list:

            nxs_filename = file+'.nxs'

            # Extract the sum of all images
            image, _, _ =PilatusSum.Extract(nxs_filename, recording_dir,
                                            show_data_stamps=False, verbose=verbose)
            
            # Extract the ROI containing reflected beams
            # Full image: ROI = [0, 0, 981, 1043]
            ROI = [ROIx0, ROIy0, ROIsizex, ROIsizey]

            #Apply the ROI
            image_ROI = image[ROI[1]:ROI[1]+ROI[3], ROI[0]:ROI[0]+ROI[2]]

            # Extract info from nexus file
            nexus = PN.PyNexusFile(recording_dir+nxs_filename, fast=True)
            stamps0D, data0D = nexus.extractData("0D")
            nbpts=int(nexus.get_nbpts())
            sensor_list = [stamps0D[i][0] if stamps0D[i][1]== None else stamps0D[i][1] for i in range(len(stamps0D))]

            if 'm4pitch' in sensor_list:
                m4pitchArg = sensor_list.index('m4pitch')
            else:
                print(PN._RED+'\t Sensor %s is not in the sensor list'%('m4pitch')+PN._RESET)
                sys.exit('Sensor not found')           

            if 'integration_time' in sensor_list:
                integration_timeArg = sensor_list.index('integration_time')
            else:
                print(PN._RED+'\t Sensor %s is not in the sensor list'%('integration_time')+PN._RESET)
                sys.exit('Sensor not found')  
           
            m4pitch = np.append(m4pitch, np.mean(data0D[m4pitchArg]))
            integration_time = np.mean(data0D[integration_timeArg])
            
            # Sum the ROI and normalize with the integration time and the number of images
            integrated_ROI = image_ROI.sum(axis=0).sum(axis=0)/integration_time/nbpts
            I = np.append(I, integrated_ROI)       

        # Convert to qz
        theta = np.abs(2*(m4pitch-m4pitch0)*np.pi/180.) #Incident angle in rad
        qz = 4*np.pi/wavelength*np.sin(theta) #qz in nm-1
            
        # Normalize by I0 and direct (Inorm is the reflectivity)
        Inorm = I/I0/direct
        
        return m4pitch, theta, qz, gains, I0, I, Inorm
Example #11
0
def Extract(nxs_filename, recording_dir, wavelength, distance, pixel_PONI_x,
            pixel_PONI_y, pixel_size, force_gamma, force_delta, force_thetai,
            fgamma, fdelta, fthetai, show_data_stamps, verbose):
    '''
    Extract the nexus scan and return useful quantities for GIXS.

    Parameters
    ----------
    nxs_filename : str
        nexus filename
    recording_dir : str
        directory where the nexus file is stored
    wavelength : float
        wavelength in nm
    distance : float
        distance from the detector to the center of the sample in mm
    pixel_PONI_x : float
        horizontal coordinate of the Point Of Normal Incidence in pixels. Measured on the
        direct beam at delta=0 and gamma=0
    pixel_PONI_y : float
        vertical coordinate of the Point Of Normal Incidence in pixels. Measured on the
        direct beam at delta=0 and gamma=0    
    pixel_size : float
        pixel size in microns
    force_gamma : bool, optional
        enforce the value of gamma
    force_delta : bool, optional
        enforce the value of delta
    force_thetai : bool, optional
        enforce the value of thetai
    fgamma : float, optional
        value of gamma (deg) to be used if force_gamma is True or if gamma is absent from the sensor list
    fdelta : float, optional
        value of delta (deg) to be used if force_delta is True or if delta is absent from the sensor list
    fthetai : float, optional
        value of thetai (deg) to be used if force_thetai is True or if thetai is absent from the sensor list  
    show_data_stamps : bool, optional
        print the list of sensors from the nexus file
    verbose : bool, optional
        verbose mode


    Returns
    -------
    array_like
        images_sum, the Pilatus image integrated over the scan (usually time)
    array_like
        qxy, the 2D grid of qxy for 2D plots
    array_like
        qz, the 2D grid of qz for 2D plots
    array_like
        integrated_qxy, an array containing the profile integrated along the horizontal axis  
    array_like
        integrated_qz, an array containing the profile integrated along the vertical axis
    array_like
        qxy_array, an array containing the list of qxy
    array_like
        qz_array, an array containing the list of qz
    str
        prt_gamma, a label indicating the value of gamma (for plot)
    str
        prt_delta, a label indicating the value of delta (for plot)
    str
        prt_thetai, a label indicating the value of thetai (for plot)


    Raises
    ------
    SystemExit('Nexus not found')
        when Nexus file is not found
    SystemExit('Pilatus not found')
        when Pilatus is not found
    '''

    nxs_path = recording_dir + nxs_filename

    if not os.path.isfile(nxs_path):
        print(PN._RED + 'Scan %s seems not to exist in recording directory' %
              nxs_filename + PN._RESET)
        print('\t\t recording directory: %s' % recording_dir)
        sys.exit('Nexus not found')

    else:

        i_pilatus = None

        if verbose: print(PN._BLUE + " - Open Nexus Data File :" + PN._RESET)
        if verbose: print('\t%s' % nxs_path)

        try:
            nexus = PN.PyNexusFile(nxs_path, fast=True)
        except:
            print(PN._RED +
                  '\t Nexus file seems not to exist or is not correct' +
                  PN._RESET)
            sys.exit('Nexus not found')
        nbpts = np.int(nexus.get_nbpts())
        if verbose: print("\t. Number of data points: %s" % nbpts)

        # Get stamps
        stamps = nexus.extractStamps()
        if show_data_stamps: print("\t. Available Counters:")
        for i in range(len(stamps)):
            if stamps[i][1] is not None:
                if show_data_stamps:
                    print("\t\t%s  -------> %s" % (i, stamps[i][1]))
                if stamps[i][1].lower() == 'pilatus':
                    i_pilatus = i
            else:
                if show_data_stamps:
                    print("\t\t%s  -------> %s" % (i, stamps[i][0]))

        # Check that Pilatus data are present (images)
        if i_pilatus is not None:
            if verbose:
                print('\t. Pilatus data found, (column %d, alias %s)' %
                      (i_pilatus, stamps[i_pilatus][1]))
        else:
            print(PN._RED + '\t. No pilatus data found' + PN._RESET)
            nexus.close()
            sys.exit('Pilatus not found')

        images = np.zeros([nbpts, 1043, 981])

        for i in range(nbpts):
            sys.stdout.write('Treat image %d/%d \r' % (i + 1, nbpts))
            sys.stdout.flush()

            #Extract the images from the nexus file
            stamp, image = nexus.extract_one_data_point(stamps[i_pilatus][0],
                                                        i,
                                                        verbose=False)

            # Get positions of the dead pixels
            dead_pixels = Check_dead_pixels.get_dead_pixels()

            #Remove the dead pixels
            for ii, jj in dead_pixels:
                image[ii, jj] = 0.0

            images[i, :] = image

            sys.stdout.write(30 * ' ' + '\r')
            sys.stdout.flush()

        #Extract the values of each elements of the nxs
        s, data = nexus.extractData('0D')
        nexus.close()

        i_gamma = None
        i_delta = None
        i_thetai = None

        # The sensor corresponding to thetai (alphax or alphay)
        str_thetai = 'alphax'

        for i in range(len(stamps)):
            if (stamps[i][1] != None and stamps[i][1].lower() == 'delta'):
                i_delta = i
            if (stamps[i][1] != None and stamps[i][1].lower() == 'gamma'):
                i_gamma = i
            if (stamps[i][1] != None and stamps[i][1].lower() == str_thetai):
                i_thetai = i

        # Take the value of gamma from the sensors list, or the forced one
        if (i_gamma != None) and (force_gamma == False):
            gamma = np.mean(data[i_gamma])
            prt_gamma = 'gamma found: gamma = %3.4g deg' % (gamma)
        else:
            gamma = fgamma
            if force_gamma:
                prt_gamma = 'gamma is forced to the value: gamma = %3.4g deg' % gamma
            else:
                prt_gamma = 'gamma not found, forced to the value: gamma = %3.4g deg' % gamma

        # Take the value of delta from the sensors list, or the forced one
        if (i_delta != None) and (force_delta == False):
            delta = np.mean(data[i_delta])
            prt_delta = 'delta found: delta = %3.4g deg' % (delta)
        else:
            delta = fdelta
            if force_delta:
                prt_delta = 'delta is forced to the value: delta = %3.4g deg' % delta
            else:
                prt_delta = 'delta not found, forced to the value: delta = %3.4g deg' % delta

        # Take the value of thetai from the sensors list, or the forced one
        if (i_thetai != None) and (force_thetai == False):
            thetai = np.mean(data[i_thetai])
            prt_thetai = 'thetai (%s) found: thetai = %3.4g deg' % (str_thetai,
                                                                    thetai)
        else:
            thetai = fthetai
            if force_thetai:
                prt_thetai = 'thetai is forced to the value: thetai = %3.4g deg' % thetai
            else:
                prt_thetai = 'thetai (%s) not found, forced to the value: thetai = %3.4g deg' % (
                    str_thetai, thetai)

        if verbose:
            print('\t. For more details on the geometry, see:')
            print('\t \t -Fig.2 in doi:10.1107/S0909049512022017')
            print('\t \t -Slide 4 in http://gisaxs.com/files/Strzalka.pdf')

        # Sum the images over time
        images_sum = images.sum(axis=0)

        # Replace dead zones with an intensity of -2.
        images_sum = np.where(images_sum < 0., -2., images_sum)

        pixels_x = np.arange(0, np.shape(images_sum)[1], 1)
        pixels_y = np.arange(0, np.shape(images_sum)[0], 1)

        xx, yy = np.meshgrid(pixels_x, pixels_y)

        # alphai (incident angle) in rad
        alphai = thetai * np.pi / 180.

        pixel_direct_x = pixel_PONI_x - distance / pixel_size * np.tan(
            delta * np.pi / 180.)
        pixel_direct_y = pixel_PONI_y + distance / pixel_size * np.tan(
            gamma * np.pi / 180.)

        # 2*theta in rad
        twotheta = np.arctan(pixel_size * (xx - pixel_direct_x) / distance)

        # alpha_f in rad
        deltay0 = distance * np.tan(alphai * np.pi / 180.)
        alphaf = np.arctan(
            (pixel_size * (pixel_direct_y - yy) - deltay0) / distance)

        # q in nm^-1
        k0 = 2 * np.pi / wavelength
        qz = k0 * (np.sin(alphaf) + np.sin(alphai))
        # Careful, qxy is here computed in the approx. of small exit angles
        qxy = 2 * k0 * np.sin(twotheta / 2.)

        # True values of q (not used here)
        #qx = k0*(np.cos(alphaf)*np.cos(twotheta)-np.cos(alphai))
        #qy = k0*np.cos(alphaf)*np.sin(twotheta)
        #qxy = np.sqrt(np.square(qx)+np.square(qy))
        #q = np.sqrt(np.square(qxy)+np.square(qz))

        # Profiles
        # Put all the negative pixels to zero before integration
        integrated_qxy = np.where(images_sum > 0, images_sum, 0.).sum(axis=1)
        integrated_qz = np.where(images_sum > 0, images_sum, 0.).sum(axis=0)

        pixel_x_array = np.arange(0, len(integrated_qz))
        pixel_y_array = np.arange(0, len(integrated_qxy))

        alphaf_array = np.arctan(
            (pixel_size *
             (pixel_direct_y - pixel_y_array) - deltay0) / distance)
        qz_array = 2 * np.pi / wavelength * (np.sin(alphaf_array) +
                                             np.sin(alphai))
        twotheta_array = np.arctan(pixel_size *
                                   (pixel_x_array - pixel_direct_x) / distance)
        # Careful, approx. qxy=4*pi/lambda*sin(2*theta/2)
        qxy_array = 4 * np.pi / wavelength * np.sin(twotheta_array / 2.)

        return images_sum, qxy, qz,\
               integrated_qxy, integrated_qz, qxy_array, qz_array,\
               prt_gamma, prt_delta, prt_thetai