diff --git a/httomolib/misc/blend.py b/httomolib/misc/blend.py index b0653ba..24e5804 100644 --- a/httomolib/misc/blend.py +++ b/httomolib/misc/blend.py @@ -27,6 +27,7 @@ __check_variable_type, __check_if_data_3D_array, __check_if_data_correct_type, + __check_if_positive_nonzero, ) __all__ = [ @@ -36,27 +37,24 @@ def seam_blend_stitched_data( data: np.ndarray, - seam_index: Optional[int] = None, - blending_width: Optional[int] = None, - path_to_stitched_params_file: Optional[str] = None, - shift_seam_index: int = 0, + overlap: int, + seam_index: int = 2560, + shift_seam_index: Optional[int] = None, ) -> np.ndarray: """ - Function blends the seam present in the stitched projection data. It uses the redundant by blending_width data present on both sides of the seam. - Used in HTTomo for seamless stitching of datasets coming from two different PCO cameras. + Function blends the seam present in the stitched projection data using the overlap value provided. + Used in HTTomo for seamless stitching of datasets coming from two different (PCO) cameras. Parameters ---------- data : np.ndarray 3d array of the stitched data, assuming the following axis ["angles", "detY", "detX"]. - seam_index : Optional, int - The horizontal index of the seam along the 'detX' axis. If None and 'path_to_stitched_params_file' is provided, it will be taken from the file, otherwise middle of the horizontal axis. - blending_width : Optional, int - The area for symmetric blending (e.g. with the ramp filter) around the seam position (seam_index) of the stitched data. If None and 'path_to_stitched_params_file' is provided, it will be taken from the file, otherwise 0. - path_to_stitched_params_file : Optional, str - Path to the text file with the stiching parameters. If provided 'seam_index' and 'blending_width' parameters will be overridden by the ones provided in the file. - shift_seam_index : int - performs a shift of the seam index with seam_index - shift_seam_index. This is purely an HTTomo related feature and should be ignored by users. + overlap : int + Overlap between the LEFT and the RIGHT images of the stitched data. Usually known from the experiment. + seam_index : int + The horizontal index of the seam in the stitched data. Normally equals to the width of one frame/projection before the stitching. + shift_seam_index : optional, int + performs a shift of the 'seam index' that is introduced by the data cropping. This is an HTTomo related feature and should be ignored by users. Raises ---------- ValueError: When data is not 3D. @@ -66,63 +64,47 @@ def seam_blend_stitched_data( np.ndarray: stitched data without the seam. """ ### Data and parameters checks ### - methods_name = "seam_blender" + methods_name = "seam_blend_stitched_data" __check_if_data_3D_array(data, methods_name) __check_if_data_correct_type( data, accepted_type=["float64", "float32", "uint8", "uint16", "uint32"], methods_name=methods_name, ) - __check_variable_type(seam_index, [int, type(None)], "seam_index", [], methods_name) - __check_variable_type( - blending_width, [int, type(None)], "blending_width", [], methods_name + __check_if_positive_nonzero( + seam_index, + "seam_index", + True, + True, + methods_name, ) + __check_variable_type(seam_index, [int], "seam_index", [], methods_name) __check_variable_type( - path_to_stitched_params_file, - [str, type(None)], - "path_to_stitched_params_file", - [], - methods_name, + shift_seam_index, [int, type(None)], "shift_seam_index", [], methods_name ) ################################### - angles_dim, detY, detX = data.shape - - if path_to_stitched_params_file is not None: - params = {} - with open(path_to_stitched_params_file) as f: - for line in f: - key, value = line.split() - params[key] = int(value) + if shift_seam_index is None: + shift_seam_index = 0 - blending_width = params.get("blending_width") - seam_index = params.get("seam_index") - - if blending_width is None: - blending_width = 0 - if seam_index is None: - seam_index = int(detX // 2) - - blending_width *= 2 seam_index -= shift_seam_index - if seam_index >= detX - blending_width: - err_str = f"Seam index given as '{seam_index}' must be smaller than the horizontal dimension of the data '{detX}' minus blending width." + angles_dim, detY, detX = data.shape + if seam_index < 0 or seam_index >= detX: + err_str = f"Seam index '{seam_index}' cannot be negative or larger than the horizontal dimension of the data '{detX}'. Check 'shift_seam_index'." raise ValueError(err_str) - # Split regions of data - left_part = data[:, :, 0 : (seam_index - blending_width)] - right_part = data[:, :, (seam_index + blending_width) : :] - - # Overlap regions - left_overlap = data[:, :, (seam_index - blending_width) : seam_index] - right_overlap = data[:, :, seam_index : (seam_index + blending_width)] + ramp = np.linspace(0, 1, overlap) - # Create ramp weights (0 → 1) - ramp = np.float32(np.linspace(0, 1, blending_width)) - ramp = np.tile(ramp, (detY, 1)) + blended_data = np.empty((angles_dim, detY, detX - overlap), dtype=data.dtype) - # Blend - blended_overlap = (1 - ramp) * left_overlap + ramp * right_overlap + blended_data[:, :, 0 : seam_index - overlap] = data[ + :, :, 0 : seam_index - overlap + ] # left side + blended_data[:, :, seam_index::] = data[:, :, seam_index + overlap :] # right side + blended_data[:, :, seam_index - overlap : seam_index] = ( + data[:, :, seam_index - overlap : seam_index] * ramp[::-1] + + data[:, :, seam_index : seam_index + overlap] * ramp + ) # overlap area - return np.dstack([left_part, blended_overlap, right_part]) + return blended_data diff --git a/tests/conftest.py b/tests/conftest.py index 7da3fd3..e80e634 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -56,12 +56,6 @@ def data_stitched(test_data_path): return np.load(in_file) -@pytest.fixture(scope="session") -def data_stitched_txt(test_data_path): - in_file = os.path.join(test_data_path, "stitching_params.txt") - return in_file - - @pytest.fixture def host_data(data_file): return np.copy(data_file["data"]) diff --git a/tests/test_data/stitching_params.txt b/tests/test_data/stitching_params.txt deleted file mode 100644 index 3ddde47..0000000 --- a/tests/test_data/stitching_params.txt +++ /dev/null @@ -1,2 +0,0 @@ -blending_width 30 -seam_index 151 diff --git a/tests/test_misc/test_blend.py b/tests/test_misc/test_blend.py index ed169aa..855ece5 100644 --- a/tests/test_misc/test_blend.py +++ b/tests/test_misc/test_blend.py @@ -5,19 +5,23 @@ def test_seam_blend_stitched_data(data_stitched): - result = seam_blend_stitched_data(data_stitched, seam_index=151, blending_width=30) + result = seam_blend_stitched_data( + data_stitched, overlap=20, seam_index=151, shift_seam_index=None + ) assert result.flags.c_contiguous - assert result.dtype == np.float32 - assert result.shape == (300, 4, 240) + assert result.dtype == np.uint16 + assert result.shape == (300, 4, 280) + np.testing.assert_array_almost_equal(int(np.mean(result)), 11520) -def test_seam_blend_stitched_data_txt(data_stitched, data_stitched_txt): +def test_seam_blend_stitched_data_shift(data_stitched): result = seam_blend_stitched_data( - data_stitched, path_to_stitched_params_file=data_stitched_txt + data_stitched, overlap=20, seam_index=151, shift_seam_index=10 ) assert result.flags.c_contiguous - assert result.dtype == np.float32 - assert result.shape == (300, 4, 240) + assert result.dtype == np.uint16 + assert result.shape == (300, 4, 280) + np.testing.assert_array_almost_equal(int(np.mean(result)), 11506)