Skip to content

Commit c4fb76c

Browse files
authored
Merge pull request #953 from fractal-analytics-platform/952_cellvoager_converter
cellvoager converter fixes
2 parents e86d4a8 + a36fca0 commit c4fb76c

File tree

7 files changed

+74
-18
lines changed

7 files changed

+74
-18
lines changed

.github/workflows/manifest_external_packages.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@ jobs:
3939
cmd_create_manifest: 'python src/scmultiplex/dev/create_manifest.py'
4040
custom_dependencies: 'image_registration'
4141

42-
- package: APx_fractal_task_collection
43-
github_repo: Apricot-Therapeutics/APx_fractal_task_collection
44-
github_branch: main
45-
manifest_path: src/apx_fractal_task_collection/__FRACTAL_MANIFEST__.json
46-
cmd_install: 'python -m pip install -e .'
47-
cmd_create_manifest: 'python src/apx_fractal_task_collection/dev/update_manifest.py'
48-
custom_dependencies: ''
42+
# - package: APx_fractal_task_collection
43+
# github_repo: Apricot-Therapeutics/APx_fractal_task_collection
44+
# github_branch: main
45+
# manifest_path: src/apx_fractal_task_collection/__FRACTAL_MANIFEST__.json
46+
# cmd_install: 'python -m pip install -e .'
47+
# cmd_create_manifest: 'python src/apx_fractal_task_collection/dev/update_manifest.py'
48+
# custom_dependencies: ''
4949

5050
exclude:
5151
- package: skip

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
**Note**: Numbers like (\#123) point to closed Pull Requests on the fractal-tasks-core repository.
22

3+
# 1.5.1
4+
* Tasks:
5+
* In `Convert Cellvoyager to OME-Zarr` & `Convert Cellvoyager Multiplexing to OME-Zarr` tasks, handle unset window start & end better (\#953).
6+
* In `Convert Cellvoyager to OME-Zarr` & `Convert Cellvoyager Multiplexing to OME-Zarr` tasks, normalize plate names to avoid special characters & spaces (\#953).
7+
* In `Convert Cellvoyager Multiplexing to OME-Zarr`, improve error message when no images are found (\#953).
8+
* In `Convert Cellvoyager Multiplexing to OME-Zarr`, handle order of acquisitions better (\#953).
9+
310
# 1.5.0
411

512
* Tasks:

fractal_tasks_core/__FRACTAL_MANIFEST__.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
}
5151
],
5252
"title": "Window",
53-
"description": "Optional `Window` object to set default display settings for napari."
53+
"description": "Optional `Window` object to set default display settings. If unset, it will be set to the full bit range of the image (e.g. 0-65535 for 16 bit images)."
5454
},
5555
"color": {
5656
"title": "Color",
@@ -370,7 +370,7 @@
370370
}
371371
],
372372
"title": "Window",
373-
"description": "Optional `Window` object to set default display settings for napari."
373+
"description": "Optional `Window` object to set default display settings. If unset, it will be set to the full bit range of the image (e.g. 0-65535 for 16 bit images)."
374374
},
375375
"color": {
376376
"title": "Color",

fractal_tasks_core/cellvoyager/metadata.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import fnmatch
1616
import logging
1717
import math
18+
import string
1819
from pathlib import Path
1920
from typing import Optional
2021
from typing import Union
@@ -477,3 +478,30 @@ def check_group_consistency(grouped_df: pd.DataFrame, message: str = ""):
477478
f"{message}\n"
478479
f"Difference dataframe: \n{diff_df}"
479480
)
481+
482+
483+
__SPECIAL_CHARACTERS__ = f"{string.punctuation}{string.whitespace}"
484+
485+
486+
def sanitize_string(value: str) -> str:
487+
"""
488+
Make string safe to be used in file/folder names.
489+
490+
Replace any special character with an
491+
underscore, where special characters are:
492+
493+
494+
>>> string.punctuation
495+
'!"#$%&\'()*+,-./:;<=>?@[\\\\]^_`{|}~'
496+
>>> string.whitespace
497+
' \\t\\n\\r\\x0b\\x0c'
498+
499+
Args:
500+
value: Input string
501+
502+
Returns:
503+
Sanitized value
504+
"""
505+
for character in __SPECIAL_CHARACTERS__:
506+
new_value = value.replace(character, "_")
507+
return new_value

