-
Notifications
You must be signed in to change notification settings - Fork 1
Optimise CLEM Data Transfer and Registration #707
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+230
−14
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
5b796b3
Added optional MachineConfig key to blacklist directories and files w…
tieneupin 17a725d
Added logic to blacklist files and folders based on provided substrin…
tieneupin 80de8b0
Pass substrings blacklist from machine config to DirWatcher when init…
tieneupin 84d2e02
Register a dataset as an atlas based on the image width/height instea…
tieneupin e97c4ea
Added unit test to check that the DirWatcher class initialises as exp…
tieneupin f19a5b2
Fixed typo and a MyPy error
tieneupin bb0492f
Added test to check that the '_scan_directory' class function works f…
tieneupin a708188
The assertion should be nested as well
tieneupin 38107a8
Renamed 'CLEMAlignaAndMergeParameters' to 'CLEMProcessingParameters',…
tieneupin e76c32d
Fixed typo and added debug logs to note down skipped files
tieneupin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| import os | ||
| import queue | ||
| import threading | ||
| from pathlib import Path | ||
|
|
||
| import pytest | ||
|
|
||
| from murfey.client.watchdir import DirWatcher | ||
| from tests.conftest import ExampleVisit | ||
|
|
||
|
|
||
| def test_dirwatcher_initialises(tmp_path: Path): | ||
| # Check that the DirWatcher initialises with the default attributes | ||
| watcher = DirWatcher(path=str(tmp_path)) | ||
| assert watcher._basepath == os.fspath(str(tmp_path)) | ||
| assert watcher._lastscan == {} | ||
| assert watcher._file_candidates == {} | ||
| assert watcher._statusbar is None | ||
| assert watcher.settling_time == 60 | ||
| assert watcher._appearance_time is None | ||
| assert watcher._substrings_blacklist == {} | ||
| assert watcher._transfer_all is True | ||
| assert watcher._modification_overwrite is None | ||
| assert isinstance(watcher._init_time, float) | ||
| assert isinstance(watcher.queue, queue.Queue) | ||
| assert isinstance(watcher.thread, threading.Thread) | ||
| assert watcher._stopping is False | ||
| assert watcher._halt_thread is False | ||
|
|
||
| # Check that the string representation is as expected | ||
| assert str(watcher) == f"<DirWatcher ({os.fspath(str(tmp_path))})>" | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def clem_visit_dir(tmp_path: Path): | ||
| visit_name = f"{ExampleVisit.proposal_code}{ExampleVisit.proposal_number}-{ExampleVisit.visit_number}" | ||
| visit_dir = tmp_path / "clem" / "data" / "2025" / visit_name | ||
| visit_dir.mkdir(parents=True, exist_ok=True) | ||
| return visit_dir | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def clem_test_files(clem_visit_dir: Path): | ||
| # Create test files for the DirWatcher to scan | ||
| file_list: list[Path] = [] | ||
| project_dir = clem_visit_dir / "images" / "test_grid" | ||
|
|
||
| # Example atlas collection | ||
| for s in range(20): | ||
| file_list.append( | ||
| project_dir | ||
| / "Overview 1" | ||
| / "Image 1" | ||
| / f"Image 1--Stage{str(s).zfill(2)}.tif" | ||
| ) | ||
| file_list.append( | ||
| project_dir / "Overview 1" / "Image 1" / "Metadata" / "Image 1.xlif" | ||
| ) | ||
|
|
||
| # Example image stack collection | ||
| for c in range(3): | ||
| for z in range(10): | ||
| file_list.append( | ||
| project_dir | ||
| / "TileScan 1" | ||
| / "Position 1" | ||
| / f"Position 1--C{str(c).zfill(2)}--Z{str(z).zfill(2)}.tif" | ||
| ) | ||
| file_list.append( | ||
| project_dir / "TileScan 1" / "Position 1" / "Metadata" / "Position 1.xlif" | ||
| ) | ||
|
|
||
| # Create all files and directories specified | ||
| for file in file_list: | ||
| if not file.parent.exists(): | ||
| file.parent.mkdir(parents=True) | ||
| if not file.exists(): | ||
| file.touch() | ||
| return sorted(file_list) | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def clem_junk_files(clem_visit_dir: Path): | ||
| # Create junk files that are to be blacklisted from the CLEM workflow | ||
| file_list: list[Path] = [] | ||
| project_dir = clem_visit_dir / "images" / "test_grid" | ||
|
|
||
| # Create junk atlas data | ||
| for n in range(5): | ||
| for s in range(20): | ||
| file_list.append( | ||
| project_dir | ||
| / "Image 1" | ||
| / f"Image 1_pmd_{n}" | ||
| / f"Image 1_pmd_{n}--Stage{str(s).zfill(2)}.tif" | ||
| ) | ||
| file_list.append( | ||
| project_dir / "Image 1" / f"Image 1_pmd_{n}" / "Metadata" / "Image 1.xlif" | ||
| ) | ||
|
|
||
| # Creat junk image data | ||
| for n in range(5): | ||
| for c in range(3): | ||
| for z in range(10): | ||
| file_list.append( | ||
| project_dir | ||
| / "Position 1" | ||
| / f"Position 1_pmd_{n}" | ||
| / f"Position 1_pmd_{n}--C{str(c).zfill(2)}--Z{str(z).zfill(2)}.tif" | ||
| ) | ||
| file_list.append( | ||
| project_dir | ||
| / "Position 1" | ||
| / f"Position 1_pmd_{n}" | ||
| / "Metadata" | ||
| / "Position 1.xlif" | ||
| ) | ||
|
|
||
| # Create remaining junk files | ||
| for file_path in ( | ||
| "1.xlef", | ||
| "Metadata/IOManagerConfiguation.xlif", | ||
| "Metadata/Overview 1.xlcf", | ||
| "Metadata/TileScan 1.xlcf", | ||
| "Overview 1/Image 1/Image 1_histo.lof", | ||
| "TileScan 1/Position 1/Position 1_histo.lof", | ||
| "Overview 1/Image 1/Metadata/Image 1_histo.xlif", | ||
| "TileScan 1/Position 1/Metadata/Position 1_histo.xlif", | ||
| ): | ||
| file_list.append(project_dir / file_path) | ||
|
|
||
| # Create files and directoriees | ||
| for file in file_list: | ||
| if not file.parent.exists(): | ||
| file.parent.mkdir(parents=True) | ||
| if not file.exists(): | ||
| file.touch() | ||
| return sorted(file_list) | ||
|
|
||
|
|
||
| scan_directory_params_matrix: tuple[tuple[str, dict[str, list[str]]], ...] = ( | ||
| # Workflow type | Substrings blacklist | ||
| ( | ||
| "clem", | ||
| { | ||
| "directories": [ | ||
| "_pmd_", | ||
| ], | ||
| "files": [ | ||
| ".xlef", | ||
| ".xlcf", | ||
| "_histo.lof", | ||
| "_histo.xlif", | ||
| "IOManagerConfiguation.xlif", | ||
| ], | ||
| }, | ||
| ), | ||
| ) | ||
|
|
||
|
|
||
| @pytest.mark.parametrize("test_params", scan_directory_params_matrix) | ||
| def test_scan_directory( | ||
| clem_visit_dir: Path, | ||
| clem_test_files: list[Path], | ||
| clem_junk_files: list[Path], | ||
| test_params: tuple[str, dict[str, list[str]]], | ||
| ): | ||
| # Unpack test params | ||
| workflow_type, substrings_blacklist = test_params | ||
|
|
||
| # Initialise different watchers based on the workflow to test and run the scan | ||
| if workflow_type == "clem": | ||
| watcher = DirWatcher( | ||
| path=str(clem_visit_dir), | ||
| substrings_blacklist=substrings_blacklist, | ||
| ) | ||
| result = watcher._scan_directory() | ||
|
|
||
| # Check that the result does not contain the junk files | ||
| assert [str(file) for file in clem_test_files] == sorted(result.keys()) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.