Logo Search packages:      
Sourcecode: ugene version File versions

ChromatogramView.cpp

/*****************************************************************
* Unipro UGENE - Integrated Bioinformatics Suite
* Copyright (C) 2008 Unipro, Russia (http://ugene.unipro.ru)
* All Rights Reserved
* 
*     This source code is distributed under the terms of the
*     GNU General Public License. See the files COPYING and LICENSE
*     for details.
*****************************************************************/

#include "ChromatogramView.h"

#include <core_api/GObject.h>
#include <core_api/MainWindow.h>
#include <core_api/AppContext.h>
#include <core_api/DocumentModel.h>
#include <core_api/DNAAlphabet.h>
#include <core_api/ProjectModel.h>
#include <core_api/IOAdapter.h>
#include <core_api/Log.h>
#include <core_api/Task.h>

#include <datatype/DNAChromatogram.h>

#include <gobjects/DNASequenceObject.h>
#include <gobjects/GObjectTypes.h>
#include <gobjects/DNAChromatogramObject.h>

#include <selection/DNASequenceSelection.h>

#include <util_ov_annotated_dna/ADVConstants.h>
#include <util_ov_annotated_dna/ADVSequenceObjectContext.h>
#include <util_ov_annotated_dna/AnnotatedDNAView.h>

#include <util_gui/GScrollBar.h>
#include <util_gui/GUIUtils.h>
#include <util_gui/AddNewDocumentDialogImpl.h>
#include <util_gui/ProjectTreeController.h>
#include <util_gui/ProjectTreeItemSelectorDialog.h>