fractal_tasks_core/channels.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ class OmeroChannel(BaseModel):
5959
wavelength_id: Unique ID for the channel wavelength, e.g. `A01_C01`.
6060
index: Do not change. For internal use only.
6161
label: Name of the channel.
62-
window: Optional `Window` object to set default display settings for
63-
napari.
62+
window: Optional `Window` object to set default display settings. If
63+
unset, it will be set to the full bit range of the image
64+
(e.g. 0-65535 for 16 bit images).
6465
color: Optional hex colormap to display the channel in napari (it
6566
must be of length 6, e.g. `00FFFF`).
6667
active: Should this channel be shown in the viewer?
@@ -370,6 +371,15 @@ def define_omero_channels(
370371
if channel.window:
371372
channel.window.min = 0
372373
channel.window.max = 2**bit_depth - 1
374+
else:
375+
# If no channel.window is set, create a new one with full bitrange
376+
# min & max
377+
channel.window = Window(
378+
min=0,
379+
max=2**bit_depth - 1,
380+
start=0,
381+
end=2**bit_depth - 1,
382+
)
373383

374384
# Check that channel labels are unique for this image
375385
labels = [c.label for c in new_channels]

fractal_tasks_core/tasks/cellvoyager_to_ome_zarr_init.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from fractal_tasks_core.cellvoyager.metadata import (
2828
parse_yokogawa_metadata,
2929
)
30+
from fractal_tasks_core.cellvoyager.metadata import sanitize_string
3031
from fractal_tasks_core.cellvoyager.wells import generate_row_col_split
3132
from fractal_tasks_core.cellvoyager.wells import get_filename_well_id
3233
from fractal_tasks_core.channels import check_unique_wavelength_ids
@@ -241,8 +242,9 @@ def cellvoyager_to_ome_zarr_init(
241242
parallelization_list = []
242243

243244
for plate in plates:
245+
plate_name = sanitize_string(plate)
244246
# Define plate zarr
245-
relative_zarrurl = f"{plate}.zarr"
247+
relative_zarrurl = f"{plate_name}.zarr"
246248
in_path = dict_plate_paths[plate]
247249
logger.info(f"Creating {relative_zarrurl}")
248250
# Call zarr.open_group wrapper, which handles overwrite=True/False
@@ -337,7 +339,7 @@ def cellvoyager_to_ome_zarr_init(
337339
well_wavelength_ids = sorted(list(set(well_wavelength_ids)))
338340
if well_wavelength_ids != actual_wavelength_ids:
339341
raise ValueError(
340-
f"ERROR: well {well} in plate {plate} (prefix: "
342+
f"ERROR: well {well} in plate {plate_name} (prefix: "
341343
f"{plate_prefix}) has missing channels.\n"
342344
f"Expected: {actual_channels}\n"
343345
f"Found: {well_wavelength_ids}.\n"
@@ -355,7 +357,7 @@ def cellvoyager_to_ome_zarr_init(
355357
col_list = sorted(list(set(col_list)))
356358

357359
plate_attrs = {
358-
"acquisitions": [{"id": 0, "name": plate}],
360+
"acquisitions": [{"id": 0, "name": plate_name}],
359361
"columns": [{"name": col} for col in col_list],
360362
"rows": [{"name": row} for row in row_list],
361363
"version": __OME_NGFF_VERSION__,
@@ -377,7 +379,9 @@ def cellvoyager_to_ome_zarr_init(
377379
for row, column in well_rows_columns:
378380
parallelization_list.append(
379381
{
380-
"zarr_url": f"{zarr_dir}/{plate}.zarr/{row}/{column}/0",
382+
"zarr_url": (
383+
f"{zarr_dir}/{plate_name}.zarr/{row}/{column}/0"
384+
),
381385
"init_args": InitArgsCellVoyager(
382386
image_dir=in_path,
383387
plate_prefix=plate_prefix,

fractal_tasks_core/tasks/cellvoyager_to_ome_zarr_init_multiplex.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from fractal_tasks_core.cellvoyager.metadata import (
3030
parse_yokogawa_metadata,
3131
)
32+
from fractal_tasks_core.cellvoyager.metadata import sanitize_string
3233
from fractal_tasks_core.cellvoyager.wells import generate_row_col_split
3334
from fractal_tasks_core.cellvoyager.wells import get_filename_well_id
3435
from fractal_tasks_core.channels import check_unique_wavelength_ids
@@ -151,7 +152,7 @@ def cellvoyager_to_ome_zarr_init_multiplex(
151152

152153
# Identify all plates and all channels, per input folders
153154
dict_acquisitions: dict = {}
154-
acquisitions_sorted = sorted(list(acquisitions.keys()))
155+
acquisitions_sorted = sorted(acquisitions.keys(), key=lambda x: int(x))
155156
for acquisition in acquisitions_sorted:
156157
acq_input = acquisitions[acquisition]
157158
dict_acquisitions[acquisition] = {}
@@ -191,6 +192,7 @@ def cellvoyager_to_ome_zarr_init_multiplex(
191192

192193
info = (
193194
"Listing all plates/channels:\n"
195+
f"Folder: {acq_input.image_dir}\n"
194196
f"Include patterns: {include_patterns}\n"
195197
f"Exclude patterns: {exclude_patterns}\n"
196198
f"Plates: {plates}\n"
@@ -253,9 +255,12 @@ def cellvoyager_to_ome_zarr_init_multiplex(
253255
current_plates = [item["plate"] for item in dict_acquisitions.values()]
254256
if len(set(current_plates)) > 1:
255257
raise ValueError(f"{current_plates=}")
256-
plate = current_plates[0]
258+
plate = sanitize_string(current_plates[0])
257259

258-
zarrurl = dict_acquisitions[acquisitions_sorted[0]]["plate"] + ".zarr"
260+
zarrurl = (
261+
sanitize_string(dict_acquisitions[acquisitions_sorted[0]]["plate"])
262+
+ ".zarr"
263+
)
259264
full_zarrurl = str(Path(zarr_dir) / zarrurl)
260265
logger.info(f"Creating {full_zarrurl=}")
261266
# Call zarr.open_group wrapper, which handles overwrite=True/False
@@ -416,6 +421,8 @@ def cellvoyager_to_ome_zarr_init_multiplex(
416421
Well(**well_attrs)
417422
group_well.attrs["well"] = well_attrs
418423
zarrurls["well"].append(f"{plate}.zarr/{row}/{column}")
424+
print(plate)
425+
print(zarrurls["well"])
419426
except ContainsGroupError:
420427
group_well = zarr.open_group(
421428
f"{full_zarrurl}/{row}/{column}/", mode="r+"

0 commit comments

Comments
 (0)