content: ################################################################################
  """
  Functions for Digit Recognition
  
  Created on Wed Jun 01 00:00:00 2016
  
  @author: Prasun Roy
  
  @e-mail: prasunroy.pr@gmail.com
  """
  ################################################################################
  
  # import modules
  import matplotlib.pyplot as pplt
  import numpy as np
  import os
  import pandas as pd
  import skimage.feature as skim
  import sklearn.preprocessing as pp
  import time
  
  from conf import _config
  from conf import _configinfo
  
  ################################################################################
  
  def _fscale(data, split=False, load=False, verbose=False):
      # initialize scaler
      scaler = pp.MinMaxScaler()
      
      # initialize variables
      config = _configinfo()
      sdpath = config['root_data_path'] + 'scaled.npy'
      
      # scale data
      if verbose: print('scaling features............... ', end = '')
      data = np.array(data, dtype='float64')
      if load and os.path.isfile(sdpath):
          m = np.load(sdpath)[0]
          r = np.load(sdpath)[1]
          r[r==0] = 1
          data = (data - m) / r
      elif split:
          train = data[:config['train_d']]
          valid = data[config['train_d']:]
          scaler.fit(train)
          m = scaler.data_min_
          r = scaler.data_range_
          train = scaler.transform(train)
          valid = scaler.transform(valid)
          data  = np.vstack((train, valid))
      else:
          data = scaler.fit_transform(data)
          m = scaler.data_min_
          r = scaler.data_range_
      if verbose: print('done')
      
      # save scaled config
      if not load: np.save(sdpath, np.vstack((m, r)))
      
      # return scaled data
      return data
  
  ################################################################################
  
  def _haar(data, load=True, save=False, verbose=False):
      return data
  
  ################################################################################
  
  def _hogs(data, load=True, save=False, verbose=False):
      # initialize config
      config = _config()
      
      # initialize variables
      datapath = config['hogs_data_path']
      data_hog = []
      
      # load hog data if exists
      if load and os.path.isfile(datapath):
          if verbose: print('loading descriptors............ ', end = '')
          data_hog = np.load(datapath)
          if verbose: print('done')
      
      # calculate hog data otherwise
      else:
          # initialize variables
          ix = config['shape_x']
          iy = config['shape_y']
          bn = config['bins_n']
          cx = config['cell_x']
          cy = config['cell_y']
          bw = config['blok_w']
          bh = config['blok_h']
          
          # perform hog
          t_beg = time.time()
          size = data.shape[0]
          loop = 0
          for image in data:
              if verbose: print('\rextracting descriptors......... %d%%'
                                %(loop*100//size), end = '')
              desc = skim.hog(image.reshape(ix, iy), orientations=bn,
                              pixels_per_cell=(cx, cy), cells_per_block=(bw, bh))
              data_hog.append(desc)
              loop = loop + 1
          data_hog = np.array(data_hog, dtype='float64')
          t_end = time.time()
          if verbose: print('\rextracting descriptors......... done @ %8.2f sec'
                            %(t_end - t_beg))
          
          # save data
          if save:
              if verbose: print('saving descriptors............. ', end = '')
              np.save(datapath, data_hog)
              if verbose: print('done')
      
      # return hog
      return data_hog
  
  ################################################################################
  
  def _sift(data, load=True, save=False, verbose=False):
      return data
  
  ################################################################################
  
  def _surf(data, load=True, save=False, verbose=False):
      return data
  
  ################################################################################
  
  def _plot(classifier, train, valid, step=None, save=False, verbose=False):
      # initialize config
      config = _config()
      
      # initialize variables
      if step is None: step = config['steps_d']
      plot_figs_head = config['classifier'] + '-' + config['preprocess']
      plot_data_path = config['plot_data_path']
      plot_figs_path = config['plot_figs_path']
      
      m_train = train.shape[0]
      m_valid = valid.shape[0]
      X_valid = valid[:, 1:]
      y_valid = valid[:, 0]
      error_train = []
      error_valid = []
      sizes_train = []
      
      # calculate data for plot
      for i in range(0, m_train, step):
          if verbose: print('\rgenerating plot................ %d%%'
                            %(i*100//m_train), end = '')
          
          # randomly shuffle training data
          np.random.shuffle(train)
          
          # select subset of randomized training data
          X_train = train[:i+step, 1:]
          y_train = train[:i+step, 0]
          
          # train classifier with selected data
          classifier.fit(X_train, y_train)
          
          # cross-validate classifier
          p_train = classifier.predict(X_train)
          p_valid = classifier.predict(X_valid)
          
          # estimate errors
          error_train.append(sum(y_train != p_train) / len(y_train))
          error_valid.append(sum(y_valid != p_valid) / m_valid)
          
          sizes_train.append(i+step)
      
      error_train = np.array(error_train, dtype='float64')
      error_valid = np.array(error_valid, dtype='float64')
      sizes_train = np.array(sizes_train, dtype='uint32')
      
      if verbose: print('\rgenerating plot................ done')
      
      # plot data
      pplt.plot(sizes_train, error_train, 'rs-', label='training error')
      pplt.plot(sizes_train, error_valid, 'gs-', label='cross-validation error')
      pplt.title(plot_figs_head.upper()+' Learning Curve')
      pplt.xlabel('number of training instances')
      pplt.ylabel('classification error')
      pplt.legend()
      xmin,xmax = pplt.xlim()
      ymin,ymax = pplt.ylim()
      pplt.axis([xmin, xmax+step, ymin, ymax+0.01])
      pplt.grid(True)
      
      # save data
      if save:
          if verbose: print('saving plot.................... ', end = '')
          
          data = pd.DataFrame({'x1_TrainSizes':sizes_train,
                               'y1_TrainError':error_train,
                               'y2_ValidError':error_valid})
          
          data.to_csv(plot_data_path, index=False)
          pplt.savefig(plot_figs_path)
          
          if verbose: print('done')
      
      # display plot
      pplt.show()
  
  ################################################################################
  
  
  
  
  
  
  
  
  
  