def _load_experimental_pars(argv): global gui_mode if len(argv) == 6: fname = argv[1] str4title = argv[2] nominalRadius = float(argv[3]) * 1e-6 menu_choices4lensmode = [ '2D Lens Stigmatic Lens', '1Dx Horizontal focusing', '1Dy Vertical focusing' ] lensGeometry = menu_choices4lensmode[int(argv[4])] diameter4fit_list = [float(a) * 1e-6 for a in argv[5].split(',')] for i, arg in enumerate(argv): print('arg {}: '.format(i) + argv[i]) gui_mode = False wpu.print_red(argv) elif len(argv) == 1: (fname, str4title, nominalRadius, diameter4fit_list, lensGeometry) = _intial_gui_setup() gui_mode = True else: print('ERROR: wrong number of inputs: {} \n'.format(len(argv) - 1) + 'Usage: \n' '\n' 'fit_residual_lenses.py : (no inputs) load dialogs \n' '\n' 'fit_residual_lenses.py [args] \n' '\n' 'arg1: file name with thickness image\n' 'arg2: String for Titles\n' 'arg3: nominal curvature radius for fitting\n' 'arg4: index for lens geometry:\n' '\t0 : 2D Lens Stigmatic Lens\n' '\t1 : 1Dx Horizontal focusing\n' '\t2 : 1Dy Vertical focusing\n' 'arg5: diameter4fit_list:\n' '\n') for i, arg in enumerate(argv): print('arg {}: '.format(i) + argv[i]) exit(-1) if str4title != '': str4title += ', ' return fname, str4title, nominalRadius, diameter4fit_list, lensGeometry
def dpc_integration(dpc01, dpc10, pixelsize, idx4crop=[0, -1, 0, -1], plotErrorIntegration=False, saveFileSuf=None, shifthalfpixel=False, method='FC'): ''' TODO: Write Docstring Integration of DPC to obtain phase. Currently only supports Frankot Chellappa ''' if idx4crop == '': vmin = wpu.mean_plus_n_sigma(dpc01**2 + dpc10**2, -3) vmax = wpu.mean_plus_n_sigma(dpc01**2 + dpc10**2, 3) _, idx = wpu.crop_graphic_image(dpc01**2 + dpc10**2, kargs4graph={ 'cmap': 'viridis', 'vmin': vmin, 'vmax': vmax }) else: idx = idx4crop dpc01 = wpu.crop_matrix_at_indexes(dpc01, idx) dpc10 = wpu.crop_matrix_at_indexes(dpc10, idx) if method == 'FC': phase = wps.frankotchellappa(dpc01 * pixelsize[1], dpc10 * pixelsize[0], reflec_pad=True) phase = np.real(phase) else: wpu.print_red('ERROR: Unknown integration method: ' + method) if plotErrorIntegration: wps.error_integration(dpc01 * pixelsize[1], dpc10 * pixelsize[0], phase, pixelsize, errors=False, shifthalfpixel=shifthalfpixel, plot_flag=True) if saveFileSuf is not None: wpu.save_figs_with_idx(saveFileSuf) return phase
def gui_list_data_phase_stepping(directory=''): ''' TODO: Write Docstring ''' originalDir = os.getcwd() if directory != '': if os.path.isdir(directory): os.chdir(directory) else: wpu.print_red("WARNING: Directory " + directory + " doesn't exist.") wpu.print_blue("MESSAGE: Using current working directory " + originalDir) samplef1 = easyqt.get_file_names("Choose one of the scan " + "files with sample") if len(samplef1) == 3: [samplef1, samplef2, samplef3] = samplef1 else: samplef1 = samplef1[0] os.chdir(samplef1.rsplit('/', 1)[0]) samplef2 = easyqt.get_file_names("File name with Reference")[0] samplef3 = easyqt.get_file_names("File name with Dark Image") if len(samplef3) == 1: samplef3 = samplef3[0] else: samplef3 = '' wpu.print_red('MESSAGE: You choosed to not use dark images') wpu.print_blue('MESSAGE: Sample files directory: ' + samplef1.rsplit('/', 1)[0]) samplef1.rsplit('/', 1)[0] listf1 = load_files_scan(samplef1) listf2 = load_files_scan(samplef2) listf3 = load_files_scan(samplef3) listf1.sort() listf2.sort() listf3.sort() return listf1, listf2, listf3
def _get_delta_gui(phenergy): choices = ['Diamond, 3.525g/cm^3', 'Beryllium, 1.848 g/cm^3', 'Manual Input'] menu_choices = [choices[0], choices[1], choices[2]] # Change order here! choice = easyqt.get_choice(message='Select Sample Material', title='Title', choices=menu_choices) if choice is None: choice = menu_choices[0] if choice == choices[0]: # delta Diamond, density from wikipedia: # delta at 8KeV: 1.146095341e-05 delta = 1 - xraylib.Refractive_Index_Re("C", phenergy/1e3, 3.525) material = 'Diamond' elif choice == choices[1]: # delta at 8KeV = 5.3265E-06 delta = 1 - xraylib.Refractive_Index_Re("Be", phenergy/1e3, xraylib.ElementDensity(4)) material = 'Beryllium' elif choice == 'Manual Input': # delta Diamond, density from wikipedia: material = easyqt.get_string('Enter symbol of material ' + '(if compounds, you need to' + ' provide the density):', title='Thickness Calculation', default_response='C') elementZnumber = xraylib.SymbolToAtomicNumber(material) density = xraylib.ElementDensity(elementZnumber) density = easyqt.get_float('Density [g/cm^3] ' + '(Enter for default value)', title='Thickness Calculation', default_value=density) delta = 1 - xraylib.Refractive_Index_Re(material, phenergy/1e3, density) else: wpu.print_red('ERROR: unknown option') return delta, material
def _biggest_radius(array, pixelSize, radius4fit): bool_x = (array.shape[0] // 2 < radius4fit // pixelSize[0]) bool_y = (array.shape[1] // 2 < radius4fit // pixelSize[1]) if bool_x or bool_y: radius4fit = .9 * np.min((thickness.shape[0] * pixelSize[0] / 2, thickness.shape[1] * pixelSize[1] / 2)) wpu.print_red('WARNING: Image size smaller than ' + 'the region for fit') wpu.print_red('WARNING: New Radius:' + ' {:.3f}um'.format(radius4fit * 1e6)) return radius4fit
def dpc_integration(dpc01, dpc10, pixelsize, idx4crop=[0, -1, 0, -1], plotErrorIntegration=False, saveFileSuf=None, shifthalfpixel=False, method='FC'): ''' TODO: Write Docstring Integration of DPC to obtain phase. Currently only supports Frankot Chellappa ''' if idx4crop == '': vmin = wpu.mean_plus_n_sigma(dpc01**2+dpc10**2, -3) vmax = wpu.mean_plus_n_sigma(dpc01**2+dpc10**2, 3) _, idx = wpu.crop_graphic_image(dpc01**2+dpc10**2, kargs4graph={'cmap': 'viridis', 'vmin': vmin, 'vmax': vmax}) else: idx = idx4crop dpc01 = wpu.crop_matrix_at_indexes(dpc01, idx) dpc10 = wpu.crop_matrix_at_indexes(dpc10, idx) if method == 'FC': phase = wps.frankotchellappa(dpc01*pixelsize[1], dpc10*pixelsize[0], reflec_pad=True) phase = np.real(phase) else: wpu.print_red('ERROR: Unknown integration method: ' + method) if plotErrorIntegration: wps.error_integration(dpc01*pixelsize[1], dpc10*pixelsize[0], phase, pixelsize, errors=False, shifthalfpixel=shifthalfpixel, plot_flag=True) if saveFileSuf is not None: wpu.save_figs_with_idx(saveFileSuf) return phase
def _check_harmonic_inside_image(harV, harH, nRows, nColumns, periodVert, periodHor): """ Check if full harmonic image is within the main image """ errFlag = False if (harV + .5) * periodVert > nRows / 2: wpu.print_red("ATTENTION: Harmonic Peak " + "{:d}{:d}".format(harV, harH) + " is out of image vertical range.") errFlag = True if (harH + .5) * periodHor > nColumns / 2: wpu.print_red("ATTENTION: Harmonic Peak " + "{:d}{:d} is ".format(harV, harH) + "is out of image horizontal range.") errFlag = True if errFlag: raise ValueError("ERROR: Harmonic Peak " + "{:d}{:d} is ".format(harV, harH) + "out of image frequency range.")
def _check_harmonic_inside_image(harV, harH, nRows, nColumns, periodVert, periodHor): """ Check if full harmonic image is within the main image """ errFlag = False if (harV + .5)*periodVert > nRows / 2: wpu.print_red("ATTENTION: Harmonic Peak " + "{:d}{:d}".format(harV, harH) + " is out of image vertical range.") errFlag = True if (harH + .5)*periodHor > nColumns / 2: wpu.print_red("ATTENTION: Harmonic Peak " + "{:d}{:d} is ".format(harV, harH) + "is out of image horizontal range.") errFlag = True if errFlag: raise ValueError("ERROR: Harmonic Peak " + "{:d}{:d} is ".format(harV, harH) + "out of image frequency range.")
def extract_harmonic(img, harmonicPeriod, harmonic_ij='00', searchRegion=10, isFFT=False, plotFlag=False, verbose=True): """ Function to extract one harmonic image of the FFT of single grating Talbot imaging. The function use the provided value of period to search for the harmonics peak. The search is done in a rectangle of size ``periodVert*periodHor/searchRegion**2``. The final result is a rectagle of size ``periodVert x periodHor`` centered at ``(harmonic_Vertical*periodVert x harmonic_Horizontal*periodHor)`` Parameters ---------- img : ndarray – Data (data_exchange format) Experimental image, whith proper blank image, crop and rotation already applied. harmonicPeriod : list of integers in the format [periodVert, periodHor] ``periodVert`` and ``periodVert`` are the period of the harmonics in the reciprocal space in pixels. For the checked board grating, periodVert = sqrt(2) * pixel Size / grating Period * number of rows in the image. For 1D grating, set one of the values to negative or zero (it will set the period to number of rows or colunms). harmonic_ij : string or list of string string with the harmonic to extract, for instance '00', '01', '10' or '11'. In this notation negative harmonics are not allowed. Alternativelly, it accepts a list of string ``harmonic_ij=[harmonic_Vertical, harmonic_Horizontal]``, for instance ``harmonic_ij=['0', '-1']`` Note that since the original image contain only real numbers (not complex), then negative and positive harmonics are symetric related to zero. isFFT : Boolean Flag that tells if the input image ``img`` is in the reciprocal (``isFFT=True``) or in the real space (``isFFT=False``) searchRegion: int search for the peak will be in a region of harmonicPeriod/searchRegion around the theoretical peak position plotFlag: Boolean Flag to plot the image in the reciprocal space and to show the position of the found peaked and the limits of the harmonic image verbose: Boolean verbose flag. Returns ------- 2D ndarray Copped Images of the harmonics ij This functions crops a rectagle of size ``periodVert x periodHor`` centered at ``(harmonic_Vertical*periodVert x harmonic_Horizontal*periodHor)`` from the provided FFT image. Note ---- * Note that it is the FFT of the image that is required. * The search for the peak is only used to print warning messages. **Q: Why not the real image??** **A:** Because FFT can be time consuming. If we use the real image, it will be necessary to run FFT for each harmonic. It is encourage to wrap this function within a function that do the FFT, extract the harmonics, and return the real space harmonic image. See Also -------- :py:func:`wavepy.grating_interferometry.plot_harmonic_grid` """ (nRows, nColumns) = img.shape harV = int(harmonic_ij[0]) harH = int(harmonic_ij[1]) periodVert = harmonicPeriod[0] periodHor = harmonicPeriod[1] if verbose: wpu.print_blue("MESSAGE: Extracting harmonic " + harmonic_ij[0] + harmonic_ij[1]) wpu.print_blue("MESSAGE: Harmonic period " + "Horizontal: {:d} pixels".format(periodHor)) wpu.print_blue("MESSAGE: Harmonic period " + "Vertical: {:d} pixels".format(periodVert)) # adjusts for 1D grating if periodVert <= 0 or periodVert is None: periodVert = nRows if verbose: wpu.print_blue("MESSAGE: Assuming Horizontal 1D Grating") if periodHor <= 0 or periodHor is None: periodHor = nColumns if verbose: wpu.print_blue("MESSAGE: Assuming Vertical 1D Grating") try: _check_harmonic_inside_image(harV, harH, nRows, nColumns, periodVert, periodHor) except ValueError: raise SystemExit if isFFT: imgFFT = img else: imgFFT = np.fft.fftshift(fft2(img, norm='ortho')) intensity = (np.abs(imgFFT)) # Estimate harmonic positions idxPeak_ij = _idxPeak_ij(harV, harH, nRows, nColumns, periodVert, periodHor) del_i, del_j = _error_harmonic_peak(imgFFT, harV, harH, periodVert, periodHor, searchRegion) if verbose: print("MESSAGE: extract_harmonic:" + " harmonic peak " + harmonic_ij[0] + harmonic_ij[1] + " is misplaced by:") print("MESSAGE: {:d} pixels in vertical, {:d} pixels in hor".format( del_i, del_j)) print("MESSAGE: Theoretical peak index: {:d},{:d} [VxH]".format( idxPeak_ij[0], idxPeak_ij[1])) if ((np.abs(del_i) > searchRegion // 2) or (np.abs(del_j) > searchRegion // 2)): wpu.print_red("ATTENTION: Harmonic Peak " + harmonic_ij[0] + harmonic_ij[1] + " is too far from theoretical value.") wpu.print_red("ATTENTION: {:d} pixels in vertical,".format(del_i) + "{:d} pixels in hor".format(del_j)) if plotFlag: from matplotlib.patches import Rectangle plt.figure(figsize=(8, 7)) plt.imshow(np.log10(intensity), cmap='inferno', extent=wpu.extent_func(intensity)) plt.xlabel('Pixels') plt.ylabel('Pixels') xo = idxPeak_ij[1] - nColumns // 2 - periodHor // 2 yo = nRows // 2 - idxPeak_ij[0] - periodVert // 2 # xo yo are the lower left position of the reangle plt.gca().add_patch( Rectangle((xo, yo), periodHor, periodVert, lw=2, ls='--', color='red', fill=None, alpha=1)) plt.title('Selected Region ' + harmonic_ij[0] + harmonic_ij[1], fontsize=18, weight='bold') plt.show(block=False) return imgFFT[idxPeak_ij[0] - periodVert // 2:idxPeak_ij[0] + periodVert // 2, idxPeak_ij[1] - periodHor // 2:idxPeak_ij[1] + periodHor // 2]
period_estimated = period_estimation_spline( ref_stack[:, nlines // 4, ncolumns // 4], stepSize) period_estimated += period_estimation_spline( ref_stack[:, nlines // 4, 3 * ncolumns // 4], stepSize) period_estimated += period_estimation_spline( ref_stack[:, 3 * nlines // 4, ncolumns // 4], stepSize) period_estimated += period_estimation_spline( ref_stack[:, 3 * nlines // 4, 3 * ncolumns // 4], stepSize) period_estimated /= 4.0 wpu.print_red('MESSAGE: Pattern Period from the ' + 'data: {:.4f}'.format(period_estimated * 1e6)) # ========================================================================== # %% do your thing # ========================================================================== (intensity, dk_field, dpc_1d, chi2) = main_stepping_grating(img_stack, ref_stack, period_estimated, stepSize) # %% Intensity wpu.plot_slide_colorbar(intensity, title='Intensity', xlabel=r'x [$\mu m$]', ylabel=r'y [$\mu m$]',
def plot_residual_parabolic_lens_2d(thickness, pixelsize, fitted, fitParameters, saveFigFlag=False, savePickle=False, str4title='', saveSdfData=False, vlimErrSigma=1, plotProfileFlag=True, plot3dFlag=True, makeAnimation=False): xmatrix, ymatrix = wpu.grid_coord(thickness, pixelsize) errorThickness = thickness - fitted argNotNAN = np.isfinite(errorThickness) factorx, unitx = wpu.choose_unit(xmatrix) factory, unity = wpu.choose_unit(ymatrix) factorz, unitz = wpu.choose_unit(errorThickness[argNotNAN]) ptp = np.ptp(errorThickness[argNotNAN].flatten() * factorz) wpu.print_red('PV: {0:4.3g} '.format(ptp) + unitz[-1] + 'm') sigmaError = np.std(errorThickness[argNotNAN].flatten() * factorz) wpu.print_red('SDV: {0:4.3g} '.format(sigmaError) + unitz[-1] + 'm') str4title += r'Residual, ' + \ r'R $= {:.4g} \mu m$,'.format(fitParameters[0]*1e6) + '\n' + \ r'PV $= {0:.2f}$ '.format(ptp) + '$' + unitz + ' m$, '\ 'SDV $= {0:.2f}$ '.format(sigmaError) + '$' + unitz + ' m$' # Plot Histogram plt.figure(figsize=(7, 8)) plt.hist(errorThickness[argNotNAN] * factorz, 100, color='r', histtype='step') plt.xlabel(r'Residual [$' + unitz + ' m$ ]') plt.title(str4title) if saveFigFlag: wpu.save_figs_with_idx(fname2save, extension='png') plt.show(block=False) # Plot Profiles vlimErr = wpu.mean_plus_n_sigma(errorThickness[argNotNAN] * factorz, vlimErrSigma / 2) cmap4graph = plt.cm.Spectral_r cmap4graph.set_over('m') cmap4graph.set_under('c') if plotProfileFlag: wpu.plot_profile(xmatrix * factorx, ymatrix * factory, errorThickness * factorz, title=str4title, xlabel=r'[$' + unitx + ' m$ ]', ylabel=r'[$' + unity + ' m$ ]', zlabel=r'[$' + unitz + ' m$ ]', arg4main={ 'cmap': 'Spectral_r', 'vmin': -vlimErr, 'vmax': vlimErr, 'extend': 'both' }) if savePickle or saveFigFlag: fig = plt.figure(figsize=(10, 7)) cf = plt.contourf(xmatrix * factorx, ymatrix * factory, errorThickness * factorz, 256, cmap=cmap4graph, extend='both') plt.clim(-vlimErr, vlimErr) plt.contour(cf, levels=cf.levels[::32], colors='gray') plt.xlabel(r'[$' + unitx + ' m$ ]', fontsize=22) plt.ylabel(r'[$' + unity + ' m$ ]', fontsize=22) plt.title(str4title, fontsize=22) cbar = plt.colorbar(cf, shrink=.8, aspect=20) # cbar.set_clim(-vlimErr, vlimErr) cbar.ax.set_title(r'[$' + unitz + ' m$ ]', y=1.01) plt.gca().set_aspect('equal', adjustable='box') plt.grid(color='grey') if saveFigFlag: wpu.save_figs_with_idx(fname2save, extension='png') if savePickle: wpu.save_figs_with_idx_pickle(fig, fname2save) plt.show(block=True) # Plot 3D if plot3dFlag: wpu.print_red('MESSAGE: Ploting 3d in the background') fig = plt.figure(figsize=(10, 7), facecolor="white") ax = fig.gca(projection='3d') plt.tight_layout(pad=2.5) surf = ax.plot_trisurf(xmatrix[argNotNAN].flatten() * factorx, ymatrix[argNotNAN].flatten() * factory, errorThickness[argNotNAN].flatten() * factorz, vmin=-vlimErr, vmax=vlimErr, cmap=cmap4graph, linewidth=0.1, shade=False) ax.view_init(azim=-120, elev=40) plt.xlabel(r'$x$ [$' + unitx + ' m$ ]') plt.ylabel(r'$y$ [$' + unity + ' m$ ]') plt.title(str4title) cbar = plt.colorbar(surf, shrink=.8, aspect=20, extend='both') cbar.ax.set_title(r'[$' + unitz + ' m$ ]', y=1.01) plt.tight_layout() if saveFigFlag: wpu.save_figs_with_idx(fname2save, extension='png') ax.view_init(azim=690, elev=40) wpu.save_figs_with_idx(fname2save, extension='png') if makeAnimation: # plt.show(block=False) plt.pause(1.0) wpu.rocking_3d_figure(ax, wpu.get_unique_filename(fname2save, 'gif'), elevOffset=45, azimOffset=60, elevAmp=0, azimAmpl=-1, dpi=80, npoints=5) plt.pause(1.0) plt.close('all') # plt.show(block=True) if saveSdfData: mask_for_sdf = errorThickness * 0.0 mask_for_sdf[~argNotNAN] = 1.0 errorThickness[~argNotNAN] = 00000000 wpu.save_sdf_file( errorThickness, pixelsize, wpu.get_unique_filename(fname2save + '_residual', 'sdf')) wpu.save_sdf_file( mask_for_sdf, pixelsize, wpu.get_unique_filename(fname2save + '_residual_mask', 'sdf')) return sigmaError / factorz, ptp / factorz
def plot_residual_1d(xvec, data, fitted, str4title='', saveFigFlag=False, saveAsciiFlag=False): # Plot Horizontal profile errorThickness = -data + fitted argNotNAN = np.isfinite(errorThickness) factorx, unitx = wpu.choose_unit(xvec) factory1, unity1 = wpu.choose_unit(data) factory2, unity2 = wpu.choose_unit(errorThickness) ptp = np.ptp(errorThickness[argNotNAN].flatten() * factory2) wpu.print_red('PV: {0:4.3g} '.format(ptp) + unity2[-1] + 'm') sigmaError = np.std(errorThickness[argNotNAN].flatten() * factory2) wpu.print_red('SDV: {0:4.3g} '.format(sigmaError) + unity2[-1] + 'm') str4title += '\n' + \ r'PV $= {0:.2f}$ '.format(ptp) + '$' + unity2 + ' m$, '\ 'SDV $= {0:.2f}$ '.format(sigmaError) + '$' + unity2 + ' m$' plt.figure(figsize=(10, 7)) ax1 = plt.gca() ax1.plot(xvec[argNotNAN] * factorx, data[argNotNAN] * factory1, '-ko', markersize=5, label='1D data') ax1.plot(xvec[argNotNAN] * factorx, fitted[argNotNAN] * factory1, '-+r', label='Fit parabolic') ax2 = ax1.twinx() # trick to add both axes to legend ax2.plot(np.nan, '-ko', label='1D data') ax2.plot(np.nan, '-+r', label='Fit parabolic') ax2.plot(xvec[argNotNAN] * factorx, errorThickness[argNotNAN] * factory2, '-+', markersize=5, label='fit residual') plt.title(str4title) for tl in ax2.get_yticklabels(): tl.set_color('b') ax2.legend(loc=1, fontsize='small') # trick to add both axes to legend ax1.grid(color='gray') ax1.set_xlabel(r'[$' + unitx + ' m$]') ax1.set_ylabel(r'Thickness ' + r'[$' + unity1 + ' m$]') # ax2.set_ylim([-20, 20]) ax2.set_ylim(-1.1 * np.max(np.abs(errorThickness[argNotNAN]) * factory2), 1.1 * np.max(np.abs(errorThickness[argNotNAN]) * factory2)) ax2.set_ylabel(r'Residual' + r'[$' + unity2 + ' m$]') ax2.grid(b='off') plt.xlim(-1.1 * np.max(xvec * factorx), 1.1 * np.max(xvec * factorx)) plt.tight_layout(rect=(0, 0, 1, .98)) if saveFigFlag: wpu.save_figs_with_idx(fname2save, extension='png') if saveAsciiFlag: csv_fname = wpu.get_unique_filename(fname2save, 'csv') np.savetxt(csv_fname, np.transpose([xvec, data, fitted, fitted - data]), delimiter=',\t', header="xvec, data, fitted, residual, " + str4title, fmt='%.6g') plt.show(block=False)
thickness, pixelSize, headerdic = wpu.load_sdf_file(fname) xx, yy = wpu.realcoordmatrix(thickness.shape[1], pixelSize[1], thickness.shape[0], pixelSize[0]) elif fname.split('.')[-1] == 'pickle': thickness, xx, yy = load_pickle_surf(fname, False) thickness *= 1e-6 # thickness *= -1.0 # minus1 here xx *= 1e-6 yy *= 1e-6 pixelSize = [np.mean(np.diff(xx[0, :])), np.mean(np.diff(yy[:, 0]))] else: wpu.print_red('ERROR: Wrong file type!') exit(-1) thickness -= np.nanmin(thickness) saveFigFlag = True # %% Crop metrology_flag = False if metrology_flag: thickness_temp = np.copy(thickness) thickness_temp[np.isnan(thickness)] = 0.0 idx4crop = wpu.graphical_roi_idx(thickness_temp * 1e6, verbose=True)
period_estimated += period_estimation_spline(ref_stack[:, nlines//4, 3*ncolumns//4], stepSize) period_estimated += period_estimation_spline(ref_stack[:, 3*nlines//4, ncolumns//4], stepSize) period_estimated += period_estimation_spline(ref_stack[:, 3*nlines//4, 3*ncolumns//4], stepSize) period_estimated /= 4.0 wpu.print_red('MESSAGE: Pattern Period from the ' + 'data: {:.4f}'.format(period_estimated*1e6)) # ========================================================================== # %% do your thing # ========================================================================== (intensity, dk_field, dpc_1d, chi2) = main_stepping_grating(img_stack, ref_stack, period_estimated, stepSize) # %% Intensity wpu.plot_slide_colorbar(intensity, title='Intensity',
scale=1) plt.autoscale(axis='both') plt.title('Image displacement') plt.xlabel('Horizontal Shift [Pixels]') plt.ylabel('Vertical Shift [Pixels]') plt.grid('on') plt.gca().invert_yaxis() plt.savefig('aligned_png/displacements.png') plt.show(block=True) # %% wpu.print_red('MESSAGE: Done!') # %% # # # #import numpy as np # #plt.ioff() #count = 0 #for i in range(-10, 10, 1): # # foo = np.pad(wpu.dummy_images('Shapes', (500, 500), noise=1), 100, 'edge')[50+i:650+i, 50-i:650-i] # # foo = np.pad(foo, 200, 'edge') #
def extract_harmonic(img, harmonicPeriod, harmonic_ij='00', searchRegion=10, isFFT=False, plotFlag=False, verbose=True): """ Function to extract one harmonic image of the FFT of single grating Talbot imaging. The function use the provided value of period to search for the harmonics peak. The search is done in a rectangle of size ``periodVert*periodHor/searchRegion**2``. The final result is a rectagle of size ``periodVert x periodHor`` centered at ``(harmonic_Vertical*periodVert x harmonic_Horizontal*periodHor)`` Parameters ---------- img : ndarray – Data (data_exchange format) Experimental image, whith proper blank image, crop and rotation already applied. harmonicPeriod : list of integers in the format [periodVert, periodHor] ``periodVert`` and ``periodVert`` are the period of the harmonics in the reciprocal space in pixels. For the checked board grating, periodVert = sqrt(2) * pixel Size / grating Period * number of rows in the image. For 1D grating, set one of the values to negative or zero (it will set the period to number of rows or colunms). harmonic_ij : string or list of string string with the harmonic to extract, for instance '00', '01', '10' or '11'. In this notation negative harmonics are not allowed. Alternativelly, it accepts a list of string ``harmonic_ij=[harmonic_Vertical, harmonic_Horizontal]``, for instance ``harmonic_ij=['0', '-1']`` Note that since the original image contain only real numbers (not complex), then negative and positive harmonics are symetric related to zero. isFFT : Boolean Flag that tells if the input image ``img`` is in the reciprocal (``isFFT=True``) or in the real space (``isFFT=False``) searchRegion: int search for the peak will be in a region of harmonicPeriod/searchRegion around the theoretical peak position plotFlag: Boolean Flag to plot the image in the reciprocal space and to show the position of the found peaked and the limits of the harmonic image verbose: Boolean verbose flag. Returns ------- 2D ndarray Copped Images of the harmonics ij This functions crops a rectagle of size ``periodVert x periodHor`` centered at ``(harmonic_Vertical*periodVert x harmonic_Horizontal*periodHor)`` from the provided FFT image. Note ---- * Note that it is the FFT of the image that is required. * The search for the peak is only used to print warning messages. **Q: Why not the real image??** **A:** Because FFT can be time consuming. If we use the real image, it will be necessary to run FFT for each harmonic. It is encourage to wrap this function within a function that do the FFT, extract the harmonics, and return the real space harmonic image. See Also -------- :py:func:`wavepy.grating_interferometry.plot_harmonic_grid` """ (nRows, nColumns) = img.shape harV = int(harmonic_ij[0]) harH = int(harmonic_ij[1]) periodVert = harmonicPeriod[0] periodHor = harmonicPeriod[1] if verbose: wpu.print_blue("MESSAGE: Extracting harmonic " + harmonic_ij[0] + harmonic_ij[1]) wpu.print_blue("MESSAGE: Harmonic period " + "Horizontal: {:d} pixels".format(periodHor)) wpu.print_blue("MESSAGE: Harmonic period " + "Vertical: {:d} pixels".format(periodVert)) # adjusts for 1D grating if periodVert <= 0 or periodVert is None: periodVert = nRows if verbose: wpu.print_blue("MESSAGE: Assuming Horizontal 1D Grating") if periodHor <= 0 or periodHor is None: periodHor = nColumns if verbose: wpu.print_blue("MESSAGE: Assuming Vertical 1D Grating") try: _check_harmonic_inside_image(harV, harH, nRows, nColumns, periodVert, periodHor) except ValueError: raise SystemExit if isFFT: imgFFT = img else: imgFFT = np.fft.fftshift(fft2(img, norm='ortho')) intensity = (np.abs(imgFFT)) # Estimate harmonic positions idxPeak_ij = _idxPeak_ij(harV, harH, nRows, nColumns, periodVert, periodHor) del_i, del_j = _error_harmonic_peak(imgFFT, harV, harH, periodVert, periodHor, searchRegion) if verbose: print("MESSAGE: extract_harmonic:" + " harmonic peak " + harmonic_ij[0] + harmonic_ij[1] + " is misplaced by:") print("MESSAGE: {:d} pixels in vertical, {:d} pixels in hor".format( del_i, del_j)) print("MESSAGE: Theoretical peak index: {:d},{:d} [VxH]".format( idxPeak_ij[0], idxPeak_ij[1])) if ((np.abs(del_i) > searchRegion // 2) or (np.abs(del_j) > searchRegion // 2)): wpu.print_red("ATTENTION: Harmonic Peak " + harmonic_ij[0] + harmonic_ij[1] + " is too far from theoretical value.") wpu.print_red("ATTENTION: {:d} pixels in vertical,".format(del_i) + "{:d} pixels in hor".format(del_j)) if plotFlag: from matplotlib.patches import Rectangle plt.figure(figsize=(8, 7)) plt.imshow(np.log10(intensity), cmap='inferno', extent=wpu.extent_func(intensity)) plt.xlabel('Pixels') plt.ylabel('Pixels') xo = idxPeak_ij[1] - nColumns//2 - periodHor//2 yo = nRows//2 - idxPeak_ij[0] - periodVert//2 # xo yo are the lower left position of the reangle plt.gca().add_patch(Rectangle((xo, yo), periodHor, periodVert, lw=2, ls='--', color='red', fill=None, alpha=1)) plt.title('Selected Region ' + harmonic_ij[0] + harmonic_ij[1], fontsize=18, weight='bold') plt.show(block=False) return imgFFT[idxPeak_ij[0] - periodVert//2: idxPeak_ij[0] + periodVert//2, idxPeak_ij[1] - periodHor//2: idxPeak_ij[1] + periodHor//2]