<commit_before>import numpy as np
from keras import backend as K
from keras.engine.topology import Layer
from keras import initializers
from keras.layers.pooling import _GlobalPooling1D
from keras.layers import Conv1D, Input
from deeplift.visualization import viz_sequence
import matplotlib.pyplot as plt

from concise.utils.pwm import DEFAULT_BASE_BACKGROUND, pssm_array2pwm_array
import concise.regularizers as cr
from concise.regularizers import GAMRegularizer
from concise.utils.splines import BSpline
from concise.utils.helper import get_from_module

# TODO - improve the naming
# TODO - unit-tests for the general case of smoothing: encodeSplines
# TODO - write unit-tests - use synthetic dataset from motifp - check both cases encodeSplines

############################################


def InputDNA(seq_length, name=None, **kwargs):
    """Convenience wrapper around keras.layers.Input:

    Input((seq_length, 4), name=name, **kwargs)
    """
    return Input((seq_length, 4), name=name, **kwargs)


# TODO - implement ConvRNAStructure
def InputRNAStructure(seq_length, name=None, **kwargs):
    """Convenience wrapper around keras.layers.Input:

    Input((seq_length, 5), name=name, **kwargs)
    """
    return Input((seq_length, 5), name=name, **kwargs)


def InputDNAQuantity(seq_length, n_features=1, name=None, **kwargs):
    """Convenience wrapper around keras.layers.Input:

    Input((seq_length, n_features), name=name, **kwargs)
    """
    return Input((seq_length, n_features), name=name, **kwargs)


def InputDNAQuantitySplines(seq_length, n_bases=10, name="DNASmoothPosition", **kwargs):
    """Convenience wrapper around keras.layers.Input:

    Input((seq_length, n_bases), name=name, **kwargs)
    """
    return Input((seq_length, n_bases), name=name, **kwargs)


class GlobalSumPooling1D(_GlobalPooling1D):
    """Global average pooling operation for temporal data.
    # Input shape
        3D tensor with shape: `(batch_size, steps, features)`.
    # Output shape
        2D tensor with shape:
        `(batch_size, channels)`
    """

    def call(self, inputs):
        return K.sum(inputs, axis=1)


class ConvDNA(Conv1D):
    """
    Convenience wrapper over keras.layers.Conv1D with 2 changes:
    - additional argument seq_length specifying input_shape
    - restriction in build method: input_shape[-1] needs to be 4
    """

    def __init__(self, filters,
                 kernel_size,
                 strides=1,
                 padding='valid',
                 dilation_rate=1,
                 activation=None,
                 use_bias=True,
                 kernel_initializer='glorot_uniform',
                 bias_initializer='zeros',
                 kernel_regularizer=None,
                 bias_regularizer=None,
                 activity_regularizer=None,
                 kernel_constraint=None,
                 bias_constraint=None,
                 seq_length=None,
                 background_probs=None,
                 **kwargs):

        # override input shape
        if seq_length:
            kwargs["input_shape"] = (seq_length, 4)
            kwargs.pop("batch_input_shape", None)

        super(ConvDNA, self).__init__(
            filters=filters,
            kernel_size=kernel_size,
            strides=strides,
            padding=padding,
            dilation_rate=dilation_rate,
            activation=activation,
            use_bias=use_bias,
            kernel_initializer=kernel_initializer,
            bias_initializer=bias_initializer,
            kernel_regularizer=kernel_regularizer,
            bias_regularizer=bias_regularizer,
            activity_regularizer=activity_regularizer,
            kernel_constraint=kernel_constraint,
            bias_constraint=bias_constraint,
            **kwargs)

        self.seq_length = seq_length

        if background_probs is None:
            background_probs = DEFAULT_BASE_BACKGROUND
        self.background_probs = background_probs

    def build(self, input_shape):
        if input_shape[-1] is not 4:
            raise ValueError("ConvDNA requires input_shape[-1] == 4")
        return super(ConvDNA, self).build(input_shape)

    def get_config(self):
        config = super(ConvDNA, self).get_config()
        config["seq_length"] = self.seq_length
        config["background_probs"] = self.background_probs
        return config

    # def plotWeights(self):
    #     """Plot weights as matrices
    #     """
    #     pass

    # TODO - implement plotting in bits
    def plotMotif(self, index, figsize=(10, 2)):

        W = self.get_weights()[0]

        assert isinstance(index, int)
        assert index >= 0
        assert index < W.shape[2]

        pwm = pssm_array2pwm_array(W, self.background_probs)

        return viz_sequence.plot_weights(pwm[:, :, index], figsize=figsize)

    def plotFilter(self, index, figsize=(10, 2)):
        """

        Arguments:
            index: Which motif to plot
        """

        W = self.get_weights()[0]

        assert isinstance(index, int)<commit_msg>feat: implemented Input* placeholders<commit_after>import numpy as np
from keras import backend as K
from keras.engine.topology import Layer
from keras import initializers
from keras.layers.pooling import _GlobalPooling1D
from keras.layers import Conv1D, Input
from deeplift.visualization import viz_sequence
import matplotlib.pyplot as plt

from concise.utils.pwm import DEFAULT_BASE_BACKGROUND, pssm_array2pwm_array
import concise.regularizers as cr
from concise.regularizers import GAMRegularizer
from concise.utils.splines import BSpline
from concise.utils.helper import get_from_module
from concise.preprocessing.sequence import (DNA, RNA, AMINO_ACIDS,
                                            CODONS, STOP_CODONS)
from concise.preprocessing.structure import RNAplfold_PROFILES
# TODO - improve the naming
# TODO - unit-tests for the general case of smoothing: encodeSplines
# TODO - write unit-tests - use synthetic dataset from motifp - check both cases encodeSplines

############################################

