Skip to content

Commit

Permalink
change extract_sinogram to actually just do sinograms
Browse files Browse the repository at this point in the history
fix tests to match
  • Loading branch information
jat255 committed Nov 4, 2024
1 parent b413ab7 commit 30f4743
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 72 deletions.
55 changes: 19 additions & 36 deletions etspy/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2085,69 +2085,52 @@ def recon_error(

def extract_sinogram(
self,
column: Optional[Union[int, float]] = None,
row: Optional[Union[int, float]] = None,
column: Union[int, float], # noqa: PYI041
) -> Signal2D:
"""
Extract a sinogram from a single row or column of the TomoStack.
Extract a sinogram from a single column of the TomoStack.
Exactly one of either "column" (x-axis location) or "row" (y-axis
location) must be provided. The value to use can be supplied as either
The value to use for ``column`` can be supplied as either
an integer for pixel-based indexing, or as a float for unit-based
indexing. The resulting image will have the stack's projection axis
oriented vertically and the opposite axis horizontally.
oriented vertically and the y-axis horizontally.
Parameters
----------
column
The x-axis position to use for computing the sinogram. If an integer,
pixel-basd indexing will be used. If a float, unit-based indexing will
be used.
row
The y-axis position to use for computing the sinogram. If an integer,
pixel-basd indexing will be used. If a float, unit-based indexing will
be used.
Returns
-------
sino : Signal2D
A single image representing the row or column data over the range of
A single image representing the single column data over the range of
projections in the original TomoStack.
Raises
------
ValueError
Raised if both column and row arguments are provided, or if neither
are provided.
TypeError
Raised if column is neither a float or int
"""
if (column is not None) and (row is not None):
msg = 'Only one of "column" or "row" may be provided.'
raise ValueError(msg)
if (column is None) and (row is None):
msg = 'One of "column" or "row" must be provided.'
raise ValueError(msg)
if not isinstance(column, (float, int)):
msg = (
'"column" argument must be either a float or an integer '
f"(was {type(column)})"
)
raise TypeError(msg)

# hide isig warning from TomoStackSlicer
orig_logger_state = logger.disabled
logger.disabled = True
try:
sino = self
if row:
sino = self.isig[:, row]
sino.set_signal_type("")
sino = cast(Signal2D, sino.as_signal2D((1, 0)))
if isinstance(row, float):
title = f"Sinogram at y = {row} {self.axes_manager[2].units}" # type: ignore
else:
title = f"Sinogram at row {row}"
sino = self.isig[column, :]
sino.set_signal_type("")
sino = cast(Signal2D, sino.as_signal2D((2, 0)))
if isinstance(column, float):
title = f"Sinogram at x = {column} {self.axes_manager[1].units}" # type: ignore
else:
sino = self.isig[column, :]
sino.set_signal_type("")
sino = cast(Signal2D, sino.as_signal2D((2, 0)))
if isinstance(column, float):
title = f"Sinogram at x = {column} {self.axes_manager[1].units}" # type: ignore
else:
title = f"Sinogram at column {column}"
title = f"Sinogram at column {column}"
except Exception:
# if there was an error above, reset the logger state
# before raising it
Expand Down
49 changes: 13 additions & 36 deletions etspy/tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -862,68 +862,45 @@ def test_recstack_sig_slicer(self, caplog):
class TestExtractSinogram:
"""Test extract_sinogram method."""

def test_extract_sinogram_row(self):
def test_extract_sinogram(self):
stack = ds.get_catalyst_data()
sino = stack.extract_sinogram(row=300)
ax_0, ax_1 = cast(list[Uda], [sino.axes_manager[i] for i in range(2)])
assert sino.axes_manager.shape == (600, 90)
assert sino.metadata.get_item("Signal.signal_type") == ""
assert ax_0.name == "x"
assert ax_1.name == "Projections"
assert sino.metadata.get_item("General.title") == "Sinogram at row 300"

def test_extract_sinogram_row_float(self):
stack = ds.get_catalyst_data()
sino = stack.extract_sinogram(row=102.3)
ax_0, ax_1 = cast(list[Uda], [sino.axes_manager[i] for i in range(2)])
assert sino.axes_manager.shape == (600, 90)
assert sino.metadata.get_item("Signal.signal_type") == ""
assert ax_0.name == "x"
assert ax_1.name == "Projections"
assert sino.metadata.get_item("General.title") == "Sinogram at y = 102.3 nm"

def test_extract_sinogram_column(self):
stack = ds.get_catalyst_data()
sino = stack.extract_sinogram(column=300)
sino = stack.extract_sinogram(300)
ax_0, ax_1 = cast(list[Uda], [sino.axes_manager[i] for i in range(2)])
assert sino.axes_manager.shape == (600, 90)
assert sino.metadata.get_item("Signal.signal_type") == ""
assert ax_0.name == "y"
assert ax_1.name == "Projections"
assert sino.metadata.get_item("General.title") == "Sinogram at column 300"

def test_extract_sinogram_column_float(self):
def test_extract_sinogram_float(self):
stack = ds.get_catalyst_data()
sino = stack.extract_sinogram(column=106.32)
sino = stack.extract_sinogram(106.32)
ax_0, ax_1 = cast(list[Uda], [sino.axes_manager[i] for i in range(2)])
assert sino.axes_manager.shape == (600, 90)
assert sino.metadata.get_item("Signal.signal_type") == ""
assert ax_0.name == "y"
assert ax_1.name == "Projections"
assert sino.metadata.get_item("General.title") == "Sinogram at x = 106.32 nm"

def test_extract_sinogram_neither_row_nor_column(self):
def test_extract_sinogram_bad_argument_type(self):
stack = ds.get_catalyst_data()
with pytest.raises(
ValueError,
match=re.escape('One of "column" or "row" must be provided.'),
TypeError,
match=re.escape(
'"column" argument must be either a float or an integer '
"(was <class 'str'>)",
),
):
stack.extract_sinogram()
stack.extract_sinogram("bad_val") # type: ignore

def test_extract_sinogram_both_row_and_column(self):
stack = ds.get_catalyst_data()
with pytest.raises(
ValueError,
match=re.escape('Only one of "column" or "row" may be provided.'),
):
stack.extract_sinogram(row=300, column=200)

def test_extract_sinogram_exception_handling(self):
# test that on exception, logger is still enabled
stack = ds.get_catalyst_data()
assert logging.getLogger("etspy.base").disabled is False
with pytest.raises(IndexError):
stack.extract_sinogram(column="weird") # type: ignore
# using too large of a value should trigger an error
stack.extract_sinogram(column=10000)
assert logging.getLogger("etspy.base").disabled is False

class TestFiltering:
Expand Down

0 comments on commit 30f4743

Please sign in to comment.