Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
163 commits
Select commit Hold shift + click to select a range
cfba642
UPD: fix bound
vqdang Jan 29, 2024
8979008
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
shaneahmed Feb 2, 2024
84af337
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
shaneahmed Feb 2, 2024
6aab409
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
shaneahmed Feb 16, 2024
e09e216
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
shaneahmed Feb 21, 2024
249a716
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
shaneahmed Mar 1, 2024
246b2c8
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
shaneahmed Mar 15, 2024
817a526
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
shaneahmed Mar 19, 2024
28a324f
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
shaneahmed Apr 16, 2024
ade11ba
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
shaneahmed Apr 26, 2024
f4ac670
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
shaneahmed Apr 29, 2024
87450b2
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
Abdol May 13, 2024
6fdf9e7
✅ Add test
May 13, 2024
13d3293
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
Abdol May 14, 2024
b5c8861
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
Abdol Jun 7, 2024
a1acbfd
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
shaneahmed Jun 14, 2024
60361c2
Merge branch 'develop' into bugfix-tiffwsireader-readbounds
shaneahmed Jun 21, 2024
609469d
initial draft multichannel reading
measty Jun 21, 2024
aec8390
deepsource
measty Jun 21, 2024
4972332
make .tif be recognised same as .tiff
measty Jun 24, 2024
dccf4db
fix read_rect
measty Jun 26, 2024
bcefc31
optimizations
measty Jun 26, 2024
79dcd51
fix typo
measty Jun 26, 2024
a80655b
get colors from metadata if poss.
measty Jul 2, 2024
83c6954
deepsource
measty Jul 2, 2024
6e58ec5
:white_check_mark: Adding test for mutli_channel visualisation
behnazelhaminia Jul 5, 2024
c4e4232
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 5, 2024
5563e36
replace depreciated funcTickFormatter
measty Jul 5, 2024
79040ca
Merge branch 'multichannel-reading' of https://github.com/TissueImage…
measty Jul 5, 2024
cc66c53
:white_check_mark: Adding test for mutli_channel visualisation
behnazelhaminia Jul 5, 2024
7f4423c
drop background autofluorescence channel if appropriate
measty Aug 7, 2024
e9222ea
Merge branch 'multichannel-reading' of https://github.com/TissueImage…
measty Aug 7, 2024
ba26d1d
Merge branch 'develop' of https://github.com/TissueImageAnalytics/tia…
measty Aug 7, 2024
8e2c11a
remove a print
measty Aug 7, 2024
fad00c3
:white_check_mark: Assert shape and interpolation
behnazelhaminia Aug 9, 2024
464a5a2
:white_check_mark: Test for multichannel visualisation
behnazelhaminia Aug 9, 2024
b380fb4
Merge remote-tracking branch 'origin/multichannel-reading' into multi…
behnazelhaminia Aug 9, 2024
75bbdbd
:white_check_mark: Test for multichannel visualisation
behnazelhaminia Aug 9, 2024
b148ed3
Update remote_samples.yaml
behnazelhaminia Aug 9, 2024
d27f34d
Merge branch 'develop' into multichannel-reading
shaneahmed Aug 9, 2024
93ed2d1
first channel selector draft
measty Aug 21, 2024
7f5b61c
Merge branch 'multichannel-reading' of https://github.com/TissueImage…
measty Aug 21, 2024
a3992d1
Merge branch 'multichannel-reading' of https://github.com/TissueImage…
measty Aug 21, 2024
df5a59d
multichannel ui update
measty Aug 22, 2024
e342290
Merge branch 'develop' of https://github.com/TissueImageAnalytics/tia…
measty Aug 22, 2024
6970bae
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 22, 2024
063aba8
fix a test
measty Aug 22, 2024
71dcf80
Merge branch 'multichannel-reading' of https://github.com/TissueImage…
measty Aug 22, 2024
00eb70e
more efficient channel select ui
measty Aug 25, 2024
883ce40
multichannel ui layout tweak
measty Aug 29, 2024
9df1566
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 29, 2024
ccb62d0
Merge branch 'develop' into multichannel-reading
shaneahmed Sep 20, 2024
edd6f63
robustify level sort
measty Sep 21, 2024
4b17e1e
Merge branch 'multichannel-reading' of https://github.com/TissueImage…
measty Sep 21, 2024
437345d
Merge branch 'develop' of https://github.com/TissueImageAnalytics/tia…
measty Sep 21, 2024
1bb78d8
Merge remote-tracking branch 'origin/multichannel-reading' into multi…
behnazelhaminia Sep 26, 2024
3a024dd
:white_check_mark: Adding small multiplxed image
behnazelhaminia Sep 26, 2024
d4bb297
Merge branch 'develop' into multichannel-reading
shaneahmed Oct 4, 2024
9d8ac0c
dataset fix
measty Nov 4, 2024
62503cf
Merge branch 'develop' into multichannel-reading
shaneahmed Nov 22, 2024
cc3f826
Merge branch 'develop' into multichannel-reading
shaneahmed Jan 13, 2025
02809c5
Merge branch 'develop' into multichannel-reading
shaneahmed Jan 24, 2025
a352b3e
Merge branch 'multichannel-reading' of https://github.com/TissueImage…
measty Jan 31, 2025
41d2fee
fix get_channels and address ruff
measty Jan 31, 2025
0425917
precommit fixes
measty Jan 31, 2025
e4b44d7
dont fix arg001
measty Jan 31, 2025
4ca6660
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 31, 2025
312e5b5
precommit..
measty Jan 31, 2025
29f7b38
Merge branch 'develop' into multichannel-reading
shaneahmed Feb 7, 2025
68c375c
comet format support
measty Feb 14, 2025
3b9af3c
Merge branch 'develop' into multichannel-reading
shaneahmed Feb 21, 2025
da0161b
Merge branch 'develop' of https://github.com/TissueImageAnalytics/tia…
measty Mar 6, 2025
b228d78
metadata update
measty Mar 14, 2025
08185c4
Merge branch 'multichannel-reading' of https://github.com/TissueImage…
measty Mar 14, 2025
cc62b1a
Merge branch 'multichannel-reading' of https://github.com/TissueImage…
measty May 1, 2025
77bafab
Merge branch 'develop' of https://github.com/TissueImageAnalytics/tia…
measty May 1, 2025
ea9ecc0
Merge branch 'develop' into multichannel-reading
shaneahmed May 23, 2025
4558d6b
Merge branch 'develop' into multichannel-reading
shaneahmed May 30, 2025
334bd56
Merge branch 'develop' of https://github.com/TissueImageAnalytics/tia…
measty Jun 20, 2025
6521ca8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 20, 2025
a31fc56
Merge branch 'develop' into multichannel-reading
shaneahmed Jul 4, 2025
8a06faf
Merge branch 'develop' into multichannel-reading
adamshephard Jul 11, 2025
d6a5549
fix channel table bug
measty Jul 11, 2025
1279e98
UPD: Multichannel reading comet files
adamshephard Jul 14, 2025
65c6fc4
Merge branch 'multichannel-reading' of github.com:TissueImageAnalytic…
adamshephard Jul 14, 2025
cc1efe7
Merge branch 'develop' into multichannel-reading
adamshephard Jul 25, 2025
ccf7405
UPD: Fix deepsource issues
adamshephard Aug 1, 2025
ca6bcea
UPD: Fix deepsource issues
adamshephard Aug 1, 2025
8f7efc3
UPD: Fix deepsource issues
adamshephard Aug 1, 2025
ed18c17
UPD: Fix deepsource issues
adamshephard Aug 1, 2025
8f7a3e7
UPD: Fix deepsource issues
adamshephard Aug 1, 2025
4ff5e43
UPD: Fix mypy issues
adamshephard Aug 1, 2025
755b083
UPD: Fix mypy issues
adamshephard Aug 1, 2025
d1e14c5
UPD: Fix mypy issues
adamshephard Aug 1, 2025
faf4194
UPD: Fix mypy issues
adamshephard Aug 1, 2025
5ca7fc8
FIX: Fix tiffwsireader for missing metadata
adamshephard Aug 13, 2025
c858d84
Merge branch 'develop' into multichannel-reading
adamshephard Aug 13, 2025
e52504f
FIX: Reduce complexity of wsipatchdataset init
adamshephard Aug 13, 2025
2aa6d1e
FIX: Reduce complexity of wsipatchdataset init
adamshephard Aug 13, 2025
f1099bf
FIX: Fix deepsource errors
adamshephard Aug 13, 2025
986c5a3
FIX: Fix deepsource errors
adamshephard Aug 13, 2025
c0257f5
UPD: Add sample_qptiff to tests
adamshephard Aug 13, 2025
63f6857
FIX: Fix issues with objective power
adamshephard Aug 14, 2025
b6d563e
UPD: Update tests
adamshephard Aug 14, 2025
98336b4
UPD: Update tests
adamshephard Aug 14, 2025
8073ace
ADD: Add unit test for tiffreader
adamshephard Aug 14, 2025
3291776
ADD: Add unit test for tiffreader
adamshephard Aug 14, 2025
5f1c6a2
ADD: Add unit test for tiffreader
adamshephard Aug 14, 2025
070a490
ADD: Add unit test for tiffreader
adamshephard Aug 14, 2025
3c296e5
ADD: Add unit test for tiffreader
adamshephard Aug 14, 2025
3cb94c8
ADD: Add unit test for tiffreader
adamshephard Aug 14, 2025
bf28f0e
ADD: Add unit test for tiffreader
adamshephard Aug 14, 2025
d55fccc
ADD: Add unit test for tiffreader
adamshephard Aug 14, 2025
f9131f9
UPD: Update tests
adamshephard Aug 15, 2025
492f36b
UPD: Update tests
adamshephard Aug 15, 2025
ed99162
UPD: Update tests
adamshephard Aug 15, 2025
ef7f745
Merge branch 'develop' into multichannel-reading
shaneahmed Sep 4, 2025
f5fb4bd
Merge branch 'develop' into multichannel-reading
shaneahmed Oct 3, 2025
f92aa26
Merge branch 'develop' into multichannel-reading
shaneahmed Oct 10, 2025
9a0ed9b
Merge branch 'develop' into multichannel-reading
adamshephard Oct 17, 2025
17f8678
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 17, 2025
aecdfdf
Merge branch 'develop' into multichannel-reading
shaneahmed Oct 21, 2025
0d17974
:bug: TC003 Move standard library import `collections.abc.Callable` i…
shaneahmed Oct 21, 2025
eecdf59
:white_check_mark: Use `track_tmp_path` instead of `tmp_path`
shaneahmed Oct 21, 2025
75b99bf
Merge branch 'develop' into multichannel-reading
shaneahmed Nov 14, 2025
165909b
Merge branch 'develop' into multichannel-reading
shaneahmed Nov 17, 2025
69028c4
Merge branch 'develop' into multichannel-reading
shaneahmed Dec 5, 2025
9e3e77d
Merge branch 'develop' into multichannel-reading
shaneahmed Dec 19, 2025
aa84ad5
Merge branch 'develop' into multichannel-reading
shaneahmed Jan 9, 2026
94ca8ae
Merge branch 'develop' into multichannel-reading
Jiaqi-Lv Jan 16, 2026
03a280e
update remote samples
Jiaqi-Lv Jan 16, 2026
b9b4b21
UPD: Fix deepsource issues
adamshephard Jan 20, 2026
db57128
UPD: Fix mypy issues and add tests
adamshephard Jan 20, 2026
324e365
UPD: Fix mypy issues in transforms
adamshephard Jan 21, 2026
de7b53b
UPD: Add tests
adamshephard Jan 21, 2026
b738750
UPD: Add tests
adamshephard Jan 21, 2026
bd1fac1
UPD: Add tests
adamshephard Jan 21, 2026
7c3ad13
UPD: Fix broken tests
adamshephard Jan 21, 2026
ac4cc00
UPD: Add tests
adamshephard Jan 21, 2026
b74be01
UPD: Add tests
adamshephard Jan 21, 2026
7b371bd
UPD: Fix broken tests
adamshephard Jan 22, 2026
1373730
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 22, 2026
1a4bbc8
UPD: Fix test issues
adamshephard Jan 22, 2026
73731f7
UPD: Fix test issues
adamshephard Jan 22, 2026
9c93b5e
Merge branch 'develop' into multichannel-reading
adamshephard Jan 22, 2026
be85ed6
UPD: Fix test issues
adamshephard Jan 22, 2026
9c62b87
UPD: Fix test issues and patch issues in virtualwsireader
adamshephard Jan 22, 2026
5efd94a
UPD: Fix test issues and patch issues in virtualwsireader
adamshephard Jan 22, 2026
4545dff
UPD: Add missing tests
adamshephard Jan 22, 2026
1fe57bd
Merge branch 'develop' of https://github.com/TissueImageAnalytics/tia…
measty Feb 4, 2026
34b2cfd
add tests for channel select ui
measty Feb 5, 2026
ddd1328
remove unreachable code and add validate test
measty Feb 5, 2026
1068d43
mypy
measty Feb 5, 2026
86c8fe9
improve metadata parsing tests
measty Feb 6, 2026
9ca7f82
improve coverage
measty Feb 6, 2026
6536e94
fix broken test
measty Feb 6, 2026
deaa97d
improve coverage
measty Feb 6, 2026
a71e0fb
Merge branch 'multichannel-reading' of https://github.com/TissueImage…
measty Feb 6, 2026
4588ad4
improve coverage
measty Feb 6, 2026
603e4c0
improve wsireader tests
measty Feb 6, 2026
7f84729
fix test
measty Feb 6, 2026
aafa4e9
fix post_proc behaviour in AnnotationStoreReader
measty Feb 6, 2026
f0fc8c1
standardize NGFFReader post_proc
measty Feb 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ lint.select = [
"ASYNC", # flake8-async
]
# Ignore rules which conflict with ruff formatter.
lint.ignore = ["COM812", "ISC001",]
lint.ignore = ["COM812", "ISC001"]
# Allow Ruff to discover `*.ipynb` files.
include = ["*.py", "*.pyi", "**/pyproject.toml", "*.ipynb"]

