Commit 032d4ca3343451b3153b6b119fbc88a3b13269f1

Authored by Ben Klein
2 parents de52fe1c 72ed1cd9

Merge pull request #401 from biometrics/plotting

Move bulk of R code from plot.cpp to plot_utils.R
docs/docs/api_docs/c_api/functions.md
... ... @@ -635,8 +635,8 @@ textSize | float | Size of text for title, legend and axes
635 635 xTitle/yTitle | [QString] | Title for x/y axis
636 636 xLog/yLog | bool | Plot log scale for x/y axis
637 637 xLimits/yLimits | [QPointF] | Set x/y axis limits, ex. xLimits=(lower,upper)
638   -xLabels/yLabels | [QString] | Labels for ticks on x/y axis, ex. xLabeles=percent or xLabels=c(1,5,10)
639   -xBreaks/yBreaks | [QString] | Specify breaks/ticks on x/y axis, ex. xBreaks=pretty_breaks(n=10) or xBreaks=c(1,5,10)
  638 +xLabels/yLabels | [QString] | Labels for ticks on x/y axis, ex. xLabeles=percent or xLabels=(1,5,10)
  639 +xBreaks/yBreaks | [QString] | Specify breaks/ticks on x/y axis, ex. xBreaks=pretty_breaks(n=10) or xBreaks=(1,5,10)
