diff --git a/src/agora/io/signal.py b/src/agora/io/signal.py index 20c7b950d3a3e4dbf1cb21dec29947467b938bd7..6b9457bd77b91d9303758168188603ce7d5b728f 100644 --- a/src/agora/io/signal.py +++ b/src/agora/io/signal.py @@ -9,6 +9,7 @@ import h5py import numpy as np import pandas as pd +import aliby.global_parameters as global_parameters from agora.io.bridge import BridgeH5 from agora.io.decorators import _first_arg_str_to_raw_df from agora.utils.indexing import validate_lineage @@ -36,16 +37,7 @@ class Signal(BridgeH5): "cell_label", "mother_label", ) - self.candidate_channels = ( - "GFP", - "GFPFast", - "mCherry", - "Flavin", - "Citrine", - "mKO2", - "Cy5", - "pHluorin405", - ) + self.candidate_channels = global_parameters.possible_imaging_channels def __getitem__(self, dsets: t.Union[str, t.Collection]): """Get and potentially pre-process data from h5 file and return as a dataframe.""" diff --git a/src/aliby/global_parameters.py b/src/aliby/global_parameters.py new file mode 100644 index 0000000000000000000000000000000000000000..92b58f8969de09ee31c558019ccabe52a01338c5 --- /dev/null +++ b/src/aliby/global_parameters.py @@ -0,0 +1,38 @@ +# parameters to stop the pipeline when exceeded +earlystop = dict( + min_tp=100, + thresh_pos_clogged=0.4, + thresh_trap_ncells=8, + thresh_trap_area=0.9, + ntps_to_eval=5, +) + +# imaging properties of the microscope +imaging_specifications = { + "pixel_size": 0.236, + "z_size": 0.6, + "spacing": 0.6, +} + +# possible imaging channels +possible_imaging_channels = [ + "Citrine", + "GFP", + "GFPFast", + "mCherry", + "Flavin", + "Citrine", + "mKO2", + "Cy5", + "pHluorin405", + "pHluorin488", +] + +# functions to apply to the fluorescence of each cell +fluorescence_functions = [ + "mean", + "median", + "std", + "imBackground", + "max5px_median", +] diff --git a/src/aliby/pipeline.py b/src/aliby/pipeline.py index 0d73c3356455040e0712a62a669b9de9e186c96f..ede77e7c9acce43356ee515fcca47a11f5178e04 100644 --- a/src/aliby/pipeline.py +++ b/src/aliby/pipeline.py @@ -14,6 +14,7 @@ import numpy as np from pathos.multiprocessing import Pool from tqdm import tqdm +import aliby.global_parameters as global_parameters from agora.abc import ParametersABC, ProcessABC from agora.io.metadata import MetaData, parse_logfiles from agora.io.reader import StateReader @@ -119,13 +120,7 @@ class PipelineParameters(ParametersABC): tps=tps, directory=str(directory.parent), filter="", - earlystop=dict( - min_tp=100, - thresh_pos_clogged=0.4, - thresh_trap_ncells=8, - thresh_trap_area=0.9, - ntps_to_eval=5, - ), + earlystop=global_parameters.earlystop, logfile_level="INFO", use_explog=True, ) @@ -162,10 +157,25 @@ class PipelineParameters(ParametersABC): return cls(**{k: v for k, v in defaults.items()}) def load_logs(self): + """Load and parse log files.""" parsed_flattened = parse_logfiles(self.log_dir) return parsed_flattened +def find_channels_by_group(meta): + """Parse meta data to find which imaging channels are used for each group.""" + channels_dict = {group_no: [] for group_no in meta["positions/group"]} + imaging_channels = global_parameters.possible_imaging_channels + for i, group_no in enumerate(meta["positions/group"]): + for imaging_channel in imaging_channels: + if ( + "positions/" + imaging_channel in meta + and meta["positions/" + imaging_channel][i] + ): + channels_dict[group_no].append(imaging_channel) + return channels_dict + + class Pipeline(ProcessABC): """ Initialise and run tiling, segmentation, extraction and post-processing. @@ -224,11 +234,6 @@ class Pipeline(ProcessABC): fh.setFormatter(formatter) logger.addHandler(fh) - @classmethod - def from_yaml(cls, fpath): - # an unfinished convenience function - return cls(parameters=PipelineParameters.from_yaml(fpath)) - @classmethod def from_folder(cls, dir_path): """ @@ -324,7 +329,7 @@ class Pipeline(ProcessABC): directory = self.store or root_dir / conn.unique_name if not directory.exists(): directory.mkdir(parents=True) - # download logs to use for metadata + # get logs to use for metadata conn.cache_logs(directory) print("Positions available:") for i, pos in enumerate(position_ids.keys()): diff --git a/src/extraction/core/extractor.py b/src/extraction/core/extractor.py index 0192434d554218d7286be1dbbb1680bb5b82fdbe..7cb11443b2e9b6197382911230ce82ee90dc9cec 100644 --- a/src/extraction/core/extractor.py +++ b/src/extraction/core/extractor.py @@ -16,6 +16,7 @@ from extraction.core.functions.loaders import ( load_funs, load_redfuns, ) +import aliby.global_parameters as global_parameters # define types reduction_method = t.Union[t.Callable, str, None] @@ -89,12 +90,7 @@ class Extractor(StepABC): or leaf level. """ - # TODO Move this to a location with the SwainLab defaults - default_meta = { - "pixel_size": 0.236, - "z_size": 0.6, - "spacing": 0.6, - } + default_meta = global_parameters.imaging_specifications def __init__( self, diff --git a/src/extraction/core/functions/defaults.py b/src/extraction/core/functions/defaults.py index 1c32d0e2c7c2ba652a35419e78d8bcfa94eab00b..bc9107b7f86fd00a510d443596171d5607525191 100644 --- a/src/extraction/core/functions/defaults.py +++ b/src/extraction/core/functions/defaults.py @@ -4,6 +4,7 @@ from pathlib import Path import h5py +import aliby.global_parameters as global_parameters from aliby.tile.tiler import find_channel_name @@ -21,26 +22,10 @@ def exparams_from_meta( "tree": {"general": {"None": ["area", "volume", "eccentricity"]}}, "multichannel_ops": {}, } - candidate_channels = { - "Citrine", - "GFP", - "GFPFast", - "mCherry", - "pHluorin405", - "pHluorin488", - "Flavin", - "Cy5", - "mKO2", - } + candidate_channels = set(global_parameters.possible_imaging_channels) default_reductions = {"max"} - default_metrics = { - "mean", - "median", - "std", - "imBackground", - "max5px_median", - # "nuc_est_conv", - } + default_metrics = set(global_parameters.fluorescence_functions) + # define ratiometric combinations # key is numerator and value is denominator # add more to support additional channel names