void sanityCheck()
    {
      DataFrame df;
      populateSimpleDataFrame(df);

      CfsSubsetEvaluator uut;
      uut.setDataFrame(df);
      // these values seem reasonable, but have not been manually validated. If there is a 
      // discrepancy at some time these should be manually verified.
      ASSERT_DBL_EQL(.447214, uut.evaluateSubset(IntVec(0, 1, 2)));
      ASSERT_DBL_EQL(.707107, uut.evaluateSubset(IntVec(0, 1)));
      ASSERT_DBL_EQL(1, uut.evaluateSubset(IntVec(0)));
    }
    void testFindBestSplitPoint()
    {
      int c[] = { 1, 1, 0, 0, 1 };
      std::vector<int> classes(c, c + 5);
      vector<double> values;
      for (unsigned int i = 0; i < classes.size(); i++)
      {
        values.push_back(i);
      }

      FayyadMdlDiscretizer uut;
      // call this just to set up internal data structures
      uut.calculateSplitPoints(classes, values);

      double gain;
      ASSERT_DBL_EQL(1, uut._findBestSplitPoint(0, 5, gain));
      ASSERT_DBL_EQL(0.970950594 - (2.0 * 0.0 + 3.0 * 0.918295834) / 5.0, gain);
      
      ASSERT_DBL_EQL(0, uut._findBestSplitPoint(0, 2, gain));
      ASSERT_DBL_EQL(0.0, gain);
      
      ASSERT_DBL_EQL(1, uut._findBestSplitPoint(1, 2, gain));
      ASSERT_DBL_EQL(1.0, gain);
      
      ASSERT_DBL_EQL(3, uut._findBestSplitPoint(2, 3, gain));
      ASSERT_DBL_EQL(0.918295834, gain);
    }
    void testDelta()
    {
      int c[] = { 1, 1, 0, 0, 1 };
      std::vector<int> classes(c, c + 5);
      vector<double> values;
      for (unsigned int i = 0; i < classes.size(); i++)
      {
        values.push_back(i);
      }

      FayyadMdlDiscretizer uut;
      // call this just to set up internal data structures
      uut.calculateSplitPoints(classes, values);

      // calculate it manually
      double k = 2, k1 = 1, k2 = 2;
      double ent = 0.970950594, entLeft = 0.0, entRight = 0.918295834;
      double delta = log(pow(3.0, k) - 2) / log(2.0) -
        (k * ent - k1 * entLeft - k2 * entRight);
      ASSERT_DBL_EQL(delta, uut._calculateDelta(0, 5, 1));
    }
    void testEntropy()
    {
      int c[] = { 1, 1, 0, 0, 1 };
      std::vector<int> classes(c, c + 5);
      vector<double> values;
      for (unsigned int i = 0; i < classes.size(); i++)
      {
        values.push_back(i);
      }

      FayyadMdlDiscretizer uut;
      // call this just to set up internal data structures
      uut.calculateSplitPoints(classes, values);

      ASSERT_DBL_EQL(0.970950594, uut._calculateEntropy(0, 5));
      ASSERT_DBL_EQL(0, uut._calculateEntropy(0, 2));
      ASSERT_DBL_EQL(0, uut._calculateEntropy(0, 0));
      ASSERT_DBL_EQL(0, uut._calculateEntropy(0, 1));
      ASSERT_DBL_EQL(1.0, uut._calculateEntropy(0, 4));
      ASSERT_DBL_EQL(1.0, uut._calculateEntropy(1, 4));
      ASSERT_DBL_EQL(0.918295834, uut._calculateEntropy(2, 3));
    }
    void test1()
    {
      SpinImage uut;
      uut.resize(10, 10);
      uut.setBounds(10, 0, 10);

      ASSERT_DBL_EQL(0.5, uut._calculateAlphaCenter(0));
      ASSERT_DBL_EQL(1.5, uut._calculateAlphaCenter(1));
      ASSERT_DBL_EQL(7.5, uut._calculateAlphaCenter(7));

      ASSERT_DBL_EQL(0.5, uut._calculateBetaCenter(0));
      ASSERT_DBL_EQL(1.5, uut._calculateBetaCenter(1));
      ASSERT_DBL_EQL(7.5, uut._calculateBetaCenter(7));

      ASSERT_DBL_EQL(0, uut._calculateLowerAlpha(0));
      ASSERT_DBL_EQL(0, uut._calculateLowerAlpha(0.5));
      ASSERT_DBL_EQL(0, uut._calculateLowerAlpha(1.0));
      ASSERT_DBL_EQL(0, uut._calculateLowerAlpha(1.49));
      ASSERT_DBL_EQL(1, uut._calculateLowerAlpha(1.51));
      ASSERT_DBL_EQL(6, uut._calculateLowerAlpha(7.0));
      ASSERT_DBL_EQL(7, uut._calculateLowerAlpha(7.51));

      ASSERT_DBL_EQL(0, uut._calculateLowerBeta(0));
      ASSERT_DBL_EQL(0, uut._calculateLowerBeta(0.5));
      ASSERT_DBL_EQL(0, uut._calculateLowerBeta(1.0));
      ASSERT_DBL_EQL(0, uut._calculateLowerBeta(1.49));
      ASSERT_DBL_EQL(1, uut._calculateLowerBeta(1.51));
      ASSERT_DBL_EQL(6, uut._calculateLowerBeta(7.0));
      ASSERT_DBL_EQL(7, uut._calculateLowerBeta(7.51));

      ASSERT_DBL_EQL(0, uut._calculateIndex(0.5, 0.5));
      ASSERT_DBL_EQL(0, uut._calculateIndex(.99, 0.5));
      ASSERT_DBL_EQL(1, uut._calculateIndex(1.01, 0.5));
      ASSERT_DBL_EQL(3, uut._calculateIndex(3.5, 0.5));
      ASSERT_DBL_EQL(13, uut._calculateIndex(3.5, 1.99));
      ASSERT_DBL_EQL(23, uut._calculateIndex(3.5, 2.01));

      uut.addValue(0.50, 0.50);
      uut.addValue(0.501, 0.501);
      uut.addValue(3.5, 3.5);
      uut.addValue(3.501, 3.501);

      CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, uut.getValue(0.5, 0.5), .01);
      CPPUNIT_ASSERT_DOUBLES_EQUAL(2.0, uut.getValue(3.5, 3.5), .01);

      uut.addValue(6, 3);

      ASSERT_DBL_EQL(0.25, uut.getValue(5.5, 2.5));
      ASSERT_DBL_EQL(0.25, uut.getValue(5.5, 3.5));
      ASSERT_DBL_EQL(0.25, uut.getValue(6.5, 2.5));
      ASSERT_DBL_EQL(0.25, uut.getValue(6.5, 3.5));

//       const SpinImage* image = &uut;
//       for (int b = 0; b < image->getBetaBins(); b++)
//       {
//         printf("\n");
//         for (int a = 0; a < image->getAlphaBins(); a++)
//         {
//           float v = image->bin(a, b);
//           printf("%.1f\t", v);
//         }
//       }
//       printf("\n");
//       printf("\n");
    }