//Copyright 2017 Ryan Wick //This file is part of Bandage //Bandage is free software: you can redistribute it and/or modify //it under the terms of the GNU General Public License as published by //the Free Software Foundation, either version 3 of the License, or //(at your option) any later version. //Bandage is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //GNU General Public License for more details. //You should have received a copy of the GNU General Public License //along with Bandage. If not, see . #include "blasthit.h" #include "../graph/debruijnnode.h" #include "blastquery.h" #include "../program/settings.h" #include "../program/globals.h" #include BlastHit::BlastHit(BlastQuery * query, DeBruijnNode * node, double percentIdentity, int alignmentLength, int numberMismatches, int numberGapOpens, int queryStart, int queryEnd, int nodeStart, int nodeEnd, SciNot eValue, double bitScore) : m_query(query), m_node(node), m_percentIdentity(percentIdentity), m_alignmentLength(alignmentLength), m_numberMismatches(numberMismatches), m_numberGapOpens(numberGapOpens), m_queryStart(queryStart), m_queryEnd(queryEnd), m_nodeStart(nodeStart), m_nodeEnd(nodeEnd), m_eValue(eValue), m_bitScore(bitScore) { int nodeLength = m_node->getLength(); int queryLength = m_query->getLength(); m_nodeStartFraction = double(nodeStart - 1) / nodeLength; m_nodeEndFraction = double(nodeEnd) / nodeLength; m_queryStartFraction = double(queryStart - 1) / queryLength; m_queryEndFraction = double(queryEnd) / queryLength; } std::vector BlastHit::getBlastHitParts(bool reverse, double scaledNodeLength) { std::vector returnVector; //If the colour scheme is Blast rainbow, then this function generates lots //of BlastHitParts - each small and with a different colour of the rainbow. if (g_settings->nodeColourScheme == BLAST_HITS_RAINBOW_COLOUR) { double scaledHitLength = (m_nodeEndFraction - m_nodeStartFraction) * scaledNodeLength; int partCount = ceil(g_settings->blastRainbowPartsPerQuery * fabs(m_queryStartFraction - m_queryEndFraction)); //If there are way more parts than the scaled hit length, that means //that a single part will be much less than a pixel in length. This //isn't desirable, so reduce the partCount in these cases. if (partCount > scaledHitLength * 2.0) partCount = int(scaledHitLength * 2.0); double nodeSpacing = (m_nodeEndFraction - m_nodeStartFraction) / partCount; double querySpacing = (m_queryEndFraction - m_queryStartFraction) / partCount; double nodeFraction = m_nodeStartFraction; double queryFraction = m_queryStartFraction; for (int i = 0; i < partCount; ++i) { QColor dotColour; dotColour.setHsvF(queryFraction * 0.9, 1.0, 1.0); //times 0.9 to keep the colour from getting too close to red, as that could confuse the end with the start double nextFraction = nodeFraction + nodeSpacing; if (reverse) returnVector.push_back(BlastHitPart(dotColour, 1.0 - nodeFraction, 1.0 - nextFraction)); else returnVector.push_back(BlastHitPart(dotColour, nodeFraction, nextFraction)); nodeFraction = nextFraction; queryFraction += querySpacing; } } //If the colour scheme is Blast solid, then this function generates only one //BlastHitPart with a colour dependent on the Blast query. else { if (reverse) returnVector.push_back(BlastHitPart(m_query->getColour(), 1.0 - m_nodeStartFraction, 1.0 - m_nodeEndFraction)); else returnVector.push_back(BlastHitPart(m_query->getColour(), m_nodeStartFraction, m_nodeEndFraction)); } return returnVector; } bool BlastHit::compareTwoBlastHitPointers(BlastHit * a, BlastHit * b) { return a->m_queryStart < b->m_queryStart; } double BlastHit::getQueryCoverageFraction() { int queryRegionSize = m_queryEnd - m_queryStart + 1; int queryLength = m_query->getLength(); if (queryLength == 0) return 0.0; else return double(queryRegionSize) / queryLength; } GraphLocation BlastHit::getHitStart() const { return GraphLocation(m_node, m_nodeStart); } GraphLocation BlastHit::getHitEnd() const { return GraphLocation(m_node, m_nodeEnd); } //This function returns the node sequence for this hit. QByteArray BlastHit::getNodeSequence() const { int nodeSequenceLength = m_nodeEnd - m_nodeStart + 1; return m_node->getSequence().mid(m_nodeStart-1, nodeSequenceLength); }