namespace GB2 {

ChromatogramView::ChromatogramView(QWidget* p, ADVSequenceObjectContext* v, GSequenceLineView* cv, const DNAChromatogram& chroma) 
: GSequenceLineView(p, v), editDNASeq(NULL)
{

    renderArea = new ChromatogramViewRenderArea(this, chroma);

    scaleBar = new QSlider(Qt::Vertical);
    scaleBar->setRange(100,2000);
    scaleBar->setTickPosition(QSlider::TicksLeft);
    scaleBar->setTickInterval(100);
    connect(scaleBar,SIGNAL(valueChanged(int)),SLOT(setRenderAreaHeight(int)));
    scaleBar->setValue(200);//renderArea->height()-heightAreaBC in construct renderarea to def height

    ra = (ChromatogramViewRenderArea *) renderArea;
    scaleBar->setValue(ra->height()-ra->getHeightAreaBC()+ra->addUpIfQVL);

    minusButton = new QToolButton();
    //icon
    minusButton->setText(QString(tr("-")));
    minusButton->setIcon(QIcon(":core/images/minus.png"));
    minusButton->setFixedSize(20,20);
    minusButton->setAutoRepeat(true);
    minusButton->setAutoRepeatInterval(20);
    plusButton = new QToolButton();
    //icon
    plusButton->setText(QString(tr("+")));
    plusButton->setIcon(QIcon(":core/images/plus.png"));
    plusButton->setAutoRepeat(true);
    plusButton->setAutoRepeatInterval(20);
    plusButton->setFixedSize(20,20);
    connect(minusButton,SIGNAL(clicked()),SLOT(sl_minusButtonClicked()));
    connect(plusButton,SIGNAL(clicked()),SLOT(sl_plusButtonClicked()));

    setConherentRangeView(cv);
    
    mP = new QMenu(this);

    mP->addAction(QString("A"));
    mP->addAction(QString("C"));
    mP->addAction(QString("G"));
    mP->addAction(QString("T"));
    mP->addAction(QString("N"));
    connect(mP, SIGNAL(triggered(QAction*)),SLOT(sl_onPopupMenuCkicked(QAction*))); 


    addNewSeqAction = new QAction(tr("add_new_seq"), this);
    connect(addNewSeqAction, SIGNAL(triggered()), SLOT(sl_addNewSequenceObject()));

    addExistSeqAction = new QAction(tr("add_exist_seq"),this);
    connect(addExistSeqAction, SIGNAL(triggered()), SLOT(sl_onAddExistingSequenceObject()));

    clearEditableSequence = new QAction(tr("remove_editable_sequence"),this);
    connect(clearEditableSequence, SIGNAL(triggered()), SLOT(sl_clearEditableSequence()));

    removeChanges = new QAction(tr("remove_changes"),this);
    connect(removeChanges, SIGNAL(triggered()), SLOT(sl_removeChanges()));

    connect(ctx->getAnnotatedDNAView(), SIGNAL(si_objectRemoved(GObjectView*, GObject*)), SLOT(sl_onObjectRemoved(GObjectView*, GObject*)));
    pack();
}

void ChromatogramView::pack() {

    assert(layout() == NULL);
    //layout
    QVBoxLayout *zoomLayout = new QVBoxLayout();
    zoomLayout->addWidget(plusButton);
    zoomLayout->addWidget(scaleBar);
    zoomLayout->addWidget(minusButton);
    zoomLayout->setMargin(0);
    zoomLayout->setSpacing(0);

    QHBoxLayout *layout = new QHBoxLayout();
    layout->setMargin(0);
    layout->addWidget(renderArea);
    layout->addLayout(zoomLayout);
    setLayout(layout);

    scrollBar->setHidden(true); //todo: support mode without scrollbar at all??

    setFixedHeight(renderArea->height());
}


void ChromatogramView::setRenderAreaHeight(int k)
{
    //k = chromaMax
    ChromatogramViewRenderArea* cvra = (ChromatogramViewRenderArea*) renderArea;
    cvra->setAreaHeight(k);
    addUpdateFlags(GSLV_UF_NeedCompleteRedraw);    
    update();
}

#define SCALEBAR_DIFF 5
void ChromatogramView::sl_minusButtonClicked() {
    scaleBar->setValue(scaleBar->value()-SCALEBAR_DIFF);
}

void ChromatogramView::sl_plusButtonClicked() {
    scaleBar->setValue(scaleBar->value()+SCALEBAR_DIFF);
}

void ChromatogramView::buildPopupMenu(QMenu& m) {
    QPoint cpos = renderArea->mapFromGlobal(QCursor::pos());
    if (!renderArea->rect().contains(cpos)) {
        return;
    }
    //todo: move to submenus?
    QAction* before = GUIUtils::findActionAfter(m.actions(), ADV_MENU_ZOOM);

    m.insertSeparator(before);
    if (editDNASeq != NULL) {
        m.insertAction(before, clearEditableSequence);
        m.insertAction(before, removeChanges);
    } else {
        m.insertAction(before, addNewSeqAction);
        m.insertAction(before, addExistSeqAction);
    }
    m.insertSeparator(before);

}

void ChromatogramView::mousePressEvent(QMouseEvent* me)
{
    setFocus();
    if (me->button() == Qt::RightButton || editDNASeq == NULL) {
        GSequenceLineView::mousePressEvent(me);
        return;
    }
    QPoint renderAreaPos = toRenderAreaPoint(me->pos());

    const LRegion& visibleRange = getVisibleRange();
    QRectF rect;
    for (int i=visibleRange.startPos; i<visibleRange.endPos(); ++i) {
        rect = ra->posToRect(i);
        if (rect.contains(renderAreaPos)) {
            ra->hasSel = true;
            ra->selRect = rect;
            selIndex = i;
            update();
            mP->popup(mapToGlobal(rect.bottomRight().toPoint()));
            return;
        }

    }
    ra->hasSel = false;
    update();
    GSequenceLineView::mousePressEvent(me);
}

void ChromatogramView::sl_onPopupMenuCkicked(QAction* a) {
    if (editDNASeq->isStateLocked()) {
        QMessageBox::critical(this, tr("error"), tr("sequence_object_was_locked"));
        return;
    }
    switch (a->text().at(0).toAscii()) {
        case 'A': editDNASeq->setBase(selIndex, 'A');break;
        case 'C': editDNASeq->setBase(selIndex, 'C');break;
        case 'G': editDNASeq->setBase(selIndex, 'G');break;
        case 'T': editDNASeq->setBase(selIndex, 'T');break;
        case 'N': editDNASeq->setBase(selIndex, 'N');break;
    };
    if (indexOfChangedChars.count(selIndex) == 0) {
        indexOfChangedChars.push_back(selIndex);
    }
    ra->hasSel = false;
    update();
}

void ChromatogramView::sl_addNewSequenceObject() {
    sl_clearEditableSequence();
    
    assert(editDNASeq == NULL);

    AddNewDocumentDialogModel m;
    DocumentFormatConstraints c;
    c.mustSupportWrite = true;
    c.supportedObjectTypes.append(GObjectTypes::DNA_SEQUENCE);
    AddNewDocumentDialogImpl::run(NULL, m, c);
    if (!m.successful) {
        return;
    }
    Project* p = AppContext::getProject();

    DocumentFormat* format = AppContext::getDocumentFormatRegistry()->getFormatById(m.format);
    IOAdapterFactory* iof = AppContext::getIOAdapterRegistry()->getIOAdapterFactoryById(m.io);
    Document* doc = format->createNewDocument(iof, m.url);
    p->addDocument(doc);

    DNASequenceObject* so = ctx->getSequenceObject();
    editDNASeq = qobject_cast<DNASequenceObject*>(so->clone());
    doc->addObject(editDNASeq);
    ctx->getAnnotatedDNAView()->addObject(editDNASeq);
    indexOfChangedChars.clear();
}

void ChromatogramView::sl_onAddExistingSequenceObject() {
    sl_clearEditableSequence();

    assert(editDNASeq == NULL);

    ProjectTreeControllerModeSettings s;
    s.allowMultipleSelection = false;
    s.objectTypesToShow.append(GObjectTypes::DNA_SEQUENCE);
    DNASequenceObjectConstraints ac;
    ac.exactSequenceSize = ctx->getSequenceObject()->getSequence().length();
    s.objectConstraints.append(&ac);
    ac.alphabetType = ctx->getSequenceObject()->getAlphabet()->getType();
    s.sorted = true;
    foreach(GObject* o, ctx->getAnnotatedDNAView()->getObjects()) {
        s.excludeObjectList.append(o);
    }

    QList<GObject*> objs = ProjectTreeItemSelectorDialog::selectObjects(s);
    if (objs.size()!=0) {
        editDNASeq = qobject_cast<DNASequenceObject*>(objs.first());
        QString err = ctx->getAnnotatedDNAView()->addObject(editDNASeq);
        assert(err.isEmpty());
        indexOfChangedChars.clear();
    }
}

bool ChromatogramView::isWidgetOnlyObject(GObject* o) const {
    return o == editDNASeq;
}

void ChromatogramView::sl_clearEditableSequence() {
    if (editDNASeq == NULL) {
        return;
    }
    ctx->getAnnotatedDNAView()->removeObject(editDNASeq);
}

void ChromatogramView::sl_removeChanges() {
    if (editDNASeq->isStateLocked()) {
        QMessageBox::critical(this, tr("error"), tr("sequence_object_was_locked"));
        return;
    }

    DNASequenceObject* seqObject = ctx->getSequenceObject();
    const QByteArray& sequence = seqObject->getSequence();
    for (QList<int>::iterator it = indexOfChangedChars.begin(); it != indexOfChangedChars.end(); ++it)      {
        editDNASeq->setBase(*it, sequence[*it]);
    }
    indexOfChangedChars.clear();
}

bool ChromatogramView::checkObject(GObject* obj) {
    //TODO: check state lock on modifications too!!!
    if (obj->getGObjectType()!=GObjectTypes::DNA_SEQUENCE || obj->isStateLocked()) {
        return false;   
    }
    DNASequenceObject* dnaObj = qobject_cast<DNASequenceObject*>(obj);
    bool ok = (dnaObj->getAlphabet() == ctx->getSequenceObject()->getAlphabet()
        && dnaObj->getSequence().length() == ctx->getSequenceObject()->getSequence().length());

    return ok;
}


void ChromatogramView::sl_onObjectRemoved(GObjectView* view, GObject* obj)    {
    Q_UNUSED(view);

    if (editDNASeq==NULL || !checkObject(obj)) {
        return;
    }
    indexOfChangedChars.clear();
    editDNASeq = NULL;
    update();
}

//////////////////////////////////////
////render area
ChromatogramViewRenderArea::ChromatogramViewRenderArea(ChromatogramView* p, const DNAChromatogram& _chroma)
: GSequenceLineViewRenderArea(p), linePen(Qt::gray, 1, Qt::DotLine)
{
    setFixedHeight(200);
    font.setFamily("Courier");
    font.setPointSize(12);
    fontBold = font;
    fontBold.setBold(true);
    QFontMetricsF fm(font);
    charWidth = fm.width('W');
    charHeight = fm.ascent();
    heightPD = height();
    heightAreaBC = 50;
    areaHeight = height()-heightAreaBC;

    chroma = _chroma;
    chromaMax = 0;
    for (int i = 0; i < chroma.traceLength; i++)
    {
        if (chromaMax<chroma.A[i]) chromaMax=chroma.A[i];
        if (chromaMax<chroma.C[i]) chromaMax=chroma.C[i];
        if (chromaMax<chroma.G[i]) chromaMax=chroma.G[i];
        if (chromaMax<chroma.T[i]) chromaMax=chroma.T[i];
    }
    hasSel = false;
    if (chroma.hasQV)   {
        addUpIfQVL = 0;
    }
    else    {
        addUpIfQVL = heightAreaBC - 2*charHeight;
        setFixedHeight(height()-addUpIfQVL);
        areaHeight = height()-heightAreaBC + addUpIfQVL;
    }
}

ChromatogramViewRenderArea::~ChromatogramViewRenderArea()
{
}


void ChromatogramViewRenderArea::drawAll(QPaintDevice* pd)
{
    static const QColor colorForIds[4] = { Qt::darkGreen, Qt::blue, Qt::black, Qt::red};
    static const QString baseForIds[4] = { "A", "C", "G", "T" };
    static const qreal dividerTraceOrBaseCallsLines = 2;
    static const qreal dividerBoolShowBaseCallsChars = 1.5;


    //get sequence
    const LRegion& visible = view->getVisibleRange();
    assert(!visible.isEmpty());

    ADVSequenceObjectContext* seqCtx = view->getSequenceContext();
    const QByteArray& ba = seqCtx->getSequenceData();

    GSLV_UpdateFlags uf = view->getUpdateFlags();
    bool completeRedraw = uf.testFlag(GSLV_UF_NeedCompleteRedraw) || uf.testFlag(GSLV_UF_ViewResized) || 
        uf.testFlag(GSLV_UF_VisibleRangeChanged);


    if (completeRedraw) {
        QPainter p(cachedView);
        p.setRenderHint(QPainter::Antialiasing, true);
        p.setFont(font);
        p.setPen(Qt::black);
        p.fillRect(0, 0, pd->width(), heightPD, Qt::white);
        if (pd->width()/charWidth>visible.len/dividerBoolShowBaseCallsChars) {
            //draw basecalls
            drawOriginalBaseCalls(0, heightAreaBC-charHeight-addUpIfQVL, width(), charHeight, p, visible, ba); 

            if (chroma.hasQV) {
                drawQualityValues(0, charHeight, width(), heightAreaBC - 2*charHeight, p, visible, ba);           
            }
            //drawOriginalBaseCalls(0, 0, width(), charHeight, p, visible, qobject_cast<ChromatogramView*>(view)->fastaSeq, false);
        } else {
            QRectF rect(charWidth, 0, width() - 2*charWidth, 2*charHeight);
            p.drawText(rect, Qt::AlignCenter, QString(tr("selection_is_too_big")));
            int curCP = width() - charWidth;
            for (int i = 0; i < 4; ++i) {
                curCP-= 2*charWidth;
                p.setPen(colorForIds[i]);
                p.drawRect(curCP+charWidth/6, heightAreaBC-charHeight, charWidth/2, -charHeight/2);
                p.setPen(Qt::black);
                p.drawText(curCP+charWidth, heightAreaBC-charHeight, baseForIds[i]);
            }
        }
        if (pd->width()/charWidth>visible.len/dividerTraceOrBaseCallsLines) {
            drawChromatogramTrace(0, heightAreaBC - addUpIfQVL, pd->width(), height() - heightAreaBC + addUpIfQVL, p, visible);
        } else {
            drawChromatogramBaseCallsLines(0, heightAreaBC, pd->width(), height() - heightAreaBC, p, visible, ba);
        }
    }
    QPainter p(pd);
    p.setFont(font);
    p.drawPixmap(0, 0, *cachedView);

    //p.setBrush(QBrush(Qt::green, Qt::SolidPattern));
    if (hasSel) {
        p.setPen(linePen);
        p.drawRect(selRect);
        hasSel = false;
    }
    ChromatogramView* chromaView = qobject_cast<ChromatogramView*>(view);
    if (pd->width() / charWidth > visible.len /dividerBoolShowBaseCallsChars && chromaView->editDNASeq!=NULL) {
        drawOriginalBaseCalls(0, 0, width(), charHeight, p, visible, chromaView->editDNASeq->getSequence(), false);
    }

    if (completeRedraw || uf.testFlag(GSLV_UF_SelectionChanged)) {
        //draw current selection
        //selection base on trace transform coef
        k = kLinearTransformTrace;
        b = bLinearTransformTrace;
        QPen linePenSelection(Qt::darkGray, 1, Qt::SolidLine);
        p.setPen(linePenSelection);
        p.setRenderHint(QPainter::Antialiasing, false);
        const QList<LRegion>& sel=seqCtx->getSequenceSelection()->getSelectedRegions();
        if (sel.size() >= 1) {
            LRegion self=sel.first();
            int i1=self.startPos,i2=self.endPos()-1;
            if (i1!=0)  {
                p.drawLine((k*chroma.baseCalls[i1]+b+k*chroma.baseCalls[i1-1]+b)/2,0,
                    (k*chroma.baseCalls[i1]+b+k*chroma.baseCalls[i1-1]+b)/2,pd->height());
            }else {
                p.drawLine(k*chroma.baseCalls[i1]+b-charWidth/2,0,k*chroma.baseCalls[i1]+b-charWidth/2,pd->height());
            }
            if (i2!=chroma.seqLength-1)   {
                p.drawLine((k*chroma.baseCalls[i2]+b+k*chroma.baseCalls[i2+1]+b)/2,0,
                    (k*chroma.baseCalls[i2]+b+k*chroma.baseCalls[i2+1]+b)/2,pd->height());
            } else { 
                p.drawLine(k*chroma.baseCalls[i2]+b+charWidth/2,0, k*chroma.baseCalls[i2]+b+charWidth/2,pd->height());
            }
        }
    }
}


void ChromatogramViewRenderArea::setAreaHeight(int newH) {
    areaHeight = newH;
}

int ChromatogramViewRenderArea::coordToPos(int c) const {
    const LRegion& visibleRange = view->getVisibleRange();
    if (visibleRange.startPos+visibleRange.len==chroma.seqLength 
        && c>k*chroma.baseCalls[chroma.seqLength-1]+b)
    {
        return chroma.seqLength;
    }
    int m = 0;
    while ((m+visibleRange.startPos<chroma.seqLength-1)
        && ((k*chroma.baseCalls[visibleRange.startPos+m]+b+k*chroma.baseCalls[visibleRange.startPos+m+1]+b)/2<c)) 
    {
        m+=1;
    }
    return visibleRange.startPos+m;
}

int ChromatogramViewRenderArea::posToCoord(int p, bool useVirtualSpace) const {
    const LRegion& visibleRange = view->getVisibleRange();
    if (!useVirtualSpace && !visibleRange.contains(p) && p!=visibleRange.endPos()) {
        return -1;
    }
    int res = k*chroma.baseCalls[visibleRange.startPos+p]+b;
    assert(useVirtualSpace || res <= width());
    return res;
}

QRectF ChromatogramViewRenderArea::posToRect(int i) const {
    QRectF r(kLinearTransformBaseCallsOfEdited*chroma.baseCalls[i] + bLinearTransformBaseCallsOfEdited - charWidth/2, 0, charWidth, heightAreaBC-addUpIfQVL);
    return r;
}





//draw functions

void ChromatogramViewRenderArea::drawChromatogramTrace(qreal x, qreal y, qreal w, qreal h, QPainter& p, const LRegion& visible)
{
    //founding problems

    //areaHeight how to define startValue?
    //colorForIds to private members
    static const QColor colorForIds[4] = {
        Qt::darkGreen, Qt::blue, Qt::black, Qt::red
    };
    p.setRenderHint(QPainter::Antialiasing, true);
    p.resetTransform();
    p.translate(x,y+h);

    //drawBoundingRect
    /*      p.drawLine(0,0,w,0);
    p.drawLine(0,-h,w,-h);
    p.drawLine(0,0,0,-h);
    p.drawLine(w,0,w,-h);*/


    int a1 = chroma.baseCalls[visible.startPos];
    int a2 = chroma.baseCalls[visible.endPos()-1];
    qreal leftMargin, rightMargin;
    leftMargin = rightMargin = charWidth;
    qreal k1 = w - leftMargin  - rightMargin;
    int k2 = a2 - a1;
    kLinearTransformTrace = qreal (k1) / k2;
    bLinearTransformTrace = leftMargin - kLinearTransformTrace*a1;
    int mk1 = qMin<int>(leftMargin/kLinearTransformTrace,a1);
    int mk2 = qMin<int>(rightMargin/kLinearTransformTrace,chroma.traceLength-a2-1);
    int polylineSize = a2-a1+mk1+mk2+1;
    QPolygonF polylineA(polylineSize), polylineC(polylineSize),
        polylineG(polylineSize), polylineT(polylineSize);
    for (int j = a1-mk1; j <= a2+mk2; ++j) {
        double x = kLinearTransformTrace*j+bLinearTransformTrace;
        double yA = - qMin<double>(chroma.A[j]*areaHeight/chromaMax, h);
        double yC = - qMin<double>(chroma.C[j]*areaHeight/chromaMax, h);
        double yG = - qMin<double>(chroma.G[j]*areaHeight/chromaMax, h);
        double yT = - qMin<double>(chroma.T[j]*areaHeight/chromaMax, h);
        polylineA[j-a1+mk1] = QPointF(x, yA);
        polylineC[j-a1+mk1] = QPointF(x, yC);
        polylineG[j-a1+mk1] = QPointF(x, yG);
        polylineT[j-a1+mk1] = QPointF(x, yT);
    }
    p.setPen(colorForIds[0]);
    p.drawPolyline(polylineA);
    p.setPen(colorForIds[1]);
    p.drawPolyline(polylineC);
    p.setPen(colorForIds[2]);
    p.drawPolyline(polylineG);
    p.setPen(colorForIds[3]);
    p.drawPolyline(polylineT);

    p.resetTransform();
}

void ChromatogramViewRenderArea::drawOriginalBaseCalls(qreal x, qreal y, qreal w, qreal h, QPainter& p, const LRegion& visible, const QByteArray& ba, bool is)
{
    QRectF rect;


    p.setPen(Qt::black);
    p.resetTransform();
    p.translate(x,y+h);


    int a1 = chroma.baseCalls[visible.startPos];
    int a2 = chroma.baseCalls[visible.endPos()-1];
    qreal leftMargin, rightMargin;
    leftMargin = rightMargin = charWidth;
    qreal k1 = w - leftMargin  - rightMargin;
    int k2 = a2 - a1;
    qreal kLinearTransformBaseCalls = qreal (k1) / k2;
    qreal bLinearTransformBaseCalls = leftMargin - kLinearTransformBaseCalls*a1;

    if (!is)      {
        kLinearTransformBaseCallsOfEdited = kLinearTransformBaseCalls;
        bLinearTransformBaseCallsOfEdited = bLinearTransformBaseCalls;
        xBaseCallsOfEdited = x;
        yBaseCallsOfEdited = y;
        wBaseCallsOfEdited = w;
        hBaseCallsOfEdited = h;
    }
    ChromatogramView* cview = qobject_cast<ChromatogramView*>(view);
    for (int i=visible.startPos;i<visible.endPos();i++)     {
        p.setPen(Qt::black);

        if (cview->indexOfChangedChars.count(i) == 1 && !is) p.setFont(fontBold); else p.setFont(font);
        int xP = kLinearTransformBaseCalls*chroma.baseCalls[i] + bLinearTransformBaseCalls;
        rect.setRect(xP - charWidth/2 + linePen.width(), -h, charWidth, h);
        p.drawText(rect, Qt::AlignCenter, QString(ba[i]));

        if (is)   {
            p.setPen(linePen);
            p.setRenderHint(QPainter::Antialiasing, false);
            p.drawLine(xP, 0, xP, height()-y);
        }
    }

    if (is) {
        p.setPen(linePen);
        p.setFont(QFont(QString("Courier New"), 8));
        p.drawText(charWidth*1.3, charHeight/2, QString(tr("original")));
    }
    p.resetTransform();
}

void ChromatogramViewRenderArea::drawQualityValues(qreal x, qreal y, qreal w, qreal h, QPainter& p, const LRegion& visible, const QByteArray& ba)
{
    QRectF rectangle;

    p.resetTransform();
    p.translate(x,y+h);

    //draw grid
    p.setPen(linePen);
    p.setRenderHint(QPainter::Antialiasing, false);
    for (int i = 0; i < 5; ++i) p.drawLine(0,-h*i/4, w, -h*i/4);

    QLinearGradient gradient(10, 0, 10, -h);
    gradient.setColorAt(0, Qt::green);
    gradient.setColorAt(0.33, Qt::yellow);
    gradient.setColorAt(0.66, Qt::red); 
    QBrush brush(gradient);   

    p.setBrush(brush);
    p.setPen(Qt::black);
    p.setRenderHint(QPainter::Antialiasing, true);



    int a1 = chroma.baseCalls[visible.startPos];
    int a2 = chroma.baseCalls[visible.endPos()-1];
    qreal leftMargin, rightMargin;
    leftMargin = rightMargin = charWidth;
    qreal k1 = w - leftMargin  - rightMargin;
    int k2 = a2 - a1;
    qreal kLinearTransformQV = qreal (k1) / k2;
    qreal bLinearTransformQV = leftMargin - kLinearTransformQV*a1;

    for (int i=visible.startPos;i<visible.endPos();i++)     {
        int xP = kLinearTransformQV*chroma.baseCalls[i] + bLinearTransformQV - charWidth/2 + linePen.width();
        switch (ba[i])  {
            case 'A':
                rectangle.setCoords(xP, 0, xP+charWidth, -h/100*chroma.prob_A[i]);
                p.drawRoundedRect(rectangle, 1.0, 1.0); 
                p.drawLine(xP, 0, xP, -h/100*chroma.prob_A[i]);
                break;
            case 'C': 
                rectangle.setCoords(xP, 0, xP+charWidth, -h/100*chroma.prob_C[i]);
                p.drawRoundedRect(rectangle, 1.0, 1.0); 
                break;
            case 'G': 
                rectangle.setCoords(xP, 0, xP+charWidth, -h/100*chroma.prob_G[i]);
                p.drawRoundedRect(rectangle, 1.0, 1.0); 
                break;
            case 'T': 
                rectangle.setCoords(xP, 0, xP+charWidth, -h/100*chroma.prob_T[i]);
                p.drawRoundedRect(rectangle, 1.0, 1.0); 
                break;
        }   
    }

    p.resetTransform();
}

void ChromatogramViewRenderArea::drawChromatogramBaseCallsLines(qreal x, qreal y, qreal w, qreal h, QPainter& p, const LRegion& visible, const QByteArray& ba)
{
    static const QColor colorForIds[4] = {
        Qt::darkGreen, Qt::blue, Qt::black, Qt::red
    };
    p.setRenderHint(QPainter::Antialiasing, false);
    p.resetTransform();
    p.translate(x,y+h);

    /*      //drawBoundingRect
    p.drawLine(0,0,w,0);
    p.drawLine(0,-h,w,-h);
    p.drawLine(0,0,0,-h);
    p.drawLine(w,0,w,-h);*/


    int a1 = chroma.baseCalls[visible.startPos];
    int a2 = chroma.baseCalls[visible.endPos()-1];
    qreal leftMargin, rightMargin;
    leftMargin = rightMargin = linePen.width();
    qreal k1 = w - leftMargin  - rightMargin;
    int k2 = a2 - a1;
    kLinearTransformTrace = qreal (k1) / k2;
    bLinearTransformTrace = leftMargin - kLinearTransformTrace*a1;
    double yRes = 0;
    for (int j = visible.startPos; j < visible.startPos+visible.len; j++) {
        int temp = chroma.baseCalls[j];
        double x = kLinearTransformTrace*temp+bLinearTransformTrace;
        switch (ba[j])  {
            case 'A': 
                yRes = -qMin<double>(chroma.A[temp]*areaHeight/chromaMax, h);
                p.setPen(colorForIds[0]);
                break;
            case 'C':
                yRes = -qMin<double>(chroma.C[temp]*areaHeight/chromaMax, h);
                p.setPen(colorForIds[1]);
                break;
            case 'G':
                yRes = -qMin<double>(chroma.G[temp]*areaHeight/chromaMax, h);
                p.setPen(colorForIds[2]);
                break;
            case 'T':
                yRes = -qMin<double>(chroma.T[temp]*areaHeight/chromaMax, h);
                p.setPen(colorForIds[3]);
                break;
            case 'N':
                continue;
        };        
        p.drawLine(x, 0, x, yRes);
    }
    p.resetTransform();
}





}

Generated by  Doxygen 1.6.0   Back to index