# Path: snntoolbox/simulation/backends/inisim/ttfs.py
# class SpikeConcatenate(Concatenate):
#     """Spike merge layer"""
# 
#     def __init__(self, axis, **kwargs):
#         kwargs.pop(str('config'))
#         Concatenate.__init__(self, axis, **kwargs)
# 
#     @staticmethod
#     def get_time():
# 
#         pass
# 
#     @staticmethod
#     def reset(sample_idx):
#         """Reset layer variables."""
# 
#         pass
# 
#     @property
#     def class_name(self):
#         """Get class name."""
# 
#         return self.__class__.__name__
# 
# class SpikeZeroPadding2D(ZeroPadding2D):
#     """Spike padding layer"""
# 
#     def __init__(self, *args, **kwargs):
#         kwargs.pop(str('config'))
#         ZeroPadding2D.__init__(self, *args, **kwargs)
# 
#     @staticmethod
#     def get_time():
# 
#         pass
# 
#     @staticmethod
#     def reset(sample_idx):
#         """Reset layer variables."""
# 
#         pass
# 
#     @property
#     def class_name(self):
#         """Get class name."""
# 
#         return self.__class__.__name__
# 
# class SpikeReshape(Reshape):
#     """Spike reshape layer"""
# 
#     def __init__(self, *args, **kwargs):
#         kwargs.pop(str('config'))
#         Reshape.__init__(self, *args, **kwargs)
# 
#     @staticmethod
#     def get_time():
#         pass
# 
#     @staticmethod
#     def reset(sample_idx):
#         """Reset layer variables."""
# 
#         pass
# 
#     @property
#     def class_name(self):
#         """Get class name."""
# 
#         return self.__class__.__name__


import numpy as np
import tensorflow as tf
import tensorflow.keras.backend as k
from tensorflow.keras.layers import Dense, Flatten, AveragePooling2D, \
    MaxPooling2D, Conv2D, Layer, DepthwiseConv2D
from snntoolbox.simulation.backends.inisim.ttfs import SpikeConcatenate, \
    SpikeZeroPadding2D, SpikeReshape
        from snntoolbox.bin.utils import get_log_keys, get_plot_keys
            to reference for weight shape computations.
        """

        MaxPooling2D.build(self, input_shape)
        self.init_neurons(input_shape)

    def call(self, x, mask=None):
        """Layer functionality."""
        # Skip integration of input spikes in membrane potential. Directly
        # transmit new spikes. The output psp is nonzero wherever there has
        # been an input spike at any time during simulation.

        input_psp = MaxPooling2D.call(self, x)

        if self.spiketrain is not None:
            new_spikes = tf.math.logical_xor(
                k.greater(input_psp, 0), k.greater(self.last_spiketimes, 0))
            self.add_update([(self.spiketrain,
                              self.time * k.cast(new_spikes, k.floatx()))])

        psp = self.get_psp(input_psp)

        return k.cast(psp, k.floatx())


custom_layers = {'SpikeFlatten': SpikeFlatten,
                 'SpikeDense': SpikeDense,
                 'SpikeConv2D': SpikeConv2D,
                 'SpikeAveragePooling2D': SpikeAveragePooling2D,
                 'SpikeMaxPooling2D': SpikeMaxPooling2D,

# Path: snntoolbox/simulation/backends/inisim/ttfs.py
# class SpikeConcatenate(Concatenate):
#     """Spike merge layer"""
# 
#     def __init__(self, axis, **kwargs):
#         kwargs.pop(str('config'))
#         Concatenate.__init__(self, axis, **kwargs)
# 
#     @staticmethod
#     def get_time():
# 
#         pass
# 
#     @staticmethod
#     def reset(sample_idx):
#         """Reset layer variables."""
# 
#         pass
# 
#     @property
#     def class_name(self):
#         """Get class name."""
# 
#         return self.__class__.__name__
# 
# class SpikeZeroPadding2D(ZeroPadding2D):
#     """Spike padding layer"""
# 
#     def __init__(self, *args, **kwargs):
#         kwargs.pop(str('config'))
#         ZeroPadding2D.__init__(self, *args, **kwargs)
# 
#     @staticmethod
#     def get_time():
# 
#         pass
# 
#     @staticmethod
#     def reset(sample_idx):
#         """Reset layer variables."""
# 
#         pass
# 
#     @property
#     def class_name(self):
#         """Get class name."""
# 
#         return self.__class__.__name__
# 
# class SpikeReshape(Reshape):
#     """Spike reshape layer"""
# 
#     def __init__(self, *args, **kwargs):
#         kwargs.pop(str('config'))
#         Reshape.__init__(self, *args, **kwargs)
# 
#     @staticmethod
#     def get_time():
#         pass
# 
#     @staticmethod
#     def reset(sample_idx):
#         """Reset layer variables."""
# 
#         pass
# 
#     @property
#     def class_name(self):
#         """Get class name."""
# 
#         return self.__class__.__name__


# Path: snntoolbox/simulation/backends/inisim/ttfs_dyn_thresh.py
import numpy as np
import tensorflow as tf
import tensorflow.keras.backend as k
from tensorflow.keras.layers import Dense, Flatten, AveragePooling2D, \
    MaxPooling2D, Conv2D, Layer, DepthwiseConv2D
from snntoolbox.simulation.backends.inisim.ttfs import SpikeConcatenate, \
    SpikeZeroPadding2D, SpikeReshape
        from snntoolbox.bin.utils import get_log_keys, get_plot_keys

            to reference for weight shape computations.
        """

        MaxPooling2D.build(self, input_shape)
        self.init_neurons(input_shape)

    def call(self, x, mask=None):
        """Layer functionality."""
        # Skip integration of input spikes in membrane potential. Directly
        # transmit new spikes. The output psp is nonzero wherever there has
        # been an input spike at any time during simulation.

        input_psp = MaxPooling2D.call(self, x)

        if self.spiketrain is not None:
            new_spikes = tf.math.logical_xor(
                k.greater(input_psp, 0), k.greater(self.last_spiketimes, 0))
            self.add_update([(self.spiketrain,
                              self.time * k.cast(new_spikes, k.floatx()))])

        psp = self.get_psp(input_psp)

        return k.cast(psp, k.floatx())


custom_layers = {'SpikeFlatten': SpikeFlatten,
                 'SpikeDense': SpikeDense,
                 'SpikeConv2D': SpikeConv2D,
                 'SpikeAveragePooling2D': SpikeAveragePooling2D,
                 'SpikeMaxPooling2D': SpikeMaxPooling2D,

                 'SpikeConcatenate': SpikeConcatenate,