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)
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
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
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
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()
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
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
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
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
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
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