640 640  
641 641 If specifying plot options it is a good idea to wrap the destination file in single quotes to avoid parsing errors.
642 642 The example below plots plots the six br_eval results in the Algorithm_Dataset folder described above, sets the number of legend columns and specifies some options for the CMC plot.
... ...
openbr/core/plot.cpp
... ... @@ -23,6 +23,25 @@ using namespace cv;
23 23 namespace br
24 24 {
25 25  
  26 +// Flattens file metadata to an R list()
  27 +static QString toRList(const File &opts)
  28 +{
  29 + QStringList retValues;
  30 + QString format = "%1=%2";
  31 + foreach (const QString &key, opts.localKeys()) {
  32 + const QString value = QtUtils::toString(opts.value(key));
  33 + if (value.startsWith("("))
  34 + retValues.append(format.arg(key, "\"c" + value + "\""));
  35 + else if (value == "true")
  36 + retValues.append(format.arg(key, "TRUE"));
  37 + else if (value == "false")
  38 + retValues.append(format.arg(key, "FALSE"));
  39 + else
  40 + retValues.append(format.arg(key, "\"" + value + "\""));
  41 + }
  42 + return retValues.join(",");
  43 +}
  44 +
26 45 static QStringList getPivots(const QString &file, bool headers)
27 46 {
28 47 QString str;
... ... @@ -31,14 +50,6 @@ static QStringList getPivots(const QString &file, bool headers)
31 50 return str.split("_");
32 51 }
33 52  
34   -static QString getScale(const QString &mode, const QString &title, int vals)
35   -{
36   - if (vals > 12) return " + scale_"+mode+"_discrete(\""+title+"\")";
37   - else if (vals > 11) return " + scale_"+mode+"_brewer(\""+title+"\", palette=\"Set3\")";
38   - else if (vals > 9) return " + scale_"+mode+"_brewer(\""+title+"\", palette=\"Paired\")";
39   - else return " + scale_"+mode+"_brewer(\""+title+"\", palette=\"Set1\")";
40   -}
41   -
42 53 // Custom sorting method to ensure datasets are ordered nicely
43 54 static bool sortFiles(const QString &fileA, const QString &fileB)
44 55 {
... ... @@ -51,10 +62,6 @@ struct RPlot
51 62 QFile file;
52 63 QStringList pivotHeaders;
53 64 QVector< QSet<QString> > pivotItems;
54   - float confidence; // confidence interval for plotting across splits
55   - int ncol; // Number of columns for plot legends
56   -
57   - bool flip;
58 65  
59 66 struct Pivot
60 67 {
... ... @@ -68,7 +75,7 @@ struct RPlot
68 75  
69 76 Pivot major, minor;
70 77  
71   - RPlot(QStringList files, const File &destination, bool isEvalFormat = true)
  78 + RPlot(QStringList files, const File &destination)
72 79 {
73 80 if (files.isEmpty()) qFatal("Empty file list.");
74 81 qSort(files.begin(), files.end(), sortFiles);
... ... @@ -83,13 +90,9 @@ struct RPlot
83 90 bool success = file.open(QFile::WriteOnly);
84 91 if (!success) qFatal("Failed to open %s for writing.", qPrintable(file.fileName()));
85 92  
86   - file.write("# Load libraries\n"
87   - "library(ggplot2)\n"
88   - "library(gplots)\n"
89   - "library(reshape)\n"
90   - "library(scales)\n"
91   - "\n"
92   - "# Read CSVs\n"
  93 + // Copy plot_utils.R into output script with source()
  94 + file.write(qPrintable(QString("source(\"%1\")\n\n").arg(Globals->sdkPath + "/share/openbr/plotting/plot_utils.R")));
  95 + file.write("# Read CSVs\n"
93 96 "data <- NULL\n");
94 97  
95 98 // Read files and retrieve pivots
... ... @@ -123,8 +126,6 @@ struct RPlot
123 126 }
124 127  
125 128 const QString &smooth = destination.get<QString>("smooth", "");
126   - confidence = destination.get<float>("confidence", 95) / 100.0;
127   -
128 129 major.smooth = !smooth.isEmpty() && (major.header == smooth) && (major.size > 1);
129 130 minor.smooth = !smooth.isEmpty() && (minor.header == smooth) && (minor.size > 1);
130 131 if (major.smooth) major.size = 1;
... ... @@ -132,68 +133,19 @@ struct RPlot
132 133 if (major.size < minor.size)
133 134 std::swap(major, minor);
134 135  
135   - ncol = destination.get<int>("ncol", major.size > 1 ? major.size : (minor.header.isEmpty() ? major.size : minor.size));
136   - flip = minor.header == "Algorithm";
137   - // Format data
138   - if (isEvalFormat)
139   - file.write(qPrintable(QString("\n"
140   - "# Split data into individual plots\n"
141   - "plot_index = which(names(data)==\"Plot\")\n"
142   - "Metadata <- data[grep(\"Metadata\",data$Plot),-c(1)]\n"
143   - "IM <- data[grep(\"IM\",data$Plot),-c(1)]\n"
144   - "GM <- data[grep(\"GM\",data$Plot),-c(1)]\n"
145   - "DET <- data[grep(\"DET\",data$Plot),-c(1)]\n"
146   - "IET <- data[grep(\"IET\",data$Plot),-c(1)]\n"
147   - "FAR <- data[grep(\"FAR\",data$Plot),-c(1)]\n"
148   - "FRR <- data[grep(\"FRR\",data$Plot),-c(1)]\n"
149   - "SD <- data[grep(\"SD\",data$Plot),-c(1)]\n"
150   - "TF <- data[grep(\"TF\",data$Plot),-c(1)]\n"
151   - "FT <- data[grep(\"FT\",data$Plot),-c(1)]\n"
152   - "CT <- data[grep(\"CT\",data$Plot),-c(1)]\n"
153   - "BC <- data[grep(\"BC\",data$Plot),-c(1)]\n"
154   - "TS <- data[grep(\"TS\",data$Plot),-c(1)]\n"
155   - "CMC <- data[grep(\"CMC\",data$Plot),-c(1)]\n"
156   - "FAR$Error <- \"FAR\"\n"
157   - "FRR$Error <- \"FRR\"\n"
158   - "ERR <- rbind(FAR, FRR)\n"
159   - "rm(data, FAR, FRR)\n"
160   - "\n"
161   - "# Format data\n"
162   - "Metadata$Y<-factor(Metadata$Y, levels=c(\"Genuine\",\"Impostor\",\"Ignored\",\"Gallery\",\"Probe\"))\n"
163   - "IM$Y <- as.character(IM$Y)\n"
164   - "GM$Y <- as.character(GM$Y)\n"
165   - "DET$Y <- as.numeric(as.character(DET$Y))\n"
166   - "IET$Y <- as.numeric(as.character(IET$Y))\n"
167   - "ERR$Y <- as.numeric(as.character(ERR$Y))\n"
168   - "SD$Y <- as.factor(unique(as.character(SD$Y)))\n"
169   - "TF$Y <- as.numeric(as.character(TF$Y))\n"
170   - "FT$Y <- as.numeric(as.character(FT$Y))\n"
171   - "CT$Y <- as.numeric(as.character(CT$Y))\n"
172   - "BC$Y <- as.numeric(as.character(BC$Y))\n"
173   - "TS$Y <- as.character(TS$Y)\n"
174   - "CMC$Y <- as.numeric(as.character(CMC$Y))\n"
175   - "\n"
176   - "if (%1) {\n\tsummarySE <- function(data=NULL, measurevar, groupvars=NULL, na.rm=FALSE, conf.interval=%3, .drop=TRUE) {\n\t\t"
177   - "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)"
178   - "\n\t\t}\n\n\t\tdatac <- ddply(data, groupvars, .drop=.drop, .fun = function(xx, col) {\n\t\t\t"
179   - "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},"
180   - "\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)"
181   - "\n\t\tciMult <- qt(conf.interval/2 + .5, datac$N-1)\n\t\tdatac$ci <- datac$se * ciMult\n\n\t\t"
182   - "datac$upper <- if(datac[, measurevar] + datac$ci < 1) (datac[, measurevar] + datac$ci) else 1\n\t\t"
183   - "datac$lower <- if(datac[, measurevar] - datac$ci > 0) (datac[, measurevar] - datac$ci) else 0\n\n\t\treturn(datac)\n\t}\n\t"
184   - "DET <- summarySE(DET, measurevar=\"Y\", groupvars=c(\"%2\", \"X\"))\n\t"
185   - "IET <- summarySE(IET, measurevar=\"Y\", groupvars=c(\"%2\", \"X\"))\n\t"
186   - "CMC <- summarySE(CMC, measurevar=\"Y\", groupvars=c(\"%2\", \"X\"))\n\t"
187   - "ERR <- summarySE(ERR, measurevar=\"X\", groupvars=c(\"Error\", \"%2\", \"Y\"))\n\t"
188   - "TF <- summarySE(TF, measurevar=\"Y\", groupvars=c(\"%2\", \"X\"))\n\t"
189   - "FT <- summarySE(FT, measurevar=\"Y\", groupvars=c(\"%2\", \"X\"))\n\t"
190   - "CT <- summarySE(CT, measurevar=\"Y\", groupvars=c(\"%2\", \"X\"))\n}\n\n"
191   - "# Code to format FAR values\n"
192   - "far_names <- list('0.001'=\"FAR = 0.1%\", '0.01'=\"FAR = 1%\")\n"
193   - "far_labeller <- function(variable,value) { return(far_names[as.character(value)]) }\n"
194   - "\n").arg((major.smooth || minor.smooth) ? "TRUE" : "FALSE",
195   - major.size > 1 ? major.header : (minor.header.isEmpty() ? major.header : minor.header),
196   - QString::number(confidence))));
  136 + // Set variables in R
  137 + file.write(qPrintable(QString("\nconfidence <- %1\n").arg(destination.get<float>("confidence", 95) / 100.0)));
  138 + file.write(qPrintable(QString("ncol <- %1\n").arg(destination.get<int>("ncol", major.size > 1 ? major.size : (minor.header.isEmpty() ? major.size : minor.size)))));
  139 + file.write(qPrintable(QString("basename <- \"%1\"\n").arg(basename)));
  140 + file.write(qPrintable(QString("smooth <- %1\n").arg((major.smooth || minor.smooth) && (destination.get<float>("confidence", 95) / 100.0) != 0 ? "TRUE" : "FALSE")));
  141 + file.write(qPrintable(QString("csv <- %1\n").arg(destination.getBool("csv") ? "TRUE" : "FALSE")));
  142 + file.write(qPrintable(QString("majorHeader <- \"%1\"\n").arg(major.header)));
  143 + file.write(qPrintable(QString("majorSize <- %1\n").arg(major.size)));
  144 + file.write(qPrintable(QString("majorSmooth <- %1\n").arg(major.smooth ? "TRUE" : "FALSE")));
  145 + file.write(qPrintable(QString("minorHeader <- \"%1\"\n").arg(minor.header)));
  146 + file.write(qPrintable(QString("minorSize <- %1\n").arg(minor.size)));
  147 + file.write(qPrintable(QString("minorSmooth <- %1\n").arg(minor.smooth ? "TRUE" : "FALSE")));
  148 + file.write(qPrintable(QString("flip <- %1\n").arg(minor.header == "Algorithm" ? "TRUE" : "FALSE")));
197 149  
198 150 // Open output device
199 151 file.write(qPrintable(QString("\n"
... ... @@ -205,98 +157,6 @@ struct RPlot
205 157 "# Write figures\n");
206 158 }
207 159  
208   - void plotMetadata(bool csv)
209   - {
210   - file.write(qPrintable(QString("# Code to format TAR@FAR table\n"
211   - "algs <- unique(%4)\n"
212   - "algs <- algs[!duplicated(algs)]\n"
213   - "mat <- matrix(%1,nrow=6,ncol=length(algs),byrow=FALSE)\n"
214   - "colnames(mat) <- algs \n"
215   - "rownames(mat) <- c(\"FAR = 1e-06\", \"FAR = 1e-05\", \"FAR = 1e-04\", \"FAR = 1e-03\", \"FAR = 1e-02\", \"FAR = 1e-01\")\n"
216   - "TFtable <- as.table(mat)\n"
217   - "\n"
218   - "# Code to format FAR@TAR table\n"
219   - "mat <- matrix(%2,nrow=6,ncol=length(algs),byrow=FALSE)\n"
220   - "colnames(mat) <- algs \n"
221   - "rownames(mat) <- c(\"TAR = 0.40\", \"TAR = 0.50\", \"TAR = 0.65\", \"TAR = 0.75\", \"TAR = 0.85\", \"TAR = 0.95\")\n"
222   - "FTtable <- as.table(mat)\n"
223   - "\n"
224   - "# Code to format CMC Table\n"
225   - "mat <- matrix(%3,nrow=6,ncol=length(algs),byrow=FALSE)\n"
226   - "colnames(mat) <- algs \n"
227   - "rownames(mat) <- c(\"Rank 1\", \"Rank 5\", \"Rank 10\", \"Rank 20\", \"Rank 50\", \"Rank 100\")\n"
228   - "CMCtable <- as.table(mat)\n"
229   - "\n"
230   - "# Code to format Template Size Table\n"
231   - "if (nrow(TS) != 0) {\n\t"
232   - "mat <- matrix(TS$Y,nrow=1,ncol=length(algs),byrow=FALSE)\n\t"
233   - "colnames(mat) <- algs\n\t"
234   - "rownames(mat) <- c(\"Template Size (bytes):\")\n\t"
235   - "TStable <- as.table(mat)\n}"
236   - "\n").arg((major.smooth || minor.smooth) && confidence != 0 ? "paste(as.character(round(TF$Y, 3)), round(TF$ci, 3), sep=\"\\u00b1\")" : "TF$Y",
237   - (major.smooth || minor.smooth) && confidence != 0 ? "paste(as.character(round(FT$Y, 3)), round(FT$ci, 3), sep=\"\\u00b1\")" : "FT$Y",
238   - (major.smooth || minor.smooth) && confidence != 0 ? "paste(as.character(round(CT$Y, 3)), round(CT$ci, 3), sep=\"\\u00b1\")" : "CT$Y",
239   - (major.size > 1 && minor.size > 1) && !(major.smooth || minor.smooth) ? QString("paste(TF$%1, TF$%2, sep=\"_\")").arg(major.header, minor.header)
240   - : QString("TF$%1").arg(major.size > 1 ? major.header : (minor.header.isEmpty() ? major.header : minor.header)))));
241   -
242   - file.write("\n# Write metadata table\n");
243   - QString textplot = "MT <- as.data.frame(Metadata[c(1,2,3,4,5),])\n"
244   - "par(mfrow=c(4,1))\n"
245   - "plot.new()\n"
246   - "print(title(paste(\"%1 - %2\",date(),sep=\"\\n\")))\n"
247   - "mat <- matrix(MT$X[c(1,2)],ncol=2)\n"
248   - "colnames(mat) <- c(\"Gallery\", \"Probe\")\n"
249   - "imageTable <- as.table(mat)\n"
250   - "print(textplot(imageTable,show.rownames=FALSE))\n"
251   - "print(title(\"Images\"))\n"
252   - "mat <- matrix(MT$X[c(3,4,5)],ncol=3)\n"
253   - "colnames(mat) <- c(\"Genuine\", \"Impostor\", \"Ignored\")\n"
254   - "matchTable <- as.table(mat)\n"
255   - "print(textplot(matchTable,show.rownames=FALSE))\n"
256   - "print(title(\"Matches\"))\n"
257   - "plot.new()\n"
258   - "print(title(\"Gallery * Probe = Genuine + Impostor + Ignored\"))\n";
259   - file.write(qPrintable(textplot.arg(PRODUCT_NAME, PRODUCT_VERSION)));
260   -
261   - if (csv)
262   - textplot = QString("write.csv(TFtable,file=\"%1_TF.csv\")\n"
263   - "write.csv(FTtable,file=\"%1_FT.csv\")\n"
264   - "write.csv(CMCtable,file=\"%1_CMC.csv\")\n\n").arg(basename);
265   - else
266   - textplot = "plot.new()\n"
267   - "print(textplot(TFtable))\n"
268   - "print(title(\"Table of True Accept Rates at various False Accept Rates\"))\n"
269   - "print(textplot(FTtable))\n"
270   - "print(title(\"Table of False Accept Rates at various True Accept Rates\"))\n"
271   - "print(textplot(CMCtable))\n"
272   - "print(title(\"Table of retrieval rate at various ranks\"))\n"
273   - "if (nrow(TS) != 0) {\n\t"
274   - "print(textplot(TStable, cex=1.15))\n\t"
275   - "print(title(\"Template Size by Algorithm\"))\n}\n\n";
276   - file.write(qPrintable(textplot));
277   - }
278   -
279   - void qplot(QString geom, QString data, bool flipY, File opts)
280   - {
281   - file.write(qPrintable(QString("qplot(X, %1, data=%2, geom=\"%3\", main=\"%4\"").arg(flipY ? "1-Y" : "Y", data, geom, opts.get<QString>("title", "")) +
282   - (opts.contains("size") ? QString(", size=I(%1)").arg(opts.get<QString>("size")) : QString()) +
283   - (major.size > 1 ? QString(", colour=factor(%1)").arg(major.header) : QString()) +
284   - (minor.size > 1 ? QString(", linetype=factor(%1)").arg(minor.header) : QString()) +
285   - (QString(", xlab=\"%1\", ylab=\"%2\") + theme_minimal()").arg(opts.get<QString>("xTitle"), opts.get<QString>("yTitle"))) +
286   - ((major.smooth || minor.smooth) && confidence != 0 && data != "CMC" ? QString(" + geom_errorbar(data=%1[seq(1, NROW(%1), by = 29),], aes(x=X, ymin=%2), width=0.1, alpha=I(1/2))").arg(data, flipY ? "(1-lower), ymax=(1-upper)" : "lower, ymax=upper") : QString()) +
287   - (major.size > 1 ? getScale("colour", major.header, major.size) : QString()) +
288   - (minor.size > 1 ? QString(" + scale_linetype_discrete(\"%1\")").arg(minor.header) : QString()) +
289   - (opts.getBool("xLog") ? QString(" + scale_x_log10(labels=%1, breaks=%2) + annotation_logticks(sides=\"b\")").arg(opts.get<QString>("xLabels", "trans_format(\"log10\", math_format())"), opts.get<QString>("xBreaks", "waiver()"))
290   - : QString(" + scale_x_continuous(labels=%1, breaks=%2)").arg(opts.get<QString>("xLabels", "percent"), opts.get<QString>("xBreaks", "pretty_breaks(n=10)"))) +
291   - (opts.getBool("yLog") ? QString(" + scale_y_log10(labels=%1, breaks=%2) + annotation_logticks(sides=\"l\")").arg(opts.get<QString>("yLabels", "trans_format(\"log10\", math_format())"), opts.get<QString>("yBreaks", "waiver()"))
292   - : QString(" + scale_y_continuous(labels=%1, breaks=%2)").arg(opts.get<QString>("yLabels", "percent"), opts.get<QString>("yBreaks", "pretty_breaks(n=10)"))) +
293   - (opts.contains("xLimits") ? QString(" + xlim%1").arg(QtUtils::toString(opts.get<QPointF>("xLimits", QPointF()))) : QString()) +
294   - (opts.contains("yLimits") ? QString(" + ylim%1").arg(QtUtils::toString(opts.get<QPointF>("yLimits", QPointF()))) : QString()) +
295   - QString(" + theme(legend.title = element_text(size = %1), legend.text = 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),").arg(QString::number(opts.get<float>("textSize",12))) +
296   - QString(" legend.position=%1, legend.background = element_rect(fill = 'white'), panel.grid.major = element_line(colour = \"gray\"), panel.grid.minor = element_line(colour = \"gray\", linetype = \"dashed\"))").arg(opts.contains("legendPosition") ? "c"+QtUtils::toString(opts.get<QPointF>("legendPosition")) : "'bottom'") +
297   - QString(" + guides(col=guide_legend(ncol=%1))\n\n").arg(ncol)));
298   - }
299   -
300 160 bool finalize(bool show = false)
301 161 {
302 162 file.write("dev.off()\n");
... ... @@ -315,13 +175,27 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show)
315 175 qDebug("Plotting %d file(s) to %s", files.size(), qPrintable(destination));
316 176  
317 177 RPlot p(files, destination);
  178 + p.file.write("\nformatData()\n\n");
  179 + p.file.write(qPrintable(QString("algs <- %1\n").arg((p.major.size > 1 && p.minor.size > 1) && !(p.major.smooth || p.minor.smooth) ? QString("paste(TF$%1, TF$%2, sep=\"_\")").arg(p.major.header, p.minor.header)
  180 + : QString("TF$%1").arg(p.major.size > 1 ? p.major.header : (p.minor.header.isEmpty() ? p.major.header : p.minor.header)))));
  181 + p.file.write("algs <- algs[!duplicated(algs)]\n");
  182 +
  183 + if (p.major.smooth || p.minor.smooth) {
  184 + QString groupvar = p.major.size > 1 ? p.major.header : (p.minor.header.isEmpty() ? p.major.header : p.minor.header);
  185 + foreach(const QString &data, QStringList() << "DET" << "IET" << "CMC" << "TF" << "FT" << "CT") {
  186 + p.file.write(qPrintable(QString("%1 <- summarySE(%1, measurevar=\"Y\", groupvars=c(\"%2\", \"X\"), conf.interval=confidence)"
  187 + "\n").arg(data, groupvar)));
  188 + }
  189 + p.file.write(qPrintable(QString("%1 <- summarySE(%1, measurevar=\"X\", groupvars=c(\"Error\", \"%2\", \"Y\"), conf.interval=confidence)"
  190 + "\n\n").arg("ERR", groupvar)));
  191 + }
318 192  
319 193 // Use a br::file for simple storage of plot options
320 194 QMap<QString,File> optMap;
321 195 optMap.insert("rocOptions", File(QString("[xTitle=False Accept Rate,yTitle=True Accept Rate,xLog=true,yLog=false]")));
322 196 optMap.insert("detOptions", File(QString("[xTitle=False Accept Rate,yTitle=False Reject Rate,xLog=true,yLog=true]")));
323 197 optMap.insert("ietOptions", File(QString("[xTitle=False Positive Identification Rate (FPIR),yTitle=False Negative Identification Rate (FNIR),xLog=true,yLog=true]")));
324   - optMap.insert("cmcOptions", File(QString("[xTitle=Rank,yTitle=Retrieval Rate,xLog=true,yLog=false,size=1,xLabels=c(1,5,10,50,100),xBreaks=c(1,5,10,50,100)]")));
  198 + optMap.insert("cmcOptions", File(QString("[xTitle=Rank,yTitle=Retrieval Rate,xLog=true,yLog=false,size=1,xLabels=(1,5,10,50,100),xBreaks=(1,5,10,50,100)]")));
325 199  
326 200 foreach (const QString &key, optMap.keys()) {
327 201 const QStringList options = destination.get<QStringList>(key, QStringList());
... ... @@ -333,56 +207,33 @@ bool Plot(const QStringList &amp;files, const File &amp;destination, bool show)
333 207 }
334 208  
335 209 // optional plot metadata and accuracy tables
336   - if (destination.getBool("metadata", true))
337   - p.plotMetadata(destination.getBool("csv", false));
338   - p.qplot("line", "DET", true, optMap["rocOptions"]);
339   - p.qplot("line", "DET", false, optMap["detOptions"]);
340   - p.qplot("line", "IET", false, optMap["ietOptions"]);
341   - p.qplot("line", "CMC", false, optMap["cmcOptions"]);
342   -
343   - p.file.write(qPrintable(QString("qplot(X, data=SD, geom=\"histogram\", fill=Y, position=\"identity\", alpha=I(1/2)") +
344   - QString(", xlab=\"Score\", ylab=\"Frequency\"") +
345   - QString(") + scale_fill_manual(\"Ground Truth\", values=c(\"blue\", \"red\")) + theme_minimal() + scale_x_continuous(minor_breaks=NULL) + scale_y_continuous(minor_breaks=NULL) + theme(axis.text.y=element_blank(), axis.ticks=element_blank(), axis.text.x=element_text(angle=-90, hjust=0))") +
346   - (p.major.size > 1 ? (p.minor.size > 1 ? QString(" + facet_grid(%2 ~ %1, scales=\"free\")").arg((p.flip ? p.major.header : p.minor.header), (p.flip ? p.minor.header : p.major.header)) : QString(" + facet_wrap(~ %1, scales = \"free\")").arg(p.major.header)) : QString()) +
347   - QString(" + theme(aspect.ratio=1)\n\n")));
348   -
349   - 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") +
350   - (p.major.size > 1 ? QString(", fill=factor(%1)").arg(p.major.header) : QString()) +
351   - QString(", xlab=\"False Accept Rate\", ylab=\"True Accept Rate\") + theme_minimal()") +
352   - (p.major.size > 1 ? getScale("fill", p.major.header, p.major.size) : QString()) +
353   - (p.minor.size > 1 ? QString(" + facet_grid(%2 ~ X)").arg(p.minor.header) : QString(" + facet_grid(. ~ X, labeller=far_labeller)")) +
354   - 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"));
355   -
356   - p.file.write(qPrintable(QString("qplot(X, Y, data=ERR, geom=\"line\", linetype=Error") +
357   - ((p.flip ? p.major.size : p.minor.size) > 1 ? QString(", colour=factor(%1)").arg(p.flip ? p.major.header : p.minor.header) : QString()) +
358   - QString(", xlab=\"Score\", ylab=\"Error Rate\") + theme_minimal()") +
359   - ((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()) +
360   - QString(" + scale_y_log10(labels=percent) + annotation_logticks(sides=\"l\")") +
361   - ((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()) +
362   - QString(" + theme(aspect.ratio=1)\n\n")));
363   -
364   - p.file.write(qPrintable(QString("if (nrow(IM) != 0) {\n\tlibrary(jpeg)\n\tlibrary(png)\n\tlibrary(grid)\n\t") +
365   - QString("multiplot <- function(..., plotlist=NULL, cols) {\n\t") +
366   - QString("\trequire(grid)\n\n\t\t# Make a list from the ... arguments and plotlist\n\t\tplots <- c(list(...), plotlist)\n") +
367   - QString("\t\tnumPlots = length(plots)\n\n\t\t# Make the panel\n\t\tplotCols = cols\n\t\tplotRows = ceiling(numPlots/plotCols)\n\n") +
368   - QString("\t\t# Set up the page\n\t\tgrid.newpage()\n\t\tpushViewport(viewport(layout = grid.layout(plotRows, plotCols)))\n\t\tvplayout <- function(x, y)\n\t\t\tviewport(layout.pos.row = x, layout.pos.col = y)\n\n") +
369   - QString("\t\t# Make each plot, in the correct location\n\t\tfor (i in 1:numPlots) {\n\t\t\tcurRow = ceiling(i/plotCols)\n\t\t\tcurCol = (i-1) %% plotCols + 1\n\t\t\tprint(plots[[i]], vp = vplayout(curRow, curCol))\n\t\t}\n\t}\n\n")));
370   -
371   - p.file.write(qPrintable(QString("\t# Print impostor matches above the EER\n\tfor (i in 1:nrow(IM)) {\n\t\tscore <- IM[i,1]\n\t\tfiles <- IM[i,2]\n\t\talg <- IM[i,3]\n\t\tfiles <- unlist(strsplit(files, \"[:]\"))\n\n\t\text1 <- unlist(strsplit(files[2], \"[.]\"))[2]\n\t\text2 <- unlist(strsplit(files[4], \"[.]\"))[2]\n\t\t") +
372   - QString("if (ext1 == \"jpg\" || ext1 == \"JPEG\" || ext1 == \"jpeg\" || ext1 == \"JPG\") {\n\t\t\timg1 <- readJPEG(files[2])\n\t\t} else if (ext1 == \"PNG\" || ext1 == \"png\") {\n\t\t\timg1 <- readPNG(files[2])\n\t\t} else if (ext1 == \"TIFF\" || ext1 == \"tiff\" || ext1 == \"TIF\" || ext1 == \"tif\") {\n\t\t\timg1 <- readTIFF(files[2])\n\t\t} else {\n\t\t\tnext\n\t\t}\n\t\tif (ext2 == \"jpg\" || ext2 == \"JPEG\" || ext2 == \"jpeg\" || ext2 == \"JPG\") {\n\t\t\timg2 <- readJPEG(files[4])\n\t\t} ") +
373   - QString("else if (ext2 == \"PNG\" || ext2 == \"png\") {\n\t\t\timg2 <- readPNG(files[4])\n\t\t} else if (ext2 == \"TIFF\" || ext2 == \"tiff\" || ext2 == \"TIF\" || ext2 == \"tif\") {\n\t\t\timg2 <- readTIFF(files[4])\n\t\t} else {\n\t\t\tnext\n\t\t}") +
374   - QString("\n\t\tname1 <- files[1]\n\t\tname2 <- files[3]\n\n\t\tg1 <- rasterGrob(img1, interpolate=TRUE)\n\t\tg2 <- rasterGrob(img2, interpolate=TRUE)\n\n\t\t") +
375   - QString("plot1 <- qplot(1:10, 1:10, geom=\"blank\") + annotation_custom(g1, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) + theme(axis.line=element_blank(), axis.text.x=element_blank(), axis.text.y=element_blank(), axis.ticks=element_blank(), panel.background=element_blank()) + labs(title=alg) + ylab(unlist(strsplit(files[2], \"[/]\"))[length(unlist(strsplit(files[2], \"[/]\")))]) + xlab(name1)\n\t\t") +
376   - QString("plot2 <- qplot(1:10, 1:10, geom=\"blank\") + annotation_custom(g2, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) + theme(axis.line=element_blank(), axis.text.x=element_blank(), axis.text.y=element_blank(), axis.ticks=element_blank(), panel.background=element_blank()) + labs(title=paste(\"Impostor score =\", score)) + ylab(unlist(strsplit(files[4], \"[/]\"))[length(unlist(strsplit(files[4], \"[/]\")))]) + xlab(name2)\n\n\t\t") +
377   - QString("multiplot(plot1, plot2, cols=2)\n\t}")));
378   -
379   - p.file.write(qPrintable(QString("\n\n\t# Print genuine matches below the EER\n\tfor (i in 1:nrow(GM)) {\n\t\tscore <- GM[i,1]\n\t\tfiles <- GM[i,2]\n\t\talg <- GM[i,3]\n\t\tfiles <- unlist(strsplit(files, \"[:]\"))\n\n\t\text1 <- unlist(strsplit(files[2], \"[.]\"))[2]\n\t\text2 <- unlist(strsplit(files[4], \"[.]\"))[2]\n\t\t") +
380   - QString("if (ext1 == \"jpg\" || ext1 == \"JPEG\" || ext1 == \"jpeg\" || ext1 == \"JPG\") {\n\t\t\timg1 <- readJPEG(files[2])\n\t\t} else if (ext1 == \"PNG\" || ext1 == \"png\") {\n\t\t\timg1 <- readPNG(files[2])\n\t\t} else if (ext1 == \"TIFF\" || ext1 == \"tiff\" || ext1 == \"TIF\" || ext1 == \"tif\") {\n\t\t\timg1 <- readTIFF(files[2])\n\t\t} else {\n\t\t\tnext\n\t\t}\n\t\tif (ext2 == \"jpg\" || ext2 == \"JPEG\" || ext2 == \"jpeg\" || ext2 == \"JPG\") {\n\t\t\timg2 <- readJPEG(files[4])\n\t\t} ") +
381   - QString("else if (ext2 == \"PNG\" || ext2 == \"png\") {\n\t\t\timg2 <- readPNG(files[4])\n\t\t} else if (ext2 == \"TIFF\" || ext2 == \"tiff\" || ext2 == \"TIF\" || ext2 == \"tif\") {\n\t\t\timg2 <- readTIFF(files[4])\n\t\t} else {\n\t\t\tnext\n\t\t}") +
382   - QString("\n\t\tname1 <- files[1]\n\t\tname2 <- files[3]\n\n\t\tg1 <- rasterGrob(img1, interpolate=TRUE)\n\t\tg2 <- rasterGrob(img2, interpolate=TRUE)\n\n\t\t") +
383   - QString("plot1 <- qplot(1:10, 1:10, geom=\"blank\") + annotation_custom(g1, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) + theme(axis.line=element_blank(), axis.text.x=element_blank(), axis.text.y=element_blank(), axis.ticks=element_blank(), panel.background=element_blank()) + labs(title=alg) + ylab(unlist(strsplit(files[2], \"[/]\"))[length(unlist(strsplit(files[2], \"[/]\")))]) + xlab(name1)\n\t\t") +
384   - QString("plot2 <- qplot(1:10, 1:10, geom=\"blank\") + annotation_custom(g2, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) + theme(axis.line=element_blank(), axis.text.x=element_blank(), axis.text.y=element_blank(), axis.ticks=element_blank(), panel.background=element_blank()) + labs(title=paste(\"Genuine score =\", score)) + ylab(unlist(strsplit(files[4], \"[/]\"))[length(unlist(strsplit(files[4], \"[/]\")))]) + xlab(name2)\n\n\t\t") +
385   - QString("multiplot(plot1, plot2, cols=2)\n\t}\n}\n\n")));
  210 + if (destination.getBool("metadata", true)) {
  211 + p.file.write("\n# Write metadata table\n");
  212 + p.file.write(qPrintable(QString("plotMetadata(metadata=Metadata, title=\"%1 - %2\")\n").arg(PRODUCT_NAME, PRODUCT_VERSION)));
  213 +
  214 + if (!destination.getBool("csv")) p.file.write("plot.new()\n");
  215 + QString table = "plotTable(tableData=%1, name=%2, labels=%3)\n";
  216 + p.file.write(qPrintable(table.arg("TF", "\"Table of True Accept Rates at various False Accept Rates\"",
  217 + "c(\"FAR = 1e-06\", \"FAR = 1e-05\", \"FAR = 1e-04\", \"FAR = 1e-03\", \"FAR = 1e-02\", \"FAR = 1e-01\")")));
  218 + p.file.write(qPrintable(table.arg("FT", "\"Table of False Accept Rates at various True Accept Rates\"",
  219 + "c(\"TAR = 0.40\", \"TAR = 0.50\", \"TAR = 0.65\", \"TAR = 0.75\", \"TAR = 0.85\", \"TAR = 0.95\")")));
  220 + p.file.write(qPrintable(table.arg("CT", "\"Table of retrieval rate at various ranks\"",
  221 + "c(\"Rank 1\", \"Rank 5\", \"Rank 10\", \"Rank 20\", \"Rank 50\", \"Rank 100\")")));
  222 + p.file.write(qPrintable(table.arg("TS", "\"Template Size by Algorithm\"",
  223 + "c(\"Template Size (bytes):\")")));
  224 + p.file.write("\n");
  225 + }
  226 +
  227 + // Write plots
  228 + QString plot = "plot <- plotLine(lineData=%1, options=list(%2), flipY=%3)\nplot\n";
  229 + p.file.write(qPrintable(QString(plot).arg("DET", toRList(optMap["rocOptions"]), "TRUE")));
  230 + p.file.write(qPrintable(QString(plot).arg("DET", toRList(optMap["detOptions"]), "FALSE")));
  231 + p.file.write(qPrintable(QString(plot).arg("IET", toRList(optMap["ietOptions"]), "FALSE")));
  232 + p.file.write(qPrintable(QString(plot).arg("CMC", toRList(optMap["cmcOptions"]), "FALSE")));
  233 + p.file.write("plot <- plotSD(sdData=SD)\nplot\n");
  234 + p.file.write("plot <- plotBC(bcData=BC)\nplot\n");
  235 + p.file.write("plot <- plotERR(errData=ERR)\nplot\n");
  236 + p.file.write("plotEERSamples(imData=IM, gmData=GM)\n\n");
386 237  
387 238 return p.finalize(show);
388 239 }
... ... @@ -420,7 +271,8 @@ bool filesHaveSinglePoint(const QStringList &amp;files) {
420 271 bool PlotDetection(const QStringList &files, const File &destination, bool show)
421 272 {
422 273 qDebug("Plotting %d detection file(s) to %s", files.size(), qPrintable(destination));
423   - RPlot p(files, destination, false);
  274 + RPlot p(files, destination);
  275 + p.file.write("\nformatData(type=\"detection\")\n\n");
424 276  
425 277 // Use a br::file for simple storage of plot options
426 278 QMap<QString,File> optMap;
... ... @@ -436,40 +288,26 @@ bool PlotDetection(const QStringList &amp;files, const File &amp;destination, bool show)
436 288 }
437 289 }
438 290  
439   - p.file.write("# Split data into individual plots\n"
440   - "plot_index = which(names(data)==\"Plot\")\n"
441   - "DiscreteROC <- data[grep(\"DiscreteROC\",data$Plot),-c(1)]\n"
442   - "ContinuousROC <- data[grep(\"ContinuousROC\",data$Plot),-c(1)]\n"
443   - "DiscretePR <- data[grep(\"DiscretePR\",data$Plot),-c(1)]\n"
444   - "ContinuousPR <- data[grep(\"ContinuousPR\",data$Plot),-c(1)]\n"
445   - "Overlap <- data[grep(\"Overlap\",data$Plot),-c(1)]\n"
446   - "AverageOverlap <- data[grep(\"AverageOverlap\",data$Plot),-c(1)]\n"
447   - "rm(data)\n"
448   - "\n");
449   -
450 291 QString plotType("line");
451 292 if (filesHaveSinglePoint(files))
452 293 plotType = QString("point");
453 294  
  295 + QString plot = "plot <- plotLine(lineData=%1, options=list(%2), flipY=%3, geometry=%4)\nplot\n";
454 296 foreach (const QString &type, QStringList() << "Discrete" << "Continuous") {
455 297 optMap["rocOptions"].set("title", type);
456   - p.qplot(plotType, type + "ROC", false, optMap["rocOptions"]);
  298 + p.file.write(qPrintable(QString(plot).arg(type + "ROC", toRList(optMap["rocOptions"]), "FALSE", "\"" + plotType + "\"")));
457 299 }
458 300  
459 301 foreach (const QString &type, QStringList() << "Discrete" << "Continuous") {
460 302 optMap["prOptions"].set("title", type);
461   - p.qplot(plotType, type + "PR", false, optMap["prOptions"]);
  303 + p.file.write(qPrintable(QString(plot).arg(type + "PR", toRList(optMap["prOptions"]), "FALSE", "\"" + plotType + "\"")));
462 304 }
463   -
464   - p.file.write(qPrintable(QString("qplot(X, data=Overlap, geom=\"histogram\", position=\"identity\", xlab=\"Overlap\", ylab=\"Frequency\")") +
465   - QString(" + theme_minimal() + scale_x_continuous(minor_breaks=NULL) + scale_y_continuous(minor_breaks=NULL) + theme(axis.text.y=element_blank(), axis.ticks=element_blank(), axis.text.x=element_text(angle=-90, hjust=0))") +
466   - (p.major.size > 1 ? (p.minor.size > 1 ? QString(" + facet_grid(%2 ~ %1, scales=\"free\")").arg(p.minor.header, p.major.header) : QString(" + facet_wrap(~ %1, scales = \"free\")").arg(p.major.header)) : QString()) +
467   - QString(" + theme(aspect.ratio=1, legend.position=\"bottom\")\n\n")));
  305 + p.file.write("plot <- plotOverlap(overlapData=Overlap)\nplot\n");
468 306  
469 307 p.file.write(qPrintable(QString("ggplot(AverageOverlap, aes(x=%1, y=%2, label=round(X,3)), main=\"Average Overlap\") + geom_text() + theme_minimal()").arg(p.minor.size > 1 ? p.minor.header : "'X'", p.major.size > 1 ? p.major.header : "'Y'") +
470 308 QString("%1%2\n\n").arg(p.minor.size > 1 ? "" : " + xlab(NULL)", p.major.size > 1 ? "" : " + ylab(NULL)")));
471 309  
472   - p.file.write(qPrintable(QString("ggplot(AverageOverlap, aes(x=%1, y=%2, fill=X)) + geom_tile() + scale_fill_continuous(\"Average Overlap\") + theme_minimal()").arg(p.minor.size > 1 ? p.minor.header : "'X'", p.major.size > 1 ? p.major.header : "'Y'") +
  310 + p.file.write(qPrintable(QString("ggplot(AverageOverlap, aes(x=%1, y=%2, fill=X)) + geom_tile() + scale_fill_continuous(\"Average Overlap\", guide=FALSE) + theme_minimal()").arg(p.minor.size > 1 ? p.minor.header : "'X'", p.major.size > 1 ? p.major.header : "'Y'") +
473 311 QString("%1%2\n\n").arg(p.minor.size > 1 ? "" : " + xlab(NULL)", p.major.size > 1 ? "" : " + ylab(NULL)")));
474 312  
475 313 return p.finalize(show);
... ... @@ -478,109 +316,12 @@ bool PlotDetection(const QStringList &amp;files, const File &amp;destination, bool show)
478 316 bool PlotLandmarking(const QStringList &files, const File &destination, bool show)
479 317 {
480 318 qDebug("Plotting %d landmarking file(s) to %s", files.size(), qPrintable(destination));
481   - RPlot p(files, destination, false);
482   -
483   - p.file.write(qPrintable(QString("# Split data into individual plots\n"
484   - "plot_index = which(names(data)==\"Plot\")\n"
485   - "Box <- data[grep(\"Box\",data$Plot),-c(1)]\n"
486   - "Box$X <- factor(Box$X, levels = Box$X, ordered = TRUE)\n"
487   - "Sample <- data[grep(\"Sample\",data$Plot),-c(1)]\n"
488   - "Sample$X <- as.character(Sample$X)\n"
489   - "EXT <- data[grep(\"EXT\",data$Plot),-c(1)]\n"
490   - "EXT$X <- as.character(EXT$X)\n"
491   - "EXP <- data[grep(\"EXP\",data$Plot),-c(1)]\n"
492   - "EXP$X <- as.character(EXP$X)\n"
493   - "NormLength <- data[grep(\"NormLength\",data$Plot),-c(1)]\n"
494   - "rm(data)\n"
495   - "\n")));
496   -
497   - p.file.write(qPrintable(QString("summarySE <- function(data=NULL, measurevar, groupvars=NULL, na.rm=FALSE, conf.interval=.95, .drop=TRUE) {\n\t"
498   - "require(plyr)\n\n\tlength2 <- function (x, na.rm=FALSE) {\n\t\tif (na.rm) sum(!is.na(x))\n\t\telse length(x)"
499   - "\n\t}\n\n\tdatac <- ddply(data, groupvars, .drop=.drop, .fun = function(xx, col) {\n\t\t"
500   - "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},"
501   - "\n\t\tmeasurevar\n\t)\n\n\tdatac <- rename(datac, c(\"mean\" = measurevar))\n\tdatac$se <- datac$sd / sqrt(datac$N)"
502   - "\n\tciMult <- qt(conf.interval/2 + .5, datac$N-1)\n\tdatac$ci <- datac$se * ciMult\n\n\treturn(datac)\n}\n")));
503   -
504   -
505   - p.file.write(qPrintable(QString("\nreadData <- function(data) {\n\texamples <- list()\n"
506   - "\tfor (i in 1:nrow(data)) {\n"
507   - "\t\tpath <- data[i,1]\n"
508   - "\t\tvalue <- data[i,2]\n"
509   - "\t\tfile <- unlist(strsplit(path, \"[.]\"))[1]\n"
510   - "\t\text <- unlist(strsplit(path, \"[.]\"))[2]\n"
511   - "\t\tif (ext == \"jpg\" || ext == \"JPEG\" || ext == \"jpeg\" || ext == \"JPG\") {\n"
512   - "\t\t\timg <- readJPEG(path)\n"
513   - "\t\t} else if (ext == \"PNG\" || ext == \"png\") {\n"
514   - "\t\t\timg <- readPNG(path)\n"
515   - "\t\t} else if (ext == \"TIFF\" || ext == \"tiff\" || ext == \"TIF\" || ext == \"tif\") { \n"
516   - "\t\t\timg <- readTIFF(path)\n"
517   - "}else {\n"
518   - "\t\t\tnext\n"
519   - "\t\t}\n"
520   - "\t\texample <- list(file = file, value = value, image = img)\n"
521   - "\t\texamples[[i]] <- example\n"
522   - "\t}\n"
523   - "\treturn(examples)\n"
524   - "}\n")));
525   -
526   - p.file.write(qPrintable(QString("\nlibrary(jpeg)\n"
527   - "library(png)\n"
528   - "library(grid)\n"
529   - "multiplot <- function(..., plotlist=NULL, cols) {\n"
530   - "\trequire(grid)\n"
531   - "\t# Make a list from the ... arguments and plotlist\n"
532   - "\tplots <- c(list(...), plotlist)\n"
533   - "\tnumPlots = length(plots)\n"
534   - "\t# Make the panel\n"
535   - "\tplotCols = cols\n"
536   - "\tplotRows = ceiling(numPlots/plotCols)\n"
537   - "\t# Set up the page\n"
538   - "\tgrid.newpage()\n"
539   - "\tpushViewport(viewport(layout = grid.layout(plotRows, plotCols)))\n"
540   - "\tvplayout <- function(x, y)\n"
541   - "\tviewport(layout.pos.row = x, layout.pos.col = y)\n"
542   - "\t# Make each plot, in the correct location\n"
543   - "\tfor (i in 1:numPlots) {\n"
544   - "\t\tcurRow = ceiling(i/plotCols)\n"
545   - "\t\tcurCol = (i-1) %% plotCols + 1\n"
546   - "\t\tprint(plots[[i]], vp = vplayout(curRow, curCol))\n"
547   - "\t}\n"
548   - "}\n")));
549   -
550   - p.file.write(qPrintable(QString("\nplotImage <- function(image, title=NULL, label=NULL) { \n"
551   - "\tp <- qplot(1:10, 1:10, geom=\"blank\") + annotation_custom(rasterGrob(image$image), xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) + theme(axis.line=element_blank(), axis.title.y=element_blank(), axis.text.x=element_blank(), axis.text.y=element_blank(), line=element_blank(), axis.ticks=element_blank(), panel.background=element_blank()) + labs(title=title) + xlab(label)\n"
552   - "\treturn(p)"
553   - "}\n")));
554   -
555   - p.file.write(qPrintable(QString("\nsample <- readData(Sample) \n"
556   - "rows <- sample[[1]]$value\n"
557   - "algs <- unique(Box$%1)\n"
558   - "algs <- algs[!duplicated(algs)]\n"
559   - "print(plotImage(sample[[1]],\"Sample Landmarks\",sprintf(\"Total Landmarks: %s\",sample[[1]]$value))) \n"
560   - "if (nrow(EXT) != 0 && nrow(EXP)) {\n"
561   - "\tfor (j in 1:length(algs)) {\n"
562   - "\ttruthSample <- readData(EXT[EXT$. == algs[[j]],])\n"
563   - "\tpredictedSample <- readData(EXP[EXP$. == algs[[j]],])\n"
564   - "\t\tfor (i in 1:length(predictedSample)) {\n"
565   - "\t\t\tmultiplot(plotImage(predictedSample[[i]],sprintf(\"%s\\nPredicted Landmarks\",algs[[j]]),sprintf(\"Average Landmark Error: %.3f\",predictedSample[[i]]$value)),plotImage(truthSample[[i]],\"Ground Truth\\nLandmarks\",\"\"),cols=2)\n"
566   - "\t\t}\n"
567   - "\t}\n"
568   - "}\n").arg(p.major.size > 1 ? p.major.header : (p.minor.header.isEmpty() ? p.major.header : p.minor.header))));
569   -
570   - p.file.write(qPrintable(QString("\n"
571   - "# Code to format error table\n"
572   - "StatBox <- summarySE(Box, measurevar=\"Y\", groupvars=c(\"%1\",\"X\"))\n"
573   - "OverallStatBox <- summarySE(Box, measurevar=\"Y\", groupvars=c(\"%1\"))\n"
574   - "mat <- matrix(paste(as.character(round(StatBox$Y, 3)), round(StatBox$ci, 3), sep=\" \\u00b1 \"),nrow=rows,ncol=length(algs),byrow=FALSE)\n"
575   - "mat <- rbind(mat, paste(as.character(round(OverallStatBox$Y, 3)), round(OverallStatBox$ci, 3), sep=\" \\u00b1 \"))\n"
576   - "mat <- rbind(mat, as.character(round(NormLength$Y, 3)))\n"
577   - "colnames(mat) <- algs\n"
578   - "rownames(mat) <- c(seq(0,rows-1),\"Aggregate\",\"Average IPD\")\n"
579   - "ETable <- as.table(mat)\n").arg(p.major.size > 1 ? p.major.header : (p.minor.header.isEmpty() ? p.major.header : p.minor.header))));
580   -
581   - p.file.write(qPrintable(QString("\n"
582   - "print(textplot(ETable))\n"
583   - "print(title(\"Landmarking Error Rates\"))\n")));
  319 + RPlot p(files, destination);
  320 + p.file.write("\nformatData(type=\"landmarking\")\n\n");
  321 + p.file.write(qPrintable(QString("algs <- uniqueBox$%1)\n").arg(p.major.size > 1 ? p.major.header : (p.minor.header.isEmpty() ? p.major.header : p.minor.header))));
  322 + p.file.write("algs <- algs[!duplicated(algs)]\n");
  323 + p.file.write("plotLandmarkSamples(samples=sample, expData=EXP, extData=EXT)\n");
  324 + p.file.write("plotLandmarkTables(tableData=Box)\n");
584 325  
585 326 p.file.write(qPrintable(QString("ggplot(Box, aes(Y,%1%2))").arg(p.major.size > 1 ? QString(", colour=%1").arg(p.major.header) : QString(),
586 327 p.minor.size > 1 ? QString(", linetype=%1").arg(p.minor.header) : QString()) +
... ... @@ -599,7 +340,7 @@ bool PlotMetadata(const QStringList &amp;files, const QString &amp;columns, bool show)
599 340 {
600 341 qDebug("Plotting %d metadata file(s) for columns %s", files.size(), qPrintable(columns));
601 342  
602   - RPlot p(files, "PlotMetadata", false);
  343 + RPlot p(files, "PlotMetadata");
603 344 foreach (const QString &column, columns.split(";"))
604 345 p.file.write(qPrintable(QString("qplot(%1, %2, data=data, geom=\"violin\", fill=%1) + coord_flip() + theme_minimal()\nggsave(\"%2.pdf\")\n").arg(p.major.header, column)));
605 346 return p.finalize(show);
... ...
share/openbr/plotting/plot_utils.R 0 โ†’ 100644
  1 +# Load libraries
  2 +library("ggplot2")
  3 +library("gplots")
  4 +library("reshape")
  5 +library("scales")
  6 +library("jpeg")
  7 +library("png")
  8 +library("grid")
  9 +
  10 +# Code to format FAR values
  11 +far_names <- list('0.001'="FAR = 0.1%", '0.01'="FAR = 1%")
  12 +far_labeller <- function(variable,value) { return(far_names[as.character(value)]) }
  13 +
  14 +getScale <- function(mode, title, vals) {
  15 + if (vals > 12) return(do.call(paste("scale", mode, "discrete", sep="_"), list(title)))
  16 + else if (vals > 11) return(do.call(paste("scale", mode, "brewer", sep="_"), list(title, palette="Set3")))
  17 + else if (vals > 9) return(do.call(paste("scale", mode, "brewer", sep="_"), list(title, palette="Paired")))
  18 + else return(do.call(paste("scale", mode, "brewer", sep="_"), list(title, palette="Set1")))
  19 +}
  20 +
  21 +plotMetadata <- function(metadata=NULL, title=NULL) {
  22 + MT <- as.data.frame(metadata[c(1, 2, 3, 4, 5),])
  23 + par(mfrow=c(4, 1))
  24 + plot.new()
  25 + print(title(paste(title, date(), sep="\n")))
  26 + mat <- matrix(MT$X[c(1, 2)], ncol=2)
  27 + colnames(mat) <- c("Gallery", "Probe")
  28 + imageTable <- as.table(mat)
  29 + print(textplot(imageTable, show.rownames=FALSE))
  30 + print(title("Images"))
  31 + mat <- matrix(MT$X[c(3, 4, 5)], ncol=3)
  32 + colnames(mat) <- c("Genuine", "Impostor", "Ignored")
  33 + matchTable <- as.table(mat)
  34 + print(textplot(matchTable, show.rownames=FALSE))
  35 + print(title("Matches"))
  36 + plot.new()
  37 + print(title("Gallery * Probe = Genuine + Impostor + Ignored"))
  38 +}
  39 +
  40 +plotTable <- function(tableData=NULL, name=NULL, labels=NULL) {
  41 + if (nrow(tableData) == 0) return()
  42 + if (smooth && confidence != 0) {
  43 + input = paste(as.character(round(tableData$Y, 3)), round(tableData$ci, 3), sep="\u00b1")
  44 + } else {
  45 + input = tableData$Y
  46 + }
  47 + mat <- matrix(input, nrow=length(labels), ncol=length(algs), byrow=FALSE)
  48 + colnames(mat) <- algs
  49 + rownames(mat) <- labels
  50 + table <- as.table(mat)
  51 + if (csv) {
  52 + write.csv(table, file=paste(paste(basename, deparse(substitute(data)), sep="_"), ".csv", sep=""))
  53 + } else {
  54 + print(textplot(table))
  55 + print(title(name))
  56 + }
  57 +}
  58 +
  59 +plotLandmarkTables <- function(tableData=NULL) {
  60 + if(majorSize > 1) {
  61 + var <- majorHeader
  62 + } else {
  63 + if(minorHeader == "") var <- majorHeader else var <- minorHeader
  64 + }
  65 + StatBox <- summarySE(tableData, measurevar="Y", groupvars=c(var,"X"))
  66 + OverallStatBox <- summarySE(tableData, measurevar="Y", groupvars=c(var))
  67 + mat <- matrix(paste(as.character(round(StatBox$Y, 3)), round(StatBox$ci, 3), sep=" \u00b1 "), nrow=rows, ncol=length(algs), byrow=FALSE)
  68 + mat <- rbind(mat, paste(as.character(round(OverallStatBox$Y, 3)), round(OverallStatBox$ci, 3), sep=" \u00b1 "))
  69 + mat <- rbind(mat, as.character(round(NormLength$Y, 3)))
  70 + colnames(mat) <- algs
  71 + rownames(mat) <- c(seq(0, rows-1), "Aggregate","Average IPD")
  72 + ETable <- as.table(mat)
  73 + print(textplot(ETable))
  74 + print(title("Landmarking Error Rates"))
  75 +}
  76 +
  77 +plotLine <- function(lineData=NULL, options=NULL, flipY=FALSE, geometry="line") {
  78 + textSize <- if("textSize" %in% names(options)) as.numeric(options$textSize) else 12
  79 + p <- qplot(X, if(flipY) 1-Y else Y, data=lineData, main=options$title, geom=geometry, size=if("size" %in% names(options)) I(as.numeric(options$size)) else I(.5), colour=if(majorSize > 1) factor(eval(parse(text=majorHeader))) else NULL, linetype=if(minorSize > 1) factor(eval(parse(text=minorHeader))) else NULL, xlab=options$xTitle, ylab=options$yTitle) + theme_minimal()
  80 + if (smooth && deparse(substitute(lineData)) != "CMC" && confidence != 0) p <- p + geom_errorbar(data=lineData[seq(1, NROW(lineData), by = 29),], aes(x=X, ymin=if(flipY) (1-lower) else lower, ymax=if(flipY) (1-upper) else upper), width=0.1, alpha=I(1/2))
  81 + if (majorSize > 1) p <- p + getScale("colour", majorHeader, majorSize)
  82 + if (minorSize > 1) p <- p + scale_linetype_discrete(minorHeader)
  83 +
  84 + # Set log/continuous scales, breaks and labels
  85 + if (options$xLog)
  86 + p <- p + scale_x_log10(labels=if("xLabels" %in% names(options)) eval(parse(text=options$xLabels)) else trans_format("log10", math_format()), breaks=if("xBreaks" %in% names(options)) eval(parse(text=options$xBreaks)) else waiver()) + annotation_logticks(sides="b")
  87 + else
  88 + p <- p + scale_x_continuous(labels=if("xLabels" %in% names(options)) eval(parse(text=options$xLabels)) else percent, breaks=if("xBreaks" %in% names(options)) eval(parse(text=options$xBreaks)) else pretty_breaks(n=10))
  89 + if (options$yLog)
  90 + p <- p + scale_y_log10(labels=if("yLabels" %in% names(options)) eval(parse(text=options$yLabels)) else trans_format("log10", math_format()), breaks=if("yBreaks" %in% names(options)) eval(parse(text=options$yBreaks)) else waiver()) + annotation_logticks(sides="l")
  91 + else
  92 + p <- p + scale_y_continuous(labels=if("yLabels" %in% names(options)) eval(parse(text=options$yLabels)) else percent, breaks=if("yBreaks" %in% names(options)) eval(parse(text=options$yBreaks)) else pretty_breaks(n=10))
  93 +
  94 + if ("xLimits" %in% names(options)) p <- p + xlim(eval(parse(text=options$xLimits)))
  95 + if ("yLimits" %in% names(options)) p <- p + ylim(eval(parse(text=options$yLimits)))
  96 + p <- p + theme(legend.title = element_text(size = textSize), legend.text = element_text(size = textSize), plot.title = element_text(size = textSize), axis.text = element_text(size = textSize), axis.title.x = element_text(size = textSize), axis.title.y = element_text(size = textSize), legend.position=if("legendPosition" %in% names(options)) eval(parse(text=options$legendPosition)) else "bottom", legend.background = element_rect(fill = 'white'), panel.grid.major = element_line(colour = "gray"), panel.grid.minor = element_line(colour = "gray", linetype = "dashed"))
  97 + p <- p + guides(col=guide_legend(ncol=ncol))
  98 + return(p)
  99 +}
  100 +
  101 +plotSD <- function(sdData=NULL) {
  102 + p <- qplot(X, data=sdData, geom="histogram", fill=Y, position="identity", alpha=I(1/2), xlab="Score", ylab="Frequency")
  103 + p <- p + scale_fill_manual("Ground Truth", values=c("blue", "red")) + theme_minimal() + scale_x_continuous(minor_breaks=NULL) + scale_y_continuous(minor_breaks=NULL) + theme(axis.text.y=element_blank(), axis.ticks=element_blank(), axis.text.x=element_text(angle=-90, hjust=0))
  104 + if (majorSize > 1) {
  105 + if (minorSize > 1) {
  106 + if (flip) {
  107 + A <- minorHeader
  108 + B <- majorHeader
  109 + } else {
  110 + A <- majorHeader
  111 + B <- minorHeader
  112 + }
  113 + p <- p + facet_grid(facets=as.formula(paste(A, "~", B)), scales="free")
  114 + } else {
  115 + p <- p + facet_wrap(facets=as.formula(paste("~", majorHeader)), scales="free")
  116 + }
  117 + }
  118 + p <- p + theme(aspect.ratio=1)
  119 + return(p)
  120 +}
  121 +
  122 +plotBC <- function(bcData=NULL) {
  123 + factor <- if (majorSmooth) minorHeader else majorHeader
  124 + plotString <- paste("qplot(factor(", factor, ")", if(smooth) ", Y" else "", ", data=bcData, ", if(smooth) "geom=\"boxplot\"" else "geom=\"bar\", position=\"dodge\", weight=Y", sep="")
  125 + p <- eval(parse(text=paste(plotString, if(majorSize > 1) paste(", fill=factor(", majorHeader, ")", sep="") else "", ", xlab=\"False Accept Rate\", ylab=\"True Accept Rate\") + theme_minimal()", sep="")))
  126 + if(majorSize > 1) p <- p + getScale("fill", majorHeader, majorSize)
  127 + if(minorSize > 1) p <- p + facet_grid(facets=as.formula(paste(minorHeader, "~", "X"))) else p <- p + facet_grid(. ~ X, labeller=far_labeller)
  128 + p <- p + scale_y_continuous(labels=percent) + theme(legend.position="none", axis.text.x=element_text(angle=-90, hjust=0))
  129 + if(!smooth) p <- p + geom_text(data=bcData, aes(label=bcData$Y, y=0.05))
  130 + return(p)
  131 +}
  132 +
  133 +plotERR <- function(errData=NULL) {
  134 + if(flip) {
  135 + if(majorSize > 1) color <- majorHeader
  136 + } else {
  137 + if(minorSize > 1) color <- minorHeader
  138 + }
  139 + p <- qplot(X, Y, data=errData, geom="line", linetype=Error, colour=if(exists("color")) factor(eval(parse(text=color))) else NULL, xlab="Score", ylab="Error Rate") + theme_minimal()
  140 + if(flip) {
  141 + if(majorSize > 1)
  142 + p <- p + getScale("colour", majorHeader, majorSize)
  143 + else if(minorSize > 1)
  144 + p <- p + getScale("colour", minorHeader, minorSize)
  145 + }
  146 + p <- p + scale_y_log10(labels=percent) + annotation_logticks(sides="l")
  147 + if(flip) {
  148 + if(minorSize > 1) {
  149 + facet <- minorHeader
  150 + p <- p + facet_wrap(as.formula(paste("~", facet)), scales="free_x")
  151 + }
  152 + } else {
  153 + if(majorSize >1) {
  154 + facet <- majorHeader
  155 + p <- p + facet_wrap(as.formula(paste("~", facet)), scales="free_x")
  156 + }
  157 + }
  158 + p <- p + theme(aspect.ratio=1)
  159 + return(p)
  160 +}
  161 +
  162 +plotOverlap <- function(overlapData=NULL) {
  163 + p <- qplot(X, data=overlapData, geom="histogram", position="identity", xlab="Overlap", ylab="Frequency")
  164 + p <- p + theme_minimal() + scale_x_continuous(minor_breaks=NULL) + scale_y_continuous(minor_breaks=NULL) + theme(axis.text.y=element_blank(), axis.ticks=element_blank(), axis.text.x=element_text(angle=-90, hjust=0))
  165 + if(majorSize > 1) {
  166 + if(minorSize) {
  167 + p <- p + facet_grid(facets=as.formula(paste(minorHeader, "~", majorHeader)), scales="free")
  168 + } else {
  169 + p <- p + facet_wrap(facets=as.formula(paste("~", majorHeader)), scales="free")
  170 + }
  171 + }
  172 + p <- p + theme(aspect.ratio=1, legend.position="bottom")
  173 + return(p)
  174 +}
  175 +
  176 +formatData <- function(type="eval") {
  177 + if (type == "eval") {
  178 + # Split data into individual plots
  179 + plot_index <<- which(names(data)=="Plot")
  180 + Metadata <<- data[grep("Metadata",data$Plot),-c(1)]
  181 + IM <<- data[grep("IM",data$Plot),-c(1)]
  182 + GM <<- data[grep("GM",data$Plot),-c(1)]
  183 + DET <<- data[grep("DET",data$Plot),-c(1)]
  184 + IET <<- data[grep("IET",data$Plot),-c(1)]
  185 + FAR <- data[grep("FAR",data$Plot),-c(1)]
  186 + FRR <- data[grep("FRR",data$Plot),-c(1)]
  187 + SD <<- data[grep("SD",data$Plot),-c(1)]
  188 + TF <<- data[grep("TF",data$Plot),-c(1)]
  189 + FT <<- data[grep("FT",data$Plot),-c(1)]
  190 + CT <<- data[grep("CT",data$Plot),-c(1)]
  191 + BC <<- data[grep("BC",data$Plot),-c(1)]
  192 + TS <<- data[grep("TS",data$Plot),-c(1)]
  193 + CMC <<- data[grep("CMC",data$Plot),-c(1)]
  194 + FAR$Error <- "FAR"
  195 + FRR$Error <- "FRR"
  196 + ERR <<- rbind(FAR, FRR)
  197 +
  198 + # Format data
  199 + Metadata$Y<-factor(Metadata$Y, levels=c("Genuine", "Impostor", "Ignored", "Gallery", "Probe"))
  200 + IM$Y <<- as.character(IM$Y)
  201 + GM$Y <<- as.character(GM$Y)
  202 + DET$Y <<- as.numeric(as.character(DET$Y))
  203 + IET$Y <<- as.numeric(as.character(IET$Y))
  204 + ERR$Y <<- as.numeric(as.character(ERR$Y))
  205 + SD$Y <<- as.factor(unique(as.character(SD$Y)))
  206 + TF$Y <<- as.numeric(as.character(TF$Y))
  207 + FT$Y <<- as.numeric(as.character(FT$Y))
  208 + CT$Y <<- as.numeric(as.character(CT$Y))
  209 + BC$Y <<- as.numeric(as.character(BC$Y))
  210 + TS$Y <<- as.character(TS$Y)
  211 + CMC$Y <<- as.numeric(as.character(CMC$Y))
  212 + } else if (type == "detection") {
  213 + # Split data into individual plots
  214 + DiscreteROC <<- data[grep("DiscreteROC",data$Plot),-c(1)]
  215 + ContinuousROC <<- data[grep("ContinuousROC",data$Plot),-c(1)]
  216 + DiscretePR <<- data[grep("DiscretePR",data$Plot),-c(1)]
  217 + ContinuousPR <<- data[grep("ContinuousPR",data$Plot),-c(1)]
  218 + Overlap <<- data[grep("Overlap",data$Plot),-c(1)]
  219 + AverageOverlap <<- data[grep("AverageOverlap",data$Plot),-c(1)]
  220 + } else if (type == "landmarking") {
  221 + # Split data into individual plots
  222 + Box <<- data[grep("Box",data$Plot),-c(1)]
  223 + Box$X <<- factor(Box$X, levels = Box$X, ordered = TRUE)
  224 + Sample <<- data[grep("Sample",data$Plot),-c(1)]
  225 + Sample$X <<- as.character(Sample$X)
  226 + EXT <<- data[grep("EXT",data$Plot),-c(1)]
  227 + EXT$X <<- as.character(EXT$X)
  228 + EXP <<- data[grep("EXP",data$Plot),-c(1)]
  229 + EXP$X <<- as.character(EXP$X)
  230 + NormLength <<- data[grep("NormLength",data$Plot),-c(1)]
  231 + sample <<- readImageData(Sample)
  232 + rows <<- sample[[1]]$value
  233 + }
  234 +}
  235 +
  236 +summarySE <- function(data=NULL, measurevar, groupvars=NULL, na.rm=FALSE, conf.interval=0.95, .drop=TRUE) {
  237 + # derived from http://www.cookbook-r.com/Manipulating_data/Summarizing_data/
  238 + require(plyr)
  239 +
  240 + length2 <- function (x, na.rm=FALSE) {
  241 + if (na.rm) sum(!is.na(x))
  242 + else length(x)
  243 + }
  244 +
  245 + datac <- ddply(data, groupvars, .drop=.drop, .fun = function(xx, col) {
  246 + 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))
  247 + },
  248 + measurevar
  249 + )
  250 +
  251 + datac <- rename(datac, c("mean" = measurevar))
  252 + datac$se <- datac$sd / sqrt(datac$N)
  253 + ciMult <- qt(conf.interval/2 + .5, datac$N-1)
  254 + datac$ci <- datac$se * ciMult
  255 +
  256 + datac$upper <- if(datac[, measurevar] + datac$ci < 1) (datac[, measurevar] + datac$ci) else 1
  257 + datac$lower <- if(datac[, measurevar] - datac$ci > 0) (datac[, measurevar] - datac$ci) else 0
  258 +
  259 + return(datac)
  260 +}
  261 +
  262 +multiplot <- function(..., plotlist=NULL, cols) {
  263 + require(grid)
  264 + # Make a list from the ... arguments and plotlist
  265 + plots <- c(list(...), plotlist)
  266 + numPlots = length(plots)
  267 + # Make the panel
  268 + plotCols = cols
  269 + plotRows = ceiling(numPlots/plotCols)
  270 + # Set up the page
  271 + grid.newpage()
  272 + pushViewport(viewport(layout = grid.layout(plotRows, plotCols)))
  273 + vplayout <- function(x, y)
  274 + viewport(layout.pos.row = x, layout.pos.col = y)
  275 + # Make each plot, in the correct location
  276 + for (i in 1:numPlots) {
  277 + curRow = ceiling(i/plotCols)
  278 + curCol = (i-1) %% plotCols + 1
  279 + print(plots[[i]], vp = vplayout(curRow, curCol))
  280 + }
  281 +}
  282 +
  283 +plotEERSamples <- function(imData=NULL, gmData=NULL) {
  284 + if(nrow(imData) == 0) return()
  285 +
  286 + printImages <- function(images, label) {
  287 + for (i in 1:nrow(images)) {
  288 + score <- images[i,1]
  289 + files <- images[i,2]
  290 + alg <- images[i,3]
  291 + files <- unlist(strsplit(files, "[:]"))
  292 +
  293 + ext1 <- unlist(strsplit(files[2], "[.]"))[2]
  294 + ext2 <- unlist(strsplit(files[4], "[.]"))[2]
  295 + if (ext1 == "jpg" || ext1 == "JPEG" || ext1 == "jpeg" || ext1 == "JPG") {
  296 + img1 <- readJPEG(files[2])
  297 + } else if (ext1 == "PNG" || ext1 == "png") {
  298 + img1 <- readPNG(files[2])
  299 + } else if (ext1 == "TIFF" || ext1 == "tiff" || ext1 == "TIF" || ext1 == "tif") {
  300 + img1 <- readTIFF(files[2])
  301 + } else {
  302 + next
  303 + }
  304 + if (ext2 == "jpg" || ext2 == "JPEG" || ext2 == "jpeg" || ext2 == "JPG") {
  305 + img2 <- readJPEG(files[4])
  306 + } else if (ext2 == "PNG" || ext2 == "png") {
  307 + img2 <- readPNG(files[4])
  308 + } else if (ext2 == "TIFF" || ext2 == "tiff" || ext2 == "TIF" || ext2 == "tif") {
  309 + img2 <- readTIFF(files[4])
  310 + } else {
  311 + next
  312 + }
  313 + name1 <- files[1]
  314 + name2 <- files[3]
  315 +
  316 + g1 <- rasterGrob(img1, interpolate=TRUE)
  317 + g2 <- rasterGrob(img2, interpolate=TRUE)
  318 +
  319 + plot1 <- qplot(1:10, 1:10, geom="blank") + annotation_custom(g1, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) + theme(axis.line=element_blank(), axis.text.x=element_blank(), axis.text.y=element_blank(), axis.ticks=element_blank(), panel.background=element_blank()) + labs(title=alg) + ylab(unlist(strsplit(files[2], "[/]"))[length(unlist(strsplit(files[2], "[/]")))]) + xlab(name1)
  320 + plot2 <- qplot(1:10, 1:10, geom="blank") + annotation_custom(g2, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) + theme(axis.line=element_blank(), axis.text.x=element_blank(), axis.text.y=element_blank(), axis.ticks=element_blank(), panel.background=element_blank()) + labs(title=paste(label, " score =", score)) + ylab(unlist(strsplit(files[4], "[/]"))[length(unlist(strsplit(files[4], "[/]")))]) + xlab(name2)
  321 +
  322 + multiplot(plot1, plot2, cols=2)
  323 + }
  324 + }
  325 + printImages(imData, "Impostor")
  326 + printImages(gmData, "Genuine")
  327 +}
  328 +
  329 +plotLandmarkSamples <- function(samples=NULL, expData=NULL, extData=NULL) {
  330 + print(plotImage(samples[[1]], "Sample Landmarks", sprintf("Total Landmarks: %s", samples[[1]]$value)))
  331 + if (nrow(EXT) != 0 && nrow(EXP)) {
  332 + for (j in 1:length(algs)) {
  333 + truthSample <- readData(EXT[EXT$. == algs[[j]],])
  334 + predictedSample <- readData(EXP[EXP$. == algs[[j]],])
  335 + for (i in 1:length(predictedSample)) {
  336 + multiplot(plotImage(predictedSample[[i]], sprintf("%s\nPredicted Landmarks", algs[[j]]), sprintf("Average Landmark Error: %.3f", predictedSample[[i]]$value)), plotImage(truthSample[[i]], "Ground Truth\nLandmarks", ""), cols=2)
  337 + }
  338 + }
  339 + }
  340 +}
  341 +
  342 +readImageData <- function(data) {
  343 + examples <- list()
  344 + for (i in 1:nrow(data)) {
  345 + path <- data[i,1]
  346 + value <- data[i,2]
  347 + file <- unlist(strsplit(path, "[.]"))[1]
  348 + ext <- unlist(strsplit(path, "[.]"))[2]
  349 + if (ext == "jpg" || ext == "JPEG" || ext == "jpeg" || ext == "JPG") {
  350 + img <- readJPEG(path)
  351 + } else if (ext == "PNG" || ext == "png") {
  352 + img <- readPNG(path)
  353 + } else if (ext == "TIFF" || ext == "tiff" || ext == "TIF" || ext == "tif") {
  354 + img <- readTIFF(path)
  355 + }else {
  356 + next
  357 + }
  358 + example <- list(file = file, value = value, image = img)
  359 + examples[[i]] <- example
  360 + }
  361 + return(examples)
  362 +}
  363 +
  364 +plotImage <- function(image, title=NULL, label=NULL) {
  365 + p <- qplot(1:10, 1:10, geom="blank") + annotation_custom(rasterGrob(image$image), xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf)
  366 + p <- p + theme(axis.line=element_blank(), axis.title.y=element_blank(), axis.text.x=element_blank(), axis.text.y=element_blank(), line=element_blank(), axis.ticks=element_blank(), panel.background=element_blank())
  367 + p <- p + labs(title=title) + xlab(label)
  368 + return(p)
  369 +}
  370 +
... ...