Commit e095c645be17df139c566c2ee553bd1eb59b5abc
Merge pull request #289 from biometrics/evalPlotting
Sample ROC points at fixed FAR values for easy vertical averaging.
Showing
2 changed files
with
80 additions
and
50 deletions
openbr/core/eval.cpp
| ... | ... | @@ -48,22 +48,26 @@ struct OperatingPoint |
| 48 | 48 | : score(_score), FAR(_FAR), TAR(_TAR) {} |
| 49 | 49 | }; |
| 50 | 50 | |
| 51 | -static float getTAR(const QList<OperatingPoint> &operatingPoints, float FAR) | |
| 51 | +static OperatingPoint getOperatingPoint(const QList<OperatingPoint> &operatingPoints, float FAR) | |
| 52 | 52 | { |
| 53 | 53 | int index = 0; |
| 54 | 54 | while (operatingPoints[index].FAR < FAR) { |
| 55 | 55 | index++; |
| 56 | 56 | if (index == operatingPoints.size()) |
| 57 | - return 1; | |
| 57 | + return OperatingPoint(operatingPoints.last().score, FAR, operatingPoints.last().TAR); | |
| 58 | 58 | } |
| 59 | 59 | |
| 60 | - const float x1 = (index == 0 ? 0 : operatingPoints[index-1].FAR); | |
| 61 | - const float y1 = (index == 0 ? 0 : operatingPoints[index-1].TAR); | |
| 62 | - const float x2 = operatingPoints[index].FAR; | |
| 63 | - const float y2 = operatingPoints[index].TAR; | |
| 64 | - const float m = (y2 - y1) / (x2 - x1); | |
| 65 | - const float b = y1 - m*x1; | |
| 66 | - return m * FAR + b; | |
| 60 | + const float FAR1 = (index == 0 ? 0 : operatingPoints[index-1].FAR); | |
| 61 | + const float TAR1 = (index == 0 ? 0 : operatingPoints[index-1].TAR); | |
| 62 | + const float score1 = (index == 0 ? operatingPoints[index].score : operatingPoints[index-1].score); | |
| 63 | + const float FAR2 = operatingPoints[index].FAR; | |
| 64 | + const float TAR2 = operatingPoints[index].TAR; | |
| 65 | + const float score2 = operatingPoints[index].score; | |
| 66 | + const float mTAR = (TAR2 - TAR1) / (FAR2 - FAR1); | |
| 67 | + const float bTAR = TAR1 - mTAR*FAR1; | |
| 68 | + const float mScore = (score2 - score1) / (FAR2 - FAR1); | |
| 69 | + const float bScore = score1 - mScore*FAR1; | |
| 70 | + return OperatingPoint(mScore * FAR + bScore,FAR, mTAR * FAR + bTAR); | |
| 67 | 71 | } |
| 68 | 72 | |
| 69 | 73 | static float getCMC(const QVector<int> &firstGenuineReturns, int rank) |
| ... | ... | @@ -266,23 +270,26 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv, const QSt |
| 266 | 270 | } |
| 267 | 271 | |
| 268 | 272 | // Write Detection Error Tradeoff (DET), PRE, REC |
| 269 | - int points = qMin(operatingPoints.size(), Max_Points); | |
| 270 | - for (int i=0; i<points; i++) { | |
| 271 | - const OperatingPoint &operatingPoint = operatingPoints[double(i) / double(points-1) * double(operatingPoints.size()-1)]; | |
| 272 | - lines.append(QString("DET,%1,%2").arg(QString::number(operatingPoint.FAR), | |
| 273 | + float FAR=0.000001; | |
| 274 | + for (int i=0; i<Max_Points; i++) { | |
| 275 | + OperatingPoint operatingPoint = getOperatingPoint(operatingPoints, FAR); | |
| 276 | + lines.append(QString("DET,%1,%2").arg(QString::number(FAR), | |
| 273 | 277 | QString::number(1-operatingPoint.TAR))); |
| 274 | 278 | lines.append(QString("FAR,%1,%2").arg(QString::number(operatingPoint.score), |
| 275 | - QString::number(operatingPoint.FAR))); | |
| 279 | + QString::number(FAR))); | |
| 276 | 280 | lines.append(QString("FRR,%1,%2").arg(QString::number(operatingPoint.score), |
| 277 | 281 | QString::number(1-operatingPoint.TAR))); |
| 282 | + //multiplier roughly spans 10E-6 to 1 | |
| 283 | + FAR *=1.02807; | |
| 278 | 284 | } |
| 285 | + | |
| 279 | 286 | // Write FAR/TAR Table (FT) |
| 280 | - lines.append(qPrintable(QString("FT,0.000001,%1").arg(QString::number(getTAR(operatingPoints, 0.000001), 'f', 3)))); | |
| 281 | - lines.append(qPrintable(QString("FT,0.00001,%1").arg(QString::number(getTAR(operatingPoints, 0.00001), 'f', 3)))); | |
| 282 | - lines.append(qPrintable(QString("FT,0.0001,%1").arg(QString::number(getTAR(operatingPoints, 0.0001), 'f', 3)))); | |
| 283 | - lines.append(qPrintable(QString("FT,0.001,%1").arg(QString::number(getTAR(operatingPoints, 0.001), 'f', 3)))); | |
| 284 | - lines.append(qPrintable(QString("FT,0.01,%1").arg(QString::number(getTAR(operatingPoints, 0.01), 'f', 3)))); | |
| 285 | - lines.append(qPrintable(QString("FT,0.1,%1").arg(QString::number(getTAR(operatingPoints, 0.1), 'f', 3)))); | |
| 287 | + lines.append(qPrintable(QString("FT,0.000001,%1").arg(QString::number(getOperatingPoint(operatingPoints, 0.000001).TAR, 'f', 3)))); | |
| 288 | + lines.append(qPrintable(QString("FT,0.00001,%1").arg(QString::number(getOperatingPoint(operatingPoints, 0.00001).TAR, 'f', 3)))); | |
| 289 | + lines.append(qPrintable(QString("FT,0.0001,%1").arg(QString::number(getOperatingPoint(operatingPoints, 0.0001).TAR, 'f', 3)))); | |
| 290 | + lines.append(qPrintable(QString("FT,0.001,%1").arg(QString::number(getOperatingPoint(operatingPoints, 0.001).TAR, 'f', 3)))); | |
| 291 | + lines.append(qPrintable(QString("FT,0.01,%1").arg(QString::number(getOperatingPoint(operatingPoints, 0.01).TAR, 'f', 3)))); | |
| 292 | + lines.append(qPrintable(QString("FT,0.1,%1").arg(QString::number(getOperatingPoint(operatingPoints, 0.1).TAR, 'f', 3)))); | |
| 286 | 293 | |
| 287 | 294 | //Write CMC Table (CT) |
| 288 | 295 | lines.append(qPrintable(QString("CT,1,%1").arg(QString::number(getCMC(firstGenuineReturns, 1), 'f', 3)))); |
| ... | ... | @@ -293,19 +300,18 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv, const QSt |
| 293 | 300 | lines.append(qPrintable(QString("CT,100,%1").arg(QString::number(getCMC(firstGenuineReturns, 100), 'f', 3)))); |
| 294 | 301 | |
| 295 | 302 | // Write FAR/TAR Bar Chart (BC) |
| 296 | - lines.append(qPrintable(QString("BC,0.001,%1").arg(QString::number(getTAR(operatingPoints, 0.001), 'f', 3)))); | |
| 297 | - lines.append(qPrintable(QString("BC,0.01,%1").arg(QString::number(result = getTAR(operatingPoints, 0.01), 'f', 3)))); | |
| 303 | + lines.append(qPrintable(QString("BC,0.001,%1").arg(QString::number(getOperatingPoint(operatingPoints, 0.001).TAR, 'f', 3)))); | |
| 304 | + lines.append(qPrintable(QString("BC,0.01,%1").arg(QString::number(result = getOperatingPoint(operatingPoints, 0.01).TAR, 'f', 3)))); | |
| 298 | 305 | |
| 299 | 306 | // Attempt to read template size from enrolled gallery and write to output CSV |
| 300 | 307 | size_t maxSize(0); |
| 301 | 308 | if (target.endsWith(".gal")) { |
| 302 | 309 | foreach (const Template &t, TemplateList::fromGallery(target)) maxSize = max(maxSize, t.bytes()); |
| 310 | + lines.append(QString("TS,,%1").arg(QString::number(maxSize))); | |
| 303 | 311 | } |
| 304 | 312 | |
| 305 | - lines.append(QString("TS,,%1").arg(QString::number(maxSize))); | |
| 306 | - | |
| 307 | 313 | // Write SD & KDE |
| 308 | - points = qMin(qMin(Max_Points, genuines.size()), impostors.size()); | |
| 314 | + int points = qMin(qMin(Max_Points, genuines.size()), impostors.size()); | |
| 309 | 315 | QList<double> sampledGenuineScores; sampledGenuineScores.reserve(points); |
| 310 | 316 | QList<double> sampledImpostorScores; sampledImpostorScores.reserve(points); |
| 311 | 317 | |
| ... | ... | @@ -332,10 +338,10 @@ float Evaluate(const Mat &simmat, const Mat &mask, const QString &csv, const QSt |
| 332 | 338 | |
| 333 | 339 | QtUtils::writeFile(csv, lines); |
| 334 | 340 | if (maxSize > 0) qDebug("Template Size: %i bytes", (int)maxSize); |
| 335 | - qDebug("TAR @ FAR = 0.01: %.3f",getTAR(operatingPoints, 0.01)); | |
| 336 | - qDebug("TAR @ FAR = 0.001: %.3f",getTAR(operatingPoints, 0.001)); | |
| 337 | - qDebug("TAR @ FAR = 0.0001: %.3f",getTAR(operatingPoints, 0.0001)); | |
| 338 | - qDebug("TAR @ FAR = 0.00001: %.3f",getTAR(operatingPoints, 0.00001)); | |
| 341 | + qDebug("TAR @ FAR = 0.01: %.3f",getOperatingPoint(operatingPoints, 0.01).TAR); | |
| 342 | + qDebug("TAR @ FAR = 0.001: %.3f",getOperatingPoint(operatingPoints, 0.001).TAR); | |
| 343 | + qDebug("TAR @ FAR = 0.0001: %.3f",getOperatingPoint(operatingPoints, 0.0001).TAR); | |
| 344 | + qDebug("TAR @ FAR = 0.00001: %.3f",getOperatingPoint(operatingPoints, 0.00001).TAR); | |
| 339 | 345 | |
| 340 | 346 | qDebug("\nRetrieval Rate @ Rank = %d: %.3f", Report_Retrieval, getCMC(firstGenuineReturns, Report_Retrieval)); |
| 341 | 347 | |
| ... | ... | @@ -560,8 +566,8 @@ float InplaceEval(const QString &simmat, const QString &target, const QString &q |
| 560 | 566 | |
| 561 | 567 | float result; |
| 562 | 568 | // Write FAR/TAR Bar Chart (BC) |
| 563 | - lines.append(qPrintable(QString("BC,0.001,%1").arg(QString::number(getTAR(operatingPoints, 0.001), 'f', 3)))); | |
| 564 | - lines.append(qPrintable(QString("BC,0.01,%1").arg(QString::number(result = getTAR(operatingPoints, 0.01), 'f', 3)))); | |
| 569 | + lines.append(qPrintable(QString("BC,0.001,%1").arg(QString::number(getOperatingPoint(operatingPoints, 0.001).TAR, 'f', 3)))); | |
| 570 | + lines.append(qPrintable(QString("BC,0.01,%1").arg(QString::number(result = getOperatingPoint(operatingPoints, 0.01).TAR, 'f', 3)))); | |
| 565 | 571 | |
| 566 | 572 | qDebug("TAR @ FAR = 0.01: %.3f", result); |
| 567 | 573 | QtUtils::writeFile(csv, lines); | ... | ... |
openbr/core/plot.cpp
| ... | ... | @@ -65,6 +65,8 @@ struct RPlot |
| 65 | 65 | QFile file; |
| 66 | 66 | QStringList pivotHeaders; |
| 67 | 67 | QVector< QSet<QString> > pivotItems; |
| 68 | + float confidence; | |
| 69 | + | |
| 68 | 70 | bool flip; |
| 69 | 71 | |
| 70 | 72 | struct Pivot |
| ... | ... | @@ -108,7 +110,6 @@ struct RPlot |
| 108 | 110 | pivotItems = QVector< QSet<QString> >(pivotHeaders.size()); |
| 109 | 111 | foreach (const QString &fileName, files) { |
| 110 | 112 | QStringList pivots = getPivots(fileName, false); |
| 111 | - | |
| 112 | 113 | // If the number of pivots don't match, abandon the directory/filename labeling scheme |
| 113 | 114 | if (pivots.size() != pivotHeaders.size()) { |
| 114 | 115 | pivots.clear(); |
| ... | ... | @@ -132,8 +133,13 @@ struct RPlot |
| 132 | 133 | minor = Pivot(i, size, pivotHeaders[i]); |
| 133 | 134 | } |
| 134 | 135 | } |
| 135 | - | |
| 136 | 136 | const QString &smooth = destination.get<QString>("smooth", ""); |
| 137 | + if (destination.contains(QString("confidence"))) { | |
| 138 | + const QString &CI = destination.get<QString>("confidence"); | |
| 139 | + confidence = !CI.isEmpty() ? CI.toFloat()/100.0 : 0.95; | |
| 140 | + } else { | |
| 141 | + confidence = 0.95; | |
| 142 | + } | |
| 137 | 143 | major.smooth = !smooth.isEmpty() && (major.header == smooth) && (major.size > 1); |
| 138 | 144 | minor.smooth = !smooth.isEmpty() && (minor.header == smooth) && (minor.size > 1); |
| 139 | 145 | if (major.smooth) major.size = 1; |
| ... | ... | @@ -177,29 +183,43 @@ struct RPlot |
| 177 | 183 | "TS$Y <- as.character(TS$Y)\n" |
| 178 | 184 | "CMC$Y <- as.numeric(as.character(CMC$Y))\n" |
| 179 | 185 | "\n" |
| 186 | + "if (%1) {\n\tsummarySE <- function(data=NULL, measurevar, groupvars=NULL, na.rm=FALSE, conf.interval=%5, .drop=TRUE) {\n\t\t" | |
| 187 | + "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)" | |
| 188 | + "\n\t\t}\n\n\t\tdatac <- ddply(data, groupvars, .drop=.drop, .fun = function(xx, col) {\n\t\t\t" | |
| 189 | + "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}," | |
| 190 | + "\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)" | |
| 191 | + "\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" | |
| 192 | + "DET <- summarySE(DET, measurevar=\"Y\", groupvars=c(\"%2\", \"X\"))\n\t" | |
| 193 | + "ERR <- summarySE(ERR, measurevar=\"X\", groupvars=c(\"Error\", \"%2\", \"Y\"))\n\t" | |
| 194 | + "FT <- summarySE(FT, measurevar=\"Y\", groupvars=c(\"%2\", \"X\"))\n\t" | |
| 195 | + "CT <- summarySE(CT, measurevar=\"Y\", groupvars=c(\"%2\", \"X\"))\n}\n\n" | |
| 180 | 196 | "# Code to format FAR values\n" |
| 181 | 197 | "far_names <- list('0.001'=\"FAR = 0.1%\", '0.01'=\"FAR = 1%\")\n" |
| 182 | 198 | "far_labeller <- function(variable,value) { return(far_names[as.character(value)]) }\n" |
| 183 | 199 | "\n" |
| 184 | 200 | "# Code to format TAR@FAR table\n" |
| 185 | - "algs <- unique(FT$%1)\n" | |
| 201 | + "algs <- unique(FT$%2)\n" | |
| 186 | 202 | "algs <- algs[!duplicated(algs)]\n" |
| 187 | - "mat <- matrix(FT$Y,nrow=6,ncol=length(algs),byrow=FALSE)\n" | |
| 203 | + "mat <- matrix(%3,nrow=6,ncol=length(algs),byrow=FALSE)\n" | |
| 188 | 204 | "colnames(mat) <- algs \n" |
| 189 | 205 | "rownames(mat) <- c(\"FAR = 1e-06\", \"FAR = 1e-05\", \"FAR = 1e-04\", \"FAR = 1e-03\", \"FAR = 1e-02\", \"FAR = 1e-01\")\n" |
| 190 | 206 | "FTtable <- as.table(mat)\n" |
| 191 | 207 | "\n" |
| 192 | 208 | "# Code to format CMC Table\n" |
| 193 | - "mat <- matrix(CT$Y,nrow=6,ncol=length(algs),byrow=FALSE)\n" | |
| 209 | + "mat <- matrix(%4,nrow=6,ncol=length(algs),byrow=FALSE)\n" | |
| 194 | 210 | "colnames(mat) <- algs \n" |
| 195 | 211 | "rownames(mat) <- c(\" Rank 1\", \"Rank 5\", \"Rank 10\", \"Rank 20\", \"Rank 50\", \"Rank 100\")\n" |
| 196 | 212 | "CMCtable <- as.table(mat)\n" |
| 197 | 213 | "\n" |
| 198 | 214 | "# Code to format Template Size Table\n" |
| 199 | - "mat <- matrix(TS$Y,nrow=1,ncol=length(algs),byrow=FALSE)\n" | |
| 200 | - "colnames(mat) <- algs\n" | |
| 201 | - "rownames(mat) <- c(\"Template Size (bytes):\")\n" | |
| 202 | - "TStable <- as.table(mat)\n").arg(major.header))); | |
| 215 | + "if (nrow(TS) != 0) {\n\t" | |
| 216 | + "mat <- matrix(TS$Y,nrow=1,ncol=length(algs),byrow=FALSE)\n\t" | |
| 217 | + "colnames(mat) <- algs\n\t" | |
| 218 | + "rownames(mat) <- c(\"Template Size (bytes):\")\n\t" | |
| 219 | + "TStable <- as.table(mat)\n}\n").arg(((major.smooth || minor.smooth) ? "TRUE" : "FALSE"), major.size > 1 ? major.header : (minor.header.isEmpty() ? major.header : minor.header), | |
| 220 | + (major.smooth || minor.smooth) && confidence != 0 ? "paste(as.character(round(FT$Y, 3)), round(FT$ci, 3), sep=\"\\u00b1\")" : "FT$Y", | |
| 221 | + (major.smooth || minor.smooth) && confidence != 0 ? "paste(as.character(round(CT$Y, 3)), round(CT$ci, 3), sep=\"\\u00b1\")" : "CT$Y", | |
| 222 | + QString::number(confidence)))); | |
| 203 | 223 | |
| 204 | 224 | // Open output device |
| 205 | 225 | file.write(qPrintable(QString("\n" |
| ... | ... | @@ -231,8 +251,9 @@ struct RPlot |
| 231 | 251 | "print(title(\"Table of True Accept Rates at various False Accept Rates\"))\n" |
| 232 | 252 | "print(textplot(CMCtable))\n" |
| 233 | 253 | "print(title(\"Table of retrieval rate at various ranks\"))\n" |
| 234 | - "print(textplot(TStable, cex=1.15))\n" | |
| 235 | - "print(title(\"Template Size by Algorithm\"))\n"; | |
| 254 | + "if (nrow(TS) != 0) {\n\t" | |
| 255 | + "print(textplot(TStable, cex=1.15))\n\t" | |
| 256 | + "print(title(\"Template Size by Algorithm\"))\n}\n"; | |
| 236 | 257 | file.write(qPrintable(textplot.arg(PRODUCT_NAME, PRODUCT_VERSION))); |
| 237 | 258 | } |
| 238 | 259 | |
| ... | ... | @@ -281,11 +302,12 @@ bool Plot(const QStringList &files, const File &destination, bool show) |
| 281 | 302 | |
| 282 | 303 | RPlot p(files, destination); |
| 283 | 304 | |
| 284 | - p.file.write(qPrintable(QString("qplot(X, 1-Y, data=DET%1, main=\"%2\"").arg((p.major.smooth || p.minor.smooth) ? ", geom=\"smooth\", method=loess, level=0.99" : ", geom=\"line\"", rocOpts.get<QString>("title",QString())) + | |
| 305 | + p.file.write(qPrintable(QString("qplot(X, 1-Y, data=DET, geom=\"line\", main=\"%1\"").arg(rocOpts.get<QString>("title",QString())) + | |
| 285 | 306 | (p.major.size > 1 ? QString(", colour=factor(%1)").arg(p.major.header) : QString()) + |
| 286 | 307 | (p.minor.size > 1 ? QString(", linetype=factor(%1)").arg(p.minor.header) : QString()) + |
| 287 | 308 | QString(", xlab=\"False Accept Rate\", ylab=\"True Accept Rate\") + theme_minimal()") + |
| 288 | - (p.major.size > 1 ? getScale("colour", "Algorithm", p.major.size) : QString()) + | |
| 309 | + ((p.major.smooth || p.minor.smooth) && p.confidence != 0 ? " + geom_errorbar(data=DET[seq(1, NROW(DET), by = 29),], aes(x=X, ymin=(1-Y)-ci, ymax=(1-Y)+ci), width=0.1, alpha=I(1/2))" : QString()) + | |
| 310 | + (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) + | |
| 289 | 311 | (p.minor.size > 1 ? QString(" + scale_linetype_discrete(\"%1\")").arg(p.minor.header) : QString()) + |
| 290 | 312 | QString(" + scale_x_log10(labels=trans_format(\"log10\", math_format()))") + |
| 291 | 313 | (rocOpts.contains("yLimits") ? QString(" + scale_y_continuous(labels=percent) + coord_cartesian(ylim=%1)").arg("c"+QtUtils::toString(rocOpts.get<QPointF>("yLimits",QPointF()))) : QString(" + scale_y_continuous(labels=percent)")) + |
| ... | ... | @@ -293,12 +315,14 @@ bool Plot(const QStringList &files, const File &destination, bool show) |
| 293 | 315 | QString(" + theme(legend.title = element_text(size = %1), plot.title = element_text(size = %1), axis.text = element_text(size = %1), axis.title.x = element_text(size = %1), axis.title.y = element_text(size = %1)," |
| 294 | 316 | " legend.position=%2, legend.background = element_rect(fill = 'white'), panel.grid.major = element_line(colour = \"gray\"), panel.grid.minor = element_line(colour = \"gray\", linetype = \"dashed\"), legend.text = element_text(size = %1))\n\n").arg(QString::number(rocOpts.get<float>("textSize",12)), rocOpts.contains("legendPosition") ? "c"+QtUtils::toString(rocOpts.get<QPointF>("legendPosition")) : "'bottom'"))); |
| 295 | 317 | |
| 296 | - p.file.write(qPrintable(QString("qplot(X, Y, data=DET%1").arg((p.major.smooth || p.minor.smooth) ? ", geom=\"smooth\", method=loess, level=0.99" : ", geom=\"line\"") + | |
| 318 | + p.file.write(qPrintable(QString("qplot(X, Y, data=DET, geom=\"line\"") + | |
| 297 | 319 | (p.major.size > 1 ? QString(", colour=factor(%1)").arg(p.major.header) : QString()) + |
| 298 | 320 | (p.minor.size > 1 ? QString(", linetype=factor(%1)").arg(p.minor.header) : QString()) + |
| 299 | 321 | QString(", xlab=\"False Accept Rate\", ylab=\"False Reject Rate\") + geom_abline(alpha=0.5, colour=\"grey\", linetype=\"dashed\") + theme_minimal()") + |
| 300 | - (p.major.size > 1 ? getScale("colour", "Algorithm", p.major.size) : QString()) + | |
| 322 | + ((p.major.smooth || p.minor.smooth) && p.confidence != 0 ? " + geom_errorbar(data=DET[seq(1, NROW(DET), by = 29),], aes(x=X, ymin=Y-ci, ymax=Y+ci), width=0.1, alpha=I(1/2))" : QString()) + | |
| 323 | + (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) + | |
| 301 | 324 | (p.minor.size > 1 ? QString(" + scale_linetype_discrete(\"%1\")").arg(p.minor.header) : QString()) + |
| 325 | + QString(" + theme(legend.position=%1)").arg(rocOpts.contains("legendPosition") ? "c"+QtUtils::toString(rocOpts.get<QPointF>("legendPosition")) : "'bottom'") + | |
| 302 | 326 | QString(" + scale_x_log10(labels=trans_format(\"log10\", math_format())) + scale_y_log10(labels=trans_format(\"log10\", math_format())) + annotation_logticks()\n\n"))); |
| 303 | 327 | |
| 304 | 328 | p.file.write(qPrintable(QString("qplot(X, data=SD, geom=\"histogram\", fill=Y, position=\"identity\", alpha=I(1/2)") + |
| ... | ... | @@ -311,7 +335,7 @@ bool Plot(const QStringList &files, const File &destination, bool show) |
| 311 | 335 | QString(((p.major.smooth || p.minor.smooth) ? (!uncertainty ? " + stat_summary(geom=\"line\", fun.y=mean, size=%1)" : " + stat_summary(geom=\"line\", fun.y=min, aes(linetype=\"Min/Max\"), size=%1) + stat_summary(geom=\"line\", " |
| 312 | 336 | "fun.y=max, aes(linetype=\"Min/Max\"), size=%1) + stat_summary(geom=\"line\", fun.y=mean, aes(linetype=\"Mean\"), size=%1) + scale_linetype_manual(\"Legend\", values=c(\"Mean\"=1, \"Min/Max\"=2))") : " + geom_line(size=%1)")).arg(QString::number(cmcOpts.get<float>("thickness",1))) + |
| 313 | 337 | (minimalist ? "" : " + scale_x_log10(labels=c(1,5,10,50,100), breaks=c(1,5,10,50,100)) + annotation_logticks(sides=\"b\")") + |
| 314 | - (p.major.size > 1 ? getScale("colour", "Algorithm", p.major.size) : QString()) + | |
| 338 | + (p.major.size > 1 ? getScale("colour", p.major.header, p.major.size) : QString()) + | |
| 315 | 339 | (p.minor.size > 1 ? QString(" + scale_linetype_discrete(\"%1\")").arg(p.minor.header) : QString()) + |
| 316 | 340 | (cmcOpts.contains("yLimits") ? QString(" + scale_y_continuous(labels=percent) + coord_cartesian(ylim=%1)").arg("c"+QtUtils::toString(cmcOpts.get<QPointF>("yLimits",QPointF()))) : QString(" + scale_y_continuous(labels=percent)")) + |
| 317 | 341 | QString(" + theme_minimal() + theme(legend.title = element_text(size = %1), plot.title = element_text(size = %1), axis.text = element_text(size = %1), axis.title.x = element_text(size = %1), axis.title.y = element_text(size = %1)," |
| ... | ... | @@ -320,14 +344,14 @@ bool Plot(const QStringList &files, const File &destination, bool show) |
| 320 | 344 | p.file.write(qPrintable(QString("qplot(factor(%1)%2, data=BC, %3").arg(p.major.smooth ? (p.minor.header.isEmpty() ? "Algorithm" : p.minor.header) : p.major.header, (p.major.smooth || p.minor.smooth) ? ", Y" : "", (p.major.smooth || p.minor.smooth) ? "geom=\"boxplot\"" : "geom=\"bar\", position=\"dodge\", weight=Y") + |
| 321 | 345 | (p.major.size > 1 ? QString(", fill=factor(%1)").arg(p.major.header) : QString()) + |
| 322 | 346 | QString(", xlab=\"False Accept Rate\", ylab=\"True Accept Rate\") + theme_minimal()") + |
| 323 | - (p.major.size > 1 ? getScale("fill", "Algorithm", p.major.size) : QString()) + | |
| 347 | + (p.major.size > 1 ? getScale("fill", p.major.header, p.major.size) : QString()) + | |
| 324 | 348 | (p.minor.size > 1 ? QString(" + facet_grid(%2 ~ X)").arg(p.minor.header) : QString(" + facet_grid(. ~ X, labeller=far_labeller)")) + |
| 325 | 349 | QString(" + scale_y_continuous(labels=percent) + theme(legend.position=\"none\", axis.text.x=element_text(angle=-90, hjust=0))%1").arg((p.major.smooth || p.minor.smooth) ? "" : " + geom_text(data=BC, aes(label=Y, y=0.05))") + "\n\n")); |
| 326 | 350 | |
| 327 | - p.file.write(qPrintable(QString("qplot(X, Y, data=ERR%1, linetype=Error").arg((p.major.smooth || p.minor.smooth) ? ", geom=\"smooth\", method=loess, level=0.99" : ", geom=\"line\"") + | |
| 351 | + p.file.write(qPrintable(QString("qplot(X, Y, data=ERR, geom=\"line\", linetype=Error") + | |
| 328 | 352 | ((p.flip ? p.major.size : p.minor.size) > 1 ? QString(", colour=factor(%1)").arg(p.flip ? p.major.header : p.minor.header) : QString()) + |
| 329 | 353 | QString(", xlab=\"Score\", ylab=\"Error Rate\") + theme_minimal()") + |
| 330 | - ((p.flip ? p.major.size : p.minor.size) > 1 ? getScale("colour", p.flip ? "Algorithm" : "Algorithm", p.flip ? p.major.size : p.minor.size) : QString()) + | |
| 354 | + ((p.flip ? p.major.size : p.minor.size) > 1 ? getScale("colour", p.flip ? p.major.header : p.minor.header, p.flip ? p.major.size : p.minor.size) : QString()) + | |
| 331 | 355 | QString(" + scale_y_log10(labels=percent) + annotation_logticks(sides=\"l\")") + |
| 332 | 356 | ((p.flip ? p.minor.size : p.major.size) > 1 ? QString(" + facet_wrap(~ %1, scales=\"free_x\")").arg(p.flip ? p.minor.header : p.major.header) : QString()) + |
| 333 | 357 | QString(" + theme(aspect.ratio=1)\n\n"))); | ... | ... |