Search for OTB (set env if necessary), subclass core.App for each available application.

OTBTFApp

Bases: App

Helper for OTBTF.

Source code in pyotb/apps.py
class OTBTFApp(App):
    """Helper for OTBTF."""
    @staticmethod
    def set_nb_sources(*args, n_sources=None):
        """Set the number of sources of TensorflowModelServe. Can be either user-defined or deduced from the args.

        Args:
            *args: arguments (dict). NB: we don't need kwargs because it cannot contain source#.il
            n_sources: number of sources. Default is None (resolves the number of sources based on the
                       content of the dict passed in args, where some 'source' str is found)

        """
        if n_sources:
            os.environ['OTB_TF_NSOURCES'] = str(int(n_sources))
        else:
            # Retrieving the number of `source#.il` parameters
            params_dic = {k: v for arg in args if isinstance(arg, dict) for k, v in arg.items()}
            n_sources = len([k for k in params_dic if 'source' in k and k.endswith('.il')])
            if n_sources >= 1:
                os.environ['OTB_TF_NSOURCES'] = str(n_sources)

    def __init__(self, app_name, *args, n_sources=None, **kwargs):
        """Constructor for an OTBTFApp object.

        Args:
            app_name: name of the OTBTF app
            *args: arguments (dict). NB: we don't need kwargs because it cannot contain source#.il
            n_sources: number of sources. Default is None (resolves the number of sources based on the
                       content of the dict passed in args, where some 'source' str is found)
            **kwargs: kwargs
        """
        self.set_nb_sources(*args, n_sources=n_sources)
        super().__init__(app_name, *args, **kwargs)

__init__(app_name, *args, n_sources=None, **kwargs)

Constructor for an OTBTFApp object.

Parameters:

Name Type Description Default
app_name

name of the OTBTF app

required
*args

arguments (dict). NB: we don't need kwargs because it cannot contain source#.il

()
n_sources

number of sources. Default is None (resolves the number of sources based on the content of the dict passed in args, where some 'source' str is found)

None
**kwargs

kwargs

{}
Source code in pyotb/apps.py
def __init__(self, app_name, *args, n_sources=None, **kwargs):
    """Constructor for an OTBTFApp object.

    Args:
        app_name: name of the OTBTF app
        *args: arguments (dict). NB: we don't need kwargs because it cannot contain source#.il
        n_sources: number of sources. Default is None (resolves the number of sources based on the
                   content of the dict passed in args, where some 'source' str is found)
        **kwargs: kwargs
    """
    self.set_nb_sources(*args, n_sources=n_sources)
    super().__init__(app_name, *args, **kwargs)

set_nb_sources(*args, n_sources=None) staticmethod

Set the number of sources of TensorflowModelServe. Can be either user-defined or deduced from the args.

Parameters:

Name Type Description Default
*args

arguments (dict). NB: we don't need kwargs because it cannot contain source#.il

()
n_sources

number of sources. Default is None (resolves the number of sources based on the content of the dict passed in args, where some 'source' str is found)

None
Source code in pyotb/apps.py
@staticmethod
def set_nb_sources(*args, n_sources=None):
    """Set the number of sources of TensorflowModelServe. Can be either user-defined or deduced from the args.

    Args:
        *args: arguments (dict). NB: we don't need kwargs because it cannot contain source#.il
        n_sources: number of sources. Default is None (resolves the number of sources based on the
                   content of the dict passed in args, where some 'source' str is found)

    """
    if n_sources:
        os.environ['OTB_TF_NSOURCES'] = str(int(n_sources))
    else:
        # Retrieving the number of `source#.il` parameters
        params_dic = {k: v for arg in args if isinstance(arg, dict) for k, v in arg.items()}
        n_sources = len([k for k in params_dic if 'source' in k and k.endswith('.il')])
        if n_sources >= 1:
            os.environ['OTB_TF_NSOURCES'] = str(n_sources)

PatchesExtraction

Bases: OTBTFApp

Extract patches using OTBTF.

Source code in pyotb/apps.py
class PatchesExtraction(OTBTFApp):
    """Extract patches using OTBTF."""
    def __init__(self, *args, n_sources=None, **kwargs):
        """Constructor for a PatchesExtraction object."""
        super().__init__('PatchesExtraction', *args, n_sources=n_sources, **kwargs)

__init__(*args, n_sources=None, **kwargs)

Constructor for a PatchesExtraction object.