Expand Down
10 changes: 10 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ def sample_svs(remote_sample: Callable) -> Path:
return remote_sample("svs-1-small")


@pytest.fixture(scope="session")
def sample_qptiff(remote_sample: Callable) -> Path:
"""Sample pytest fixture for qptiff images.

Download qptiff image for pytest.

"""
return remote_sample("qptiff_sample")


@pytest.fixture(scope="session")
def sample_ome_tiff(remote_sample: Callable) -> Path:
"""Sample pytest fixture for ome-tiff (brightfield pyramid) images.
Expand Down
17 changes: 17 additions & 0 deletions tests/models/test_patch_predictor.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,23 @@ def __getitem__(self: Proto, idx: int) -> object:
assert roi1.shape[1] == roi2.shape[1]
assert np.min(correlation) > 0.9, correlation

# check automask works if only mpp in metadata
reader = WSIReader.open(mini_wsi_svs)
meta = reader.info
meta.objective_power = None
reader._m_info = meta
ds = WSIPatchDataset(
img_path=mini_wsi_svs,
mode="wsi",
patch_input_shape=patch_size,
stride_shape=stride_size,
auto_get_mask=True,
resolution=0.5,
units="mpp",
)
mask_reader = ds._setup_mask_reader(None, reader, auto_get_mask=True)
assert mask_reader is not None


def test_patch_dataset_abc() -> None:
"""Test for ABC methods.
Expand Down
148 changes: 137 additions & 11 deletions tests/test_app_bokeh.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,24 @@ def get_renderer_prop(prop: str) -> json:
return resp.json()


