Commit 5b53a8c471a6ceae9427502b261270228c110db7

Authored by Scott Klum
1 parent 259aa3f0

Using R for statistics computations, finished error table

openbr/core/eval.cpp
@@ -1056,6 +1056,7 @@ float EvalLandmarking(const QString &predictedGallery, const QString &truthGalle @@ -1056,6 +1056,7 @@ float EvalLandmarking(const QString &predictedGallery, const QString &truthGalle
1056 } 1056 }
1057 while (pointErrors.size() < predictedPoints.size()) 1057 while (pointErrors.size() < predictedPoints.size())
1058 pointErrors.append(QList<float>()); 1058 pointErrors.append(QList<float>());
  1059 +
1059 if (normalizationIndexA >= truthPoints.size()) qFatal("Normalization index A is out of range."); 1060 if (normalizationIndexA >= truthPoints.size()) qFatal("Normalization index A is out of range.");
1060 if (normalizationIndexB >= truthPoints.size()) qFatal("Normalization index B is out of range."); 1061 if (normalizationIndexB >= truthPoints.size()) qFatal("Normalization index B is out of range.");
1061 const float normalizedLength = QtUtils::euclideanLength(truthPoints[normalizationIndexB] - truthPoints[normalizationIndexA]); 1062 const float normalizedLength = QtUtils::euclideanLength(truthPoints[normalizationIndexB] - truthPoints[normalizationIndexA]);
@@ -1068,8 +1069,6 @@ float EvalLandmarking(const QString &amp;predictedGallery, const QString &amp;truthGalle @@ -1068,8 +1069,6 @@ float EvalLandmarking(const QString &amp;predictedGallery, const QString &amp;truthGalle
1068 qDebug() << "Skipped" << skipped << "files due to point size mismatch."; 1069 qDebug() << "Skipped" << skipped << "files due to point size mismatch.";
1069 1070
1070 QList<float> averagePointErrors; averagePointErrors.reserve(pointErrors.size()); 1071 QList<float> averagePointErrors; averagePointErrors.reserve(pointErrors.size());
1071 - QList<float> medianPointErrors; medianPointErrors.reserve(pointErrors.size());  
1072 - QList<float> stddevPointErrors; stddevPointErrors.reserve(pointErrors.size());  
1073 1072
1074 float normalizedErrorLimit = 1.5; 1073 float normalizedErrorLimit = 1.5;
1075 1074
@@ -1082,15 +1081,9 @@ float EvalLandmarking(const QString &amp;predictedGallery, const QString &amp;truthGalle @@ -1082,15 +1081,9 @@ float EvalLandmarking(const QString &amp;predictedGallery, const QString &amp;truthGalle
1082 worstExamples.insert(exampleIndices[j].second); 1081 worstExamples.insert(exampleIndices[j].second);
1083 } 1082 }
1084 std::sort(pointErrors[i].begin(), pointErrors[i].end()); 1083 std::sort(pointErrors[i].begin(), pointErrors[i].end());
1085 - double mean, stddev;  
1086 - Common::MeanStdDev(pointErrors[i],&mean,&stddev);  
1087 - averagePointErrors.append(mean);  
1088 - stddevPointErrors.append(stddev);  
1089 - medianPointErrors.append(Common::Median(pointErrors[i])); 1084 + averagePointErrors.append(Common::Mean(pointErrors[i]));
1090 } 1085 }
1091 const float averagePointError = Common::Mean(averagePointErrors); 1086 const float averagePointError = Common::Mean(averagePointErrors);
1092 - const float medianPointError = Common::Mean(medianPointErrors);  
1093 - const float stddevPointError = Common::Mean(stddevPointErrors);  
1094 1087
1095 QStringList lines; 1088 QStringList lines;
1096 lines.append("Plot,X,Y"); 1089 lines.append("Plot,X,Y");
@@ -1103,17 +1096,6 @@ float EvalLandmarking(const QString &amp;predictedGallery, const QString &amp;truthGalle @@ -1103,17 +1096,6 @@ float EvalLandmarking(const QString &amp;predictedGallery, const QString &amp;truthGalle
1103 // Alternatively, can we just pass this through a predetermined transform and write? 1096 // Alternatively, can we just pass this through a predetermined transform and write?
1104 Enroll(truth[sampleIndex],"landmarking_examples"); 1097 Enroll(truth[sampleIndex],"landmarking_examples");
1105 1098
1106 - // Error table  
1107 - for (int i=0; i<averagePointErrors.size(); i++) {  
1108 - lines.append(QString("AE,%1,%2").arg(QString::number(i),QString::number(averagePointErrors[i], 'f', 3)));  
1109 - lines.append(QString("ME,%1,%2").arg(QString::number(i),QString::number(medianPointErrors[i], 'f', 3)));  
1110 - lines.append(QString("SE,%1,%2").arg(QString::number(i),QString::number(stddevPointErrors[i], 'f', 3)));  
1111 - }  
1112 -  
1113 - lines.append(QString("AE,%1,%2").arg(QString::number(averagePointErrors.size()),QString::number(averagePointError, 'f', 3)));  
1114 - lines.append(QString("ME,%1,%2").arg(QString::number(averagePointErrors.size()),QString::number(medianPointError, 'f', 3)));  
1115 - lines.append(QString("SE,%1,%2").arg(QString::number(averagePointErrors.size()),QString::number(stddevPointError, 'f', 3)));  
1116 -  
1117 for (int i=0; i<pointErrors.size(); i++) { 1099 for (int i=0; i<pointErrors.size(); i++) {
1118 const QList<float> &pointError = pointErrors[i]; 1100 const QList<float> &pointError = pointErrors[i];
1119 const int keep = qMin(Max_Points, pointError.size()); 1101 const int keep = qMin(Max_Points, pointError.size());
@@ -1122,13 +1104,11 @@ float EvalLandmarking(const QString &amp;predictedGallery, const QString &amp;truthGalle @@ -1122,13 +1104,11 @@ float EvalLandmarking(const QString &amp;predictedGallery, const QString &amp;truthGalle
1122 } 1104 }
1123 1105
1124 lines.append(QString("AvgError,0,%1").arg(averagePointError)); 1106 lines.append(QString("AvgError,0,%1").arg(averagePointError));
  1107 + lines.append(QString("NormLength,0,%1").arg(Common::Mean(normalizedLengths)));
1125 1108
1126 QtUtils::writeFile(csv, lines); 1109 QtUtils::writeFile(csv, lines);
1127 1110
1128 qDebug("Average Error for all Points: %.3f", averagePointError); 1111 qDebug("Average Error for all Points: %.3f", averagePointError);
1129 - qDebug("Average Median Error for all Points: %.3f", medianPointError);  
1130 - qDebug("Average Standard Deviation of Error for all Points: %.3f", stddevPointError);  
1131 - qDebug("Average Normalization Length (pixels): %.3f", Common::Mean(normalizedLengths));  
1132 1112
1133 return averagePointError; 1113 return averagePointError;
1134 } 1114 }
openbr/core/plot.cpp
@@ -469,15 +469,23 @@ bool PlotLandmarking(const QStringList &amp;files, const File &amp;destination, bool sho @@ -469,15 +469,23 @@ bool PlotLandmarking(const QStringList &amp;files, const File &amp;destination, bool sho
469 qDebug("Plotting %d landmarking file(s) to %s", files.size(), qPrintable(destination)); 469 qDebug("Plotting %d landmarking file(s) to %s", files.size(), qPrintable(destination));
470 RPlot p(files, destination, false); 470 RPlot p(files, destination, false);
471 471
  472 + qDebug() << p.major.header << p.minor.header;
  473 +
472 p.file.write(qPrintable(QString("# Split data into individual plots\n" 474 p.file.write(qPrintable(QString("# Split data into individual plots\n"
473 "plot_index = which(names(data)==\"Plot\")\n" 475 "plot_index = which(names(data)==\"Plot\")\n"
474 "Box <- data[grep(\"Box\",data$Plot),-c(1)]\n" 476 "Box <- data[grep(\"Box\",data$Plot),-c(1)]\n"
  477 + "Box$X <- factor(Box$X, levels = Box$X, ordered = TRUE)\n"
475 "EX <- data[grep(\"EX\",data$Plot),-c(1)]\n" 478 "EX <- data[grep(\"EX\",data$Plot),-c(1)]\n"
476 - "AE <- data[grep(\"AE\",data$Plot),-c(1)]\n"  
477 - "ME <- data[grep(\"ME\",data$Plot),-c(1)]\n"  
478 - "SE <- data[grep(\"SE\",data$Plot),-c(1)]\n" 479 + "NormLength <- data[grep(\"NormLength\",data$Plot),-c(1)]\n"
479 "EX$X <- as.character(EX$X)\n" 480 "EX$X <- as.character(EX$X)\n"
480 "EX$Y <- as.character(EX$Y)\n" 481 "EX$Y <- as.character(EX$Y)\n"
  482 + "\n"
  483 + "\n\tsummarySE <- function(data=NULL, measurevar, groupvars=NULL, na.rm=FALSE, conf.interval=.95, .drop=TRUE) {\n\t\t"
  484 + "require(plyr)\n\n\t\tlength2 <- function (x, na.rm=FALSE) {\n\t\t\tif (na.rm) sum(!is.na(x))\n\t\t\telse length(x)"
  485 + "\n\t\t}\n\n\t\tdatac <- ddply(data, groupvars, .drop=.drop, .fun = function(xx, col) {\n\t\t\t"
  486 + "c(N=length2(xx[[col]], na.rm=na.rm), mean=mean(xx[[col]], na.rm=na.rm), sd=sd(xx[[col]], na.rm=na.rm))\n\t\t\t},"
  487 + "\n\t\t\tmeasurevar\n\t\t)\n\n\t\tdatac <- rename(datac, c(\"mean\" = measurevar))\n\t\tdatac$se <- datac$sd / sqrt(datac$N)"
  488 + "\n\t\tciMult <- qt(conf.interval/2 + .5, datac$N-1)\n\t\tdatac$ci <- datac$se * ciMult\n\n\t\treturn(datac)\n\t}\n\t"
481 "rm(data)\n" 489 "rm(data)\n"
482 "\n"))); 490 "\n")));
483 491
@@ -535,22 +543,24 @@ bool PlotLandmarking(const QStringList &amp;files, const File &amp;destination, bool sho @@ -535,22 +543,24 @@ bool PlotLandmarking(const QStringList &amp;files, const File &amp;destination, bool sho
535 543
536 p.file.write(qPrintable(QString("\n" 544 p.file.write(qPrintable(QString("\n"
537 "# Code to format error table\n" 545 "# Code to format error table\n"
538 - "l <- list(AE$Y,ME$Y,SE$Y)\n"  
539 - "mat <- matrix(do.call(rbind, l),nrow=nrow(AE),ncol=3,byrow=TRUE)\n"  
540 - "colnames(mat) <- c(\"Mean\",\"Median\",\"Std. Dev.\") \n"  
541 - "rownames(mat) <- c(seq(0,nrow(AE)-2),\"Average\")\n" 546 + "StatBox <- summarySE(Box, measurevar=\"Y\", groupvars=c(\"X\"))\n\t"
  547 + "OverallStatBox <- summarySE(Box, measurevar=\"Y\")\n"
  548 + "mat <- matrix(paste(as.character(round(StatBox$Y, 3)), round(StatBox$ci, 3), sep=\" \\u00b1 \"),nrow=nrow(StatBox),ncol=1,byrow=TRUE)\n"
  549 + "mat <- rbind(mat, paste(as.character(round(OverallStatBox$Y, 3)), round(OverallStatBox$ci, 3), sep=\" \\u00b1 \"))\n"
  550 + "colnames(mat) <- c(\"Error Rate\")\n"
  551 + "rownames(mat) <- c(seq(0,nrow(StatBox)-1),\"Aggregate\")\n"
542 "ETable <- as.table(mat)\n"))); 552 "ETable <- as.table(mat)\n")));
543 553
544 p.file.write(qPrintable(QString("\n" 554 p.file.write(qPrintable(QString("\n"
545 "print(textplot(ETable))\n" 555 "print(textplot(ETable))\n"
546 - "print(title(expression(atop(\"Landmark Error Rates\", atop(italic(\"Average Normalization Distance: 91.419 (pixels)\"))))))\n"))); 556 + "print(title(sprintf(\"Landmark Error Rates\\nAverage Normalization Distance: %.3f (pixels)\",NormLength$Y)))\n")));
547 557
548 p.file.write(qPrintable(QString("ggplot(Box, aes(Y,%1%2))").arg(p.major.size > 1 ? QString(", colour=%1").arg(p.major.header) : QString(), 558 p.file.write(qPrintable(QString("ggplot(Box, aes(Y,%1%2))").arg(p.major.size > 1 ? QString(", colour=%1").arg(p.major.header) : QString(),
549 p.minor.size > 1 ? QString(", linetype=%1").arg(p.minor.header) : QString()) + 559 p.minor.size > 1 ? QString(", linetype=%1").arg(p.minor.header) : QString()) +
550 QString(" + annotation_logticks(sides=\"b\") + stat_ecdf() + scale_x_log10(\"Normalized Error\", breaks=c(0.001,0.01,0.1,1,10)) + scale_y_continuous(\"Cumulative Density\", label=percent) + theme_minimal()\n\n"))); 560 QString(" + annotation_logticks(sides=\"b\") + stat_ecdf() + scale_x_log10(\"Normalized Error\", breaks=c(0.001,0.01,0.1,1,10)) + scale_y_continuous(\"Cumulative Density\", label=percent) + theme_minimal()\n\n")));
551 561
552 p.file.write(qPrintable(QString("ggplot(Box, aes(factor(X), Y%1%2))").arg(p.major.size > 1 ? QString(", colour=%1").arg(p.major.header) : QString(), p.minor.size > 1 ? QString(", linetype=%1").arg(p.minor.header) : QString()) + 562 p.file.write(qPrintable(QString("ggplot(Box, aes(factor(X), Y%1%2))").arg(p.major.size > 1 ? QString(", colour=%1").arg(p.major.header) : QString(), p.minor.size > 1 ? QString(", linetype=%1").arg(p.minor.header) : QString()) +
553 - QString("+ annotation_logticks(sides=\"l\") + geom_boxplot(alpha=0.5) + geom_jitter(size=1, alpha=0.5) + scale_x_discrete(\"Landmark\") + scale_y_log10(\"Normalized Error\", breaks=c(0.01,0.1,1,10)) + theme_minimal()\n\n"))); 563 + QString("+ annotation_logticks(sides=\"l\") + geom_boxplot(alpha=0.5) + geom_jitter(size=1, alpha=0.5) + scale_x_discrete(\"Landmark\") + scale_y_log10(\"Normalized Error\", breaks=c(0.001,0.01,0.1,1,10)) + theme_minimal()\n\n")));
554 564
555 p.file.write(qPrintable(QString("ggplot(Box, aes(factor(X), Y%1%2))").arg(p.major.size > 1 ? QString(", colour=%1").arg(p.major.header) : QString(), p.minor.size > 1 ? QString(", linetype=%1").arg(p.minor.header) : QString()) + 565 p.file.write(qPrintable(QString("ggplot(Box, aes(factor(X), Y%1%2))").arg(p.major.size > 1 ? QString(", colour=%1").arg(p.major.header) : QString(), p.minor.size > 1 ? QString(", linetype=%1").arg(p.minor.header) : QString()) +
556 QString("+ annotation_logticks(sides=\"l\") + geom_violin(alpha=0.5) + scale_x_discrete(\"Landmark\") + scale_y_log10(\"Normalized Error\", breaks=c(0.001,0.01,0.1,1,10))\n\n"))); 566 QString("+ annotation_logticks(sides=\"l\") + geom_violin(alpha=0.5) + scale_x_discrete(\"Landmark\") + scale_y_log10(\"Normalized Error\", breaks=c(0.001,0.01,0.1,1,10))\n\n")));