Source code in pyotb/apps.py
def __init__(self, *args, n_sources=None, **kwargs):
    """Constructor for a PatchesExtraction object."""
    super().__init__('PatchesExtraction', *args, n_sources=n_sources, **kwargs)

TensorflowModelServe

Bases: OTBTFApp

Serve a Tensorflow model using OTBTF.

Source code in pyotb/apps.py
class TensorflowModelServe(OTBTFApp):
    """Serve a Tensorflow model using OTBTF."""
    def __init__(self, *args, n_sources=None, **kwargs):
        """Constructor for a TensorflowModelServe object."""
        super().__init__('TensorflowModelServe', *args, n_sources=n_sources, **kwargs)

__init__(*args, n_sources=None, **kwargs)

Constructor for a TensorflowModelServe object.

Source code in pyotb/apps.py
def __init__(self, *args, n_sources=None, **kwargs):
    """Constructor for a TensorflowModelServe object."""
    super().__init__('TensorflowModelServe', *args, n_sources=n_sources, **kwargs)

TensorflowModelTrain

Bases: OTBTFApp

Train a Tensorflow model using OTBTF.

Source code in pyotb/apps.py
class TensorflowModelTrain(OTBTFApp):
    """Train a Tensorflow model using OTBTF."""
    def __init__(self, *args, n_sources=None, **kwargs):
        """Constructor for a TensorflowModelTrain object."""
        super().__init__('TensorflowModelTrain', *args, n_sources=n_sources, **kwargs)

__init__(*args, n_sources=None, **kwargs)

Constructor for a TensorflowModelTrain object.

Source code in pyotb/apps.py
def __init__(self, *args, n_sources=None, **kwargs):
    """Constructor for a TensorflowModelTrain object."""
    super().__init__('TensorflowModelTrain', *args, n_sources=n_sources, **kwargs)

get_available_applications(as_subprocess=False)

Find available OTB applications.

Parameters:

Name Type Description Default
as_subprocess

indicate if function should list available applications using subprocess call

False

Returns:

Type Description

tuple of available applications

Source code in pyotb/apps.py
def get_available_applications(as_subprocess=False):
    """Find available OTB applications.

    Args:
        as_subprocess: indicate if function should list available applications using subprocess call

    Returns:
        tuple of available applications

    """
    app_list = ()
    if as_subprocess and sys.executable:
        # Currently, there is an incompatibility between OTBTF and Tensorflow that causes segfault
        # when OTBTF apps are used in a script where tensorflow has already been imported.
        # See https://github.com/remicres/otbtf/issues/28
        # Thus, we run this piece of code in a clean independent `subprocess` that doesn't interact with Tensorflow
        env = os.environ.copy()
        if "PYTHONPATH" not in env:
            env["PYTHONPATH"] = ""
        env["PYTHONPATH"] = ":" + str(Path(otb.__file__).parent)
        env["OTB_LOGGER_LEVEL"] = "CRITICAL"  # in order to suppress warnings while listing applications
        pycmd = "import otbApplication; print(otbApplication.Registry.GetAvailableApplications())"
        cmd_args = [sys.executable, "-c", pycmd]

        try:
            import subprocess  # pylint: disable=import-outside-toplevel
            params = {"env": env, "stdout": subprocess.PIPE, "stderr": subprocess.PIPE}
            with subprocess.Popen(cmd_args, **params) as p:
                logger.debug('Exec "%s \'%s\'"', ' '.join(cmd_args[:-1]), pycmd)
                stdout, stderr = p.communicate()
                stdout, stderr = stdout.decode(), stderr.decode()
                # ast.literal_eval is secure and will raise more handy Exceptions than eval
                from ast import literal_eval  # pylint: disable=import-outside-toplevel
                app_list = literal_eval(stdout.strip())
                assert isinstance(app_list, (tuple, list))
        except subprocess.SubprocessError:
            logger.debug("Failed to call subprocess")
        except (ValueError, SyntaxError, AssertionError):
            logger.debug("Failed to decode output or convert to tuple:\nstdout=%s\nstderr=%s", stdout, stderr)

        if not app_list:
            logger.info("Failed to list applications in an independent process. Falling back to local python import")
    # Find applications using the normal way
    if not app_list:
        app_list = otb.Registry.GetAvailableApplications()
    if not app_list:
        logger.warning("Unable to load applications. Set env variable OTB_APPLICATION_PATH then try again")
        return ()

    logger.info("Successfully loaded %s OTB applications", len(app_list))
    return app_list