// ------------------------------------------------------------------------
double imageCost(PatchParams &params, TestData::Pointer &data,
                 VectorType &point, VectorType &normal, ClassifierMap &classifiers,
                 LengthData::Pointer &lengths, bool save)
{
    typedef TestData::LineGroup LineGroup;
    LineGroup testLines;
    data->ExtractTestLines(normal, point, testLines);

    FlipChecker::Pointer checker = FlipChecker::New();

    LineGroup::iterator lineIt = testLines.begin();
    double totalCost = 0;
    while(lineIt != testLines.end())
    {
        double minValue = 1000;
        unsigned int minIndex = 0;

        if(lineIt->second.size() == 0)
        {
            totalCost += minValue;
            lineIt++;
            continue;
        }

        const std::string type = lineIt->first;

        bool flipImage = checker->FlipImage("MV-" + lineIt->first, data->GetId());
        bool flipPoints = checker->FlipPoints("MV-" + lineIt->first, data->GetId());

        if((type == "2C" || type == "3C") && flipImage)
        {
            flipPoints = !flipPoints;
        }

        TestData::ImageGroup images;
        data->GetImageGroup(type, images);

        for(unsigned int i = 0; i < lineIt->second.size(); i++)
        {
            // create a valve line from the data
            TestData::LineType line = lineIt->second[i];

            ValveLine<3>::Pointer alignedValve = ValveLine<3>::New();
            createAlignedValve(line, images.image, alignedValve, flipImage, flipPoints);

            double pointDist = alignedValve->GetP1().EuclideanDistanceTo(alignedValve->GetP2());
            double lengthProb = lengths->Predict("MV-" + type, params.timeStep, pointDist);
            double lengthCost = -log(std::max(lengthProb, 0.00000001));

            double lineSum = 0.0;
            for(unsigned int j = 0; j < 2; j++)
            {

                MatrixType feature;
                extractLBPFeature(params, alignedValve, alignedValve->GetPoint(j+1), feature);

                SVMClassifier::IntMatrixType classes;
                MatrixType probs;
                classifiers["MV-"+type][j]->PredictProbability(feature, classes, probs);

                double prob = probs(0,1);
                double cost = -log(std::max(prob, 0.000000001));

                lineSum += cost;

            }

            std::cout << "Costs: " << type << " " << lineSum << " " << lengthCost << std::endl;
            lineSum += lengthCost;

            if(lineSum < minValue)
            {
                minIndex = i;
                minValue = lineSum;
            }
        }

        // save the min index
        if(save)
        {
            TestData::LineType fline = lineIt->second[minIndex];
            ValveLine<3>::Pointer toSave = ValveLine<3>::New();
            createAlignedValve(fline, images.image, toSave, flipImage, flipPoints);
            ValveWriter<3>::Pointer writer = ValveWriter<3>::New();
            writer->SetFileName(type);
            writer->SetInput(toSave);
            writer->Write();
        }

        lineIt++;

        totalCost += minValue;

    }

    if(totalCost < 0.0) totalCost = 1000;

    return totalCost;

}