# --------------------------------------------
# Input()


def InputDNA(seq_length, name=None, **kwargs):
    """Input placeholder for array returned by encodeDNA/encodeRNA

    Wrapper for: keras.layers.Input((seq_length, 4), name=name, **kwargs)
    """
    return Input((seq_length, 4), name=name, **kwargs)


InputRNA = InputDNA


def InputCodon(seq_length, ignore_stop_codons=True, name=None, **kwargs):
    """Input placeholder for array returned by encodeCodon

    Wrapper for: keras.layers.Input((seq_length, 61 or 61), name=name, **kwargs)
    """
    if ignore_stop_codons:
        vocab = CODONS
    else:
        vocab = CODONS + STOP_CODONS

    return Input((seq_length, len(vocab)), name=name, **kwargs)


def InputAA(seq_length, name=None, **kwargs):
    """Input placeholder for array returned by encodeAA

    Wrapper for: keras.layers.Input((seq_length, 22), name=name, **kwargs)
    """
    return Input((seq_length, len(AMINO_ACIDS)), name=name, **kwargs)


def InputRNAStructure(seq_length, name=None, **kwargs):
    """Input placeholder for array returned by encodeRNAStructure

    Wrapper for: keras.layers.Input((seq_length, 5), name=name, **kwargs)
    """
    return Input((seq_length, len(RNAplfold_PROFILES)), name=name, **kwargs)


def InputSplines(seq_length, n_bases=10, name=None, **kwargs):
    """Input placeholder for array returned by encodeSplines

    Wrapper for: keras.layers.Input((seq_length, n_bases), name=name, **kwargs)
    """
    return Input((seq_length, len(RNAplfold_PROFILES)), name=name, **kwargs)


# TODO - deprecate
def InputDNAQuantity(seq_length, n_features=1, name=None, **kwargs):
    """Convenience wrapper around keras.layers.Input:

    Input((seq_length, n_features), name=name, **kwargs)
    """
    return Input((seq_length, n_features), name=name, **kwargs)


# TODO - deprecate
def InputDNAQuantitySplines(seq_length, n_bases=10, name="DNASmoothPosition", **kwargs):
    """Convenience wrapper around keras.layers.Input:

    Input((seq_length, n_bases), name=name, **kwargs)
    """
    return Input((seq_length, n_bases), name=name, **kwargs)

# --------------------------------------------

# TODO - implement ConvRNAStructure


class GlobalSumPooling1D(_GlobalPooling1D):
    """Global average pooling operation for temporal data.
    # Input shape
        3D tensor with shape: `(batch_size, steps, features)`.
    # Output shape
        2D tensor with shape:
        `(batch_size, channels)`
    """

    def call(self, inputs):
        return K.sum(inputs, axis=1)


# TODO how to write a generic class for it?

class ConvDNA(Conv1D):
    """
    Convenience wrapper over keras.layers.Conv1D with 2 changes:
    - additional argument seq_length specifying input_shape
    - restriction in build method: input_shape[-1] needs to be 4
    """

    def __init__(self, filters,
                 kernel_size,
                 strides=1,
                 padding='valid',
                 dilation_rate=1,
                 activation=None,
                 use_bias=True,
                 kernel_initializer='glorot_uniform',
                 bias_initializer='zeros',
                 kernel_regularizer=None,
                 bias_regularizer=None,
                 activity_regularizer=None,
                 kernel_constraint=None,
                 bias_constraint=None,
                 seq_length=None,
                 background_probs=None,
                 **kwargs):

        # override input shape
        if seq_length:
            kwargs["input_shape"] = (seq_length, 4)
            kwargs.pop("batch_input_shape", None)

        super(ConvDNA, self).__init__(
            filters=filters,
            kernel_size=kernel_size,
            strides=strides,
            padding=padding,
            dilation_rate=dilation_rate,
            activation=activation,
            use_bias=use_bias,
            kernel_initializer=kernel_initializer,
            bias_initializer=bias_initializer,
            kernel_regularizer=kernel_regularizer,
            bias_regularizer=bias_regularizer,
            activity_regularizer=activity_regularizer,
            kernel_constraint=kernel_constraint,
            bias_constraint=bias_constraint,
            **kwargs)

        self.seq_length = seq_length

        if background_probs is None:
            background_probs = DEFAULT_BASE_BACKGROUND
        self.background_probs = background_probs

    def build(self, input_shape):
        if input_shape[-1] is not 4:
            raise ValueError("ConvDNA requires input_shape[-1] == 4")
        return super(ConvDNA, self).build(input_shape)

    def get_config(self):
        config = super(ConvDNA, self).get_config()
        config["seq_length"] = self.seq_length
        config["background_probs"] = self.background_probs
        return config

    # def plotWeights(self):
    #     """Plot weights as matrices
    #     """
    #     pass

    # plot_as_motif
    # TODO - implement plotting in bits
    def plotMotif(self, index, figsize=(10, 2)):

        W = self.get_weights()[0]

        assert isinstance(index, int)
        assert index >= 0
        assert index < W.shape[2]

        pwm = pssm_array2pwm_array(W, self.background_probs)

        return viz_sequence.plot_weights(pwm[:, :, index], figsize=figsize)

    # TODO - rename into plot_weights(index=None),
    # plot_type="raw", "motif", "motif_info", "matrix" ???
    def plotFilter(self, index, figsize=(10, 2)):
        """

        Arguments:
            index: Which motif to plot
        """

        W = self.get_weights()[0]

        assert isinstance(index, int)
{'fraction_non_alphanumeric': 0.10972483336181849, 'fraction_numerical': 0.0070928046487779865, 'mean_word_length': 2.746158770806658, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6768031', 'n_tokens_mistral': 3488, 'n_tokens_neox': 3268, 'n_words': 813}