/** 
* @file testImageNetMedian.cpp
* @brief test our median prototype idea
* @author Erik Rodner
* @date 01/04/2012

*/
#include <core/basics/Config.h>

#ifdef NICE_USELIB_MATIO

#include <core/matlabAccess/MatFileIO.h>

//----------

#include <vislearning/matlabAccessHighLevel/ImageNetData.h>

//----------

#include <gp-hik-core/FMKGPHyperparameterOptimization.h>
#include <gp-hik-core/parameterizedFunctions/PFAbsExp.h>
#include <gp-hik-core/tools.h>

using namespace std;
using namespace NICE;


/** 
    test the basic functionality of fast-hik hyperparameter optimization 
*/
int main (int argc, char **argv)
{   
  std::set_terminate(__gnu_cxx::__verbose_terminate_handler);

  Config conf ( argc, argv );
  
  
//  std::string root = "/home/dbv/bilder/imagenet/devkit-1.0/demo/";
  std::string root = "/users2/rodner/data/imagenet/devkit-1.0/demo/";
  ImageNetData imageNet ( root );

  cerr << "Reading ImageNet data files (takes some seconds)..." << endl;
  NICE::Vector y;
  sparse_t data;
  imageNet.getBatchData ( data, y, "train", "training" );

  uint n = y.size();
  map<int, int> examples;
  for ( uint i = 0 ; i < n; i++ )
    examples.insert( pair<int, int> (i, i) );

  y.resize(n);

  cerr << "Sorting features ..." << endl;
  FeatureMatrix fm ( data, examples );

  // count the number of examples of each class
  Vector elementCounts (y.Max()+1, 0.0);
  for ( uint i = 0 ; i < n; i++ )
    elementCounts[ y[i] ]++;

  // calculate the median for each class
  map<int, SparseVector> medians;
  for ( int dim = 0 ; dim < fm.get_d(); dim++ )
  {
    cerr << "Calculating the median values for dimension " << dim << endl;
    SparseVector classMedians;
    fm.getFeatureValues(dim).getClassMedians ( classMedians, y, elementCounts );
    for ( SparseVector::const_iterator i = classMedians.begin(); i != classMedians.end(); i++ )
    {
      int classno = i->first;
      double medianValue = i->second;
      medians[classno].insert ( pair<int, double> ( dim, medianValue ) );
    }
  }

  // ------------------------------ TESTING ------------------------------
 
  cerr << "Reading ImageNet test data files (takes some seconds)..." << endl;
  imageNet.preloadData ( "val", "testing" );
 
  for ( uint i = 0 ; i < imageNet.getNumPreloadedExamples(); i++ )
  {
    const SparseVector & svec = imageNet.getPreloadedExample ( i );
    set< pair<double, int> > scores;
    
    // calculate the distance to each of the classes !
    for ( map<int, SparseVector>::const_iterator k = medians.begin(); k != medians.end(); k++ )
    {
      const SparseVector & prototype = k->second;
      int classno = k->first;
      //double kval = prototype.minimumKernel ( svec );
      double kval = prototype.innerProduct ( svec );
      scores.insert ( pair<double, int> ( -1.0 * kval, classno ) );
    }

    cerr << "# groundtruth example: " << imageNet.getPreloadedLabel(i) << " " << i << " / " << imageNet.getNumPreloadedExamples() << endl;
    uint nBestClasses = std::min( 5, (int)scores.size() );
    uint kk = 0;
    for ( set< pair<double, int> >::const_iterator k = scores.begin(); k != scores.end() && kk < nBestClasses; k++, kk++ )
      cerr << k->second << " ";
    cerr << endl;
  }
  
  return 0;
}
#else
int main (int argc, char **argv)
{
  std::cerr << "MatIO library is missing in your system - this program will have no effect. " << std::endl;  
}

#endif