/// <summary>
        /// Report the depth at which the k correct templates are found
        /// </summary>
        /// <param name="kVals"></param>
        /// <param name="rejectThresh"></param>
        /// <param name="testUnLabel"></param>
        /// <param name="verbose"></param>
        static void ReportTrainData(List <int> kVals, TestCollection testUnLabel, string dataFile)
        {
            using (Microsoft.LiveLabs.TrainDataFileWriter write = new Microsoft.LiveLabs.TrainDataFileWriter(dataFile))
            {
                foreach (int k in kVals)
                {
                    int iFace = 0;
                    foreach (Face face in testUnLabel.Faces)
                    {
                        face.DoDistances(testUnLabel.Faces, testUnLabel.DistanceComputer);
                        face.Sort();
                        ReportTrainData(face, -1, iFace, write);
                        face.Dispose();
                        ++iFace;
                    }
                }

                write.Dispose();
            }
        }
        static void ReportTrainData(Face face, int kMax, int iFace, Microsoft.LiveLabs.TrainDataFileWriter write)
        {
            if (kMax <= 0)
            {
                kMax = face.Distances.Length;
            }
            else
            {
                kMax = Math.Min(kMax, face.Distances.Length);
            }

            // Find index of closest me class
            int myId        = face.ID;
            int myGroup     = face.GroupId;
            int myBestMatch = -1;
            int otherBest   = -1;
            int iFound      = 0;

            for (int k = 0; k < kMax && iFound < 2; ++k)
            {
                DistanceMeasure d = face.Distances[k];

                if (d.face.GroupId == myGroup)
                {
                    if (d.face.ID != myId && myBestMatch < 0 && d.Distance > 1.0)
                    {
                        myBestMatch = k;
                        ++iFound;
                    }
                }
                else if (otherBest < 0)
                {
                    otherBest = k;
                    ++iFound;
                }
            }

            if (myBestMatch < 0)
            {
                throw new Exception("Did not find a best my match for face " + face.ID.ToString());
            }

            double[] extraData = new double[3];

            if (iFace % 2 == 0)
            {
                extraData[0] = L1Distance(face.Data, face.Distances[myBestMatch].face.Data);
                extraData[1] = L1Distance(face.Data, face.Distances[otherBest].face.Data);
                extraData[0] = Math.Max(1.0, extraData[0]);
                extraData[2] = (extraData[0] - extraData[1]) / extraData[0];
            }
            else
            {
                extraData[0] = L1Distance(face.Data, face.Distances[otherBest].face.Data);
                extraData[1] = L1Distance(face.Data, face.Distances[myBestMatch].face.Data);
                extraData[1] = Math.Max(1.0, extraData[1]);
                extraData[2] = (extraData[1] - extraData[0]) / extraData[1];
            }
            extraData[2]  = Math.Max(-3.0, extraData[2]);
            extraData[2]  = Math.Min(3.0, extraData[2]);
            extraData[2] *= 10000;

            write.WriteNewInput(face.Data);
            write.WriteDataContinue(extraData);
            double[] target = new double[1];
            target[0] = myGroup;
            write.WriteNewTarget(target);
        }