def get_channel_ui_elements() -> tuple[
bkmodels.DataTable,
bkmodels.DataTable,
bkmodels.ColorPicker,
bkmodels.Button,
bkmodels.Slider,
]:
"""Return channel selection UI widgets."""
channel_select = main.UI["channel_select"]
inner_column = channel_select.children[1]
table_row = inner_column.children[0]
channel_table, color_table = table_row.children
picker_row = inner_column.children[1]
color_picker, apply_button = picker_row.children
enhance_slider = inner_column.children[2]
return channel_table, color_table, color_picker, apply_button, enhance_slider


@pytest.fixture(scope="module", autouse=True)
def annotation_path(data_path: dict[str, Path]) -> dict[str, object]:
"""Download some testing slides and overlays.
Expand All @@ -143,6 +161,10 @@ def annotation_path(data_path: dict[str, Path]) -> dict[str, object]:
"patch-extraction-vf",
data_path["base_path"] / "slides",
)
data_path["qptiff"] = fetch_sample_to_dir(
"qptiff_sample",
data_path["base_path"] / "slides",
)
data_path["annotations"] = fetch_sample_to_dir(
"annotation_store_svs_1",
data_path["base_path"] / "overlays",
Expand Down Expand Up @@ -185,6 +207,7 @@ def run_app() -> None:
title="Tiatoolbox TileServer",
layers={},
)
app.json.sort_keys = False
CORS(app, send_wildcard=True)
app.run(host="127.0.0.1", port=int(main.port), threaded=True)

Expand All @@ -195,7 +218,21 @@ def doc(data_path: dict[str, object]) -> Generator[Document, object, None]:
# start tile server
p = multiprocessing.Process(target=run_app, daemon=True)
p.start()
time.sleep(2) # allow time for server to start
# wait until server is ready
start = time.time()
url = f"http://127.0.0.1:{main.port}/tileserver/session_id"
while True:
try:
resp = requests.get(url, timeout=1)
if resp.status_code == 200:
break
except requests.RequestException:
pass
if time.time() - start > 10:
p.terminate()
msg = f"Tileserver failed to start within 10s: {url}"
raise RuntimeError(msg)
time.sleep(0.2)

main.doc_config.set_sys_args(argv=["dummy_str", str(data_path["base_path"])])
handler = FunctionHandler(main.doc_config.setup_doc)
Expand Down Expand Up @@ -249,8 +286,8 @@ def test_config_loaded(data_path: pytest.TempPathFactory) -> None:
def test_slide_select(doc: Document, data_path: pytest.TempPathFactory) -> None:
"""Test slide selection."""
slide_select = doc.get_model_by_name("slide_select0")
# check there are three available slides
assert len(slide_select.options) == 3
# check there are four available slides
assert len(slide_select.options) == 4
assert slide_select.options[0][0] == data_path["slide1"].name

# select a slide and check it is loaded
Expand All @@ -272,7 +309,7 @@ def test_dual_window(doc: Document, data_path: pytest.TempPathFactory) -> None:
doc.get_model_by_name("slide_windows")
control_tabs.active = 1
slide_select = doc.get_model_by_name("slide_select1")
assert len(slide_select.options) == 3
assert len(slide_select.options) == 4
assert slide_select.options[0][0] == data_path["slide1"].name

control_tabs.active = 0
Expand Down Expand Up @@ -309,13 +346,32 @@ def test_add_slide_layer(doc: Document, data_path: pytest.TempPathFactory) -> No

def test_transform_overlay(doc: Document, data_path: pytest.TempPathFactory) -> None:
"""Test adding a transform overlay."""
layer_drop = doc.get_model_by_name("layer_drop0")
affine_layer_path = str(data_path["affine_trans"]) # sample .npy file

click = MenuItemClick(layer_drop, affine_layer_path)
layer_drop._trigger_event(click)
class DummyResponse:
"""Dummy response for mocking requests.put()."""

assert len(layer_drop.menu) == 6
text = json.dumps("dummy.npy")
status_code = 200

def dummy_put(*_: object, **__: object) -> DummyResponse:
"""Dummy put method to replace requests.Session.put()."""
return DummyResponse()

# Patch the method on the Session class
old_put = requests.sessions.Session.put
requests.sessions.Session.put = dummy_put

try:
layer_drop = doc.get_model_by_name("layer_drop0")
affine_layer_path = str(data_path["affine_trans"])

click = MenuItemClick(layer_drop, affine_layer_path)
layer_drop._trigger_event(click)

assert len(layer_drop.menu) == 6

finally:
requests.sessions.Session.put = old_put


def test_add_annotation_layer(doc: Document, data_path: pytest.TempPathFactory) -> None:
Expand Down Expand Up @@ -855,7 +911,7 @@ def test_option_buttons() -> None:
def test_populate_slide_list(doc: Document, data_path: pytest.TempPathFactory) -> None:
"""Test populating the slide list."""
slide_select = doc.get_model_by_name("slide_select0")
assert len(slide_select.options) == 3
assert len(slide_select.options) == 4
main.populate_slide_list(
data_path["base_path"] / "slides",
search_txt="TCGA-HE-7130-01Z-00-DX1",
Expand All @@ -864,7 +920,77 @@ def test_populate_slide_list(doc: Document, data_path: pytest.TempPathFactory) -
main.populate_slide_list(
data_path["base_path"] / "slides",
)
assert len(slide_select.options) == 3
assert len(slide_select.options) == 4


def test_channel_color_ui_callbacks(
doc: Document,
data_path: pytest.TempPathFactory,
) -> None:
"""Test channel color selection and apply changes callbacks on qptiff."""
slide_select = doc.get_model_by_name("slide_select0")
slide_select.value = [data_path["qptiff"].name]
assert main.UI["vstate"].slide_path == data_path["qptiff"]

channel_table, color_table, color_picker, apply_button, _ = (
get_channel_ui_elements()
)
# check we see 5 channels
assert len(channel_table.source.data["channels"]) == 5

# if no channels selected, check apply button does nothing
old_colors = color_table.source.data["colors"].copy()
color_picker.color = "#ffff00"
click = ButtonClick(apply_button)
apply_button._trigger_event(click)
assert color_table.source.data["colors"] == old_colors

# select the first channel and set it to red
channel_index = 0
color_table.source.selected.indices = [channel_index]
color_picker.color = "#ff0000"
channel_table.source.selected.indices = [channel_index]
click = ButtonClick(apply_button)
apply_button._trigger_event(click)
assert color_table.source.data["colors"] != old_colors

# check that getting a tile now red
tile = get_tile("slide", 0, 0, 0, show=False).astype(np.float32)
sum_r = tile[:, :, 0].sum()
sum_gb = tile[:, :, 1:].sum()
assert sum_r > 0
# may be tiny non-zero g and b values due to webp compression
# but should be almost pure red
assert (sum_gb) / (sum_r + 1e-5) < 0.1


def test_enhance_slider_callback(
doc: Document,
data_path: pytest.TempPathFactory,
) -> None:
"""Test enhance slider callback on qptiff."""
slide_select = doc.get_model_by_name("slide_select0")
slide_select.value = [data_path["qptiff"].name]
assert main.UI["vstate"].slide_path == data_path["qptiff"]

channel_table, color_table, color_picker, apply_button, enhance_slider = (
get_channel_ui_elements()
)
assert len(channel_table.source.data["channels"]) > 0

channel_index = 0
color_table.source.selected.indices = [channel_index]
color_picker.color = "#ff0000"
channel_table.source.selected.indices = [channel_index]
click = ButtonClick(apply_button)
apply_button._trigger_event(click)

before = get_tile("slide", 0, 0, 0, show=False).astype(np.float32)
enhance_slider.value = 2.0
after = get_tile("slide", 0, 0, 0, show=False).astype(np.float32)
# enhance should have made it brighter
diff = after - before
assert np.max(diff) > 0


def test_clearing_doc(doc: Document) -> None:
Expand Down
80 changes: 80 additions & 0 deletions tests/test_bokeh_main_urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""Tests for channel information retrieval and update in the Bokeh app."""

