00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "omgexperiment.h"
00023 #include "omglocality.h"
00024 #include "omgui.h"
00025 #include "omggraph.h"
00026 #include "omgdataseries.h"
00027 #include <omgversion.h>
00028
00029 #include <QFileInfo>
00030 #include <QDir>
00031 #include <QImage>
00032 #include <QDateTime>
00033 #include <QDomDocument>
00034 #include <QDomElement>
00035 #include <QStringList>
00036 #include <QMap>
00037 #include <QMapIterator>
00038 #include <QMutexLocker>
00039 #include <QPainter>
00040 OmgExperiment::OmgExperiment() : QThread(),
00041 mAbortFlag(false),
00042 mWorkDir(""),
00043 mRunningFlag(false)
00044 {
00045
00046 setGuid();
00047
00048 setName(guid());
00049 }
00050 OmgExperiment::~OmgExperiment()
00051 {
00052
00053 QVectorIterator<OmgModel *> myIterator(mModelVector);
00054 while ( myIterator.hasNext() )
00055 {
00056 OmgModel * mypModel=myIterator.next();
00057 delete mypModel;
00058 }
00059
00060
00061 wait();
00062 }
00063
00064 QString OmgExperiment::name()
00065 {
00066 return mName;
00067 }
00068
00069 void OmgExperiment::setName(QString theName)
00070 {
00071 mName=theName;
00072 }
00073
00074
00075 QString OmgExperiment::description()
00076 {
00077 return mDescription;
00078 }
00079
00080 void OmgExperiment::setDescription(QString theDescription)
00081 {
00082 mDescription=theDescription;
00083 }
00084
00085 QString OmgExperiment::workDir()
00086 {
00087 return mWorkDir;
00088 }
00089
00090 void OmgExperiment::setWorkDir(QString theWorkDir)
00091 {
00092 mWorkDir=theWorkDir;
00093 if (!mWorkDir.endsWith(QDir::separator()))
00094 {
00095 mWorkDir += QDir::separator();
00096 }
00097
00098 QVectorIterator<OmgModel *> myIterator(mModelVector);
00099 while (myIterator.hasNext())
00100 {
00101 OmgModel * mypModel=myIterator.next();
00102 QString mySubDirName = mypModel->algorithm().name();
00103 mySubDirName.replace(" ","_");
00104 mypModel->setWorkDir(mWorkDir + QDir::separator()
00105 + mySubDirName + QDir::separator());
00106 }
00107 }
00108
00109 void OmgExperiment::addModel(OmgModel * thepModel)
00110 {
00111 emit logMessage(tr("Adding model ")
00112 + thepModel->algorithm().name() + " : "
00113 + thepModel->taxonName());
00114
00115 QString mySubDirName = thepModel->algorithm().name();
00116 mySubDirName.replace(" ","_");
00117 thepModel->setWorkDir(mWorkDir + QDir::separator()
00118 + mySubDirName + QDir::separator());
00119 mModelVector.push_back(thepModel);
00120 }
00121
00122 OmgModel * OmgExperiment::getModel(int theModelId)
00123 {
00124 if (theModelId >= 0 && theModelId < mModelVector.count())
00125 {
00126 return mModelVector.at(theModelId);
00127 }
00128 return NULL;
00129 }
00130
00131 OmgModel * OmgExperiment::getModel(QString theGuid)
00132 {
00133 QVectorIterator<OmgModel *> myIterator(mModelVector);
00134 while (myIterator.hasNext())
00135 {
00136 OmgModel * mypModel=myIterator.next();
00137 if (mypModel->guid()==theGuid)
00138 {
00139 return mypModel;
00140 }
00141 }
00142 return NULL;
00143 }
00144
00145 void OmgExperiment::removeModel(QString theGuid)
00146 {
00147 QMutableVectorIterator<OmgModel *> myIterator(mModelVector);
00148 while (myIterator.hasNext())
00149 {
00150 OmgModel * mypModel=myIterator.next();
00151 if (mypModel->guid()==theGuid)
00152 {
00153 delete mypModel;
00154 myIterator.remove();
00155 return ;
00156 }
00157 }
00158 return ;
00159 }
00160 void OmgExperiment::removeAlgorithm(QString theName)
00161 {
00162 QMutableVectorIterator<OmgModel *> myIterator(mModelVector);
00163 while (myIterator.hasNext())
00164 {
00165 OmgModel * mypModel=myIterator.next();
00166 if (mypModel->algorithm().name()==theName)
00167 {
00168 delete mypModel;
00169 myIterator.remove();
00170 }
00171 }
00172 return ;
00173 }
00174 void OmgExperiment::removeTaxon(QString theName)
00175 {
00176 QMutableVectorIterator<OmgModel *> myIterator(mModelVector);
00177 while (myIterator.hasNext())
00178 {
00179 OmgModel * mypModel=myIterator.next();
00180 if (mypModel->taxonName()==theName)
00181 {
00182 delete mypModel;
00183 myIterator.remove();
00184 }
00185 }
00186 return ;
00187 }
00188 void OmgExperiment::run()
00189 {
00190
00191
00192 mAbortFlag=false;
00193 mRunningFlag=true;
00194 emit logMessage(tr("Experiment started"));
00195 mLastPos=0;
00196 int myTotal=count();
00197 emit experimentMaximum(myTotal);
00198
00199 if (mWorkDir.isEmpty())
00200 {
00201 emit logMessage(tr("Experiment working directory not defined explicity, defaulting to:"));
00202 mWorkDir = QDir::convertSeparators(Omgui::getModelOutputDir())
00203 + QDir::separator()
00204 + name()
00205 + QDir::separator();
00206 emit logMessage(mWorkDir);
00207 }
00208
00209 if (!mWorkDir.endsWith(QDir::separator()))
00210 {
00211 mWorkDir += QDir::separator();
00212 }
00213
00214 QDir myWorkDir( mWorkDir );
00215 if (!myWorkDir.exists())
00216 {
00217 emit logMessage(tr("Experiment working directory does not exist...creating"));
00218 QDir myDir(mWorkDir);
00219 if (!myDir.mkdir(mWorkDir))
00220 {
00221 emit logMessage(tr("Experiment failed to create working directory\n") + mWorkDir );
00222 emit experimentProgress(myTotal);
00223 mRunningFlag=false;
00224 emit experimentStopped();
00225 return;
00226 }
00227 else
00228 {
00229 emit logMessage(tr("Experiment created working directory\n") + mWorkDir );
00230 }
00231 }
00232 emit logMessage(tr("Saving before we start experiment"));
00233 save();
00234 emit logMessage(tr("Experiment saved ") + mWorkDir );
00235
00236 QVectorIterator<OmgModel *> myIterator(mModelVector);
00237 while (myIterator.hasNext() && mAbortFlag==false)
00238 {
00239 OmgModel * mypModel=myIterator.next();
00240 if (mypModel==NULL)
00241 {
00242 emit logMessage(tr("Model is null is NULL, skipping"));
00243 continue;
00244 }
00245
00246
00247
00248 if (mypModel->isCompleted())
00249 {
00250 mLastPos++;
00251 emit experimentProgress(mLastPos);
00252 emit logMessage(tr("Model for ") + mypModel->taxonName() + tr(" already exists, skipping to next job."));
00253 continue;
00254 }
00255 OmgAlgorithm myAlgorithm = mypModel->algorithm();
00256
00257 QString mySubDirName = myAlgorithm.name();
00258 mySubDirName.replace(" ","_");
00259 QDir myDir(mWorkDir + mySubDirName);
00260 if (!myDir.exists())
00261 {
00262 emit logMessage(tr("Algorithm working directory does not exist...creating"));
00263 emit logMessage(mWorkDir + mySubDirName);
00264 QDir mySubDir(mWorkDir);
00265 if (!mySubDir.mkdir(mySubDirName))
00266 {
00267 emit logMessage(tr("Experiment failed to create working directory\n") + mWorkDir + mySubDirName);
00268 mRunningFlag=false;
00269 emit experimentStopped();
00270 return;
00271 }
00272 }
00273 mypModel->setWorkDir(mWorkDir + mySubDirName + QDir::separator());
00274
00275 mypModel->setStartDateTimeStamp(QDateTime::currentDateTime());
00276 mCurrentStatus = tr("Creating model definition for ") + mypModel->taxonName();
00277 QString myModelXml = mpModellerPlugin->createModel(mypModel);
00278 emit logMessage(tr("Model has completed:"));
00279 if (mypModel->hasError())
00280 {
00281 emit logMessage(tr("But has an error!"));
00282 mypModel->setCompleted(false);
00283 mypModel->appendToLog(tr("Model failed to complete the model creation stage"));
00284
00285
00286
00287
00288
00289 QString myShapefileName = mypModel->taxonName();
00290 if (mypModel->toShapefile(mypModel->workDir() + myShapefileName + ".shp"))
00291 {
00292 emit logMessage(tr("Creating shapefile as: ") +
00293 QString(myShapefileName + ".shp").toLocal8Bit());
00294 mypModel->setShapefileName(myShapefileName + ".shp");
00295 }
00296 }
00297 else
00298 {
00299 emit logMessage(tr("Without errors"));
00300 emit logMessage(tr("Parsing model"));
00301
00302
00303
00304 mypModel->parseModelResult(myModelXml);
00305 emit logMessage(tr("Model parsed"));
00306
00307
00308
00309
00310 QString myShapefileName = mypModel->taxonName();
00311 if (mypModel->toShapefile(mypModel->workDir() + myShapefileName + ".shp"))
00312 {
00313 emit logMessage(tr("Creating shapefile as: ") +
00314 QString(myShapefileName + ".shp").toLocal8Bit());
00315 mypModel->setShapefileName(myShapefileName + ".shp");
00316 }
00317
00318 if (mAbortFlag)
00319 {
00320 emit logMessage(tr("Saving Experiment"));
00321 save();
00322 mRunningFlag=false;
00323 emit experimentStopped();
00324 return;
00325 }
00326
00327 mCurrentStatus = tr("Projecting model for ") + mypModel->taxonName();
00328 emit logMessage(mCurrentStatus);
00329 mpModellerPlugin->projectModel(mypModel);
00330
00331
00332
00333 mCurrentStatus = tr("Model projection completed for ") + mypModel->taxonName();
00334 if (mypModel->hasError())
00335 {
00336 emit logMessage(tr("Model projection had error!"));
00337 mypModel->setCompleted(false);
00338 mypModel->appendToLog(tr("Model failed to complete the model projection stage"));
00339 }
00340 else
00341 {
00342 emit logMessage(tr("Model projection completed! Post processing..."));
00343 mypModel->postProcess();
00344 }
00345 }
00346
00347 emit logMessage(tr("Saving Experiment"));
00348 save();
00349 emit logMessage(tr("Experiment saved"));
00350 emit logMessage(mypModel->taxonName() + " done");
00351 if (mypModel->isCompleted())
00352 {
00353 emit modelCompleted(mypModel->guid());
00354 }
00355 mLastPos++;
00356
00357
00358 toSummaryHtml(true);
00359 emit experimentProgress(mLastPos);
00360 }
00361 toSummaryHtml(true);
00362
00363 emit experimentProgress(myTotal);
00364 mCurrentStatus = tr("Experiment completed");
00365 emit logMessage(tr("Experiment stopped"));
00366 mRunningFlag=false;
00367 emit experimentStopped();
00368 }
00369
00370 void OmgExperiment::save()
00371 {
00372 Omgui::createTextFile(mWorkDir + QDir::separator() + guid() + ".xml" , toXml());
00373 }
00374
00375 void OmgExperiment::setModellerPlugin(OmgModellerPluginInterface * thePlugin)
00376 {
00377 mpModellerPlugin = thePlugin;
00378 }
00379
00380 int OmgExperiment::count()
00381 {
00382 return mModelVector.count();
00383 }
00384
00385 void OmgExperiment::clear()
00386 {
00387 mModelVector.clear();
00388 }
00389
00390 void OmgExperiment::removeCompleted()
00391 {
00392 int myPos=0;
00393
00394 QVectorIterator<OmgModel *> myIterator(mModelVector);
00395 while (myIterator.hasNext())
00396 {
00397 OmgModel * mypModel=myIterator.next();
00399 if (mypModel->isCompleted())
00400 {
00401 mModelVector.remove(myPos);
00402 delete mypModel;
00403 }
00404 else
00405 {
00406 myPos++;
00407 }
00408 }
00409 }
00410 bool OmgExperiment::isRunning()
00411 {
00412 return mRunningFlag;
00413 }
00414
00415 bool OmgExperiment::isAborted()
00416 {
00417 return mAbortFlag;
00418 }
00419
00420 void OmgExperiment::abort()
00421 {
00422 mAbortFlag=true;
00423 mCurrentStatus = tr("Experiment aborting...");
00424 }
00425
00426 OmgModellerPluginInterface * OmgExperiment::modellerPlugin()
00427 {
00428 return mpModellerPlugin;
00429 }
00430
00431
00432 void OmgExperiment::reset()
00433 {
00434 QVectorIterator<OmgModel *> myIterator(mModelVector);
00435 while (myIterator.hasNext())
00436 {
00437 OmgModel * mypModel = myIterator.next();
00438 mypModel->reset();
00439 }
00440 }
00441
00442 const QString OmgExperiment::toString()
00443 {
00444 QString myString("Experiment details:\n=========================\n\n");
00445
00446 QVectorIterator<OmgModel *> myIterator(mModelVector);
00447 while (myIterator.hasNext())
00448 {
00449 OmgModel * mypModel = myIterator.next();
00450 myString += mypModel->toString();
00451 myString += "\n --- \n";
00452 }
00453 myString += "\n========================\n";
00454 return myString;
00455 }
00456 QString OmgExperiment::toSummaryHtml(bool theForceFlag)
00457 {
00458 bool myShowGraphsFlag = false;
00459 if (mWorkDir.isEmpty())
00460 {
00461 mWorkDir = QDir::convertSeparators(Omgui::getModelOutputDir())
00462 + name();
00463 }
00464
00465 QDir myWorkDir( mWorkDir );
00466 QString myOutputFileName;
00467 if (!myWorkDir.exists())
00468 {
00469 emit logMessage(tr("Working directory does not exist...html not saved"));
00470 emit logMessage("Working dir: " + mWorkDir);
00471 qDebug("Working dir: " + mWorkDir.toLocal8Bit());
00472 return "";
00473 }
00474 else
00475 {
00476 emit logMessage(tr("Saving experiment report as html"));
00477 myOutputFileName = mWorkDir + QDir::separator() + "experiment_report.html";
00478 if (QFile::exists(myOutputFileName) && !theForceFlag)
00479 {
00480
00481
00482 return myOutputFileName;
00483 }
00484 }
00485
00486
00487
00488
00489 QString myReport = Omgui::getHtmlHeader();
00490 myReport += getStatsHtml();
00491 if (myShowGraphsFlag)
00492 {
00493 myReport += getGraphsHtml("",theForceFlag);
00494 }
00495 myReport += Omgui::getHtmlFooter();
00496 Omgui::createTextFile(myOutputFileName , myReport);
00497 return myOutputFileName;
00498 }
00499
00500 QString OmgExperiment::toPrintHtml(bool theForceFlag)
00501 {
00502 bool myShowGraphsFlag = false;
00503
00504
00505
00506 QString myReport = getStatsHtml();
00507 if (myShowGraphsFlag)
00508 {
00509 myReport += getGraphsHtml(mWorkDir + QDir::separator(), theForceFlag);
00510 }
00511 return myReport;
00512 }
00513
00514 QString OmgExperiment::getStatsHtml()
00515 {
00516 int mySuccessCount = 0;
00517 int myFailureCount = 0;
00518 int myNotRunCount = 0;
00519 long myTotalTime = 0;
00520
00521 QMap<QString,double> myAlgorithmSuccessMap;
00522 QMap<QString,double> myRocScoreMap;
00523 QMap<QString,double> myAccuracyMap;
00524 QMap<QString,double> myOmissionMap;
00525 QMap<QString,double> myCommissionMap;
00526 QMap<QString,double> myPercentCellsPresentMap;
00527 QMap<QString,double> myTimeMap;
00528 QVectorIterator<OmgModel *> myIterator(mModelVector);
00529 while (myIterator.hasNext())
00530 {
00531 OmgModel * mypModel = myIterator.next();
00532 if (!mypModel->isCompleted())
00533 {
00534 if (mypModel->hasError())
00535 {
00536 ++myFailureCount;
00537 }
00538 else
00539 {
00540 ++myNotRunCount;
00541 }
00542 }
00543 else
00544 {
00545
00546 if (mypModel->hasError())
00547 {
00548 ++myFailureCount;
00549 }
00550 else
00551 {
00552 ++mySuccessCount;
00553 int myElapsedTime = mypModel->startDateTimeStamp().secsTo(mypModel->endDateTimeStamp());
00554
00555 if (myAccuracyMap.contains(mypModel->algorithm().name()))
00556 {
00557
00558
00559 myAlgorithmSuccessMap[mypModel->algorithm().name()] =
00560 myAlgorithmSuccessMap.value(mypModel->algorithm().name()) + 1;
00561 myRocScoreMap[mypModel->algorithm().name()] =
00562 myRocScoreMap.value(mypModel->algorithm().name()) +
00563 mypModel->rocScore();
00564 myAccuracyMap[mypModel->algorithm().name()] =
00565 myAccuracyMap.value(mypModel->algorithm().name()) +
00566 mypModel->accuracy();
00567 myOmissionMap[mypModel->algorithm().name()] =
00568 myOmissionMap.value(mypModel->algorithm().name()) +
00569 mypModel->omission();
00570 myCommissionMap[mypModel->algorithm().name()] =
00571 myCommissionMap.value(mypModel->algorithm().name()) +
00572 mypModel->commission();
00573 myPercentCellsPresentMap[mypModel->algorithm().name()] =
00574 myPercentCellsPresentMap.value(mypModel->algorithm().name()) +
00575 mypModel->percentCellsPresent();
00576 myTimeMap[mypModel->algorithm().name()] =
00577 myTimeMap.value(mypModel->algorithm().name()) +
00578 myElapsedTime;
00579
00580 myTotalTime += myElapsedTime;
00581 }
00582 else
00583 {
00584
00585
00586 myAlgorithmSuccessMap[mypModel->algorithm().name()] = 1;
00587 myRocScoreMap[mypModel->algorithm().name()] = mypModel->rocScore();
00588 myAccuracyMap[mypModel->algorithm().name()] = mypModel->accuracy();
00589 myOmissionMap[mypModel->algorithm().name()] = mypModel->omission();
00590 myCommissionMap[mypModel->algorithm().name()] = mypModel->commission();
00591 myPercentCellsPresentMap[mypModel->algorithm().name()] =
00592 mypModel->percentCellsPresent();
00593 myTimeMap[mypModel->algorithm().name()] = myElapsedTime;
00594 myTotalTime += myElapsedTime;
00595 }
00596 }
00597 }
00598 }
00599
00600 QString myString;
00601 myString += "<table width=\"100%\">\n";
00602 myString += "<tr>\n";
00603 myString += "<td>\n";
00604 myString += "<p><img src=\":/om_icon_big.png\"></p>";
00605 myString += "</td>\n";
00606 myString += "<td>\n";
00607 myString += "<p align=\"right\">\n";
00608 myString += "<h1>openModeller Desktop</h1>\n";
00609 myString += tr("openModeller is open source software") + "<br />";
00610 myString += "<a href=\"http://openmodeller.sf.net\">http://openmodeller.sf.net</a><br />";
00611 myString += "<h2>" + tr("Experiment Report") + "</h2>\n";
00612 myString += "<h2>" + Omgui::xmlEncode(mName) + "</h2>\n";
00613 myString += "</p>\n";
00614 myString += "</td>\n";
00615 myString += "</tr>\n";
00616 myString += "</table>\n";
00617 myString += "<h3>" +
00618 tr("Description") + "</h3>\n";
00619 myString += "<p>" + Omgui::xmlEncode(mDescription) + "</p>\n";
00620 myString += "<h3 class=\"glossyBlue\">" +
00621 tr("Summary of experiment") + "</h3>\n";
00622 myString += "<table width=\"100%\">\n";
00623 myString += "<tr>\n";
00624 myString += "<td></td>";
00625 myString += "<td><b>" + QObject::tr("Score") + "</b></td>";
00626 myString += "</tr>\n";
00627 myString += "<tr>\n";
00628 myString += "<td>";
00629 myString += "<b>" + tr("Total number of models:") + "</b>";
00630 myString += "</td><td>";
00631 myString += QString::number(mModelVector.size());
00632 myString += "<td>";
00633 myString += "</tr>\n";
00634 myString += "<tr>\n";
00635 myString += "<td>";
00636 myString += "<b>" + tr("Succesfully completed models:") + "</b> ";
00637 myString += "</td><td>";
00638 myString += QString::number(mySuccessCount);
00639 myString += "<td>";
00640 myString += "</tr>\n";
00641 myString += "<tr>\n";
00642 myString += "<td>";
00643 myString += "<b>" + tr("Failed models:") + "</b> ";
00644 myString += "</td><td>";
00645 myString += QString::number(myFailureCount);
00646 myString += "<td>";
00647 myString += "</tr>\n";
00648 myString += "<tr>\n";
00649 myString += "<td>";
00650 myString += "<b>" + tr("Models not started:") + "</b> ";
00651 myString += "</td><td>";
00652 myString += QString::number(myNotRunCount);
00653 myString += "</td>";
00654 myString += "</tr>\n";
00655 myString += "<tr>\n";
00656 myString += "<td>";
00657 myString += "<b>" + tr("Elapsed time for all models (excludes report generation time):") + "</b> ";
00658 myString += "</td><td>";
00659 myString += Omgui::secondsToString <long> (myTotalTime, Omgui::longTimeForm);
00660 myString += "<td>";
00661 myString += "</tr>\n";
00662 myString += "<tr>\n";
00663 myString += "<td>";
00664 myString += "<b>" + tr("Number of failed models:") + "</b> ";
00665 myString += "</td><td>";
00666 myString += QString::number(myFailureCount);
00667 myString += "<td>";
00668 myString += "</tr>\n";
00669 myString += "</table>\n";
00670
00671
00672
00673 myString += "<h3 class=\"glossyBlue\">" + tr("Algorithm Scores") + "</h3>\n";
00674 myString += "<p><table width=\"100%\">\n";
00675 myString += "<tr>\n";
00676 myString += "<td><b>" + QObject::tr("Algorithm") + "</b></td>";
00677 myString += "<td><b>" + QObject::tr("Avg. AUC") + "</b></td>";
00678 myString += "<td><b>" + QObject::tr("Avg. Accuracy") + "</b></td>";
00679 myString += "<td><b>" + QObject::tr("Avg. Omission") + "</b></td>";
00680 myString += "<td><b>" + QObject::tr("Avg. Commission") + "</b></td>";
00681 myString += "<td><b>" + QObject::tr("Avg. Time") + "</b></td>";
00682 myString += "</tr>\n";
00683 QStringList myKeys = static_cast<QStringList> (myAccuracyMap.keys());
00684 QStringListIterator myListIterator(myKeys);
00685 while (myListIterator.hasNext())
00686 {
00687 QString myKey = myListIterator.next();
00688 myString += "<tr>\n";
00689 myString += "<td>" + myKey + "</td>";
00690 double myAverageRocScore = myRocScoreMap.value(myKey) / myAlgorithmSuccessMap.value(myKey);
00691 myString += "<td>" + QString::number(myAverageRocScore,'f',3) + "</td>";
00692 double myAverageAccuracy = myAccuracyMap.value(myKey) / myAlgorithmSuccessMap.value(myKey);
00693 myString += "<td>" + QString::number(myAverageAccuracy,'f',3) + "%</td>";
00694 double myAverageOmission = myOmissionMap.value(myKey) / myAlgorithmSuccessMap.value(myKey);
00695 myString += "<td>" + QString::number(myAverageOmission,'f',3) + "%</td>";
00696 double myAverageCommission = myCommissionMap.value(myKey) / myAlgorithmSuccessMap.value(myKey);
00697 if (myAverageCommission < 0)
00698 {
00699 myString += "<td> n/a </td>";
00700 }
00701 else
00702 {
00703 myString += "<td>" + QString::number(myAverageCommission,'f',3) + "%</td>";
00704 }
00705 long myAverageDuration = static_cast<long> (myTimeMap.value(myKey) / myAlgorithmSuccessMap.value(myKey));
00706 myString += "<td>" + Omgui::secondsToString (myAverageDuration,Omgui::shortTimeForm) + "</td>";
00707 myString += "</tr>\n";
00708 }
00709 myString += "</table>\n";
00710 myString += "</p>\n";
00711 return myString;
00712 }
00713
00714 QString OmgExperiment::getGraphsHtml(QString theImagePrefix , bool theForceFlag )
00715 {
00716 if (theForceFlag)
00717 {
00718 makeAlgorithmSummaryGraphs( mWorkDir );
00719 }
00720 QString myString = "<table width=\"100%\">";
00721 myString += "<tr><td>";
00722 myString += "<h3>" + tr("Roc Score Summary") + "</h3>";
00723 myString += "</td><td>";
00724 myString += "<h3>" + tr("Accuracy Summary") + "</h3>";
00725 myString += "</td></tr>";
00726
00727 myString += "<tr><td>";
00728 myString += "</td><td>";
00729 myString += "</td></tr>";
00730
00731 myString += "<tr><td>";
00732 myString += "<img src=\"" + theImagePrefix + "roc.png\">";
00733 myString += "</td><td>";
00734 myString += "<img src=\"" + theImagePrefix + "accuracy.png\">";
00735 myString += "</td></tr>";
00736 myString += "<tr><td>";
00737 myString += "<h3>" + tr("Omission Summary") + "</h3>";
00738 myString += "</td><td>";
00739 myString += "<h3>" + tr("Commission Summary") + "</h3>";
00740 myString += "</td></tr>";
00741
00742 myString += "<tr><td>";
00743 myString += "</td><td>";
00744 myString += "</td></tr>";
00745
00746 myString += "<tr><td>";
00747 myString += "<img src=\"" + theImagePrefix + "omission.png\">";
00748 myString += "</td><td>";
00749 myString += "<img src=\"" + theImagePrefix + "commission.png\">";
00750 myString += "</td></tr>";
00751 myString += "<tr><td>";
00752 myString += "<h3>" + tr("Percent Cells Present Summary") + "</h3>";
00753 myString += "</td><td>";
00754 myString += "<h3>" + tr("Run Time Summary") + "</h3>";
00755 myString += "</td></tr>";
00756
00757 myString += "<tr><td>";
00758 myString += "</td><td>";
00759 myString += "</td></tr>";
00760
00761 myString += "<tr><td>";
00762 myString += "<img src=\"" + theImagePrefix + "cellspresent.png\">";
00763 myString += "</td><td>";
00764 myString += "<img src=\"" + theImagePrefix + "time.png\"></p>";
00765 myString += "</td></tr>";
00766 myString += "</table>";
00767 return myString;
00768 }
00769
00770 QString OmgExperiment::toAlgorithmSummaryHtml(QString theAlgorithmName,bool theForceFlag)
00771 {
00772 QString myWorkDirName = QDir::convertSeparators(Omgui::getModelOutputDir())
00773 + QDir::separator()
00774 + name()
00775 + QDir::separator()
00776 + theAlgorithmName.replace(" ","_")
00777 + QDir::separator();
00778 QString myString = "<table>\n";
00779 unsigned int myColumns=4;
00780 unsigned int myCurrentColumn=1;
00781
00782
00783 QVectorIterator<OmgModel *> myIterator(mModelVector);
00784 while (myIterator.hasNext())
00785 {
00786 OmgModel * mypModel = myIterator.next();
00787 QString myName = mypModel->algorithm().name().replace(" ","_");;
00788
00789
00790
00791 if (myName != theAlgorithmName)
00792 {
00793 continue;
00794 }
00795 if (myCurrentColumn == 1)
00796 {
00797 myString += "<tr>\n";
00798 }
00799 myString += "<td><img src=\"" + myWorkDirName +
00800 mypModel->thumbnailFileName()+ "\"/></td>\n";
00801 if (myCurrentColumn >= myColumns)
00802 {
00803 myString += "</tr>\n";
00804 myCurrentColumn=0;
00805 }
00806 ++myCurrentColumn;
00807 }
00808 myString += "</table>\n";
00809
00810 return myString;
00811 }
00812 QString OmgExperiment::toTaxonSummaryHtml(QString theTaxonName,bool theForceFlag)
00813 {
00814 QString myWorkDirName = QDir::convertSeparators(Omgui::getModelOutputDir())
00815 + QDir::separator()
00816 + name()
00817 + QDir::separator();
00818 QString myString = "<table>\n";
00819 unsigned int myColumns=4;
00820 unsigned int myCurrentColumn=1;
00821
00822
00823 QVectorIterator<OmgModel *> myIterator(mModelVector);
00824 while (myIterator.hasNext())
00825 {
00826 OmgModel * mypModel = myIterator.next();
00827 QString myName = mypModel->taxonName();
00828
00829
00830
00831 if (myName != theTaxonName)
00832 {
00833 continue;
00834 }
00835 if (myCurrentColumn == 1)
00836 {
00837 myString += "<tr>\n";
00838 }
00839 QString myFullThumbnailName = myWorkDirName +
00840 mypModel->algorithm().name().replace(" ","_") +
00841 QDir::separator() + mypModel->thumbnailFileName();
00842 QFileInfo myFileInfo(myFullThumbnailName);
00843 if (!myFileInfo.exists())
00844 {
00845 continue;
00846 }
00847 myString += "<td><img src=\"" + myFullThumbnailName + "\"/></td>\n";
00848 if (myCurrentColumn >= myColumns)
00849 {
00850 myString += "</tr>\n";
00851 myCurrentColumn=0;
00852 }
00853 ++myCurrentColumn;
00854 }
00855 myString += "</table>\n";
00856
00857 return myString;
00858 }
00859
00860
00861 QString OmgExperiment::toXml() const
00862 {
00863 QString myOmgVersion =
00864 QString::number(OMGMAJORVERSION) +
00865 QString::number(OMGMINORVERSION) +
00866 QString::number(OMGRELEASEVERSION);
00867 QString myString("<Experiment Guid=\"" + guid() + "\" Name=\"" + Omgui::xmlEncode(mName) + "\""
00868 + " Description=\"" + Omgui::xmlEncode(mDescription) + "\""
00869 + " openModellerDesktopVersion=\"" + myOmgVersion + "\">\n");
00870 myString+=QString(" <Models>\n");
00871 QVectorIterator<OmgModel *> myIterator(mModelVector);
00872 while (myIterator.hasNext())
00873 {
00874 OmgModel * mypModel = myIterator.next();
00875 myString += mypModel->toXml()+"\n";
00876 }
00877 myString+=QString(" </Models>\n");
00878 myString+=QString("</Experiment>\n");
00879 return myString;
00880 }
00881 bool OmgExperiment::fromXml(const QString theXml)
00882 {
00883 QDomDocument myDocument("mydocument");
00884 myDocument.setContent(theXml);
00885 QDomElement myRootElement = myDocument.firstChildElement("Experiment");
00886 if (myRootElement.isNull())
00887 {
00888
00889
00890 return false;
00891 }
00892 mName = Omgui::xmlDecode(myRootElement.attribute("Name"));
00893 mDescription = Omgui::xmlDecode(myRootElement.attribute("Description"));
00894 setGuid( myRootElement.attribute("Guid") );
00895
00896 QDomElement myModelsElement= myRootElement.firstChildElement("Models");
00897
00898 QDomElement myModelElement= myModelsElement.firstChildElement("Model");
00899 while(!myModelElement.isNull())
00900 {
00901
00902 if (myModelElement.tagName()!="Model")
00903 {
00904
00905
00906
00907 myModelElement = myModelElement.nextSiblingElement();
00908 continue;
00909 }
00910 OmgModel * mypModel = new OmgModel();
00911
00912 QDomDocument myModelDoc("model");
00913
00914
00915
00916
00917 QDomElement myCopy = myModelElement.cloneNode().toElement();
00918 myModelDoc.appendChild(myCopy);
00919 QString myXml = myModelDoc.toString();
00920
00921 if (mypModel->fromXml(myXml))
00922 {
00923 addModel(mypModel);
00924 }
00925
00926
00927
00928 myModelElement = myModelElement.nextSiblingElement();
00929 }
00930 return true;
00931 }
00932
00933 void OmgExperiment::makeAlgorithmSummaryGraphs(QString theWorkDir)
00934 {
00935
00936
00937
00938
00939
00940
00941 QMap<QString,QList <double> > myRocScoreMap;
00942 QMap<QString,QList <double> > myAccuracyMap;
00943 QMap<QString,QList <double> > myOmissionMap;
00944 QMap<QString,QList <double> > myCommissionMap;
00945 QMap<QString,QList <double> > myPercentCellsPresentMap;
00946 QMap<QString,QList <double> > myTimeMap;
00947
00948 QVectorIterator<OmgModel *> myIterator(mModelVector);
00949 while (myIterator.hasNext())
00950 {
00951 OmgModel * mypModel = myIterator.next();
00952 QString myName = mypModel->algorithm().name();
00953
00954 addValueToSummaryGraph(myRocScoreMap,myName,mypModel->rocScore());
00955 addValueToSummaryGraph(myAccuracyMap,myName,mypModel->accuracy());
00956 addValueToSummaryGraph(myOmissionMap,myName,mypModel->omission());
00957 addValueToSummaryGraph(myCommissionMap,myName,mypModel->commission());
00958 addValueToSummaryGraph(myPercentCellsPresentMap,myName,mypModel->percentCellsPresent());
00959 int myElapsedTime = mypModel->startDateTimeStamp().secsTo(mypModel->endDateTimeStamp());
00960 addValueToSummaryGraph(myTimeMap,myName,myElapsedTime);
00961 }
00962
00963
00964
00965
00966 summaryMapToGraph( myRocScoreMap, theWorkDir, "roc" );
00967 summaryMapToGraph( myAccuracyMap, theWorkDir, "accuracy" );
00968 summaryMapToGraph( myOmissionMap, theWorkDir, "omission" );
00969 summaryMapToGraph( myCommissionMap, theWorkDir, "commission" );
00970 summaryMapToGraph( myPercentCellsPresentMap, theWorkDir, "cellspresent" );
00971 summaryMapToGraph( myTimeMap, theWorkDir, "time" );
00972 }
00973 void OmgExperiment::addValueToSummaryGraph(
00974
00975 QMap<QString,QList <double> > & theMap,
00976 QString theAlgorithmName,
00977 double theValue)
00978 {
00979 if (!theMap.contains(theAlgorithmName))
00980 {
00981 QList <double> myList;
00982
00983
00984
00985
00986
00987 myList << theValue;
00988 theMap[theAlgorithmName] = myList;
00989 }
00990 else
00991 {
00992 QList <double> myList =
00993 theMap[theAlgorithmName];
00994
00995
00996
00997
00998
00999 myList << theValue;
01000 theMap[theAlgorithmName] = myList;
01001 }
01002 }
01003
01004 void OmgExperiment::summaryMapToGraph( QMap<QString,QList <double> > &theMap,
01005 QString theWorkDir, QString theImageSuffix )
01006 {
01007
01008
01009 QImage myImage(350,350,QImage::Format_ARGB32);
01010 myImage.fill(Qt::white);
01011 QPainter myPainter(&myImage);
01012 OmgGraph myGraph(&myPainter);
01013 int myCount=0;
01014 QMapIterator<QString,QList <double> > myIterator(theMap);
01015 while (myIterator.hasNext())
01016 {
01017 myIterator.next();
01018
01019 QString myName = myIterator.key();
01020 QList <double> myList = myIterator.value();
01021 OmgDataSeries mySeries;
01022 mySeries.setLabel( myName );
01023 mySeries.setYValuesList( myList );
01024
01025
01026 switch (myCount)
01027 {
01028 case 0: mySeries.setFillColor(Qt::red);
01029 break;
01030 case 1: mySeries.setFillColor(Qt::green);
01031 break;
01032 case 2: mySeries.setFillColor(Qt::blue);
01033 break;
01034 case 3: mySeries.setFillColor(Qt::darkMagenta);
01035 break;
01036 case 4: mySeries.setFillColor(Qt::yellow);
01037 break;
01038 case 5: mySeries.setFillColor(Qt::darkRed);
01039 break;
01040 case 6: mySeries.setFillColor(Qt::darkCyan);
01041 break;
01042 case 7: mySeries.setFillColor(Qt::darkGray);
01043 break;
01044 case 8: mySeries.setFillColor(Qt::magenta);
01045 break;
01046 default: mySeries.setFillColor(Omgui::randomColour());
01047 }
01048 mySeries.setLineColor(mySeries.fillColor().lighter());
01049 myGraph.addSeries( mySeries );
01050 ++myCount;
01051 }
01052 myGraph.setVertexLabelsEnabled(false);
01053 myGraph.setGridLinesEnabled(true);
01054 myGraph.setAreaFillEnabled(false);
01055 myGraph.clear();
01056 myGraph.render();
01057 myImage.save( theWorkDir + QDir::separator() + theImageSuffix + ".png");
01058 }