Skip to content
This repository has been archived by the owner on Jun 18, 2023. It is now read-only.

Commit

Permalink
Use entry points to list YATSM change algos
Browse files Browse the repository at this point in the history
  • Loading branch information
ceholden committed Apr 11, 2016
1 parent e79f87b commit a30424e
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 5 deletions.
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
'sklearn': ('http://scikit-learn.org/stable', None),
'numpy': ('http://docs.scipy.org/doc/numpy/', None),
'pandas': ('http://pandas.pydata.org/pandas-docs/stable/', None),
'setuptools': ('https://pythonhosted.org/setuptools/', None),
'python': ('https://docs.python.org/dev', None)
}
todo_include_todos = True
Expand Down
56 changes: 56 additions & 0 deletions docs/guide/developer/custom_timeseries_algorithms.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
.. _guide_developer_custom_ts_algo:

===================================================
Integration of user-provided time series algorithms
===================================================

The YATSM package provides some time series algorithms as part of the
project, but developers can also build and integrate their own algorithms
into the suite of time series algorithms that can be utilized by programs like
:ref:`yatsm line <yatsm_line>` or :ref:`yatsm pixel <yatsm_pixel>`.

YATSM uses the setuptools_ module concept of "entry points" to
enumerate time series algorithms. YATSM algorithms are registered into a
group based on the type of algorithm -- there are entry point groups for
algorithms that find change as separate from algorithsm which postprocess
existing change results. Both categories link an entry point name to a
class or function usable within the YATSM package. For example, from the
``setup.py`` installation setup script:

.. code-block:: python
[yatsm.algorithms.change]
CCDCesque=yatsm.algorithms.ccdc:CCDCesque
This entry point definition links the name of the algorithm, "CCDCesque", to
the module (:mod:`yatsm.algorithms.ccdc`) containing the relevant
time series algorithm class, :class:`yatsm.algorithms.ccdc.CCDCesque`. Users
select the "CCDCesque" algorithm by defining it their configuration files.

Using entry points, you can create your own algorithms, distribute them in
separate Python packages, and YATSM will be able to find them and enable them
to work within the YATSM package.

Behind the scenes
-----------------

YATSM uses the function ``iter_entry_points`` from the setuptools_ module to
find and load all entry points associated with the YATSM package.

.. todo::

Create example ``yatsm_algorithms`` repository to act as a template for
including additional algorithms via setuptools_.


References:
-----------

- https://pythonhosted.org/setuptools/setuptools.html
- http://stackoverflow.com/questions/774824/explain-python-entry-points
- http://stackoverflow.com/questions/13545289/how-do-i-add-a-setuptools-entry-point-as-an-example-in-my-main-project
- https://docs.python.org/3/library/pkgutil.html


.. _pkgutil: https://docs.python.org/3/library/pkgutil.html
.. _setuptools: https://pythonhosted.org/setuptools/setuptools.html
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ To get started with YATSM, please follow this user guide:
guide/map_changes
guide/classification
guide/phenology
guide/developer/custom_timeseries_algorithms.rst


Command Line Interface Utilities
Expand Down
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ def run(self):
classify=yatsm.cli.classify:classify
map=yatsm.cli.map:map
changemap=yatsm.cli.changemap:changemap
[yatsm.algorithms.change]
CCDCesque=yatsm.algorithms.ccdc:CCDCesque
'''

desc = ('Algorithms for remote sensing land cover and condition monitoring '
Expand Down
32 changes: 30 additions & 2 deletions yatsm/algorithms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,34 @@
- :py:class:`ccdc.CCDCesque`
"""
from .ccdc import CCDCesque # noqa
from collections import defaultdict
import functools
from pkg_resources import iter_entry_points

available = ['CCDCesque'] #:

def _broken_ep(ep, exc, *args, **kwargs):
""" Delay error due to broken entry point until it executes
"""
import logging
logger = logging.getLogger('yatsm')
logger.critical('Trying to import "{0.name}" algorithm entry point '
'raised a {1}'.format(ep, exc))
raise exc


def _iep(s):
""" Handle loading entry point 's' through iter entry points
"""
d = defaultdict(dict)
for _ep in iter_entry_points(s):
try:
d[_ep.name] = _ep.load()
except Exception as e:
d[_ep.name] = functools.partial(_broken_ep, _ep, e)
return d


available = {
'change': _iep('yatsm.algorithms.change'),
'postprocess': _iep('yatsm.algorithms.postprocess') # TODO: use this ep!
}
7 changes: 4 additions & 3 deletions yatsm/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,14 @@ def parse_config_file(config_file):
'configuration file' % algo)

# Embed algorithm in YATSM key
if algo not in algorithms.available:
# TODO: broaden this concept to at least algo['change']
if algo not in algorithms.available['change']:
raise NotImplementedError('Algorithm specified (%s) is not currently '
'available' % algo)
cfg['YATSM']['algorithm_cls'] = getattr(algorithms, algo)
cfg['YATSM']['algorithm_cls'] = algorithms.available['change'][algo]
if not cfg['YATSM']['algorithm_cls']:
raise KeyError('Could not find algorithm specified (%s) in '
'`yatsm.algorithms`' % algo)
'`yatsm.algorithms.available`' % algo)

# Add in dummy phenology and classification dicts if not included
if 'phenology' not in cfg:
Expand Down

0 comments on commit a30424e

Please sign in to comment.