Calculate the receptive field of the SOM on some data.

        The receptive field is the common ending of all sequences which
        lead to the activation of a given BMU. If a SOM is well-tuned to
        specific sequences, it will have longer receptive fields, and therefore
        gives a better description of the dynamics of a given system.

        Parameters
        ----------
        X : numpy array
            Input data.
        identities : list
            A list of symbolic identities associated with each input.
            We expect this list to be as long as the input data.
        max_len : int, optional, default 10
            The maximum length to attempt to find. Raising this increases
            memory use.
        threshold : float, optional, default .9
            The threshold at which we consider a receptive field
            valid. If at least this proportion of the sequences of a neuron
            have the same suffix, that suffix is counted as acquired by the
            SOM.
        batch_size : int, optional, default 1
            The batch size to use in prediction

        Returns
        -------
        receptive_fields : dict
            A dictionary mapping from the neuron id to the found sequences
            for that neuron. The sequences are represented as lists of
            symbols from identities.

def receptive_field(self,
                        X,
                        identities,
                        max_len=10,
                        threshold=0.9,
                        batch_size=1):
        """
        Calculate the receptive field of the SOM on some data.

        The receptive field is the common ending of all sequences which
        lead to the activation of a given BMU. If a SOM is well-tuned to
        specific sequences, it will have longer receptive fields, and therefore
        gives a better description of the dynamics of a given system.

        Parameters
        ----------
        X : numpy array
            Input data.
        identities : list
            A list of symbolic identities associated with each input.
            We expect this list to be as long as the input data.
        max_len : int, optional, default 10
            The maximum length to attempt to find. Raising this increases
            memory use.
        threshold : float, optional, default .9
            The threshold at which we consider a receptive field
            valid. If at least this proportion of the sequences of a neuron
            have the same suffix, that suffix is counted as acquired by the
            SOM.
        batch_size : int, optional, default 1
            The batch size to use in prediction

        Returns
        -------
        receptive_fields : dict
            A dictionary mapping from the neuron id to the found sequences
            for that neuron. The sequences are represented as lists of
            symbols from identities.

        """
        receptive_fields = defaultdict(list)
        predictions = self.predict(X, batch_size)

        if len(predictions) != len(identities):
            raise ValueError("X and identities are not the same length: "
                             "{0} and {1}".format(len(X), len(identities)))

        for idx, p in enumerate(predictions.tolist()):
            receptive_fields[p].append(identities[idx+1 - max_len:idx+1])

        rec = {}

        for k, v in receptive_fields.items():
            # if there's only one sequence, we don't know
            # anything abouw how salient it is.
            seq = []
            if len(v) <= 1:
                continue
            else:
                for x in reversed(list(zip(*v))):
                    x = Counter(x)
                    if x.most_common(1)[0][1] / sum(x.values()) > threshold:
                        seq.append(x.most_common(1)[0][0])
                    else:
                        rec[k] = seq
                        break

        return rec