epicure.appose_epyseg

 1import appose
 2import numpy as np
 3import epicure.Utils as ut
 4import logging
 5from importlib import resources
 6import platform
 7
 8def share_as_ndarray(img: np.ndarray) -> appose.NDArray:
 9    """Copies a NumPy array into a same-sized newly allocated block of shared memory."""
10    shared = appose.NDArray(str(img.dtype), img.shape)
11    shared.ndarray()[:] = img
12    return shared
13        
14def go_epyseg( image, parameters, progress_bar=None, logger=None ):
15    """ Install a python environment with napari_epyseg if necessary with appose and run epyseg on the image within that environment """
16    _logger = logger or logging.getLogger(__name__)
17    try:
18        pixi_file = resources.files("epicure.resources").joinpath("pixi.toml")
19        _logger.info("Build/Load napari_epyseg environement")
20        env = appose.pixi( pixi_file ).log_debug()
21        env = env.subscribe_output( lambda line: print("OUT:", line, end="") )
22        env = env.subscribe_error( lambda line: print("DBG:", line, end="") )
23        ## get cuda installation if Linux or Windows (tensorflow with cuda)
24        is_gpu_platform = platform.system() in ("Linux", "Windows")
25        env_name = "cuda" if is_gpu_platform else "default"
26        if ut.version_above(appose, '0.11'):
27            env = env.build()
28            env = env.activate(env_name)
29        else:
30            env = env.environment(env_name).build()
31        _logger.info(f"Environment built at: {env.base()}")
32        _logger.info( "Initiate environment to run epyseg" )
33        python = env.python().init("import numpy as np; import napari_epyseg; from napari_epyseg.call_epyseg import run_epyseg")
34
35        epyseg_script = '''
36### Script to run epyseg in another python environement, created with appose and launched as a task
37data = image.ndarray()
38#task.update(f'Start segmentation with epyseg')
39import logging
40class ApposeLogHandler(logging.Handler):
41    def emit(self, record):
42        msg = self.format(record)
43        task.update(message=msg)
44
45def setup_logger( name="epyseg_worker" ):
46    logger = logging.getLogger(name)
47    handler = ApposeLogHandler()
48    formatter = logging.Formatter('[Napari-epyseg] - %(message)s')
49    handler.setFormatter( formatter )
50    logger.addHandler(handler)
51    logger.setLevel( extras["logger_level"] )
52    return logger
53
54logger = setup_logger()
55segres = run_epyseg( data, parameters, progress_bar=extras["progress_bar"], logger=logger )
56if segres is not None:
57    ## Write the results on the shared memory object
58    image.ndarray()[:] = segres
59logger.info( "Segmentation finished" )
60'''
61        def log_listener(event):
62            """ Transfer appose task message to the main logger """
63            if event.message:
64                _logger.info(f"[task] {event.message}")
65
66        try:
67            with share_as_ndarray(image) as shared_image:
68                task = python.task(epyseg_script)
69                task.listen( log_listener )
70                task.inputs["image"] = shared_image 
71                task.inputs["parameters"] = parameters
72                ## other convenient tools to print msg, show progress..
73                task.inputs["extras"] = { "logger_name":_logger.name, "logger_level":_logger.level, "progress_bar": progress_bar }
74                _logger.info( "Start segmentation in appose service task.." )
75                task.wait_for()
76                result = shared_image.ndarray()
77                return result
78        except Exception as e:
79            raise RuntimeError("Running epyseg in separated environement failed") from e
80        finally:
81            python.close()
82    except Exception as e:
83        raise RuntimeError("Epyseg in separated environement failed") from e
def share_as_ndarray(img: numpy.ndarray) -> appose.shm.NDArray:
 9def share_as_ndarray(img: np.ndarray) -> appose.NDArray:
10    """Copies a NumPy array into a same-sized newly allocated block of shared memory."""
11    shared = appose.NDArray(str(img.dtype), img.shape)
12    shared.ndarray()[:] = img
13    return shared

Copies a NumPy array into a same-sized newly allocated block of shared memory.

def go_epyseg(image, parameters, progress_bar=None, logger=None):
15def go_epyseg( image, parameters, progress_bar=None, logger=None ):
16    """ Install a python environment with napari_epyseg if necessary with appose and run epyseg on the image within that environment """
17    _logger = logger or logging.getLogger(__name__)
18    try:
19        pixi_file = resources.files("epicure.resources").joinpath("pixi.toml")
20        _logger.info("Build/Load napari_epyseg environement")
21        env = appose.pixi( pixi_file ).log_debug()
22        env = env.subscribe_output( lambda line: print("OUT:", line, end="") )
23        env = env.subscribe_error( lambda line: print("DBG:", line, end="") )
24        ## get cuda installation if Linux or Windows (tensorflow with cuda)
25        is_gpu_platform = platform.system() in ("Linux", "Windows")
26        env_name = "cuda" if is_gpu_platform else "default"
27        if ut.version_above(appose, '0.11'):
28            env = env.build()
29            env = env.activate(env_name)
30        else:
31            env = env.environment(env_name).build()
32        _logger.info(f"Environment built at: {env.base()}")
33        _logger.info( "Initiate environment to run epyseg" )
34        python = env.python().init("import numpy as np; import napari_epyseg; from napari_epyseg.call_epyseg import run_epyseg")
35
36        epyseg_script = '''
37### Script to run epyseg in another python environement, created with appose and launched as a task
38data = image.ndarray()
39#task.update(f'Start segmentation with epyseg')
40import logging
41class ApposeLogHandler(logging.Handler):
42    def emit(self, record):
43        msg = self.format(record)
44        task.update(message=msg)
45
46def setup_logger( name="epyseg_worker" ):
47    logger = logging.getLogger(name)
48    handler = ApposeLogHandler()
49    formatter = logging.Formatter('[Napari-epyseg] - %(message)s')
50    handler.setFormatter( formatter )
51    logger.addHandler(handler)
52    logger.setLevel( extras["logger_level"] )
53    return logger
54
55logger = setup_logger()
56segres = run_epyseg( data, parameters, progress_bar=extras["progress_bar"], logger=logger )
57if segres is not None:
58    ## Write the results on the shared memory object
59    image.ndarray()[:] = segres
60logger.info( "Segmentation finished" )
61'''
62        def log_listener(event):
63            """ Transfer appose task message to the main logger """
64            if event.message:
65                _logger.info(f"[task] {event.message}")
66
67        try:
68            with share_as_ndarray(image) as shared_image:
69                task = python.task(epyseg_script)
70                task.listen( log_listener )
71                task.inputs["image"] = shared_image 
72                task.inputs["parameters"] = parameters
73                ## other convenient tools to print msg, show progress..
74                task.inputs["extras"] = { "logger_name":_logger.name, "logger_level":_logger.level, "progress_bar": progress_bar }
75                _logger.info( "Start segmentation in appose service task.." )
76                task.wait_for()
77                result = shared_image.ndarray()
78                return result
79        except Exception as e:
80            raise RuntimeError("Running epyseg in separated environement failed") from e
81        finally:
82            python.close()
83    except Exception as e:
84        raise RuntimeError("Epyseg in separated environement failed") from e

Install a python environment with napari_epyseg if necessary with appose and run epyseg on the image within that environment