text: # Krzysztof Joachimiak 2017
  # sciquence: Time series & sequences in Python
  #
  # Transform
  # Author: Krzysztof Joachimiak
  #
  # License: MIT
  
  from ..base import Processor
  
  
  import numpy as np
  
  # TODO: optimize, tweak processor classes. Consider adding transformer classes.
  #  Maybe functions should have arbitrary number of params
  # TODO: REFACTOR!!!!
  
  class RNNIput(Processor):
  
      def __init__(self, window_size, step=1, strategy='central'):
          self.window_size = window_size
          self.step = step
          self.strategy = strategy
  
      def fit_process(self, X, y):
          return super(RNNIput, self).fit_process(X, y)
  
      def fit(self, X, y):
          return super(RNNIput, self).fit(X, y)
  
      def process(self, X, y):
          return super(RNNIput, self).process(X, y)
  
  
  
  class Seq2SeqInput(Processor):
  
      def __init__(self):
          pass
  
      def fit_process(self, X, y):
          return super(Seq2SeqInput, self).fit_process(X, y)
  
      def fit(self, X, y):
          return super(Seq2SeqInput, self).fit(X, y)
  
      def process(self, X, y):
          return super(Seq2SeqInput, self).process(X, y)
  
  
  
  
  def _get_neighbourhood(matrix, row, padding):
      return matrix[row-padding:row+padding+1]
  
  def rnn_input(X, y, window_size, step=1):
      # TODO: Add diffrent labeling strategies
      '''
  
      Prepare input for recurrent neural network.
      Input is prepared from two parallel time series:
      series of feature vectors and series of labels.
  
      Parameters
      ----------
      X: ndarray (time_series_length, n_features)
          A time series of feature vectors
      y: ndarray (time_series_length, )
          A time series of labels
      window_size: int
          Integer odd number
      step: int
          Step of sliding window
  
      Returns
      -------
      new_X: ndarray (n_samples, n_timesteps, n_features)
          Input for recurrent neural network
      new_y: ndarray (n_samples, )
          Time series of labels
  
      '''
      new_X = []
      new_y = []
      margin = window_size / 2
      for i in xrange(margin, len(X) - margin, step):
          neigh = _get_neighbourhood(X, i, margin)
          new_X.append(neigh.reshape(1, window_size, neigh.shape[1]))
          if y is not None: new_y.append(y[i])
      return np.vstack(new_X), np.vstack(new_y) if y is not None else None
  
  
  
  def seq2seq_input(X, y, window_size, step=1, output_dim=1):
      # TODO: add examples, especially for output_dim usecase
      # TODO: remove & unify with rnn_input
      '''
  
      Prepare input for sequence2sequence recurrent neural network.
      Input is prepared from two parallel time series:
      series of feature vectors and series of labels.
  
  
      Parameters
      ----------
      X: ndarray (time_series_length, n_features)
          A time series of feature vectors
      y: ndarray (time_series_length, )
          A time series of labels
      window_size: int
          Integer odd number
      step: int
          Step of sliding window
  
      Returns
      -------
      new_X: ndarray (n_samples, n_timesteps, n_features)
          Input for recurrent neural network
      new_y: ndarray (n_samples, n_timesteps, output_dim)
          Time series of labels
  
      '''
      new_x = []
      new_y = []
      for i in xrange(0, len(X) - window_size+1, step):
          new_x.append(X[i:i + window_size].reshape(1, window_size, X.shape[1]))
          if y is not None: new_y.append(y[i:i+window_size].reshape(1, window_size, 1))
      return np.vstack(new_x), np.vstack(new_y) if y is not None else None
  
  
  
  
  
  
  
  
  
  
  