def crossValidate(ftb, project, featureThreshold, imagesOnly, numSplits):

    message = ''
    fullSet = FeatureSet_Discrete()
    fullSet.source_path = project.getName()

    classId = 0
    for ds in project.listChildren():
        message += 'Processing dataset id:%d\n' % ds.getId()
        message += addToFeatureSet(ftb, ds, fullSet, classId, imagesOnly)
        classId += 1

    tmp = fullSet.ContiguousDataMatrix()
    experiment = DiscreteClassificationExperimentResult(training_set=fullSet)

    for i in range(numSplits):
        trainSet, testSet = fullSet.Split()
        trainSet.Normalize()
        testSet.Normalize(trainSet)

        weights = FisherFeatureWeights.NewFromFeatureSet(trainSet)

        nFeatures = ceil(len(weights.names) * featureThreshold)
        message += 'Selecting top %d features\n' % nFeatures
        weights = weights.Threshold(nFeatures)
        trainSet = reduceFeatures(trainSet, weights)

        reducedTestSet = reduceFeatures(testSet, weights)
        reducedTrainSet = reduceFeatures(trainSet, weights)

	batchResult = DiscreteBatchClassificationResult.New(
            reducedTrainSet, reducedTestSet, weights, batch_number=i)
	experiment.individual_results.append(batchResult)

    out = StringIO()
    experiment.Print(output_stream=out)
    experiment.PerSampleStatistics(output_stream=out)

    pid = project.getId()
    WndcharmStorage.addTextFileAnnotationTo(
        ftb.conn, out.getvalue(), 'Project', pid,
        'Wndcharm_Cross_Validation_Results.txt',
        'Wndcharm Cross Validation Results for Project:%d' % pid)

    message += 'Attached cross-validation results\n'
    #return experiment
    return message