//This function is used for sorting the paths for a query from best to worst. //it uses < to mean 'better than'. bool BlastQueryPath::operator<(BlastQueryPath const &other) const { //First we compare using the E-value product. This seems to value stronger //hits as well as paths with fewer, longer hits. SciNot aEValueProduct = getEvalueProduct(); SciNot bEValueProduct = other.getEvalueProduct(); if (aEValueProduct != bEValueProduct) return aEValueProduct < bEValueProduct; //If the code got here, then the two paths have the same e-value product, //possibly because they contain the same hits, or possibly because they both //contain hits so strong as to have an e-value of zero. //Now we compare using mean percent identity. double aMeanPercIdentity = getMeanHitPercIdentity(); double bMeanPercIdentity = other.getMeanHitPercIdentity(); if (aMeanPercIdentity != bMeanPercIdentity) return aMeanPercIdentity > bMeanPercIdentity; //Now we use the absolute value of the length discrepancy. double aLengthDiscrepancy = fabs(getRelativeLengthDiscrepancy()); double bLengthDiscrepancy = fabs(other.getRelativeLengthDiscrepancy()); if (aLengthDiscrepancy != bLengthDiscrepancy) return aLengthDiscrepancy < bLengthDiscrepancy; //Now we use fraction of query covered by hits. double aHitsQueryCoverage = getHitsQueryCoverage(); double bHitsQueryCoverage = other.getHitsQueryCoverage(); if (aHitsQueryCoverage != bHitsQueryCoverage) return aHitsQueryCoverage > bHitsQueryCoverage; return false; }
QueryPathsDialog::QueryPathsDialog(QWidget * parent, BlastQuery * query) : QDialog(parent), ui(new Ui::QueryPathsDialog) { ui->setupUi(this); setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); connect(this, SIGNAL(rejected()), this, SLOT(hidden())); connect(ui->tableWidget, SIGNAL(itemSelectionChanged()), this, SLOT(tableSelectionChanged())); g_memory->queryPathDialogIsVisible = true; g_memory->queryPaths.clear(); ui->tableWidget->setHorizontalHeaderLabels(QStringList() << "Path" << "Length\n(bp)" << "Query\ncovered\nby path" << "Query\ncovered\nby hits" << "Mean hit\nidentity" << "Total\nhit mis-\nmatches" << "Total\nhit gap\nopens" << "Length\ndiscre-\npancy" << "E-value\nproduct"); QString queryDescription = "Query name: " + query->getName(); queryDescription += " type: " + query->getTypeString(); queryDescription += " length: " + formatIntForDisplay(query->getLength()); if (query->getSequenceType() == PROTEIN) queryDescription += " (" + formatIntForDisplay(3 * query->getLength()) + " bp)"; else queryDescription += " bp"; ui->queryLabel->setText(queryDescription); ui->tableWidget->clearContents(); ui->tableWidget->setSortingEnabled(false); int pathCount = query->getPathCount(); ui->tableWidget->setRowCount(pathCount); if (pathCount == 0) return; QList<BlastQueryPath> paths = query->getPaths(); for (int i = 0; i < pathCount; ++i) { BlastQueryPath * queryPath = &paths[i]; QTableWidgetItem * pathString = new QTableWidgetItem(queryPath->getPath().getString(true)); pathString->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); int length = queryPath->getPath().getLength(); TableWidgetItemInt * pathLength = new TableWidgetItemInt(formatIntForDisplay(length), length); pathLength->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); double queryCoveragePath = queryPath->getPathQueryCoverage(); TableWidgetItemDouble * pathQueryCoveragePath = new TableWidgetItemDouble(formatDoubleForDisplay(100.0 * queryCoveragePath, 2) + "%", queryCoveragePath); pathQueryCoveragePath->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); pathLength->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); double queryCoverageHits = queryPath->getHitsQueryCoverage(); TableWidgetItemDouble * pathQueryCoverageHits = new TableWidgetItemDouble(formatDoubleForDisplay(100.0 * queryCoverageHits, 2) + "%", queryCoverageHits); pathQueryCoverageHits->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); double percIdentity = queryPath->getMeanHitPercIdentity(); TableWidgetItemDouble * pathPercIdentity = new TableWidgetItemDouble(formatDoubleForDisplay(percIdentity, 2) + "%", percIdentity); pathPercIdentity->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); int mismatches = queryPath->getTotalHitMismatches(); TableWidgetItemInt * pathMismatches = new TableWidgetItemInt(formatIntForDisplay(mismatches), mismatches); pathMismatches->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); int gapOpens = queryPath->getTotalHitGapOpens(); TableWidgetItemInt * pathGapOpens = new TableWidgetItemInt(formatIntForDisplay(gapOpens), gapOpens); pathGapOpens->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); double lengthDisc = queryPath->getRelativeLengthDiscrepancy(); QString lengthDiscSign = ""; if (lengthDisc > 0.0) lengthDiscSign = "+"; TableWidgetItemDouble * pathLengthDisc = new TableWidgetItemDouble(lengthDiscSign + formatDoubleForDisplay(100.0 * lengthDisc, 2) + "%", lengthDisc); pathLengthDisc->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); double evalueProduct = queryPath->getEvalueProduct(); TableWidgetItemDouble * pathEvalueProduct = new TableWidgetItemDouble(QString::number(evalueProduct), evalueProduct); pathEvalueProduct->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); ui->tableWidget->setItem(i, 0, pathString); ui->tableWidget->setItem(i, 1, pathLength); ui->tableWidget->setItem(i, 2, pathQueryCoveragePath); ui->tableWidget->setItem(i, 3, pathQueryCoverageHits); ui->tableWidget->setItem(i, 4, pathPercIdentity); ui->tableWidget->setItem(i, 5, pathMismatches); ui->tableWidget->setItem(i, 6, pathGapOpens); ui->tableWidget->setItem(i, 7, pathLengthDisc); ui->tableWidget->setItem(i, 8, pathEvalueProduct); } ui->tableWidget->resizeColumns(); ui->tableWidget->setSortingEnabled(true); ui->queryPathsInfoText->setInfoText("This table shows information about the possible paths through the graph which " "represent the query. These paths can be either simple (residing within a single " "node) or complex (spanning multiple nodes). The columns in the table are as " "follows:" "<br><br>" "<b>Path</b>: This is the query path through the graph, as written in Bandage's " "path notation. The nodes in the path are separated by commas. The start position " "in the first node is shown in parentheses at the beginning of the path. The end " "position in the last node is shown in parentheses at the end of the path." "<br><br>" "<b>Length</b>: This is the path length. It is shown in base pairs, whether the " "query is a nucleotide query or a protein query." "<br><br>" "<b>Query covered by path</b>: This is the fraction of the query which is covered " "by the path. It is calculated by taking 100% and subtracting the fraction of the " "query which is not captured by the start and the fraction of the query which is " "not captured by the end." "<br><br>" "<b>Query covered by hits</b>: This is the fraction of the query which is covered " "by the BLAST hits in this path. Since a path may contain nodes or parts of nodes which " "are not covered by BLAST hits, this value will be less than or equal to the 'Query " "covered by path' value." "<br><br>" "<b>Mean hit identity</b>: This is the mean of the percent identity for the BLAST " "hits in this path, weighted by the hits' lengths." "<br><br>" "<b>Total hit mismatches</b>: This is the sum of the mismatches for the BLAST hits " "in this path." "<br><br>" "<b>Total hit gap opens</b>: This is the sum of the gap opens for the BLAST hits " "in this path." "<br><br>" "<b>Length discrepancy</b>: This is the percent difference in the path length and " "the appropriate length for the relecant fraction of the query. A positive value " "indicates that the path is too long; a negative value indicates that the path is " "too short." "<br><br>" "<b>E-value product</b>: This is the product of the e-values for the BLAST hits " "in this path."); }