diff --git a/docs/source/specifications/metadata.org b/docs/source/specifications/metadata.org index 139faf2def930e3b3c3c092c85e401c75d32f7ff..52d514a3465236a9079a8bba3ee721b013808a28 100644 --- a/docs/source/specifications/metadata.org +++ b/docs/source/specifications/metadata.org @@ -4,7 +4,7 @@ Draft for recommended metadata for images to provide a standard interface for al * Essential data - DimensionOrder: str - Order of dimensions (e.g., TCZYX for Channel, Time, Z,X,Y) + Order of dimensions (e.g., TCZYX for Time, Channel, Z, Y, X) - PixelSize: float Size of pixel, useful for segmentation. - Channels: List[str] diff --git a/examples/tiler/pypipeline_unit_test_00_000001_Brightfield_003.tif b/examples/tiler/pypipeline_unit_test_00_000001_Brightfield_003.tif index f813c15a9c8aef8a6e629ff17e460aef4acdb630..569f33a72ab18f65c79e28e38869a4f17cd30cca 100755 Binary files a/examples/tiler/pypipeline_unit_test_00_000001_Brightfield_003.tif and b/examples/tiler/pypipeline_unit_test_00_000001_Brightfield_003.tif differ diff --git a/examples/tiler/pypipeline_unit_test_00_000001_Brightfield_003_square.tif b/examples/tiler/pypipeline_unit_test_00_000001_Brightfield_003_square.tif new file mode 100755 index 0000000000000000000000000000000000000000..f813c15a9c8aef8a6e629ff17e460aef4acdb630 Binary files /dev/null and b/examples/tiler/pypipeline_unit_test_00_000001_Brightfield_003_square.tif differ diff --git a/src/agora/abc.py b/src/agora/abc.py index 6c1fd343e04bf42fb798642484b0b55c2de0a97a..c396b4b1503c7558dc51eaf9032b7cb14485bc38 100644 --- a/src/agora/abc.py +++ b/src/agora/abc.py @@ -10,6 +10,8 @@ from typing import Union from flatten_dict import flatten from yaml import dump, safe_load +from agora.logging import timer + atomic = t.Union[int, float, str, bool] @@ -239,21 +241,12 @@ class StepABC(ProcessABC): def _run_tp(self): pass - def run_tp(self, tp: int, log: bool = True, **kwargs): + @timer + def run_tp(self, tp: int, **kwargs): """ Time and log the timing of a step. """ - if log: - t = perf_counter() - result = self._run_tp(tp, **kwargs) - self._log( - f"Timing:{self.__class__.__name__}:{perf_counter()-t}s", - "debug", - ) - else: - result = self._run_tp(tp, **kwargs) - - return result + return self._run_tp(tp, **kwargs) def run(self): # Replace run withn run_tp diff --git a/src/agora/io/metadata.py b/src/agora/io/metadata.py index 61caa3aa6c868f33a0f40ce220a02d3a3d028285..c058e9f430672a9fc4cb6a7e25d4e328368a2044 100644 --- a/src/agora/io/metadata.py +++ b/src/agora/io/metadata.py @@ -168,8 +168,9 @@ def get_meta_swainlab(parsed_metadata: dict): def get_meta_from_legacy(parsed_metadata: dict): - channels = parsed_metadata["channels/channel"] - return {"channels": channels} + result = parsed_metadata + result["channels"] = result["channels/channel"] + return result def parse_swainlab_metadata(filedir: t.Union[str, PosixPath]): diff --git a/src/agora/io/signal.py b/src/agora/io/signal.py index 1b174089ba5f176cdfb1a90be5fc7a16666ce243..0210ef3427552c8d7fa62a9f366976459d112e51 100644 --- a/src/agora/io/signal.py +++ b/src/agora/io/signal.py @@ -84,7 +84,7 @@ class Signal(BridgeH5): try: df.columns = (df.columns * self.tinterval // 60).astype(int) except Exception as e: - self._log(f"Unable to convert columns to minutes: {e}") + self._log(f"Unable to convert columns to minutes: {e}", "debug") return df @cached_property diff --git a/src/agora/io/writer.py b/src/agora/io/writer.py index bc8769a2ec44e5c3ff4bead42d0fdec53ea20ad1..264478482875c6992241ed9ad00613f0ef96fbf0 100644 --- a/src/agora/io/writer.py +++ b/src/agora/io/writer.py @@ -1,4 +1,3 @@ -import itertools import logging from collections.abc import Iterable from pathlib import Path @@ -55,6 +54,11 @@ class DynamicWriter: if Path(file).exists(): self.metadata = load_attributes(file) + def _log(self, message: str, level: str = "warn"): + # Log messages in the corresponding level + logger = logging.getLogger("aliby") + getattr(logger, level)(f"{self.__class__.__name__}: {message}") + def _append(self, data, key, hgroup): """ Append data to existing dataset in the h5 file otherwise create a new one. @@ -170,7 +174,9 @@ class DynamicWriter: self._append(value, key, hgroup) except Exception as e: print(key, value) - raise (e) + self._log( + f"{key}:{value} could not be written: {e}", "error" + ) # write metadata for key, value in meta.items(): hgroup.attrs[key] = value @@ -564,7 +570,7 @@ class Writer(BridgeH5): dset[()] = df.index.get_level_values(level=name).tolist() # create dataset and write columns if ( - df.columns.dtype == np.int + df.columns.dtype == int or df.columns.dtype == np.dtype("uint") or df.columns.name == "timepoint" ): @@ -601,9 +607,7 @@ class Writer(BridgeH5): ) # split indices in existing and additional new = df.index.tolist() - if ( - df.index.nlevels == 1 - ): + if df.index.nlevels == 1: # cover cases with a single index new = [(x,) for x in df.index.tolist()] ( diff --git a/src/agora/logging.py b/src/agora/logging.py new file mode 100644 index 0000000000000000000000000000000000000000..a004b0182363d495c32ffcb2edf9d51cd8875303 --- /dev/null +++ b/src/agora/logging.py @@ -0,0 +1,20 @@ +#!/usr/bin/env jupyter +""" +Add general logging functions and decorators +""" + +import logging +from time import perf_counter + + +def timer(func): + # Log duration of a function into aliby logfile + def wrap_func(*args, **kwargs): + t1 = perf_counter() + result = func(*args, **kwargs) + logging.getLogger("aliby").debug( + f"{func.__qualname__} took {(perf_counter()-t1):.4f}s" + ) + return result + + return wrap_func diff --git a/src/aliby/pipeline.py b/src/aliby/pipeline.py index 0062c61a75b96e2fe112f1cad2b637a842d19d49..f7f47cfb316bde17a6aad3a1abc6568f9397c294 100644 --- a/src/aliby/pipeline.py +++ b/src/aliby/pipeline.py @@ -475,7 +475,7 @@ class Pipeline(ProcessABC): step == "tiler" and i == min_process_from ): - print( + logging.getLogger("aliby").info( f"Found {steps['tiler'].n_traps} traps in {image.name}" ) elif ( diff --git a/src/aliby/tile/tiler.py b/src/aliby/tile/tiler.py index a3216e9eb7f0987238161a977249b4c74a1bb4dc..34aa89d1c2af76976f134a0fd38d58919cedc9bb 100644 --- a/src/aliby/tile/tiler.py +++ b/src/aliby/tile/tiler.py @@ -261,14 +261,13 @@ class Tiler(StepABC): """ imgdmy_obj = ImageDummy(parameters) dummy_image = imgdmy_obj.get_data_lazy() - dummy_omero_metadata = ( # Default to "tczyx" if image.dimorder is None - { - f"size_{dim}": dim_size - for dim, dim_size in zip( - imgdmy_obj.dimorder or "tczyx", dummy_image.shape - ) - }, - ) + # Default to "tczyx" if image.dimorder is None + dummy_omero_metadata = { + f"size_{dim}": dim_size + for dim, dim_size in zip( + imgdmy_obj.dimorder or "tczyx", dummy_image.shape + ) + } dummy_omero_metadata.update( { "channels": [