Skip to content

Commit 59a7c83

Browse files
authored
Merge pull request #216 from DiamondLightSource/center360
Center360 and stitching corrections
2 parents b582acc + 87d9a4f commit 59a7c83

File tree

9 files changed

+183
-318
lines changed

9 files changed

+183
-318
lines changed

httomolibgpu/misc/morph.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444

4545

4646
def sino_360_to_180(
47-
data: cp.ndarray, overlap: int = 0, rotation: Literal["left", "right"] = "left"
47+
data: cp.ndarray, overlap: float = 0, side: Literal["left", "right"] = "left"
4848
) -> cp.ndarray:
4949
"""
5050
Converts 0-360 degrees sinogram to a 0-180 sinogram.
@@ -55,9 +55,9 @@ def sino_360_to_180(
5555
----------
5656
data : cp.ndarray
5757
Input 3D data.
58-
overlap : scalar, optional
59-
Overlapping number of pixels.
60-
rotation : string, optional
58+
overlap : float
59+
Overlapping number of pixels. Floats will be converted to integers.
60+
side : string
6161
'left' if rotation center is close to the left of the
6262
field-of-view, 'right' otherwise.
6363
Returns
@@ -74,26 +74,28 @@ def sino_360_to_180(
7474

7575
overlap = int(np.round(overlap))
7676
if overlap >= dz:
77-
raise ValueError("overlap must be less than data.shape[2]")
77+
raise ValueError("Overlap must be less than data.shape[2]")
7878
if overlap < 0:
79-
raise ValueError("only positive overlaps are allowed.")
79+
raise ValueError("Only positive overlaps are allowed.")
8080

81-
if rotation not in ["left", "right"]:
82-
raise ValueError('rotation parameter must be either "left" or "right"')
81+
if side not in ["left", "right"]:
82+
raise ValueError(
83+
f'The value {side} is invalid, only "left" or "right" strings are accepted'
84+
)
8385

8486
n = dx // 2
8587

8688
out = cp.empty((n, dy, 2 * dz - overlap), dtype=data.dtype)
8789

88-
if rotation == "left":
90+
if side == "left":
8991
weights = cp.linspace(0, 1.0, overlap, dtype=cp.float32)
9092
out[:, :, -dz + overlap :] = data[:n, :, overlap:]
9193
out[:, :, : dz - overlap] = data[n : 2 * n, :, overlap:][:, :, ::-1]
9294
out[:, :, dz - overlap : dz] = (
9395
weights * data[:n, :, :overlap]
9496
+ (weights * data[n : 2 * n, :, :overlap])[:, :, ::-1]
9597
)
96-
if rotation == "right":
98+
if side == "right":
9799
weights = cp.linspace(1.0, 0, overlap, dtype=cp.float32)
98100
out[:, :, : dz - overlap] = data[:n, :, :-overlap]
99101
out[:, :, -dz + overlap :] = data[n : 2 * n, :, :-overlap][:, :, ::-1]

httomolibgpu/recon/rotation.py

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -416,27 +416,26 @@ def find_center_360(
416416
data: cp.ndarray,
417417
ind: Optional[int] = None,
418418
win_width: int = 10,
419-
side: Optional[Literal[0, 1]] = None,
419+
side: Optional[Literal["left", "right"]] = None,
420420
denoise: bool = True,
421421
norm: bool = False,
422422
use_overlap: bool = False,
423-
) -> Tuple[float, float, Optional[Literal[0, 1]], float]:
423+
) -> Tuple[np.float32, np.float32, Optional[Literal["left", "right"]], np.float32]:
424424
"""
425425
Find the center-of-rotation (COR) in a 360-degree scan and also an offset
426426
to perform data transformation from 360 to 180 degrees scan. See :cite:`vo2021data`.
427427
428-
Parameters
428+
Parameters Tuple[np.float32, np.float32, Literal["left", "right"], np.float32]:
429429
----------
430430
data : cp.ndarray
431431
3D tomographic data as a Cupy array.
432432
ind : int, optional
433433
Index of the slice to be used for estimate the CoR and the overlap.
434434
win_width : int, optional
435435
Window width used for finding the overlap area.
436-
side : {None, 0, 1}, optional
437-
Overlap size. Only there options: None, 0, or 1. "None" corresponds
438-
to fully automated determination. "0" corresponds to the left side.
439-
"1" corresponds to the right side.
436+
side : {None, left, right}, optional
437+
Chose between "left", "right" or "None" which corresponds to fully
438+
automated determination of the side.
440439
denoise : bool, optional
441440
Apply the Gaussian filter if True.
442441
norm : bool, optional
@@ -451,8 +450,8 @@ def find_center_360(
451450
Center-of-rotation.
452451
overlap : float
453452
Width of the overlap area between two halves of the sinogram.
454-
side : int
455-
Overlap side between two halves of the sinogram.
453+
side : str
454+
Overlap side (left or right) between two halves of the sinogram.
456455
overlap_position : float
457456
Position of the window in the first image giving the best
458457
correlation metric.
@@ -475,10 +474,7 @@ def find_center_360(
475474
(overlap, side, overlap_position) = _find_overlap(
476475
sino_top, sino_bot, win_width, side, denoise, norm, use_overlap
477476
)
478-
if side == 0:
479-
cor = overlap / 2.0 - 1.0
480-
else:
481-
cor = ncol - overlap / 2.0 - 1.0
477+
cor = ncol - overlap / 2
482478

483479
return cor, overlap, side, overlap_position
484480

@@ -498,10 +494,9 @@ def _find_overlap(
498494
2D array. Projection image or sinogram image.
499495
win_width : int
500496
Width of the searching window.
501-
side : {None, 0, 1}, optional
502-
Only there options: None, 0, or 1. "None" corresponding to fully
503-
automated determination. "0" corresponding to the left side. "1"
504-
corresponding to the right side.
497+
side : {None, left, right}, optional
498+
Chose between "left", "right" or "None" which corresponds to fully
499+
automated determination of the side.
505500
denoise : bool, optional
506501
Apply the Gaussian filter if True.
507502
norm : bool, optional
@@ -514,8 +509,8 @@ def _find_overlap(
514509
-------
515510
overlap : float
516511
Width of the overlap area between two images.
517-
side : int
518-
Overlap side between two images.
512+
side : str
513+
Overlap side (left or right) between two images.
519514
overlap_position : float
520515
Position of the window in the first image giving the best
521516
correlation metric.
@@ -525,25 +520,25 @@ def _find_overlap(
525520
ncol2 = mat2.shape[1]
526521
win_width = int(np.clip(win_width, 6, min(ncol1, ncol2) // 2))
527522

528-
if side == 1:
523+
if side == "right":
529524
(list_metric, offset) = _search_overlap(
530525
mat1,
531526
mat2,
532527
win_width,
533-
side=side,
528+
side=1, # right side
534529
denoise=denoise,
535530
norm=norm,
536531
use_overlap=use_overlap,
537532
)
538533
overlap_position = _calculate_curvature(list_metric)[1]
539534
overlap_position += offset
540535
overlap = ncol1 - overlap_position + win_width // 2
541-
elif side == 0:
536+
elif side == "left":
542537
(list_metric, offset) = _search_overlap(
543538
mat1,
544539
mat2,
545540
win_width,
546-
side=side,
541+
side=0, # left side
547542
denoise=denoise,
548543
norm=norm,
549544
use_overlap=use_overlap,
@@ -556,7 +551,7 @@ def _find_overlap(
556551
mat1,
557552
mat2,
558553
win_width,
559-
side=1,
554+
side=1, # right side
560555
denoise=denoise,
561556
norm=norm,
562557
use_overlap=use_overlap,
@@ -565,7 +560,7 @@ def _find_overlap(
565560
mat1,
566561
mat2,
567562
win_width,
568-
side=0,
563+
side=0, # left side
569564
denoise=denoise,
570565
norm=norm,
571566
use_overlap=use_overlap,
@@ -577,11 +572,11 @@ def _find_overlap(
577572
overlap_position2 += offset2
578573

579574
if curvature1 > curvature2:
580-
side = 1
575+
side = "right"
581576
overlap_position = overlap_position1
582577
overlap = ncol1 - overlap_position + win_width // 2
583578
else:
584-
side = 0
579+
side = "left"
585580
overlap_position = overlap_position2
586581
overlap = overlap_position + win_width // 2
587582

0 commit comments

Comments
 (0)