import json
from types import SimpleNamespace
from typing import Any

from tiatoolbox.visualization.bokeh_app import main


class DummySession:
"""A minimal session mock that records GET and PUT requests."""

def __init__(self) -> None:
"""Initialize tracking attributes for request inspection."""
self.last_get: str | None = None
self.last_put: str | None = None
self.last_put_data: Any = None

def get(self, url: str) -> SimpleNamespace:
"""Record GET requests and return a dummy successful response."""
self.last_get = url
return SimpleNamespace(
text=json.dumps({"channels": {"c0": [1, 0, 0]}, "active": []}),
status_code=200,
)

def put(self, url: str, data: str | None = None) -> SimpleNamespace:
"""Record PUT requests and return a dummy successful response."""
self.last_put = url
self.last_put_data = data
return SimpleNamespace(status_code=200)


def test_get_channel_info_uses_configured_port() -> None:
"""Ensure get_channel_info uses the configured host and port."""
dummy = DummySession()
# replace UI with a minimal mapping exposing 's'
old_ui = getattr(main, "UI", None)
main.UI = {"s": dummy}
old_host2 = getattr(main, "host2", "127.0.0.1")
old_port = getattr(main, "port", "5000")
try:
main.host2 = "127.0.0.1"
main.port = "12345"
channels, _active = main.get_channel_info()
expected = f"http://{main.host2}:{main.port}/tileserver/channels"
assert dummy.last_get == expected
assert "c0" in channels
finally:
# restore
if old_ui is None:
delattr(main, "UI")
else:
main.UI = old_ui
main.host2 = old_host2
main.port = old_port


def test_set_channel_info_uses_configured_port() -> None:
"""Ensure set_channel_info uses the configured host and port."""
dummy = DummySession()
old_ui = getattr(main, "UI", None)
main.UI = {"s": dummy}
old_host2 = getattr(main, "host2", "127.0.0.1")
old_port = getattr(main, "port", "5000")

main.host2 = "127.0.0.1"
main.port = "54321"
expected = f"http://{main.host2}:{main.port}/tileserver/channels"
try:
colors = {"c0": "#ff0000"}
main.set_channel_info(colors, [0])
finally:
assert dummy.last_put == expected
if old_ui is None:
delattr(main, "UI")
else:
main.UI = old_ui
main.host2 = old_host2
main.port = old_port
Loading