From 3e63662286723fe22fc928899f3a78375fbc1071 Mon Sep 17 00:00:00 2001 From: Arora0 Date: Wed, 3 Apr 2024 19:06:20 +0200 Subject: [PATCH 01/20] add fft tool to specsanalyzer core --- specsanalyzer/core.py | 244 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 236 insertions(+), 8 deletions(-) diff --git a/specsanalyzer/core.py b/specsanalyzer/core.py index 940aaf5..9d48120 100755 --- a/specsanalyzer/core.py +++ b/specsanalyzer/core.py @@ -135,15 +135,28 @@ def convert_image( if conversion_parameters["apply_fft_filter"]: try: - if "fft_filter_peaks" not in conversion_parameters.keys(): - conversion_parameters["fft_filter_peaks"] = kwds.pop( - "fft_filter_peaks", - self._config["fft_filter_peaks"], - ) - img = fourier_filter_2d(raw_img, conversion_parameters["fft_filter_peaks"]) + fft_filter_params: dict = self._correction_matrix_dict["fft_tool_params"] + (amp, pos_x, pos_y, sig_x, sig_y) = ( + fft_filter_params['amplitude'], + fft_filter_params['pos_x'], + fft_filter_params['pos_y'], + fft_filter_params['sigma_x'], + fft_filter_params['sigma_y'], + ) + fft_filter_peaks = create_fft_params_dict(amp, pos_x, pos_y, sig_x, sig_y) + img = fourier_filter_2d(raw_img, fft_filter_peaks) + conversion_parameters["fft_filter_peaks"] = fft_filter_peaks except KeyError: - img = raw_img - conversion_parameters["apply_fft_filter"] = False + try: + if "fft_filter_peaks" not in conversion_parameters.keys(): + conversion_parameters["fft_filter_peaks"] = kwds.pop( + "fft_filter_peaks", + self._config["fft_filter_peaks"], + ) + img = fourier_filter_2d(raw_img, conversion_parameters["fft_filter_peaks"]) + except KeyError: + img = raw_img + conversion_parameters["apply_fft_filter"] = False else: img = raw_img @@ -565,3 +578,218 @@ def cropit(val): # pylint: disable=unused-argument plt.show() if apply: cropit("") + + + def fft_tool( + self, + raw_image: np.ndarray, + apply: bool = False, + **kwds, + ): + """FFT tool to play around with the peak parameters in the Fourier plane. + Built to filter out the meshgrid appearing in the raw data images. + Args: + raw_image: A single 2-D data set. + """ + matplotlib.use("module://ipympl.backend_nbagg") + try: + fft_tool_params = ( + kwds["fft_tool_params"] if "fft_tool_params" in kwds + else self._correction_matrix_dict["fft_tool_params"] + ) + (amp, pos_x, pos_y, sig_x, sig_y) = ( + fft_tool_params['amplitude'], + fft_tool_params['pos_x'], + fft_tool_params['pos_y'], + fft_tool_params['sigma_x'], + fft_tool_params['sigma_y'], + ) + except KeyError: + (amp, pos_x, pos_y, sig_x, sig_y) = (0.95, 114, 50, 13, 22) + + fft_filter_peaks = create_fft_params_dict(amp, pos_x, pos_y, sig_x, sig_y) + try: + img = fourier_filter_2d( + raw_image, + peaks=fft_filter_peaks, + ret="fft" + ) + + mask = fourier_filter_2d( + raw_image, + peaks=fft_filter_peaks, + ret="mask" + ) + + filtered = fourier_filter_2d( + raw_image, + peaks=fft_filter_peaks, + ret="filtered" + ) + except IndexError: + print("Load the scan first!") + raise + + fig = plt.figure() + ax = fig.add_subplot(1,2,1) + im = ax.imshow(np.abs(img), origin='lower') + fig.colorbar(im) + global cont # makes the contour removal possible inside update() + cont = ax.contour(mask) + + # Plot raw image + ax2 = fig.add_subplot(2,2,2) + ax2.imshow(raw_image, origin='lower') + + # Plot fft filtered image + ax3 = fig.add_subplot(2,2,4) + filt = ax3.imshow(filtered, origin='lower') + plt.tight_layout() + + posx_slider = ipw.FloatSlider( + description="pos_x", + value=pos_x, + min=0, + max=150, + step=1, + ) + posy_slider = ipw.FloatSlider( + description="pos_y", + value=pos_y, + min=0, + max=128, + step=1, + ) + sigx_slider = ipw.FloatSlider( + description="sig_x", + value=sig_x, + min=0, + max=200, + step=1, + ) + sigy_slider = ipw.FloatSlider( + description="sig_y", + value=sig_y, + min=0, + max=200, + step=1, + ) + amp_slider = ipw.FloatSlider( + description="Amplitude", + value=amp, + min=0, + max=1, + step=0.01, + ) + clim_slider = ipw.FloatRangeSlider( + description="colorbar limits", + value=[raw_image.min(), raw_image.max()], + min=raw_image.min(), + max=raw_image.max(), + ) + + def update(v_vals, posx, posy, sigx, sigy, amp): + fft_filter_peaks = create_fft_params_dict(amp, posx, posy, sigx, sigy) + msk = fourier_filter_2d( + raw_image, + peaks=fft_filter_peaks, + ret='mask' + ) + filtered_new = fourier_filter_2d( + raw_image, + peaks=fft_filter_peaks, + ret='filtered' + ) + im.set_clim(vmin=v_vals[0], vmax=v_vals[1]) + filt.set_data(filtered_new) + global cont + for i in range(len(cont.collections)): + cont.collections[i].remove() + cont = ax.contour(msk) + + fig.canvas.draw_idle() + + ipw.interact( + update, + amp=amp_slider, + posx=posx_slider, + posy=posy_slider, + sigx=sigx_slider, + sigy=sigy_slider, + v_vals=clim_slider, + ) + def apply_fft(apply: bool): # pylint: disable=unused-argument + amp = amp_slider.value + pos_x = posx_slider.value + pos_y = posy_slider.value + sig_x = sigx_slider.value + sig_y = sigy_slider.value + self._correction_matrix_dict['fft_tool_params'] = { + "amplitude": amp, + "pos_x": pos_x, + "pos_y": pos_y, + "sigma_x": sig_x, + "sigma_y": sig_y, + } + amp_slider.close() + posx_slider.close() + posy_slider.close() + sigx_slider.close() + sigy_slider.close() + clim_slider.close() + apply_button.close() + + apply_button = ipw.Button(description="Apply") + display(apply_button) + apply_button.on_click(apply_fft) + plt.show() + if apply: + apply_fft(True) + + +def create_fft_params_dict(amp, posx, posy, sigx, sigy): + """Function to create fft filter peaks dict using the + provided Gaussian peak parameters. The peaks are defined + relative to each other such that they are periodically + aranged in a 256 x 150 Fourier space. + Args: + amp: Gaussian peak amplitude + posx: x-position + posy: y-position + sigx: FWHM in x-axis + sigy: FWHM in y-axis + """ + + fft_filter_peaks = [ + {'amplitude': amp, + 'pos_x': 128-posy, + 'pos_y': 0, + 'sigma_x': sigx, + 'sigma_y': sigy}, + {'amplitude': amp, + 'pos_x': 128+posy, + 'pos_y': 0, + 'sigma_x': sigx, + 'sigma_y': sigy}, + {'amplitude': amp, + 'pos_x': 0, + 'pos_y': posx, + 'sigma_x': sigx, + 'sigma_y': sigy}, + {'amplitude': amp, + 'pos_x': 128-posy, + 'pos_y': posx, + 'sigma_x': sigx, + 'sigma_y': sigy}, + {'amplitude': amp, + 'pos_x': 128+posy, + 'pos_y': posx, + 'sigma_x': sigx, + 'sigma_y': sigy}, + {'amplitude': amp, + 'pos_x': 256, + 'pos_y': posx, + 'sigma_x': sigx, + 'sigma_y': sigy}, + ] + return fft_filter_peaks From fb22f2ea912c65e4908021154054dda52b5cb2e1 Mon Sep 17 00:00:00 2001 From: Arora0 Date: Wed, 3 Apr 2024 19:06:59 +0200 Subject: [PATCH 02/20] create fft tool interface with specsanalyzer --- specsscan/core.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/specsscan/core.py b/specsscan/core.py index f1ca599..bc16fd9 100755 --- a/specsscan/core.py +++ b/specsscan/core.py @@ -312,6 +312,30 @@ def crop_tool(self, scan: int = None, path: Path | str = "", **kwds): **kwds, ) + + def fft_tool(self, scan: int = None, path: Path | str = "", **kwds): + + matplotlib.use("module://ipympl.backend_nbagg") + if scan is not None: + scan_path = get_scan_path(path, scan, self._config["data_path"]) + + data = load_images( + scan_path=scan_path, + tqdm_enable_nested=self._config["enable_nested_progress_bar"], + ) + image = data[0] + else: + try: + image = self.metadata["loader"]["raw_data"][0] + except KeyError as exc: + raise ValueError("No image loaded, load image first!") from exc + + self.spa.fft_tool( + image, + **kwds, + ) + + def check_scan( self, scan: int, From 3843b388f7eb8c8942d22961a2446d7d184c23ec Mon Sep 17 00:00:00 2001 From: Arora0 Date: Mon, 15 Apr 2024 00:04:07 +0200 Subject: [PATCH 03/20] add ed, mdc and add log clim slider etc. --- specsanalyzer/core.py | 94 +++++++++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/specsanalyzer/core.py b/specsanalyzer/core.py index 9d48120..5c1701c 100755 --- a/specsanalyzer/core.py +++ b/specsanalyzer/core.py @@ -605,7 +605,7 @@ def fft_tool( fft_tool_params['sigma_y'], ) except KeyError: - (amp, pos_x, pos_y, sig_x, sig_y) = (0.95, 114, 50, 13, 22) + (amp, pos_x, pos_y, sig_x, sig_y) = (0.95, 86, 116, 13, 22) fft_filter_peaks = create_fft_params_dict(amp, pos_x, pos_y, sig_x, sig_y) try: @@ -614,6 +614,11 @@ def fft_tool( peaks=fft_filter_peaks, ret="fft" ) + fft_filtered = fourier_filter_2d( + raw_image, + peaks=fft_filter_peaks, + ret="filtered_fft" + ) mask = fourier_filter_2d( raw_image, @@ -631,33 +636,46 @@ def fft_tool( raise fig = plt.figure() - ax = fig.add_subplot(1,2,1) - im = ax.imshow(np.abs(img), origin='lower') - fig.colorbar(im) - global cont # makes the contour removal possible inside update() - cont = ax.contour(mask) + ax = fig.add_subplot(3,2,1) + im_fft = ax.imshow(np.abs(img).T, origin='lower', aspect='auto') + fig.colorbar(im_fft) + + ax.set_title("FFT") + cont = ax.contour(mask.T) # Plot raw image - ax2 = fig.add_subplot(2,2,2) - ax2.imshow(raw_image, origin='lower') + ax2 = fig.add_subplot(3,2,2) + fft_filt = ax2.imshow(np.abs(fft_filtered).T, origin='lower', aspect='auto') + ax2.set_title("Filtered FFT") + fig.colorbar(fft_filt) # Plot fft filtered image - ax3 = fig.add_subplot(2,2,4) - filt = ax3.imshow(filtered, origin='lower') - plt.tight_layout() + ax3 = fig.add_subplot(2,2,3) + filt = ax3.imshow(filtered.T, origin='lower', aspect='auto') + ax3.set_title("Filtered Image") + fig.colorbar(filt) + + ax4 = fig.add_subplot(3,2,4) + edc, = ax4.plot(np.sum(filtered, 0), label='EDC') + ax4.legend() + + ax5 = fig.add_subplot(3,2,6) + mdc, = ax5.plot(np.sum(filtered, 1), label='MDC') + ax5.legend() + # plt.tight_layout() posx_slider = ipw.FloatSlider( description="pos_x", value=pos_x, min=0, - max=150, + max=128, step=1, ) posy_slider = ipw.FloatSlider( description="pos_y", value=pos_y, min=0, - max=128, + max=150, step=1, ) sigx_slider = ipw.FloatSlider( @@ -681,11 +699,12 @@ def fft_tool( max=1, step=0.01, ) - clim_slider = ipw.FloatRangeSlider( + clim_slider = ipw.FloatLogSlider( description="colorbar limits", - value=[raw_image.min(), raw_image.max()], - min=raw_image.min(), - max=raw_image.max(), + value=1e4, + base=10, + min=-1, + max=int(np.log10(np.abs(img).max())) + 1, ) def update(v_vals, posx, posy, sigx, sigy, amp): @@ -700,12 +719,26 @@ def update(v_vals, posx, posy, sigx, sigy, amp): peaks=fft_filter_peaks, ret='filtered' ) - im.set_clim(vmin=v_vals[0], vmax=v_vals[1]) - filt.set_data(filtered_new) - global cont + + fft_filtered_new = fourier_filter_2d( + raw_image, + peaks=fft_filter_peaks, + ret='filtered_fft' + ) + + im_fft.set_clim(vmax=v_vals) + fft_filt.set_clim(vmax=v_vals) + + filt.set_data(filtered_new.T) + fft_filt.set_data(np.abs(fft_filtered_new.T)) + + nonlocal cont for i in range(len(cont.collections)): cont.collections[i].remove() - cont = ax.contour(msk) + cont = ax.contour(msk.T) + + edc.set_ydata(np.sum(filtered_new, 0)) + mdc.set_ydata(np.sum(filtered_new, 1)) fig.canvas.draw_idle() @@ -762,34 +795,35 @@ def create_fft_params_dict(amp, posx, posy, sigx, sigy): fft_filter_peaks = [ {'amplitude': amp, - 'pos_x': 128-posy, + 'pos_x': 1*posx, 'pos_y': 0, 'sigma_x': sigx, 'sigma_y': sigy}, {'amplitude': amp, - 'pos_x': 128+posy, + 'pos_x': 2*posx, 'pos_y': 0, 'sigma_x': sigx, 'sigma_y': sigy}, {'amplitude': amp, 'pos_x': 0, - 'pos_y': posx, + 'pos_y': posy, 'sigma_x': sigx, 'sigma_y': sigy}, {'amplitude': amp, - 'pos_x': 128-posy, - 'pos_y': posx, + 'pos_x': 1*posx, + 'pos_y': posy, 'sigma_x': sigx, 'sigma_y': sigy}, {'amplitude': amp, - 'pos_x': 128+posy, - 'pos_y': posx, + 'pos_x': 2*posx, + 'pos_y': posy, 'sigma_x': sigx, 'sigma_y': sigy}, {'amplitude': amp, - 'pos_x': 256, - 'pos_y': posx, + 'pos_x': 3*posx, + 'pos_y': posy, 'sigma_x': sigx, 'sigma_y': sigy}, ] + return fft_filter_peaks From 7195062460eaa35ea7b31147ac442d088086b060 Mon Sep 17 00:00:00 2001 From: rettigl Date: Mon, 15 Apr 2024 13:13:43 +0200 Subject: [PATCH 04/20] change fft y-axis scaling to have 0 in the center --- specsanalyzer/img_tools.py | 4 +++- specsscan/config/example_config_FHI.yaml | 13 ++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/specsanalyzer/img_tools.py b/specsanalyzer/img_tools.py index d8b9a40..f7090b3 100755 --- a/specsanalyzer/img_tools.py +++ b/specsanalyzer/img_tools.py @@ -61,6 +61,8 @@ def fourier_filter_2d( # Do Fourier Transform of the (real-valued) image image_fft = np.fft.rfft2(image) + # shift fft axis to have 0 in the center + image_fft = np.fft.fftshift(image_fft, axes=0) mask = np.ones(image_fft.shape) xgrid, ygrid = np.meshgrid( range(image_fft.shape[0]), @@ -85,7 +87,7 @@ def fourier_filter_2d( ) from exc # apply mask to the FFT, and transform back - filtered = np.fft.irfft2(image_fft * mask) + filtered = np.fft.irfft2(np.fft.ifftshift(image_fft * mask, axes=0)) # strip negative values filtered = filtered.clip(min=0) if ret == "filtered": diff --git a/specsscan/config/example_config_FHI.yaml b/specsscan/config/example_config_FHI.yaml index 12405c6..5662598 100644 --- a/specsscan/config/example_config_FHI.yaml +++ b/specsscan/config/example_config_FHI.yaml @@ -86,12 +86,12 @@ spa_params: # sigma_x/sigma_y: the peak width (standard deviation) along each direction fft_filter_peaks: - amplitude: 1 - pos_x: 79 + pos_x: 208 pos_y: 0 sigma_x: 8 sigma_y: 8 - amplitude: 1 - pos_x: 176 + pos_x: 48 pos_y: 0 sigma_x: 8 sigma_y: 8 @@ -101,17 +101,12 @@ spa_params: sigma_x: 5 sigma_y: 8 - amplitude: 1 - pos_x: 78 + pos_x: 208 pos_y: 109 sigma_x: 5 sigma_y: 5 - amplitude: 1 - pos_x: 175 + pos_x: 48 pos_y: 108 sigma_x: 5 sigma_y: 5 - - amplitude: 1 - pos_x: 254 - pos_y: 109 - sigma_x: 5 - sigma_y: 8 From d55d47d4d0820f75a34f5c1065c465c5995a7101 Mon Sep 17 00:00:00 2001 From: rettigl Date: Mon, 15 Apr 2024 14:07:19 +0200 Subject: [PATCH 05/20] fix creation of peaks, apply to config --- specsanalyzer/core.py | 151 ++++++++++++++----------------------- specsanalyzer/img_tools.py | 2 +- 2 files changed, 56 insertions(+), 97 deletions(-) diff --git a/specsanalyzer/core.py b/specsanalyzer/core.py index 5c1701c..9fa2a68 100755 --- a/specsanalyzer/core.py +++ b/specsanalyzer/core.py @@ -137,11 +137,11 @@ def convert_image( try: fft_filter_params: dict = self._correction_matrix_dict["fft_tool_params"] (amp, pos_x, pos_y, sig_x, sig_y) = ( - fft_filter_params['amplitude'], - fft_filter_params['pos_x'], - fft_filter_params['pos_y'], - fft_filter_params['sigma_x'], - fft_filter_params['sigma_y'], + fft_filter_params["amplitude"], + fft_filter_params["pos_x"], + fft_filter_params["pos_y"], + fft_filter_params["sigma_x"], + fft_filter_params["sigma_y"], ) fft_filter_peaks = create_fft_params_dict(amp, pos_x, pos_y, sig_x, sig_y) img = fourier_filter_2d(raw_img, fft_filter_peaks) @@ -579,7 +579,6 @@ def cropit(val): # pylint: disable=unused-argument if apply: cropit("") - def fft_tool( self, raw_image: np.ndarray, @@ -594,83 +593,68 @@ def fft_tool( matplotlib.use("module://ipympl.backend_nbagg") try: fft_tool_params = ( - kwds["fft_tool_params"] if "fft_tool_params" in kwds + kwds["fft_tool_params"] + if "fft_tool_params" in kwds else self._correction_matrix_dict["fft_tool_params"] ) (amp, pos_x, pos_y, sig_x, sig_y) = ( - fft_tool_params['amplitude'], - fft_tool_params['pos_x'], - fft_tool_params['pos_y'], - fft_tool_params['sigma_x'], - fft_tool_params['sigma_y'], + fft_tool_params["amplitude"], + fft_tool_params["pos_x"], + fft_tool_params["pos_y"], + fft_tool_params["sigma_x"], + fft_tool_params["sigma_y"], ) except KeyError: (amp, pos_x, pos_y, sig_x, sig_y) = (0.95, 86, 116, 13, 22) fft_filter_peaks = create_fft_params_dict(amp, pos_x, pos_y, sig_x, sig_y) try: - img = fourier_filter_2d( - raw_image, - peaks=fft_filter_peaks, - ret="fft" - ) - fft_filtered = fourier_filter_2d( - raw_image, - peaks=fft_filter_peaks, - ret="filtered_fft" - ) + img = fourier_filter_2d(raw_image, peaks=fft_filter_peaks, ret="fft") + fft_filtered = fourier_filter_2d(raw_image, peaks=fft_filter_peaks, ret="filtered_fft") - mask = fourier_filter_2d( - raw_image, - peaks=fft_filter_peaks, - ret="mask" - ) + mask = fourier_filter_2d(raw_image, peaks=fft_filter_peaks, ret="mask") - filtered = fourier_filter_2d( - raw_image, - peaks=fft_filter_peaks, - ret="filtered" - ) + filtered = fourier_filter_2d(raw_image, peaks=fft_filter_peaks, ret="filtered") except IndexError: print("Load the scan first!") raise fig = plt.figure() - ax = fig.add_subplot(3,2,1) - im_fft = ax.imshow(np.abs(img).T, origin='lower', aspect='auto') + ax = fig.add_subplot(3, 2, 1) + im_fft = ax.imshow(np.abs(img).T, origin="lower", aspect="auto") fig.colorbar(im_fft) ax.set_title("FFT") cont = ax.contour(mask.T) # Plot raw image - ax2 = fig.add_subplot(3,2,2) - fft_filt = ax2.imshow(np.abs(fft_filtered).T, origin='lower', aspect='auto') + ax2 = fig.add_subplot(3, 2, 2) + fft_filt = ax2.imshow(np.abs(fft_filtered).T, origin="lower", aspect="auto") ax2.set_title("Filtered FFT") fig.colorbar(fft_filt) # Plot fft filtered image - ax3 = fig.add_subplot(2,2,3) - filt = ax3.imshow(filtered.T, origin='lower', aspect='auto') + ax3 = fig.add_subplot(2, 2, 3) + filt = ax3.imshow(filtered.T, origin="lower", aspect="auto") ax3.set_title("Filtered Image") fig.colorbar(filt) - ax4 = fig.add_subplot(3,2,4) - edc, = ax4.plot(np.sum(filtered, 0), label='EDC') + ax4 = fig.add_subplot(3, 2, 4) + (edc,) = ax4.plot(np.sum(filtered, 0), label="EDC") ax4.legend() - ax5 = fig.add_subplot(3,2,6) - mdc, = ax5.plot(np.sum(filtered, 1), label='MDC') + ax5 = fig.add_subplot(3, 2, 6) + (mdc,) = ax5.plot(np.sum(filtered, 1), label="MDC") ax5.legend() # plt.tight_layout() posx_slider = ipw.FloatSlider( - description="pos_x", - value=pos_x, - min=0, - max=128, - step=1, - ) + description="pos_x", + value=pos_x, + min=0, + max=128, + step=1, + ) posy_slider = ipw.FloatSlider( description="pos_y", value=pos_y, @@ -707,23 +691,15 @@ def fft_tool( max=int(np.log10(np.abs(img).max())) + 1, ) - def update(v_vals, posx, posy, sigx, sigy, amp): - fft_filter_peaks = create_fft_params_dict(amp, posx, posy, sigx, sigy) - msk = fourier_filter_2d( - raw_image, - peaks=fft_filter_peaks, - ret='mask' - ) - filtered_new = fourier_filter_2d( - raw_image, - peaks=fft_filter_peaks, - ret='filtered' - ) + def update(v_vals, pos_x, pos_y, sig_x, sig_y, amp): + fft_filter_peaks = create_fft_params_dict(amp, pos_x, pos_y, sig_x, sig_y) + msk = fourier_filter_2d(raw_image, peaks=fft_filter_peaks, ret="mask") + filtered_new = fourier_filter_2d(raw_image, peaks=fft_filter_peaks, ret="filtered") fft_filtered_new = fourier_filter_2d( raw_image, peaks=fft_filter_peaks, - ret='filtered_fft' + ret="filtered_fft", ) im_fft.set_clim(vmax=v_vals) @@ -745,25 +721,33 @@ def update(v_vals, posx, posy, sigx, sigy, amp): ipw.interact( update, amp=amp_slider, - posx=posx_slider, - posy=posy_slider, - sigx=sigx_slider, - sigy=sigy_slider, + pos_x=posx_slider, + pos_y=posy_slider, + sig_x=sigx_slider, + sig_y=sigy_slider, v_vals=clim_slider, ) + def apply_fft(apply: bool): # pylint: disable=unused-argument amp = amp_slider.value pos_x = posx_slider.value pos_y = posy_slider.value sig_x = sigx_slider.value sig_y = sigy_slider.value - self._correction_matrix_dict['fft_tool_params'] = { + self._correction_matrix_dict["fft_tool_params"] = { "amplitude": amp, "pos_x": pos_x, "pos_y": pos_y, "sigma_x": sig_x, "sigma_y": sig_y, } + self.config["fft_filter_peaks"] = create_fft_params_dict( + amp, + pos_x, + pos_y, + sig_x, + sig_y, + ) amp_slider.close() posx_slider.close() posy_slider.close() @@ -794,36 +778,11 @@ def create_fft_params_dict(amp, posx, posy, sigx, sigy): """ fft_filter_peaks = [ - {'amplitude': amp, - 'pos_x': 1*posx, - 'pos_y': 0, - 'sigma_x': sigx, - 'sigma_y': sigy}, - {'amplitude': amp, - 'pos_x': 2*posx, - 'pos_y': 0, - 'sigma_x': sigx, - 'sigma_y': sigy}, - {'amplitude': amp, - 'pos_x': 0, - 'pos_y': posy, - 'sigma_x': sigx, - 'sigma_y': sigy}, - {'amplitude': amp, - 'pos_x': 1*posx, - 'pos_y': posy, - 'sigma_x': sigx, - 'sigma_y': sigy}, - {'amplitude': amp, - 'pos_x': 2*posx, - 'pos_y': posy, - 'sigma_x': sigx, - 'sigma_y': sigy}, - {'amplitude': amp, - 'pos_x': 3*posx, - 'pos_y': posy, - 'sigma_x': sigx, - 'sigma_y': sigy}, + {"amplitude": amp, "pos_x": -posx, "pos_y": 0, "sigma_x": sigx, "sigma_y": sigy}, + {"amplitude": amp, "pos_x": posx, "pos_y": 0, "sigma_x": sigx, "sigma_y": sigy}, + {"amplitude": amp, "pos_x": 0, "pos_y": posy, "sigma_x": sigx, "sigma_y": sigy}, + {"amplitude": amp, "pos_x": -posx, "pos_y": posy, "sigma_x": sigx, "sigma_y": sigy}, + {"amplitude": amp, "pos_x": posx, "pos_y": posy, "sigma_x": sigx, "sigma_y": sigy}, ] return fft_filter_peaks diff --git a/specsanalyzer/img_tools.py b/specsanalyzer/img_tools.py index f7090b3..2a940c2 100755 --- a/specsanalyzer/img_tools.py +++ b/specsanalyzer/img_tools.py @@ -75,7 +75,7 @@ def fourier_filter_2d( mask -= peak["amplitude"] * gauss2d( xgrid, ygrid, - peak["pos_x"], + image_fft.shape[0] / 2 + peak["pos_x"], peak["pos_y"], peak["sigma_x"], peak["sigma_y"], From e2872b758465844c11137df50aa14077ab3523dd Mon Sep 17 00:00:00 2001 From: rettigl Date: Mon, 15 Apr 2024 14:30:58 +0200 Subject: [PATCH 06/20] update test data version --- tests/data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/data b/tests/data index 9a11106..b84798f 160000 --- a/tests/data +++ b/tests/data @@ -1 +1 @@ -Subproject commit 9a11106b902dbf1089de50813eae649ccf6e3a83 +Subproject commit b84798f1c85f76461cdd4b5741bf1a4a0ba555e4 From b831db1ab5a41dde2011d45b254b11164ba6c297 Mon Sep 17 00:00:00 2001 From: rettigl Date: Mon, 15 Apr 2024 14:41:46 +0200 Subject: [PATCH 07/20] fix linting --- specsscan/core.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/specsscan/core.py b/specsscan/core.py index bc16fd9..5bb4b23 100755 --- a/specsscan/core.py +++ b/specsscan/core.py @@ -312,9 +312,7 @@ def crop_tool(self, scan: int = None, path: Path | str = "", **kwds): **kwds, ) - def fft_tool(self, scan: int = None, path: Path | str = "", **kwds): - matplotlib.use("module://ipympl.backend_nbagg") if scan is not None: scan_path = get_scan_path(path, scan, self._config["data_path"]) @@ -335,7 +333,6 @@ def fft_tool(self, scan: int = None, path: Path | str = "", **kwds): **kwds, ) - def check_scan( self, scan: int, From bee28be9637f3fd1d9a94bfe723eb8d645eccaa6 Mon Sep 17 00:00:00 2001 From: rettigl Date: Tue, 16 Apr 2024 20:26:15 +0200 Subject: [PATCH 08/20] revert back application of fft_filter_parameters --- specsanalyzer/core.py | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/specsanalyzer/core.py b/specsanalyzer/core.py index 9fa2a68..ba7a81d 100755 --- a/specsanalyzer/core.py +++ b/specsanalyzer/core.py @@ -135,28 +135,15 @@ def convert_image( if conversion_parameters["apply_fft_filter"]: try: - fft_filter_params: dict = self._correction_matrix_dict["fft_tool_params"] - (amp, pos_x, pos_y, sig_x, sig_y) = ( - fft_filter_params["amplitude"], - fft_filter_params["pos_x"], - fft_filter_params["pos_y"], - fft_filter_params["sigma_x"], - fft_filter_params["sigma_y"], - ) - fft_filter_peaks = create_fft_params_dict(amp, pos_x, pos_y, sig_x, sig_y) - img = fourier_filter_2d(raw_img, fft_filter_peaks) - conversion_parameters["fft_filter_peaks"] = fft_filter_peaks + if "fft_filter_peaks" not in conversion_parameters.keys(): + conversion_parameters["fft_filter_peaks"] = kwds.pop( + "fft_filter_peaks", + self._config["fft_filter_peaks"], + ) + img = fourier_filter_2d(raw_img, conversion_parameters["fft_filter_peaks"]) except KeyError: - try: - if "fft_filter_peaks" not in conversion_parameters.keys(): - conversion_parameters["fft_filter_peaks"] = kwds.pop( - "fft_filter_peaks", - self._config["fft_filter_peaks"], - ) - img = fourier_filter_2d(raw_img, conversion_parameters["fft_filter_peaks"]) - except KeyError: - img = raw_img - conversion_parameters["apply_fft_filter"] = False + img = raw_img + conversion_parameters["apply_fft_filter"] = False else: img = raw_img From 7b9355ec8032aedf1c66e973a87f63ee02c46f46 Mon Sep 17 00:00:00 2001 From: rettigl Date: Tue, 16 Apr 2024 20:29:06 +0200 Subject: [PATCH 09/20] update example config --- specsscan/config/example_config_FHI.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specsscan/config/example_config_FHI.yaml b/specsscan/config/example_config_FHI.yaml index 5662598..12fca1b 100644 --- a/specsscan/config/example_config_FHI.yaml +++ b/specsscan/config/example_config_FHI.yaml @@ -86,7 +86,7 @@ spa_params: # sigma_x/sigma_y: the peak width (standard deviation) along each direction fft_filter_peaks: - amplitude: 1 - pos_x: 208 + pos_x: -49 pos_y: 0 sigma_x: 8 sigma_y: 8 @@ -101,12 +101,12 @@ spa_params: sigma_x: 5 sigma_y: 8 - amplitude: 1 - pos_x: 208 + pos_x: -50 pos_y: 109 sigma_x: 5 sigma_y: 5 - amplitude: 1 - pos_x: 48 + pos_x: 47 pos_y: 108 sigma_x: 5 sigma_y: 5 From 96fcd313d66dd2602dec8825db6ce946b1f48b38 Mon Sep 17 00:00:00 2001 From: rettigl Date: Tue, 16 Apr 2024 20:43:01 +0200 Subject: [PATCH 10/20] fix tests --- tests/test_specsscan.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_specsscan.py b/tests/test_specsscan.py index 3b77349..0eeb602 100755 --- a/tests/test_specsscan.py +++ b/tests/test_specsscan.py @@ -65,14 +65,16 @@ def test_conversion_3d(): path=test_dir, iterations=[0], ) - assert res_xarray.sum(axis=(0, 1, 2)) != res_xarray2.sum(axis=(0, 1, 2)) + assert abs(res_xarray.values.sum(axis=(0, 1, 2)) - res_xarray2.values.sum(axis=(0, 1, 2))) > 1 res_xarray2 = sps.load_scan( scan=4450, path=test_dir, iterations=np.s_[0:2], ) - assert res_xarray.sum(axis=(0, 1, 2)) == res_xarray2.sum(axis=(0, 1, 2)) + assert ( + abs(res_xarray.values.sum(axis=(0, 1, 2)) - res_xarray2.values.sum(axis=(0, 1, 2))) < 1e-4 + ) with pytest.raises(IndexError): sps.load_scan( From 671d53f686c7bd1008c288231c23bffd5483d15f Mon Sep 17 00:00:00 2001 From: rettigl Date: Tue, 16 Apr 2024 20:53:37 +0200 Subject: [PATCH 11/20] try different fix --- tests/test_specsscan.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/test_specsscan.py b/tests/test_specsscan.py index 0eeb602..959f646 100755 --- a/tests/test_specsscan.py +++ b/tests/test_specsscan.py @@ -65,16 +65,19 @@ def test_conversion_3d(): path=test_dir, iterations=[0], ) - assert abs(res_xarray.values.sum(axis=(0, 1, 2)) - res_xarray2.values.sum(axis=(0, 1, 2))) > 1 + np.testing.assert_raises( + AssertionError, + np.testing.assert_allclose, + res_xarray.values, + res_xarray2.values, + ) res_xarray2 = sps.load_scan( scan=4450, path=test_dir, iterations=np.s_[0:2], ) - assert ( - abs(res_xarray.values.sum(axis=(0, 1, 2)) - res_xarray2.values.sum(axis=(0, 1, 2))) < 1e-4 - ) + np.testing.assert_allclose(res_xarray, res_xarray2) with pytest.raises(IndexError): sps.load_scan( From 8267c39b8680f0021aa4a23dc93263345bdfe821 Mon Sep 17 00:00:00 2001 From: rettigl Date: Wed, 17 Apr 2024 11:27:32 +0200 Subject: [PATCH 12/20] correct writing of slow/fast axes to metadata --- specsscan/core.py | 24 ++++++++++++++++++++---- specsscan/helpers.py | 14 +++++++------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/specsscan/core.py b/specsscan/core.py index 5bb4b23..545871c 100755 --- a/specsscan/core.py +++ b/specsscan/core.py @@ -224,6 +224,9 @@ def load_scan( else: res_xarray = res_xarray.transpose("Angle", "Ekin", dim) + slow_axes = {dim} if dim else set() + fast_axes = set(res_xarray.dims) - slow_axes + projection = "reciprocal" if "Angle" in fast_axes else "real" conversion_metadata = res_xarray.attrs.pop("conversion_parameters") # rename coords and store mapping information, if available @@ -238,6 +241,13 @@ def load_scan( if k in res_xarray.dims } res_xarray = res_xarray.rename(rename_dict) + for k, v in coordinate_mapping.items(): + if k in fast_axes: + fast_axes.remove(k) + fast_axes.add(v) + if k in slow_axes: + slow_axes.remove(k) + slow_axes.add(v) self._scan_info["coordinate_depends"] = depends_dict axis_dict = { @@ -262,8 +272,9 @@ def load_scan( df_lut, self._scan_info, self.config, - fast_axis="Angle" if "Angle" in res_xarray.dims else "Position", - slow_axis=dim, + fast_axes=list(fast_axes), + slow_axes=list(slow_axes), + projection=projection, metadata=copy.deepcopy(metadata), collect_metadata=collect_metadata, ), @@ -432,13 +443,18 @@ def check_scan( except KeyError: pass + slow_axes = {"Iteration"} + fast_axes = set(res_xarray.dims) - slow_axes + projection = "reciprocal" if "Angle" in fast_axes else "real" + self.metadata.update( **handle_meta( df_lut, self._scan_info, self.config, - fast_axis="Angle" if "Angle" in res_xarray.dims else "Position", - slow_axis=dims[1], + fast_axes=list(fast_axes), + slow_axes=list(slow_axes), + projection=projection, metadata=metadata, collect_metadata=collect_metadata, ), diff --git a/specsscan/helpers.py b/specsscan/helpers.py index 5b0e4c2..174da88 100644 --- a/specsscan/helpers.py +++ b/specsscan/helpers.py @@ -348,8 +348,9 @@ def handle_meta( df_lut: pd.DataFrame, scan_info: dict, config: dict, - fast_axis: str, - slow_axis: str, + fast_axes: list[str], + slow_axes: list[str], + projection: str, metadata: dict = None, collect_metadata: bool = False, ) -> dict: @@ -360,8 +361,8 @@ def handle_meta( from ``parse_lut_to_df()`` scan_info (dict): scan_info class dict containing containing the contents of info.txt file config (dict): config dictionary containing the contents of config.yaml file - fast_axis (str): The fast-axis dimension of the scan - slow_axis (str): The slow-axis dimension of the scan + fast_axes (list[str]): The fast-axis dimensions of the scan + slow_axes (list[str]): The slow-axis dimensions of the scan metadata (dict, optional): Metadata dictionary with additional metadata for the scan. Defaults to empty dictionary. collect_metadata (bool, optional): Option to collect further metadata e.g. from EPICS @@ -470,14 +471,13 @@ def handle_meta( metadata["scan_info"]["energy_scan_mode"] = energy_scan_mode - projection = "reciprocal" if fast_axis in {"Anlge", "angular0", "angular1"} else "real" metadata["scan_info"]["projection"] = projection metadata["scan_info"]["scheme"] = ( "angular dispersive" if projection == "reciprocal" else "spatial dispersive" ) - metadata["scan_info"]["slow_axes"] = slow_axis - metadata["scan_info"]["fast_axes"] = ["Ekin", fast_axis] + metadata["scan_info"]["slow_axes"] = slow_axes + metadata["scan_info"]["fast_axes"] = fast_axes print("Done!") From 0f7a4bca797e3a6413f53f6badc4c0db1ee48dd5 Mon Sep 17 00:00:00 2001 From: rettigl Date: Wed, 17 Apr 2024 11:51:12 +0200 Subject: [PATCH 13/20] ignore type checking --- specsscan/core.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specsscan/core.py b/specsscan/core.py index 545871c..2f522e0 100755 --- a/specsscan/core.py +++ b/specsscan/core.py @@ -272,7 +272,7 @@ def load_scan( df_lut, self._scan_info, self.config, - fast_axes=list(fast_axes), + fast_axes=list(fast_axes), # type: ignore slow_axes=list(slow_axes), projection=projection, metadata=copy.deepcopy(metadata), @@ -452,7 +452,7 @@ def check_scan( df_lut, self._scan_info, self.config, - fast_axes=list(fast_axes), + fast_axes=list(fast_axes), # type: ignore slow_axes=list(slow_axes), projection=projection, metadata=metadata, From 55a8674490de56c0b15cdbe4185ce0772570d6a3 Mon Sep 17 00:00:00 2001 From: Arora0 Date: Fri, 19 Apr 2024 14:47:58 +0200 Subject: [PATCH 14/20] add snake case and rename create_fft_params function --- specsanalyzer/core.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/specsanalyzer/core.py b/specsanalyzer/core.py index ba7a81d..d88707b 100755 --- a/specsanalyzer/core.py +++ b/specsanalyzer/core.py @@ -573,7 +573,9 @@ def fft_tool( **kwds, ): """FFT tool to play around with the peak parameters in the Fourier plane. - Built to filter out the meshgrid appearing in the raw data images. + Built to filter out the meshgrid appearing in the raw data images. The + optimized parameters are stored in the class config dict under + fft_filter_peaks. Args: raw_image: A single 2-D data set. """ @@ -594,7 +596,7 @@ def fft_tool( except KeyError: (amp, pos_x, pos_y, sig_x, sig_y) = (0.95, 86, 116, 13, 22) - fft_filter_peaks = create_fft_params_dict(amp, pos_x, pos_y, sig_x, sig_y) + fft_filter_peaks = create_fft_params(amp, pos_x, pos_y, sig_x, sig_y) try: img = fourier_filter_2d(raw_image, peaks=fft_filter_peaks, ret="fft") fft_filtered = fourier_filter_2d(raw_image, peaks=fft_filter_peaks, ret="filtered_fft") @@ -679,7 +681,7 @@ def fft_tool( ) def update(v_vals, pos_x, pos_y, sig_x, sig_y, amp): - fft_filter_peaks = create_fft_params_dict(amp, pos_x, pos_y, sig_x, sig_y) + fft_filter_peaks = create_fft_params(amp, pos_x, pos_y, sig_x, sig_y) msk = fourier_filter_2d(raw_image, peaks=fft_filter_peaks, ret="mask") filtered_new = fourier_filter_2d(raw_image, peaks=fft_filter_peaks, ret="filtered") @@ -728,7 +730,7 @@ def apply_fft(apply: bool): # pylint: disable=unused-argument "sigma_x": sig_x, "sigma_y": sig_y, } - self.config["fft_filter_peaks"] = create_fft_params_dict( + self.config["fft_filter_peaks"] = create_fft_params( amp, pos_x, pos_y, @@ -751,25 +753,25 @@ def apply_fft(apply: bool): # pylint: disable=unused-argument apply_fft(True) -def create_fft_params_dict(amp, posx, posy, sigx, sigy): - """Function to create fft filter peaks dict using the +def create_fft_params(amp, pos_x, pos_y, sig_x, sig_y) -> list[dict]: + """Function to create fft filter peaks list using the provided Gaussian peak parameters. The peaks are defined relative to each other such that they are periodically aranged in a 256 x 150 Fourier space. Args: amp: Gaussian peak amplitude - posx: x-position - posy: y-position - sigx: FWHM in x-axis - sigy: FWHM in y-axis + pos_x: x-position + pos_y: y-position + sig_x: FWHM in x-axis + sig_y: FWHM in y-axis """ fft_filter_peaks = [ - {"amplitude": amp, "pos_x": -posx, "pos_y": 0, "sigma_x": sigx, "sigma_y": sigy}, - {"amplitude": amp, "pos_x": posx, "pos_y": 0, "sigma_x": sigx, "sigma_y": sigy}, - {"amplitude": amp, "pos_x": 0, "pos_y": posy, "sigma_x": sigx, "sigma_y": sigy}, - {"amplitude": amp, "pos_x": -posx, "pos_y": posy, "sigma_x": sigx, "sigma_y": sigy}, - {"amplitude": amp, "pos_x": posx, "pos_y": posy, "sigma_x": sigx, "sigma_y": sigy}, + {"amplitude": amp, "pos_x": -pos_x, "pos_y": 0, "sigma_x": sig_x, "sigma_y": sig_y}, + {"amplitude": amp, "pos_x": pos_x, "pos_y": 0, "sigma_x": sig_x, "sigma_y": sig_y}, + {"amplitude": amp, "pos_x": 0, "pos_y": pos_y, "sigma_x": sig_x, "sigma_y": sig_y}, + {"amplitude": amp, "pos_x": -pos_x, "pos_y": pos_y, "sigma_x": sig_x, "sigma_y": sig_y}, + {"amplitude": amp, "pos_x": pos_x, "pos_y": pos_y, "sigma_x": sig_x, "sigma_y": sig_y}, ] return fft_filter_peaks From eb72284742871d265515ae48de50a99e23c24ac5 Mon Sep 17 00:00:00 2001 From: Arora0 Date: Fri, 19 Apr 2024 14:50:07 +0200 Subject: [PATCH 15/20] add tests for fft-tool --- tests/test_specsscan.py | 50 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/tests/test_specsscan.py b/tests/test_specsscan.py index 959f646..9976309 100755 --- a/tests/test_specsscan.py +++ b/tests/test_specsscan.py @@ -8,10 +8,17 @@ import specsscan from specsscan import __version__ from specsscan import SpecsScan +from specsanalyzer.core import create_fft_params package_dir = os.path.dirname(specsscan.__file__) test_dir = package_dir + "/../tests/data/" - +fft_filter_peaks = create_fft_params( + amp=1, + pos_x=82, + pos_y=116, + sig_x=15, + sig_y=23 +) def test_version(): """Test if the package has the correct version string.""" @@ -262,6 +269,47 @@ def test_crop_tool(): assert res_xarray.Ekin[-1] == 22.826511627906974 +def test_fft_tool(): + """Test the fft tool""" + + sps = SpecsScan( + config=test_dir + "config.yaml", + user_config={}, + system_config={}, + ) + res_xarray = sps.load_scan( + scan=3610, + path=test_dir, + ) + + assert(res_xarray.data.sum() == 62232679364.331406) + + res_xarray = sps.load_scan( + scan=3610, + path=test_dir, + fft_filter_peaks=fft_filter_peaks, + apply_fft_filter=True, + ) + assert(res_xarray.data.sum() == 62197237155.50347) + + sps.fft_tool( + fft_tool_params={ + "amplitude": 1, + "pos_x": 82, + "pos_y": 116, + "sigma_x": 15, + "sigma_y": 23 + }, + apply=True + ) + res_xarray = sps.load_scan( + scan=3610, + path=test_dir, + apply_fft_filter=True + ) + assert(res_xarray.data.sum() == 62197237155.50347) + + def test_conversion_and_save_to_nexus(): """Test the conversion of a tilt scan and saving as NeXus""" config = {"nexus": {"input_files": [package_dir + "/config/NXmpes_arpes_config.json"]}} From e65c55adce353307cdabfce3f97c43cb8b7a4b11 Mon Sep 17 00:00:00 2001 From: Arora0 Date: Fri, 19 Apr 2024 14:50:55 +0200 Subject: [PATCH 16/20] add examples for fft-tool --- .../1_specsanalyzer_conversion_examples.ipynb | 51 ++++++++++++++++ tutorial/2_specsscan_example.ipynb | 59 ++++++++++++++++++- 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/tutorial/1_specsanalyzer_conversion_examples.ipynb b/tutorial/1_specsanalyzer_conversion_examples.ipynb index 5472e6d..a2d9ec7 100644 --- a/tutorial/1_specsanalyzer_conversion_examples.ipynb +++ b/tutorial/1_specsanalyzer_conversion_examples.ipynb @@ -169,6 +169,57 @@ "res_xarray.plot()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Alternatively, one can use the interactive fft tool to optimize the fft peak positions of the grid." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "spa.fft_tool(tsv_data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The peak parameters are stored in the config dict which can be passed as kwds to the convert_image function" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fft_filter_peaks = spa.config['fft_filter_peaks']\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "res_xarray = spa.convert_image(\n", + " tsv_data,\n", + " lens_mode,\n", + " kinetic_energy,\n", + " pass_energy,\n", + " work_function,\n", + " apply_fft_filter=True,\n", + " fft_filter_peaks=fft_filter_peaks\n", + ")\n", + "plt.figure()\n", + "res_xarray.plot()" + ] + }, { "cell_type": "markdown", "metadata": {}, diff --git a/tutorial/2_specsscan_example.ipynb b/tutorial/2_specsscan_example.ipynb index cab131c..0f1ac21 100644 --- a/tutorial/2_specsscan_example.ipynb +++ b/tutorial/2_specsscan_example.ipynb @@ -184,6 +184,61 @@ ")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Removal of Mesh Artifact" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to remove the meshgrid artifact present in the data, an fft filtering is applied already in the data loaded previously. For this, parameters of the fft peaks corresponding to the grid are required which can be provided in the config file. Alternatively, one can also interactively optimize the parameters using the fft tool" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sps.fft_tool(\n", + " fft_tool_params={\n", + " \"amplitude\": 1,\n", + " \"pos_x\": 82,\n", + " \"pos_y\": 116,\n", + " \"sigma_x\": 15,\n", + " \"sigma_y\": 23\n", + " },\n", + " apply=True # Use apply=False for interactive mode\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load the scan again for the new changes to apply to all the images" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "res_xarray = sps.load_scan(\n", + " scan=4450,\n", + " path=path,\n", + " apply_fft_filter=True\n", + ")\n", + "\n", + "plt.figure()\n", + "res_xarray[:,:,0].plot()" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -200,7 +255,7 @@ "outputs": [], "source": [ "plt.figure()\n", - "sps.result.loc[{\"Angle\": slice(-5, 5)}].sum(axis=0).plot()" + "sps.result.loc[{\"angular1\": slice(-5, 5)}].sum(axis=0).plot()" ] }, { @@ -317,7 +372,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.8.0" }, "vscode": { "interpreter": { From 5807b1305ac227651440adebd996709e9276733b Mon Sep 17 00:00:00 2001 From: Arora0 Date: Fri, 19 Apr 2024 15:24:40 +0200 Subject: [PATCH 17/20] assert almost close instead of exact comparison --- tests/test_specsscan.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/tests/test_specsscan.py b/tests/test_specsscan.py index 9976309..6e58bce 100755 --- a/tests/test_specsscan.py +++ b/tests/test_specsscan.py @@ -282,7 +282,11 @@ def test_fft_tool(): path=test_dir, ) - assert(res_xarray.data.sum() == 62232679364.331406) + np.testing.assert_almost_equal( + res_xarray.data.sum(), + 62232679364.331406, + decimal=3 + ) res_xarray = sps.load_scan( scan=3610, @@ -290,7 +294,11 @@ def test_fft_tool(): fft_filter_peaks=fft_filter_peaks, apply_fft_filter=True, ) - assert(res_xarray.data.sum() == 62197237155.50347) + np.testing.assert_almost_equal( + res_xarray.data.sum(), + 62197237155.50347, + decimal=3 + ) sps.fft_tool( fft_tool_params={ @@ -307,7 +315,11 @@ def test_fft_tool(): path=test_dir, apply_fft_filter=True ) - assert(res_xarray.data.sum() == 62197237155.50347) + np.testing.assert_almost_equal( + res_xarray.data.sum(), + 62197237155.50347, + decimal=3 + ) def test_conversion_and_save_to_nexus(): From fef2a1cb986b2fb7f4d20236e1c26c8ee4e6d997 Mon Sep 17 00:00:00 2001 From: rettigl Date: Fri, 19 Apr 2024 21:19:27 +0200 Subject: [PATCH 18/20] linting --- tests/test_specsscan.py | 45 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 36 deletions(-) diff --git a/tests/test_specsscan.py b/tests/test_specsscan.py index 6e58bce..642b9a8 100755 --- a/tests/test_specsscan.py +++ b/tests/test_specsscan.py @@ -6,19 +6,14 @@ import pytest import specsscan +from specsanalyzer.core import create_fft_params from specsscan import __version__ from specsscan import SpecsScan -from specsanalyzer.core import create_fft_params package_dir = os.path.dirname(specsscan.__file__) test_dir = package_dir + "/../tests/data/" -fft_filter_peaks = create_fft_params( - amp=1, - pos_x=82, - pos_y=116, - sig_x=15, - sig_y=23 -) +fft_filter_peaks = create_fft_params(amp=1, pos_x=82, pos_y=116, sig_x=15, sig_y=23) + def test_version(): """Test if the package has the correct version string.""" @@ -282,11 +277,7 @@ def test_fft_tool(): path=test_dir, ) - np.testing.assert_almost_equal( - res_xarray.data.sum(), - 62232679364.331406, - decimal=3 - ) + np.testing.assert_almost_equal(res_xarray.data.sum(), 62232679364.331406, decimal=3) res_xarray = sps.load_scan( scan=3610, @@ -294,32 +285,14 @@ def test_fft_tool(): fft_filter_peaks=fft_filter_peaks, apply_fft_filter=True, ) - np.testing.assert_almost_equal( - res_xarray.data.sum(), - 62197237155.50347, - decimal=3 - ) + np.testing.assert_almost_equal(res_xarray.data.sum(), 62197237155.50347, decimal=3) sps.fft_tool( - fft_tool_params={ - "amplitude": 1, - "pos_x": 82, - "pos_y": 116, - "sigma_x": 15, - "sigma_y": 23 - }, - apply=True - ) - res_xarray = sps.load_scan( - scan=3610, - path=test_dir, - apply_fft_filter=True - ) - np.testing.assert_almost_equal( - res_xarray.data.sum(), - 62197237155.50347, - decimal=3 + fft_tool_params={"amplitude": 1, "pos_x": 82, "pos_y": 116, "sigma_x": 15, "sigma_y": 23}, + apply=True, ) + res_xarray = sps.load_scan(scan=3610, path=test_dir, apply_fft_filter=True) + np.testing.assert_almost_equal(res_xarray.data.sum(), 62197237155.50347, decimal=3) def test_conversion_and_save_to_nexus(): From b810859f5428129a220a59abcef7ffb8fca1fc18 Mon Sep 17 00:00:00 2001 From: rettigl Date: Fri, 19 Apr 2024 21:34:25 +0200 Subject: [PATCH 19/20] update start intensity, and update docstring --- specsanalyzer/core.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/specsanalyzer/core.py b/specsanalyzer/core.py index d88707b..9acec64 100755 --- a/specsanalyzer/core.py +++ b/specsanalyzer/core.py @@ -572,12 +572,21 @@ def fft_tool( apply: bool = False, **kwds, ): - """FFT tool to play around with the peak parameters in the Fourier plane. - Built to filter out the meshgrid appearing in the raw data images. The - optimized parameters are stored in the class config dict under - fft_filter_peaks. + """FFT tool to play around with the peak parameters in the Fourier plane. Built to filter + out the meshgrid appearing in the raw data images. The optimized parameters are stored in + the class config dict under fft_filter_peaks. + Args: - raw_image: A single 2-D data set. + raw_image (np.ndarray): The source image + apply (bool, optional): Option to directly apply the settings. Defaults to False. + **kwds: Keyword arguments: + + - fft_tool_params (dict): Dictionary of parameters for fft_tool, containing keys + `amplitude`: Normalized amplitude of subtraction + `pos_x`: horzontal spatial frequency of th mesh + `pos_y`: vertical spatial frequency of the mesh + `sigma_x`: horizontal frequency width + `sigma_y`: vertical frequency width """ matplotlib.use("module://ipympl.backend_nbagg") try: @@ -655,14 +664,14 @@ def fft_tool( description="sig_x", value=sig_x, min=0, - max=200, + max=50, step=1, ) sigy_slider = ipw.FloatSlider( description="sig_y", value=sig_y, min=0, - max=200, + max=50, step=1, ) amp_slider = ipw.FloatSlider( @@ -674,7 +683,7 @@ def fft_tool( ) clim_slider = ipw.FloatLogSlider( description="colorbar limits", - value=1e4, + value=int(np.abs(img).max() / 500), base=10, min=-1, max=int(np.log10(np.abs(img).max())) + 1, From 7382d01fa1df71b85ede8e7c4d6cdf3e8825c2e2 Mon Sep 17 00:00:00 2001 From: rettigl Date: Fri, 19 Apr 2024 21:35:11 +0200 Subject: [PATCH 20/20] update test config --- specsscan/config/example_config_FHI.yaml | 8 ++++---- tests/data | 2 +- tests/test_specsscan.py | 5 ++++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/specsscan/config/example_config_FHI.yaml b/specsscan/config/example_config_FHI.yaml index 12fca1b..bcd7398 100644 --- a/specsscan/config/example_config_FHI.yaml +++ b/specsscan/config/example_config_FHI.yaml @@ -86,12 +86,12 @@ spa_params: # sigma_x/sigma_y: the peak width (standard deviation) along each direction fft_filter_peaks: - amplitude: 1 - pos_x: -49 + pos_x: 79 pos_y: 0 sigma_x: 8 sigma_y: 8 - amplitude: 1 - pos_x: 48 + pos_x: -80 pos_y: 0 sigma_x: 8 sigma_y: 8 @@ -101,12 +101,12 @@ spa_params: sigma_x: 5 sigma_y: 8 - amplitude: 1 - pos_x: -50 + pos_x: 78 pos_y: 109 sigma_x: 5 sigma_y: 5 - amplitude: 1 - pos_x: 47 + pos_x: -81 pos_y: 108 sigma_x: 5 sigma_y: 5 diff --git a/tests/data b/tests/data index b84798f..a6ef660 160000 --- a/tests/data +++ b/tests/data @@ -1 +1 @@ -Subproject commit b84798f1c85f76461cdd4b5741bf1a4a0ba555e4 +Subproject commit a6ef660ee7032f1d474d30f12299e3bbd417a5c4 diff --git a/tests/test_specsscan.py b/tests/test_specsscan.py index 642b9a8..f27d1ae 100755 --- a/tests/test_specsscan.py +++ b/tests/test_specsscan.py @@ -275,9 +275,10 @@ def test_fft_tool(): res_xarray = sps.load_scan( scan=3610, path=test_dir, + apply_fft_filter=False, ) - np.testing.assert_almost_equal(res_xarray.data.sum(), 62232679364.331406, decimal=3) + np.testing.assert_almost_equal(res_xarray.data.sum(), 62145561928.15108, decimal=3) res_xarray = sps.load_scan( scan=3610, @@ -291,6 +292,8 @@ def test_fft_tool(): fft_tool_params={"amplitude": 1, "pos_x": 82, "pos_y": 116, "sigma_x": 15, "sigma_y": 23}, apply=True, ) + assert sps.config["spa_params"]["fft_filter_peaks"] == fft_filter_peaks + assert sps.spa.config["fft_filter_peaks"] == fft_filter_peaks res_xarray = sps.load_scan(scan=3610, path=test_dir, apply_fft_filter=True) np.testing.assert_almost_equal(res_xarray.data.sum(), 62197237155.50347, decimal=3)