# Path: snntoolbox/simulation/utils.py
# def get_layer_synaptic_operations(spiketrains_b_l, fanout):
#     """
#     Return total number of synaptic operations in the layer for a batch of
#     samples.
# 
#     Parameters
#     ----------
# 
#     spiketrains_b_l: ndarray
#         Batch of spiketrains of a layer. Shape: (batch_size, layer_shape)
#     fanout: Union[int, ndarray]
#         Number of outgoing connections per neuron. Can be a single integer, or
#         an array of the same shape as the layer, if the fanout varies from
#         neuron to neuron (as is the case in convolution layers with
#         stride > 1).
# 
#     Returns
#     -------
# 
#     layer_ops: int
#         The total number of operations in the layer for a batch of samples.
#     """
# 
#     if np.isscalar(fanout):
#         return np.array([np.count_nonzero(s) for s in spiketrains_b_l]) * \
#             fanout
#     elif hasattr(fanout, 'shape'):  # For conv layers with stride > 1
#         return np.array([np.sum(fanout[s != 0]) for s in spiketrains_b_l])
#     else:
#         raise TypeError("The 'fanout' parameter should either be integer or "
#                         "ndarray.")
# 
# def remove_name_counter(name_in):
#     """
#     Tensorflow adds a counter to layer names, e.g. <name>/kernel:0 ->
#     <name>_0/kernel:0. Need to remove this _0.
#     The situation gets complicated because SNN toolbox assigns layer names
#     that contain the layer shape, e.g. 00Conv2D_3x32x32. In addition,
#     we may get another underscore in the parameter name, e.g.
#     00DepthwiseConv2D_3X32x32_0/depthwise_kernel:0.
#     """
# 
#     if '_' not in name_in or '/' not in name_in:
#         return name_in
# 
#     split_dash = str(name_in).split('/')
#     assert len(split_dash) == 2, "Variable name must not contain '/'."
#     # We are only interested in the part before the /.
#     split_underscore = split_dash[0].split('_')
#     # The first '_' is assigned by SNN toolbox and should be kept.
#     return (split_underscore[0] + '_' + split_underscore[1] + '/' +
#             split_dash[1])


import tensorflow as tf
import numpy as np
from snntoolbox.simulation.target_simulators.\
    INI_temporal_mean_rate_target_sim import SNN as SNN_
from snntoolbox.simulation.utils import get_layer_synaptic_operations, \
    remove_name_counter
        from snntoolbox.utils.utils import echo
        if 'input_b_l_t' in self._log_keys:
            self.input_b_l_t[Ellipsis, 0] = input_b_l
        if self.neuron_operations_b_t is not None:
            self.neuron_operations_b_t[:, 0] += self.fanin[1] * \
                self.num_neurons[1] * np.ones(self.batch_size) * 2

        print("Current accuracy of batch:")
        if self.config.getint('output', 'verbose') > 0:
            guesses_b = np.argmax(np.sum(output_b_l_t, 2), 1)
            echo('{:.2%}_'.format(np.mean(kwargs[str('truth_b')] ==
                                          guesses_b)))

        return np.cumsum(output_b_l_t, 2)

    def load(self, path, filename):
        SNN_.load(self, path, filename)

    def set_spiketrains(self, spiketrains_b_l_t, i):
        if self.spiketrains_n_b_l_t is not None:
            self.spiketrains_n_b_l_t[i][0][:] = spiketrains_b_l_t

    def set_spikerates(self, spikerates_b_l, i):
        if self.spikerates_n_b_l is not None:
            self.spikerates_n_b_l[i][0][:] = spikerates_b_l

    def set_neuron_operations(self, i):
        self.neuron_operations_b_t += self.num_neurons_with_bias[i + 1]

    def set_synaptic_operations(self, spiketrains_b_l_t, i):
        for t in range(self.synaptic_operations_b_t.shape[-1]):

