# Path: deepcpg/models/utils.py
# class Model(object):
#     """Abstract model call.
# 
#     Abstract class of DNA, CpG, and Joint models.
# 
#     Parameters
#     ----------
#     dropout: float
#         Dropout rate.
#     l1_decay: float
#         L1 weight decay.
#     l2_decay: float
#         L2 weight decay.
#     init: str
#         Name of Keras initialization.
#     """
# 
#     def __init__(self, dropout=0.0, l1_decay=0.0, l2_decay=0.0,
#                  init='glorot_uniform'):
#         self.dropout = dropout
#         self.l1_decay = l1_decay
#         self.l2_decay = l2_decay
#         self.init = init
#         self.name = self.__class__.__name__
#         self.scope = None
# 
#     def inputs(self, *args, **kwargs):
#         """Return list of Keras model inputs."""
#         pass
# 
#     def _build(self, input, output):
#         """Build final model at the end of `__call__`."""
#         model = km.Model(input, output, name=self.name)
#         if self.scope:
#             for layer in model.layers:
#                 if not is_input_layer(layer):
#                     layer.name = '%s/%s' % (self.scope, layer.name)
#         return model
# 
#     def __call__(self, inputs=None):
#         """Build model.
# 
#         Parameters
#         ----------
#         inputs: list
#             Keras model inputs
#         """
#         pass
# 
# Path: deepcpg/utils.py
# def get_from_module(identifier, module_params, ignore_case=True):
#     """Return object from module.
# 
#     Return object with name `identifier` from module with items `module_params`.
# 
#     Parameters
#     ----------
#     identifier: str
#         Name of object, e.g. a function, in module.
#     module_params: dict
#         `dict` of items in module, e.g. `globals()`
#     ignore_case: bool
#         If `True`, ignore case of `identifier`.
# 
#     Returns
#     -------
#     object
#         Object with name `identifier` in module, e.g. a function or class.
#     """
#     if ignore_case:
#         _module_params = dict()
#         for key, value in six.iteritems(module_params):
#             _module_params[key.lower()] = value
#         _identifier = identifier.lower()
#     else:
#         _module_params = module_params
#         _identifier = identifier
#     item = _module_params.get(_identifier)
#     if not item:
#         raise ValueError('Invalid identifier "%s"!' % identifier)
#     return item


import inspect
from keras import layers as kl
from keras import models as km
from keras import regularizers as kr
from keras.layers.merge import concatenate
from .utils import Model
from ..utils import get_from_module





class JointModel(Model):
    """Abstract class of a Joint model."""

    def __init__(self, *args, **kwargs):
        super(JointModel, self).__init__(*args, **kwargs)
        self.mode = 'concat'
        self.scope = 'joint'

    def _get_inputs_outputs(self, models):
        inputs = []
        outputs = []
        for model in models:
            inputs.extend(model.inputs)
            outputs.extend(model.outputs)
        return (inputs, outputs)

    def _build(self, models, layers=[]):
        for layer in layers:
            layer.name = '%s/%s' % (self.scope, layer.name)

        inputs, outputs = self._get_inputs_outputs(models)
        x = concatenate(outputs)
        for layer in layers:
            x = layer(x)


# Path: deepcpg/models/utils.py
# class Model(object):
#     """Abstract model call.
# 
#     Abstract class of DNA, CpG, and Joint models.
# 
#     Parameters
#     ----------
#     dropout: float
#         Dropout rate.
#     l1_decay: float
#         L1 weight decay.
#     l2_decay: float
#         L2 weight decay.
#     init: str
#         Name of Keras initialization.
#     """
# 
#     def __init__(self, dropout=0.0, l1_decay=0.0, l2_decay=0.0,
#                  init='glorot_uniform'):
#         self.dropout = dropout
#         self.l1_decay = l1_decay
#         self.l2_decay = l2_decay
#         self.init = init
#         self.name = self.__class__.__name__
#         self.scope = None
# 
#     def inputs(self, *args, **kwargs):
#         """Return list of Keras model inputs."""
#         pass
# 
#     def _build(self, input, output):
#         """Build final model at the end of `__call__`."""
#         model = km.Model(input, output, name=self.name)
#         if self.scope:
#             for layer in model.layers:
#                 if not is_input_layer(layer):
#                     layer.name = '%s/%s' % (self.scope, layer.name)
#         return model
# 
#     def __call__(self, inputs=None):
#         """Build model.
# 
#         Parameters
#         ----------
#         inputs: list
#             Keras model inputs
#         """
#         pass
# 
# Path: deepcpg/utils.py
# def get_from_module(identifier, module_params, ignore_case=True):
#     """Return object from module.
# 
#     Return object with name `identifier` from module with items `module_params`.
# 
#     Parameters
#     ----------
#     identifier: str
#         Name of object, e.g. a function, in module.
#     module_params: dict
#         `dict` of items in module, e.g. `globals()`
#     ignore_case: bool
#         If `True`, ignore case of `identifier`.
# 
#     Returns
#     -------
#     object
#         Object with name `identifier` in module, e.g. a function or class.
#     """
#     if ignore_case:
#         _module_params = dict()
#         for key, value in six.iteritems(module_params):
#             _module_params[key.lower()] = value
#         _identifier = identifier.lower()
#     else:
#         _module_params = module_params
#         _identifier = identifier
#     item = _module_params.get(_identifier)
#     if not item:
#         raise ValueError('Invalid identifier "%s"!' % identifier)
#     return item


# Path: deepcpg/models/joint.py
import inspect
from keras import layers as kl
from keras import models as km
from keras import regularizers as kr
from keras.layers.merge import concatenate
from .utils import Model
from ..utils import get_from_module






class JointModel(Model):
    """Abstract class of a Joint model."""

    def __init__(self, *args, **kwargs):
        super(JointModel, self).__init__(*args, **kwargs)
        self.mode = 'concat'
        self.scope = 'joint'

    def _get_inputs_outputs(self, models):
        inputs = []
        outputs = []
        for model in models:
            inputs.extend(model.inputs)
            outputs.extend(model.outputs)
        return (inputs, outputs)

    def _build(self, models, layers=[]):
        for layer in layers:
            layer.name = '%s/%s' % (self.scope, layer.name)

        inputs, outputs = self._get_inputs_outputs(models)
        x = concatenate(outputs)
        for layer in layers:
            x = layer(x)


        model = km.Model(inputs, x, name=self.name)