view phe/variant/variant_factory.py @ 10:c2f8e7580133 draft

Uploaded
author ulfschaefer
date Mon, 21 Dec 2015 10:50:17 -0500
parents 834a312c0114
children
line wrap: on
line source

'''Classes and functions for working with variant callers.

Created on 22 Sep 2015

@author: alex
'''
import glob
import inspect
import logging
import os
import sys

from phe.variant import VariantCaller

def dynamic_caller_loader():
    """Fancy way of dynamically importing existing variant callers.
    
    Returns
    -------
    dict:
        Available variant callers dictionary. Keys are parameters that
        can be used to call variants.
    """

    # We assume the caller are in the same directory as THIS file.
    variants_dir = os.path.dirname(__file__)
    variants_dir = os.path.abspath(variants_dir)

    # This is populated when the module is first imported.
    avail_callers = {}

    # Add this directory to the syspath.
    sys.path.insert(0, variants_dir)

    # Find all "py" files.
    for caller_mod in glob.glob(os.path.join(variants_dir, "*.py")):

        # Derive name of the module where caller is.
        caller_mod_file = os.path.basename(caller_mod)

        # Ignore __init__ file, only base class is there.
        if caller_mod_file.startswith("__init__"):
            continue

        # Import the module with a caller.
        mod = __import__(caller_mod_file.replace(".pyc", "").replace(".py", ""))

        # Find all the classes contained in this module.
        classes = inspect.getmembers(mod, inspect.isclass)
        for cls_name, cls in classes:
            # For each class, if it is a sublass of VariantCaller, add it.
            if cls_name != "VariantCaller" and issubclass(cls, VariantCaller):
                # The name is inherited and defined within each caller.
                avail_callers[cls.name] = cls

    sys.path.remove(variants_dir)

    return avail_callers

_avail_variant_callers = dynamic_caller_loader()

def available_callers():
    """Return list of available variant callers."""
    return _avail_variant_callers.keys()

def factory(variant=None, custom_options=None):
    """Make an instance of a variant class.
    
    Parameters:
    -----------
    variant: str, optional
        Name of the variant class to instantiate.
    custom_options: str, optional
        Custom options to be passed directly to the implementing class.
    
    Returns:
    --------
    :py:class:`phe.variant.VariantCaller`:
        Instance of the :py:class:`phe.variant.VariantCaller` for given
        variant name, or None if one couldn't be found.
    """
    if variant is not None and isinstance(variant, str):

        variant = variant.lower()
        if variant in _avail_variant_callers:
            return _avail_variant_callers[variant](cmd_options=custom_options)
        else:
            logging.error("No implementation for %s mapper.")
            return None

    logging.warn("Unknown parameters. Mapper could not be initialised.")
    return None