# Path: snntoolbox/simulation/utils.py
# def get_layer_synaptic_operations(spiketrains_b_l, fanout):
#     """
#     Return total number of synaptic operations in the layer for a batch of
#     samples.
# 
#     Parameters
#     ----------
# 
#     spiketrains_b_l: ndarray
#         Batch of spiketrains of a layer. Shape: (batch_size, layer_shape)
#     fanout: Union[int, ndarray]
#         Number of outgoing connections per neuron. Can be a single integer, or
#         an array of the same shape as the layer, if the fanout varies from
#         neuron to neuron (as is the case in convolution layers with
#         stride > 1).
# 
#     Returns
#     -------
# 
#     layer_ops: int
#         The total number of operations in the layer for a batch of samples.
#     """
# 
#     if np.isscalar(fanout):
#         return np.array([np.count_nonzero(s) for s in spiketrains_b_l]) * \
#             fanout
#     elif hasattr(fanout, 'shape'):  # For conv layers with stride > 1
#         return np.array([np.sum(fanout[s != 0]) for s in spiketrains_b_l])
#     else:
#         raise TypeError("The 'fanout' parameter should either be integer or "
#                         "ndarray.")
# 
# def remove_name_counter(name_in):
#     """
#     Tensorflow adds a counter to layer names, e.g. <name>/kernel:0 ->
#     <name>_0/kernel:0. Need to remove this _0.
#     The situation gets complicated because SNN toolbox assigns layer names
#     that contain the layer shape, e.g. 00Conv2D_3x32x32. In addition,
#     we may get another underscore in the parameter name, e.g.
#     00DepthwiseConv2D_3X32x32_0/depthwise_kernel:0.
#     """
# 
#     if '_' not in name_in or '/' not in name_in:
#         return name_in
# 
#     split_dash = str(name_in).split('/')
#     assert len(split_dash) == 2, "Variable name must not contain '/'."
#     # We are only interested in the part before the /.
#     split_underscore = split_dash[0].split('_')
#     # The first '_' is assigned by SNN toolbox and should be kept.
#     return (split_underscore[0] + '_' + split_underscore[1] + '/' +
#             split_dash[1])


# Path: snntoolbox/simulation/target_simulators/INI_temporal_pattern_target_sim.py
import tensorflow as tf
import numpy as np
from snntoolbox.simulation.target_simulators.\
    INI_temporal_mean_rate_target_sim import SNN as SNN_
from snntoolbox.simulation.utils import get_layer_synaptic_operations, \
    remove_name_counter
        from snntoolbox.utils.utils import echo

        if 'input_b_l_t' in self._log_keys:
            self.input_b_l_t[Ellipsis, 0] = input_b_l
        if self.neuron_operations_b_t is not None:
            self.neuron_operations_b_t[:, 0] += self.fanin[1] * \
                self.num_neurons[1] * np.ones(self.batch_size) * 2

        print("Current accuracy of batch:")
        if self.config.getint('output', 'verbose') > 0:
            guesses_b = np.argmax(np.sum(output_b_l_t, 2), 1)
            echo('{:.2%}_'.format(np.mean(kwargs[str('truth_b')] ==
                                          guesses_b)))

        return np.cumsum(output_b_l_t, 2)

    def load(self, path, filename):
        SNN_.load(self, path, filename)

    def set_spiketrains(self, spiketrains_b_l_t, i):
        if self.spiketrains_n_b_l_t is not None:
            self.spiketrains_n_b_l_t[i][0][:] = spiketrains_b_l_t

    def set_spikerates(self, spikerates_b_l, i):
        if self.spikerates_n_b_l is not None:
            self.spikerates_n_b_l[i][0][:] = spikerates_b_l

    def set_neuron_operations(self, i):
        self.neuron_operations_b_t += self.num_neurons_with_bias[i + 1]

    def set_synaptic_operations(self, spiketrains_b_l_t, i):
        for t in range(self.synaptic_operations_b_t.shape[-1]):

            ops = get_layer_synaptic_operations(spiketrains_b_l_t[Ellipsis, t],