/***************************************************************************** # Copyright (C) 1994-2008 by David Gordon. # All rights reserved. # # This software is part of a beta-test version of the Consed/Autofinish # package. It should not be redistributed or # used for any commercial purpose, including commercially funded # sequencing, without written permission from the author and the # University of Washington. # # This software is provided ``AS IS'' and any express or implied # warranties, including, but not limited to, the implied warranties of # merchantability and fitness for a particular purpose, are disclaimed. # In no event shall the authors or the University of Washington be # liable for any direct, indirect, incidental, special, exemplary, or # consequential damages (including, but not limited to, procurement of # substitute goods or services; loss of use, data, or profits; or # business interruption) however caused and on any theory of liability, # whether in contract, strict liability, or tort (including negligence # or otherwise) arising in any way out of the use of this software, even # if advised of the possibility of such damage. # # Building Consed from source is error prone and not simple which is # why I provide executables. Due to time limitations I cannot # provide any assistance in building Consed. Even if you do not # modify the source, you may introduce errors due to using a # different version of the compiler, a different version of motif, # different versions of other libraries than I used, etc. For this # reason, if you discover Consed bugs, I can only offer help with # those bugs if you first reproduce those bugs with an executable # provided by me--not an executable you have built. # # Modifying Consed is also difficult. Although Consed is modular, # some modules are used by many other modules. Thus making a change # in one place can have unforeseen effects on many other features. # It may takes months for you to notice these other side-effects # which may not seen connected at all. It is not feasable for me to # provide help with modifying Consed sources because of the # potentially huge amount of time involved. # #*****************************************************************************/ // // ContigWin.cpp // // implementation for ContigWin object // // NOTE: this is not the main module. the main() procedure is // in file main.cpp. // // // standard or system include files #include using namespace std; #include #include // miscellaneous application include files #include "numutil.h" #include "mbt_errors.h" #include "mbt_exception.h" // contig and related data structure include files #include "ntide.h" #include "locatedFragment.h" #include "contig.h" #include "contigview.h" #include "assembly.h" #include "guiapp.h" #include "consed.h" #include "guicontigwin.h" #include "colormode.h" #include "tedwin.h" #include "textbox.h" #include "consed.h" #include "gotoList.h" #include "lowconsqual.h" #include "highQualityDiscrepancyGotoList.h" #include "editedGotoList.h" #include "editedButNotNsGotoList.h" #include "tagsGotoList.h" #include "fileselector.h" #include "filename.h" #include "edit_complement_contig.h" #include "please_wait.h" #include "filePopupAndGetFilename.h" #include "teditor.h" #include "compareContigs.h" #include "consedParameters.h" #include "tag.h" #include "tagTypes.h" #include "guiPopupTagInfo.h" #include "guiGetTagType.h" #include "guiteditor.h" #include "bErrorMessageIfNoPhd.h" #include "bIsNumericMaybeWithWhitespace.h" #include "pickPrimers.h" #include "editAddConsensusTag.h" #include "editAddReadTag.h" #include "guiMultiContigNavigator.h" #include "createUnalignedHighQualityNavigator.h" #include "editMakeHighQuality.h" #include "popupErrorMessage2.h" #include "popupInfoMessage.h" #include "multiProblemGotoList.h" #include "gotoListType.h" #include "guiTearContig.h" #include "popupErrorMessage.h" #include "oligoTag.h" #include "library.h" #include "editChangeToXs.h" #include "guiGetReferenceRead.h" #include "soGetErrno.h" #include "soAddCommas.h" #include "editChangeToNs.h" #include "editOverstrikeAllReadsAtConsPos.h" #include "bGuiGetAnswerYesNo.h" #include "editAddTagsToAllReadsAtConsPos.h" #include "editOverstrikeConsensus.h" #include "nNumberFromBase4.h" static int nLastUsedUnpaddedConsPos = 0; // // ctor for ContigWin object // ContigWin :: ContigWin ( ) : pContig_(0), pContigView_( 0 ), pTeditor_( NULL ), bButton1PressedInReadBasesArea_( false ), bButton1PressedInConsensusBasesArea_( false ), pGuiMultiContigNav_( NULL ), nOldConsPosOfPointer_( -666 ), nOldReadLineOfPointer_( -666 ), bDrewEverythingSinceLastDrewVerticalLine_( false ), nCurrentVerticalLineScreenCharPos_( -666 ) { // // create the companion GuiContigWin object // pGcw_ = new GuiContigWin( this ); // GuiContigWin will call ContigWin mem funs // // initialize pointer to current color mode. // this may eventually become an array of color modes. // for an extensive discussion of ColorModes, see // colormode.h // pColorMode_ = GAPP->pColorMeansQualityAndTags_; // initialize various ContigWin & GuiContigWin states nLeftEdgeConsensusPosition_ = 1; // first base in consensus emptySlider(); emptyVerticalScrollBar(); pGcw_->makeVisible(); // if you got here, it's safe to tell the ConsEd object // you exist ConsEd::pGetConsEd()->addNewContigWin(this); } // this is put here so that ~ContigWin is not called directly, but rather // to check if it is ok to delete it void ContigWin :: deleteIfOK() { if (ConsEd::pGetConsEd()->bIsThisContigWinOnAnyCompareContigsWindow( this ) ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "You must first dismiss the Compare Contigs Window since it refers to this Aligned Reads Window with contig %s", (char*) pContig_->soGetName().data() ); InputDataError ide(""); // flag the exception as already having been reported ide.setUserNotified(); throw ide; // we're outta here } delete this; } // this is here to avoid circular includes ContigWin :: ~ContigWin() { delete pTeditor_; delete pGcw_; ConsEd::pGetConsEd()->removeContigWin(this); } // tell ConsEd you died // this member function receives notification from the GuiContigWin // that the user has pressed a char void ContigWin :: charPress(const char c) { GuiApp::beep(); } // member function for buttonpress events void ContigWin :: buttonPress(int nButton, int bupd, int nXCharPos, int nYCharPos) { // paranoia made necessary by lack of typedef assert ((bupd == GedButtonDown) || (bupd == GedButtonUp)); GuiApp::beep(); if (bupd == GedButtonDown) { // cout << "user pressed button "; } else { // cout << "user released button "; } // cout << nButton << '\n'; cout.flush(); } // This is just for switching between the two ways of sorting the // reads void ContigWin :: getNewContigView() { if (!pContig_ ) return; assert( nLeftEdgeConsensusPosition_ <= nGetRightEdgeConsensusPosition() ); pContigView_ = pContig_->pGetContigView( nLeftEdgeConsensusPosition_, nGetRightEdgeConsensusPosition() ); resetRoomForReadNames(); } void ContigWin :: horizontalScrollBarMoved( int nNewScrollBarPosition ) { int nError; // set private member data to new scroll bar position // the slider position equals the position within the // entire displayable region of the contig - consensus based nLeftEdgeConsensusPosition_ = nNewScrollBarPosition; // handle startup if (!pContig_) return; assert( nLeftEdgeConsensusPosition_ <= nGetRightEdgeConsensusPosition() ); pContigView_ = pContig_->pGetContigView(nLeftEdgeConsensusPosition_, nGetRightEdgeConsensusPosition() ); // handle startup if (!pContigView_ ) return; maybeSortReadsAtCursor(); displayHowReadsAreSorted(); resetRoomForReadNames(); // nIndexOfTopVisibleRead_ = 0; // setTopAndBottomVisibleFragments(); pGcw_->guiResetVerticalScrollBar( nIndexOfTopVisibleRead_, // val 0, // min pContigView_->nGetNumberOfFragments() - 1, // max pGcw_->nGetDisplayedReadsHigh()); // size drawBasesAndConsensus( true ); // erase first } void ContigWin :: windowResized() { if (!pContig_) return; // nLeftEdgeConsensusPosition_ remains unchanged assert( nLeftEdgeConsensusPosition_ <= nGetRightEdgeConsensusPosition() ); int nOldNumberOfReads = pContigView_->nGetNumberOfFragments(); char cOldSort = pContigView_->cHowAreReadsSorted_; int nOldConsPosOfSortWindow = pContigView_->nConsPosOfSortWindow_; pContigView_ = pContig_->pGetContigView(nLeftEdgeConsensusPosition_, nGetRightEdgeConsensusPosition() ); // try to preserve the sort of the reads before the resize // (this is a little fishy--I can't see how the resize could change // the sort? DG 6/2010) if ( nLeftEdgeConsensusPosition_ <= nOldConsPosOfSortWindow && nOldConsPosOfSortWindow <= nGetRightEdgeConsensusPosition() ) { pContigView_->maybeSortReadsAtCursor( nOldConsPosOfSortWindow ); } displayHowReadsAreSorted(); bool bEraseFirst = ( ( nOldNumberOfReads == pContigView_->nGetNumberOfFragments() ) && ( cOldSort == pContigView_->cHowAreReadsSorted_ ) && ( nOldConsPosOfSortWindow == pContigView_->nConsPosOfSortWindow_ ) ? false : true ); resetRoomForReadNames(); // nIndexOfTopVisibleRead_ = 0; pGcw_->guiResetVerticalScrollBar( nIndexOfTopVisibleRead_, // val 0, // min pContigView_->nGetNumberOfFragments() - 1, // max pGcw_->nGetDisplayedReadsHigh()); // size // adjust the scroll bar slider size pGcw_->guiResizeSlider(); drawBasesAndConsensus( bEraseFirst ); } // for use by program control of vertical scroll bar void ContigWin :: verticalScrollBarMoved( int nNewScrollBarPosition ) { int nError; // set private member data to new scroll bar position // the slider position equals the position within the // entire displayable region of the contig - consensus based nIndexOfTopVisibleRead_ = nNewScrollBarPosition; pGcw_->guiSetSliderPosOfVerticalScrollBar( nNewScrollBarPosition ); bool bHighlight = ( nIndexOfTopVisibleRead_ == 0 ) ? false : true; pGcw_->highlightVerticalScrollBar( bHighlight ); drawBasesAndConsensus( true ); // erase first } void ContigWin :: verticalScrollToMakeThisReadVisible( LocatedFragment* pLocFrag ) { int nReadLine = nGetReadLineFromLocatedFragment( pLocFrag ); if ( nReadLine == -1 ) return; if ( nIndexOfTopVisibleRead_ > nReadLine ) { verticalScrollBarMoved( nReadLine ); } else { // now we are concerned about the case in which the read // is below the bottom of the aligned reads window if ( pGcw_->bReadLineIsBelowBottomOfWindow( nReadLine ) ) { ++nIndexOfTopVisibleRead_; while( pGcw_->bReadLineIsBelowBottomOfWindow( nReadLine ) ) { ++nIndexOfTopVisibleRead_; } verticalScrollBarMoved( nIndexOfTopVisibleRead_ ); } } } // for scrolling not directly initiated by user void ContigWin :: scrollToConsensusPos( const int nNewPos ) { int nPos = nNewPos; // preserve const param // don't scroll past the displayable ends if (nPos < pContig_->nGetFirstDisplayableContigPos()) { nPos = pContig_->nGetFirstDisplayableContigPos(); } else { // how far can we scroll and not run off the end of the consensus? int nMaxAllowedContigPos = pContig_->nGetLastDisplayableContigPos() - nGetDisplayedBasesWide() + 1; if ( nPos > nMaxAllowedContigPos) { nPos = nMaxAllowedContigPos; } } // this will set ContigWin member data and redraw (calling // GuiContigWin routines) horizontalScrollBarMoved(nPos); // tell GuiContigWin to set the slider appropriately pGcw_->guiSetSliderPos(nPos); } // for scrolling by navigator // will put nNewPos in the center, if possible void ContigWin :: scrollToConsensusPosInCenter( const int nNewPos ) { // if the position is already on the screen, don't move if ( (nLeftEdgeConsensusPosition_ <= nNewPos) && (nNewPos <= nGetRightEdgeConsensusPosition() ) ) return; int nBasesWide = nGetDisplayedBasesWide(); int nLeftEdgePosition = nNewPos - ( nBasesWide / 2 ) + 1; scrollToConsensusPos( nLeftEdgePosition ); } void ContigWin :: scrollToConsensusPosInCenterAndSetCursorOnConsensus( const int nNewCursorConsPos ) { // handle startup if ( !pContig_ ) return; assert( pContig_->bIsOnConsensus( nNewCursorConsPos ) ); // if the position is already on the screen, don't move bool bNeedToScroll = true; if ( ( nLeftEdgeConsensusPosition_ <= nNewCursorConsPos ) && ( nNewCursorConsPos <= nGetRightEdgeConsensusPosition() ) ) bNeedToScroll = false; if ( bNeedToScroll ) { int nBasesWide = nGetDisplayedBasesWide(); int nNewLeftEdgePosition = nNewCursorConsPos - ( nBasesWide / 2 ) + 1; // now check that this position is ok // don't scroll past the displayable ends--code from scrollToConsensusPos if (nNewLeftEdgePosition < pContig_->nGetFirstDisplayableContigPos()) { nNewLeftEdgePosition = pContig_->nGetFirstDisplayableContigPos(); } else { // how far can we scroll and not run off the end of the consensus? int nMaxAllowedContigPos = pContig_->nGetLastDisplayableContigPos() - nGetDisplayedBasesWide() + 1; if ( nNewLeftEdgePosition > nMaxAllowedContigPos) { nNewLeftEdgePosition = nMaxAllowedContigPos; } } // code from horizontalScrollBarMoved nLeftEdgeConsensusPosition_ = nNewLeftEdgePosition; assert( nLeftEdgeConsensusPosition_ <= nGetRightEdgeConsensusPosition() ); // if we scrolled, we need to get a new batch of reads pContigView_ = pContig_->pGetContigView( nLeftEdgeConsensusPosition_, nGetRightEdgeConsensusPosition() ); } // handle startup if ( !pContigView_ ) return; bool bMustResetVerticalScrollBar = false; // scroll back to top each time we navigate to a new positions if ( nIndexOfTopVisibleRead_ != 0 ) { nIndexOfTopVisibleRead_ = 0; pGcw_->highlightVerticalScrollBar( false ); // turn off green bMustResetVerticalScrollBar = true; } // we cannot use: // maybeSortByQualityAtCursor(); // because the cursor is not yet set pContigView_->maybeSortReadsAtCursor( nNewCursorConsPos ); displayHowReadsAreSorted(); if ( bNeedToScroll ) { resetRoomForReadNames(); bMustResetVerticalScrollBar = true; // tell GuiContigWin to set the slider appropriately pGcw_->guiSetSliderPos( nLeftEdgeConsensusPosition_ ); } if ( bMustResetVerticalScrollBar ) { pGcw_->guiResetVerticalScrollBar( nIndexOfTopVisibleRead_, // val 0, // min pContigView_->nGetNumberOfFragments() - 1, // max pGcw_->nGetDisplayedReadsHigh() ); // size } // now do the code for setting the cursor // clear the cursor from all child tedwins prior to move drawTeditorCursors( false ); // remove old cursor from this ContigWin drawCursor( false ); // record cursor position (doesn't draw anything) editCursor_.setCursorOnCons( pContig_, nNewCursorConsPos ); // also scroll traces if ( pTeditor_ ) { // don't scroll the teditor if it contains all the traces-- // it will take forever. Instead, recreate it. if ( ! pTeditor_->pGuiTeditor_->bShowTracesInScrollingWindow_ ) { TedWin* pTedWin = pTeditor_->pGetGuiTedWinScrollMaster()->pTedWinGet(); pTedWin->scrollToConsPosAndRefresh( nNewCursorConsPos - nOffsetToPutBaseInTheMiddle ); } } // finally! drawBasesAndConsensus( true ); drawCursor( true ); drawVerticalLineAtCursorIfNecessary(); } void ContigWin :: initializeContigWinForNewContig( const int nStartLeftEdgeConsPos, const bool bPutInCenter ) { if (bPutInCenter ) { nLeftEdgeConsensusPosition_ = nStartLeftEdgeConsPos - nGetDisplayedBasesWide() / 2 ; } else nLeftEdgeConsensusPosition_ = nStartLeftEdgeConsPos; nLeftEdgeConsensusPosition_ = MAX( nLeftEdgeConsensusPosition_, pContig_->nGetFirstDisplayableContigPos() ); // added 5/13/99 since if give cons pos off right end of // reads, loadGuiColorTextArraysForConsensusPositions will crash nLeftEdgeConsensusPosition_ = MIN( nLeftEdgeConsensusPosition_, pContig_->nGetLastDisplayableContigPos() ); int nViewRightEdge = nLeftEdgeConsensusPosition_ + MIN( nGetDisplayedBasesWide(), pContig_->nGetPaddedConsLength() ); assert( nLeftEdgeConsensusPosition_ <= nViewRightEdge ); pContigView_ = pContig_->pGetContigView(nLeftEdgeConsensusPosition_, nViewRightEdge); // I don't see how the cursor could be set yet.. (DG, 6/2010) // maybeSortByQualityAtCursor(); displayHowReadsAreSorted(); resetRoomForReadNames(); setTopAndBottomVisibleFragments(); // update the label telling current contig pGcw_->setContigLabel( pContig_->soGetFancyName() ); // adjust the scroll bar to reflect the new contig setSliderForNewContig(); setVerticalScrollBarForNewContig(); // activate the infobuttons that only apply to an active contig pGcw_->setButtonStatesForActiveContig(); drawBasesAndConsensus( false ); // do not erase first displayContigErrorRate(); } // pop up a dibox with information about the contig void ContigWin :: showContigInfo() { if (! ConsEd::pGetAssembly() ) return; if (! pGetContig()) return; TextBox* pTB = new TextBox( "Contig Information"); pContig_->setHighQualitySegment(); if ( pContig_->bIsThereAHighQualitySegment() ) { pTB->appendWithArgs( "high quality segment from unpadded pos %d to %d\n", pContig_->nUnpaddedHighQualitySegmentStart_, pContig_->nUnpaddedHighQualitySegmentEnd_ ); } else pTB->append( "The quality of this contig is so poor that it has no high quality segment\n" ); // get ptr to view, an array of pointer to FragAttach from ContigView* cvp = pContig_->view(0, pContig_->nGetPaddedConsLength() - 1); int nFrag = cvp->nGetNumberOfFragments(); pTB->appendWithArgs("number of reads: %d\n", nFrag ); // dump each fragment in view, aligned by char for (int i = 0; i < nFrag; i++) { // here's the attachment object LocatedFragment* pLF = cvp->pLocatedFragmentGet(i); // display fragment name, alignment, etc. pTB->append( pLF->soGetFragmentName() ); if (pLF->bComp()) { pTB->append( " C " ); } else { pTB->append( " " ); } pTB->appendWithArgs(" length %d %d %d \n", pLF->nGetPaddedFragLength(), pLF->nGetAlignStart(), pLF->nGetAlignEnd() ); } pTB->makeVisible(); } void ContigWin :: createMultiProblemNavigator() { PleaseWait* pPleaseWait = new PleaseWait( pGcw_->widGetGuiContigWinTopLevel() ); multiProblemGotoList* pMultiProblemGotoList = new multiProblemGotoList( lowConsensusQualityType | highQualityDiscrepancyWithoutCompressionsAndG_dropoutsType | singleStrandedRegionsType | singleSubcloneRegionsType | unalignedHighQualityRegionsType, pContig_ ); RWCString soColumnHeadings1 = "Contig Read Consensus "; RWCString soColumnHeadings2 = "Name Name Positions"; char* szTitle = "Low Cons Qual/High Quality Discrep (no comp/G_dropouts)/Single Stranded and Chem/Single Subclone/Unaligned High Qual (no chimeric)"; pGuiMultiContigNav_ = new guiMultiContigNavigator( szTitle, soColumnHeadings1, soColumnHeadings2, 100, "", NULL, NULL, pGcw_->widGetGuiContigWinTopLevel(), pMultiProblemGotoList, this ); delete pPleaseWait; } void ContigWin :: createLowConsensusQualityNavigator() { // create the gotoList. The navigator is currently responsible // for destroying gotoList LowConsQualGotoList* pGotoList = new LowConsQualGotoList(pContig_); RWCString soColumnHeadings1 = "Contig Read Consensus "; RWCString soColumnHeadings2 = "Name Name Positions"; char szTitle[200]; sprintf( szTitle, "Low consensus quality (<=%d or 98)", consedParameters::pGetConsedParameters()->nQualityThresholdForLowConsensusQuality_ ); pGuiMultiContigNav_ = new guiMultiContigNavigator( szTitle, soColumnHeadings1, soColumnHeadings2, 100, "", NULL, NULL, pGcw_->widGetGuiContigWinTopLevel(), pGotoList, this ); } void ContigWin :: createHighQualityDiscrepancyNavigator( const bool bExcludeInCompressionTags, const bool bExcludeMostPads ) { PleaseWait* pPleaseWait = new PleaseWait( pGcw_->widGetGuiContigWinTopLevel() ); // create the gotoList. The navigator is currently responsible // for destroying gotoList highQualityDiscrepancyGotoList* pGotoList = new highQualityDiscrepancyGotoList(pContig_, bExcludeInCompressionTags, bExcludeMostPads ); RWCString soColumnHeadings1 = "Contig Read Consensus "; RWCString soColumnHeadings2 = "Name Name Positions"; char szTitle[200]; sprintf( szTitle, "High quality (>=%d) discrepanices. (Ignore if within %d bases of unaligned region) %s", consedParameters::pGetConsedParameters()->nQualityThresholdForFindingHighQualityDiscrepancies_, consedParameters::pGetConsedParameters()->nIgnoreHighQualityDiscrepanciesThisManyBasesFromEndOfAlignedRegion_, ( bExcludeInCompressionTags ? " exclude in compression tags" : "" ) ); pGuiMultiContigNav_ = new guiMultiContigNavigator( szTitle, soColumnHeadings1, soColumnHeadings2, 100, "", NULL, NULL, pGcw_->widGetGuiContigWinTopLevel(), pGotoList, this ); delete pPleaseWait; } void ContigWin :: createEditedNavigator() { // create the gotoList. The navigator is currently responsible // for destroying gotoList editedGotoList* pGotoList = new editedGotoList(pContig_); RWCString soColumnHeadings1 = "Contig Read Consensus "; RWCString soColumnHeadings2 = "Name Name Positions"; pGuiMultiContigNav_ = new guiMultiContigNavigator( "Edits", soColumnHeadings1, soColumnHeadings2, 100, "", NULL, NULL, pGcw_->widGetGuiContigWinTopLevel(), pGotoList, this ); } void ContigWin :: createEditedButNotNsNavigator() { // create the gotoList. The navigator is currently responsible // for destroying gotoList editedButNotNsGotoList* pGotoList = new editedButNotNsGotoList(pContig_); RWCString soColumnHeadings1 = "Contig Read Consensus "; RWCString soColumnHeadings2 = "Name Name Positions"; pGuiMultiContigNav_ = new guiMultiContigNavigator( "Edits But Not N's", soColumnHeadings1, soColumnHeadings2, 100, "", NULL, NULL, pGcw_->widGetGuiContigWinTopLevel(), pGotoList, this ); } void ContigWin :: createTagsNavigator() { // create the gotoList. The navigator is currently responsible // for destroying gotoList // handle case of empty window if (!pContig_ ) return; bool bUserPushedCancel = false; RWCString soTemp; guiGetTagType* pGuiGetTagType = new guiGetTagType(); RWCString soTagTypeSelectedByUser; pGuiGetTagType->popupBoxAndWaitForUserToSelectTagType( soTagTypeSelectedByUser, bUserPushedCancel, false, // include all tag types tagType::both, // allow navigation // on both read and consensus tags false, // bAllowUserToEnterComment soTemp, soTemp ); delete pGuiGetTagType; if (bUserPushedCancel ) return; tagsGotoList* pGotoList = new tagsGotoList(pContig_, soTagTypeSelectedByUser ); RWCString soColumnHeadings1; RWCString soColumnHeadings2; tagTypes::pGetTagTypes()->getColumnHeadingsForNavigatorBox( soTagTypeSelectedByUser, soColumnHeadings1, soColumnHeadings2 ); pGuiMultiContigNav_ = new guiMultiContigNavigator( soTagTypeSelectedByUser + " tags", soColumnHeadings1, soColumnHeadings2, 100, // width in chars "", NULL, NULL, pGcw_->widGetGuiContigWinTopLevel(), NULL, this ); // if you create the XmSelectionBox with the list already there, the // selection box will resize itself to the size of the largest entry. // In the case of autoFinishExpTag's, this is huge--larger than the // largest monitor. But the method below works--it thus respects the // "100" above and doesn't resize it. for( int nGotoItem = 0; nGotoItem < pGotoList->nGetNumGotoItems(); ++nGotoItem ) { gotoItem* pGotoItem = pGotoList->pGetGotoItem( nGotoItem ); pGuiMultiContigNav_->appendToList( pGotoItem ); } pGuiMultiContigNav_->displayList( false ); // don't re-sort } void ContigWin :: createUnalignedHighQualityNavigator2() { createUnalignedHighQualityNavigator( pGcw_->widGetGuiContigWinTopLevel(), pContig_, this ); } void ContigWin :: emptySlider() { // dummy values to create "full" slider pGcw_->guiResetSlider(0, // val = leftmost pos 0, // minimum 10, // max 10); // slider size } void ContigWin :: emptyVerticalScrollBar() { pGcw_->guiResetVerticalScrollBar(0, // val 0, // minimum 10, // max 10); // slider size } void ContigWin :: setSliderForNewContig() { if (!pContig_) { emptySlider(); } else { pGcw_->guiResetSlider(nLeftEdgeConsensusPosition_, // val pContig_->nGetFirstDisplayableContigPos(), // min pContig_->nGetLastDisplayableContigPos(), // max nGetDisplayedBasesWide()); // size } } void ContigWin :: setVerticalScrollBarForNewContig() { if (!pContig_) emptyVerticalScrollBar(); else pGcw_->guiResetVerticalScrollBar( nIndexOfTopVisibleRead_, // val 0, // min pContigView_->nGetNumberOfFragments() - 1, // max pGcw_->nGetDisplayedReadsHigh()); // size } // used, for example, when adding a column of pads void ContigWin :: resetSliderMax() { pGcw_->guiResetSliderMax( pContig_->nGetLastDisplayableContigPos() ); } ////////////////////////////////////////////////////////////////////// // // raw callbacks supplied to GuiContigWin, MenuMainWin, etc. // these are all friends of the ContigWin class. // // this is yet another layer of indirection applied to // callbacks. these routines serve only to convert the client data // pointer returned in ContigWin callbacks into pointers to the // ContigWin objects that they apply to. This allows the GuiContigWin // to remain (largely) ignorant of the ContigWin. // ////////////////////////////////////////////////////////////////////// void ContigWin :: colorMeansMatch() { pColorMode_ = GAPP->pColorMeansMatch_; refreshContigWinAndTeditor(); } void ContigWin :: colorMeansQuality() { pColorMode_ = GAPP->pColorMeansQuality_; refreshContigWinAndTeditor(); } void ContigWin :: colorMeansEdited() { pColorMode_ = GAPP->pColorMeansEdited_; refreshContigWinAndTeditor(); } void ContigWin :: colorMeansQualityAndTags() { pColorMode_ = GAPP->pColorMeansQualityAndTags_; refreshContigWinAndTeditor(); } void ContigWin :: colorMeansEditedAndTags() { pColorMode_ = GAPP->pColorMeansEditedAndTags_; refreshContigWinAndTeditor(); } // callback for File menu "Export consensus" button void cbExportConsensus(void* clientData) { ContigWin* pCw = (ContigWin* )clientData; // is there something to save? if (! (ConsEd::pGetAssembly() && pCw->pGetContig()) ) { // no, pointers are null. describe the problem InputDataError ide("There is no contig being edited."); // tell the user popupErrorMessage2( pCw->pGcw_->widGetGuiContigWinTopLevel(), ide.szGetDesc()); // flag the exception as already having been reported ide.setUserNotified(); throw ide; // we're outta here } // build file name for dir mask & selection box default FileName soAssemblyDirName( ConsEd::pGetAssembly()->soGetAceFileName().soGetDirectory()); FileName soDirMask = soAssemblyDirName + "*.fasta"; FileName soTryOutFileName = soAssemblyDirName + pCw->pGetContig()->soGetName() + ".fasta"; FileName soUserOutFileName = GuiApp::popupFileSelector("Save consensus to file", soDirMask, soTryOutFileName); // if user cancelled or did not supply name, bail now if (soUserOutFileName.isNull()) { return; } bool bGoAhead = true; if (soUserOutFileName.bFileByThisNameExists()) { bGoAhead = GuiApp::popupDecisionMessage("File %s exists. Save anyway?", (const char*)soUserOutFileName); } if (bGoAhead) { pCw->pGetContig()->writeConsensusToFastaFile(soUserOutFileName); } } //////////////////////////////////////////////////////////// // // PURPOSE: Draws the scale, fragment bases, and consensus in // the cases of refresh, scrolling, etc // // HOW TO USE IT: // // // INPUTS: nix // // OUTPUTS: nix // // REV: Jan 26, 1995 (David Gordon) // //////////////////////////////////////////////////////////// void ContigWin :: drawBasesAndConsensus( const bool bEraseFirst ) { int nError; // not sure I always want to clear the window--perhaps only in the // case of scrolling if ( bEraseFirst ) pGcw_->guiClearContigWindow(); if (! pContig_) return; // nothing to draw drawScale(); if ( consedParameters::pGetConsedParameters()->nShowProteinTranslation_ != nDontShowProteinTranslation ) drawProteinTranslation(); drawConsensus(); if ( bDrawSeparatorBetweenTopAndBottomStrandReads() ) { pGcw_->nGuiDrawSepLine(); } // drawReadWRItems(); drawFragmentNames(); drawBases(); drawHighlightedBases(); bDrewEverythingSinceLastDrewVerticalLine_ = true; drawVerticalLineAtCursorNoRedraw(); } void ContigWin :: drawScale() { if (consedParameters::pGetConsedParameters()->bCountPads_ ) drawScalePadded( ); else drawScaleUnpadded( ); } void ContigWin :: drawScaleUnpadded() { int nCon; int nCharScreenPosition; char szLabel[50]; // find unpadded consensus index from padded position. // this is possibly expensive, so we call it only for the // first base, and then use the ntides bIsPad() fun on subsequent // bases, keeping our own count as we iterate through the // window. // convert to a biased number based on any tags. (E.g., if you // are displaying a region of a chromosome and want to display the // numbers in chromosome positions.) int nUnpadPos = pContig_->nUnpaddedIndexStartingAtUserDefinedPosition( nLeftEdgeConsensusPosition_ ); bool bFirstTimeThrough = true; for(nCon = nLeftEdgeConsensusPosition_; nCon <= nGetRightEdgeConsensusPosition(); ++nCon ) { // is the current consensus position a pad ? bool bConIsPad = pContig_->ntGetCons(nCon).bIsPad(); // if not first time through, update the unpadded position if (! bFirstTimeThrough) { // if this consensus pos is not a base, increment unpadded pos if ( ! bConIsPad ) { nUnpadPos++; } } else { bFirstTimeThrough = false; } // screen position depends on all displayed bases, including pads nCharScreenPosition = nConsensusPositionToScreenChar( nCon ); // only draw a tickmark if the current consensus position // is not a pad if (! bConIsPad ) { // draw big ticks every 5 if (nUnpadPos % 5 == 0) { pGcw_->guiDrawScaleBigTick( nCharScreenPosition ); const int nWriteEvery10IfSmallerThanThis = 1000000; bool bDrawNumber = false; if ( ( nUnpadPos < nWriteEvery10IfSmallerThanThis ) && ( nUnpadPos % 10 == 0 ) ) bDrawNumber = true; else if ( ( nUnpadPos >= nWriteEvery10IfSmallerThanThis ) && ( nUnpadPos % 20 == 0 ) ) bDrawNumber = true; if ( bDrawNumber ) { RWCString soUnpadded; if ( nUnpadPos >= 10000 ) { soUnpadded = soAddCommas( nUnpadPos ); } else { soUnpadded = RWCString( (long) nUnpadPos ); } pGcw_->guiDrawScaleNumber( nCharScreenPosition, soUnpadded.data() ); pGcw_->guiDrawScaleBigBigTick( nCharScreenPosition ); } } else { pGcw_->guiDrawScaleLittleTick( nCharScreenPosition ); } } } pGcw_->guiDrawScaleHorizontalLine(); } void ContigWin :: drawScalePadded() { int nCon; int nCharScreenPosition; char szLabel[50]; for(nCon = nLeftEdgeConsensusPosition_; nCon <= nGetRightEdgeConsensusPosition(); ++nCon ) { // screen position depends on all displayed bases, including pads nCharScreenPosition = nConsensusPositionToScreenChar( nCon ); // draw big ticks every 5 if (nCon % 5 == 0) { pGcw_->guiDrawScaleBigTick( nCharScreenPosition ); if (nCon % 10 == 0) { sprintf(szLabel, "%d", nCon ); pGcw_->guiDrawScaleNumber( nCharScreenPosition, szLabel ); } } else { pGcw_->guiDrawScaleLittleTick( nCharScreenPosition ); } } pGcw_->guiDrawScaleHorizontalLine(); } //////////////////////////////////////////////////////////// // // PURPOSE: Draws the bases of the fragments (not the consensus) // // REV: Feb 2, 1995 (David Gordon) // //////////////////////////////////////////////////////////// void ContigWin :: drawBases() { int nTryScreenCharStart = 0; GuiColorText* pGctToUse; char szCharsToDraw[1000]; int nNumberOfCharsToDraw; int nActualScreenCharStart; int nError; int nMaxReadLine = MIN( pContigView_->nGetNumberOfFragments() - 1, pGcw_->nGetDisplayedReadsHigh() + nIndexOfTopVisibleRead_ ); for(int nReadLine = nIndexOfTopVisibleRead_; nReadLine <= nMaxReadLine; ++nReadLine) { LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet(nReadLine); // this must be reloaded for each if ( bMustLoadGuiColorTextArrayForTags() ) { loadGuiColorTextArrayForTags( pLocFrag ); } nTryScreenCharStart = 0; while( bGetNextColorWordForRead( pLocFrag, nTryScreenCharStart, nGetDisplayedBasesWide() - 1, nActualScreenCharStart, szCharsToDraw, nNumberOfCharsToDraw, pGctToUse ) ) { pGcw_->guiDrawReadColorWord(nActualScreenCharStart, nReadLine, szCharsToDraw, nNumberOfCharsToDraw, pGctToUse ); } if ( bMustLoadGuiColorTextArrayForTags() ) { // draw tag color int nNumberOfCharsWide; GuiColorText* pGctToUseForTag; nTryScreenCharStart = 0; while ( bGetNextTagOnLine( true, // read tag pLocFrag, nTryScreenCharStart, nGetDisplayedBasesWide() - 1, nActualScreenCharStart, nNumberOfCharsWide, pGctToUseForTag ) ) { pGcw_->guiDrawHalfCharacterTag( true, // read tag nActualScreenCharStart, nReadLine, nNumberOfCharsWide, pGctToUseForTag ); } // the tag color will have covered up the letter // so draw the letter again RWCString soBasesToDraw; nTryScreenCharStart = 0; while( bGetNextTaggedBasesForRead( pLocFrag, nTryScreenCharStart, nGetDisplayedBasesWide() - 1, nActualScreenCharStart, soBasesToDraw, pGctToUse ) ) { pGcw_->guiDrawBasesWithoutBackground( true, // on read nActualScreenCharStart, nReadLine, soBasesToDraw, pGctToUse ); } } } // if the cursor is currently on a fragment, draw it. if (editCursor_.bCursorOnFrag()) { drawCursor(editCursor_.bGetBlinkState()); } } void ContigWin :: drawProteinTranslation() { char szLabel[300]; for( int nReadingFrame = 1; nReadingFrame <= 3; ++nReadingFrame ) { proteinTranslationArrayType* pProteinTranslationArray = pContigView_->pProteinTranslation_[ nReadingFrame ]; proteinTranslationScreenCharXArrayType* pProteinTranslationScreenCharXArray = pContigView_->pProteinTranslationScreenCharX_[ nReadingFrame ]; if ( consedParameters::pGetConsedParameters()->nShowProteinTranslation_ == nShowProteinTranslationTopStrand ) sprintf( szLabel, "Reading Frame %d", nReadingFrame ); else sprintf( szLabel, "Reading Frame %d", -nReadingFrame ); pGcw_->guiDrawProteinTranslationLabel( szLabel, nReadingFrame ); assert( pProteinTranslationArray->length() == pProteinTranslationScreenCharXArray->length() ); for( int nAminoAcid = 0; nAminoAcid < pProteinTranslationArray->length(); ++nAminoAcid ) { char cAminoAcid = (*pProteinTranslationArray)[ nAminoAcid ]; int nScreenCharX = (*pProteinTranslationScreenCharXArray)[ nAminoAcid ]; GuiColorText* pGctToUse; if ( cAminoAcid == 'M' ) pGctToUse = pGcw_->pGctProteinStartCodon_; else if ( cAminoAcid == '*' ) pGctToUse = pGcw_->pGctProteinStopCodon_; else pGctToUse = pGcw_->pGctProteinTranslation_; pGcw_->guiDrawAminoAcid( cAminoAcid, nScreenCharX, nReadingFrame, pGctToUse ); } } } //////////////////////////////////////////////////////////// // // PURPOSE: draws the consensus // // REV: Feb 2, 1995 (David Gordon) // //////////////////////////////////////////////////////////// void ContigWin :: drawConsensus() { pGcw_->guiDrawConsensusLabel(); char szCharsToDraw[1000]; int nNumberOfCharsToDraw; GuiColorText* pGuiColorTextToUse; int nActualScreenCharStart; int nTryScreenCharStart = 0; while( bGetNextColorWordForConsensus( nTryScreenCharStart, nGetDisplayedBasesWide(), nActualScreenCharStart, szCharsToDraw, nNumberOfCharsToDraw, pGuiColorTextToUse ) ) { pGcw_->guiDrawConsensusColorWord( nActualScreenCharStart, szCharsToDraw, nNumberOfCharsToDraw, pGuiColorTextToUse ); } // quality in shown in all colormodes. Hence show tags in all colormodes // except the one that isn't supposed to show tags. if ( pColorMode_ != GAPP->pColorMeansQuality_ ) { loadGuiColorTextArrayForConsensusTags(); // draw tag color bool bSomeTagsWereDrawn = false; int nNumberOfCharsWide; GuiColorText* pGctToUseForTag; nTryScreenCharStart = 0; while ( bGetNextTagOnLine( false, // consensus tags 0, // doesn't matter for consensus tags nTryScreenCharStart, nGetDisplayedBasesWide() - 1, nActualScreenCharStart, nNumberOfCharsWide, pGctToUseForTag ) ) { pGcw_->guiDrawHalfCharacterTag( false, // consensus tag nActualScreenCharStart, 0, // ignored for consensus tags nNumberOfCharsWide, pGctToUseForTag ); bSomeTagsWereDrawn = true; } if (bSomeTagsWereDrawn ) { // the tag color will have covered up the letter // so draw the letter again RWCString soBasesToDraw; int nActualScreenCharStart; bool bThereAreVisibleConsensusBases = bGetEntireVisibleConsensusBases( soBasesToDraw, nActualScreenCharStart ); if ( bThereAreVisibleConsensusBases ) { GuiColorText* pGctToUse = GAPP->pColorMeansQuality_->pColorConsensus99_; // just using forground // color (the color of the letter), so any base will do. pGcw_->guiDrawBasesWithoutBackground( false, // consensus tag nActualScreenCharStart, 0, // not used when drawing consensus soBasesToDraw, pGctToUse ); } } } // draw the cursor if on consensus if (editCursor_.bCursorOnCons()) { drawCursor(editCursor_.bGetBlinkState()); } pGcw_->guiDrawConsensusSeparatorLine(); } // void ContigWin :: drawReadWRItems() { // if ( pCP->nNumberOfColumnsBeforeReadNameInAlignedReadsWindow_ <= 0 ) // return; // for(int nReadLine = nIndexOfTopVisibleRead_; // nReadLine < pContigView_->nGetNumberOfFragments(); // ++nReadLine) { // LocatedFragment* pLocFrag = // pContigView_->pLocatedFragmentGet( nReadLine ); // RWCString soAbbreviation; // pLocFrag->getAbbreviationForWholeReadItems( soAbbreviation, // soColor ); // if ( !soAbbreviation.isNull() ) // pGcw_->guiDrawAbbreviationForReadWRItem( soAbbreviation, // soColor ); // } // } //////////////////////////////////////////////////////////// // // PURPOSE: draws the fragment names and direction // // REV: Feb 2, 1995 (David Gordon) // //////////////////////////////////////////////////////////// void ContigWin :: drawFragmentNames() { int nError; int nMaxReadLine = MIN( pContigView_->nGetNumberOfFragments() - 1, pGcw_->nGetDisplayedReadsHigh() + nIndexOfTopVisibleRead_ ); for(int nReadLine = nIndexOfTopVisibleRead_; nReadLine <= nMaxReadLine; ++nReadLine) { LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet( nReadLine ); if ( !pLocFrag->soReadPrefix_.isNull() ) { pGcw_->guiDrawReadPrefix( nReadLine, pLocFrag->soReadPrefix_, pLocFrag->pGctForReadPrefix_ ); } bool bIsHighlighted = pLocFrag->bReadCurrentlyHighlighted_; RWCString soReadName = pLocFrag->soGetFragmentName(); nError = pGcw_->nGuiDrawFragmentName( nReadLine, soReadName, bIsHighlighted ); bool bThisReadsTraceIsUp = bIsThisTraceDisplayed( pLocFrag ); nError = pGcw_->nGuiDrawSequencingDirectionArrow( nReadLine, pLocFrag->bComp(), bThisReadsTraceIsUp ); } } //////////////////////////////////////////////////////////// // // PURPOSE: Allows drawing a bunch of bases at once with a single // XDrawString call, rather than making an X call for each base. // This is made possible by getting a contiguous string of bases // that are to be drawn in a single color. // // HOW TO USE IT: // // // INPUTS: // pLocatedFragment, pointer to the located fragment being displayed // on the current line // nTryScreenCharStart, 'give me a color word that starts at or after // this position.' (also output) // // nRightMostScreenChar, don't bother extending the color word past here, // even if there are more bases in the same color, since they // would be off the screen // OUTPUTS: // function return: true if there was another color word. Otherwise // false // nTryScreenCharStart, positioned at the location after the color word // word returned // nActualScreenCharStart, this may differ from the initial value of // nTryScreenCharStart because the former may be a position before // the fragment actually begins. In such a case, // nActualScreenCharStart would be set to the beginning of the // fragment // pGctToUse, points to a GuiColorText object with the // graphics context of the appropriate color // // REV: Feb 2, 1995 (David Gordon) // //////////////////////////////////////////////////////////// bool ContigWin :: bGetNextColorWordForRead( LocatedFragment* pLocatedFragment, int& nTryScreenCharStart, const int nRightMostScreenChar, int& nActualScreenCharStart, char *szCharsToDraw, int& nNumberOfCharsToDraw, GuiColorText*& pGctToUse ) { int nLeftIntersectScreenChar; int nRightIntersectScreenChar; char cBase; bool bSameColor; int nConsensusPosition; int nPossibleEndOfColorWord; GuiColorText* pGctTemp; bool bThereIsAnotherColorWord = bIntersect( nTryScreenCharStart, nRightMostScreenChar, nConsensusPositionToScreenChar( pLocatedFragment->nGetAlignStart() ), nConsensusPositionToScreenChar( pLocatedFragment->nGetAlignEnd() ), nLeftIntersectScreenChar, nRightIntersectScreenChar ); if (!bThereIsAnotherColorWord) goto error_return; /*------------------------------------------------------------*/ /* handle the case in which the fragment may extend beyond the*/ /* end of the consensus length - 1 is the */ /* last consensus subscript */ /* Don't display any portion of the read that extends beyond */ /* the ends of the consensus. /*------------------------------------------------------------*/ bThereIsAnotherColorWord = bIntersect( nLeftIntersectScreenChar, nRightIntersectScreenChar, 0, nConsensusPositionToScreenChar( pContig_->nGetLastDisplayableContigPos() ), nActualScreenCharStart, nPossibleEndOfColorWord ); if (!bThereIsAnotherColorWord) goto error_return; nConsensusPosition = nScreenCharToConsensusPosition( nActualScreenCharStart ); GetColorAndBaseForRead( pLocatedFragment, nConsensusPosition, pGctToUse, cBase); szCharsToDraw[0] = cBase; nNumberOfCharsToDraw = 1; bSameColor = true; while( bSameColor ) { ++nConsensusPosition; if (nConsensusPosition <= nScreenCharToConsensusPosition( nPossibleEndOfColorWord ) ) { GetColorAndBaseForRead( pLocatedFragment, nConsensusPosition, pGctTemp, cBase ); if ( pGctTemp == pGctToUse ) { /*------------------------------------------------------------*/ /* the number of characters is 1 greater than the highest */ /* subscript */ /*------------------------------------------------------------*/ szCharsToDraw[nNumberOfCharsToDraw] = cBase; ++nNumberOfCharsToDraw; } else bSameColor = false; } else bSameColor = false; } nTryScreenCharStart = nConsensusPositionToScreenChar( nConsensusPosition ); bThereIsAnotherColorWord = true; error_return: return( bThereIsAnotherColorWord ) ; } // pack as many bases as possible into the same XDraw call that // are all the same color (and thus use the same graphics context) bool ContigWin :: bGetNextColorWordForConsensus( int& nTryScreenCharStart, const int nRightMostScreenChar, int& nActualScreenCharStart, char *szCharsToDraw, int& nNumberOfCharsToDraw, GuiColorText*& pGctToUse ) { int nLeftIntersectScreenChar; int nRightIntersectScreenChar; int nRightMostConsPosOnScreen; char cBase; bool bSameColor; int nConsensusPosition; GuiColorText* pGctTemp; bool bThereIsAnotherColorWord = bIntersect( nTryScreenCharStart, nRightMostScreenChar, nConsensusPositionToScreenChar( pContig_->nGetStartConsensusIndex() ), nConsensusPositionToScreenChar( pContig_->nGetEndConsensusIndex() ), nLeftIntersectScreenChar, nRightIntersectScreenChar ); if (!bThereIsAnotherColorWord) goto error_return; nActualScreenCharStart = nLeftIntersectScreenChar; nConsensusPosition = nScreenCharToConsensusPosition( nActualScreenCharStart ); nRightMostConsPosOnScreen = nScreenCharToConsensusPosition( nRightIntersectScreenChar ); GetColorAndBaseForConsensus( nConsensusPosition, pGctToUse, cBase); szCharsToDraw[0] = cBase; nNumberOfCharsToDraw = 1; // now see if there are other subsequent bases in the same color bSameColor = true; while( bSameColor ) { ++nConsensusPosition; if (nConsensusPosition <= nRightMostConsPosOnScreen ) { GetColorAndBaseForConsensus( nConsensusPosition, pGctTemp, cBase ); if ( pGctTemp == pGctToUse ) { /*------------------------------------------------------------*/ /* the number of characters is 1 greater than the highest */ /* subscript */ /*------------------------------------------------------------*/ szCharsToDraw[nNumberOfCharsToDraw] = cBase; ++nNumberOfCharsToDraw; } else bSameColor = false; } else bSameColor = false; } nTryScreenCharStart = nConsensusPositionToScreenChar( nConsensusPosition ); bThereIsAnotherColorWord = true; error_return: return( bThereIsAnotherColorWord ) ; } //////////////////////////////////////////////////////////// // // PURPOSE: returns a single base and a single color (guicolortext // object) for that base // // REV: Feb 2, 1995 (David Gordon) // //////////////////////////////////////////////////////////// void ContigWin :: GetColorAndBaseForRead( LocatedFragment* pLocatedFragment, const int nConsensusPosition, GuiColorText*& pGctForBase, char& cBase ) { Ntide nt = pLocatedFragment->ntGetFragFromConsPos(nConsensusPosition); cBase = nt.cGetBaseUpperOrLower(); pGctForBase = pColorMode_->pGuiColorTextGet( pLocatedFragment, nConsensusPosition); } // This is used for coloring the consensus bases void ContigWin :: GetColorAndBaseForConsensus( const int nConsensusPosition, GuiColorText*& pGctForBase, char& cBase ) { Ntide nt = pContig_->ntGetCons( nConsensusPosition ); cBase = nt.cGetBaseUpperOrLower(); // always color the consensus using the color means quality color scheme pGctForBase = GAPP->pColorMeansQuality_->pGetGuiColorTextForConsensus( pContig_, nConsensusPosition); } // if passed true, draw the cursor at the current position // if passed false, draw the normal (non-cursor) background again void ContigWin :: drawCursor(const bool bMakeVisible) { // may not be one. if (! editCursor_.bCursorValid()) { return; } // is the cursor in the current view, and if so where int nScreenCharPos; int nFragLine; bool bOnFrag; bool bCursorInView = editCursor_.bGetViewPos(this, nScreenCharPos, bOnFrag, nFragLine); if (! bCursorInView) { return; } // done if (bOnFrag) { // which located fragment is the cursor on LocatedFragment* pLocFrag = editCursor_.pLocFragGet(); Ntide nt = pLocFrag->ntGetFragFromConsPos(editCursor_.nConsPosGet()); // get the character representation of the base char szBase[2]; szBase[0] = nt.cGetBaseUpperOrLower(); szBase[1] = '\0'; // draw routine wants null terminated string RWCString soBase = szBase; GuiColorText* pGuiColorText; // which color depends on whether you're drawing or undrawing // the cursor if (bMakeVisible && editCursor_.bGetBlinkState()) { pGuiColorText = pColorMode_->pGuiColorTextCursorGet(); // tell the GuiContigWin to draw a single char at cursor pos pGcw_->guiDrawReadColorWord(nScreenCharPos, nFragLine, szBase, // null terminated 1, // number of chars to draw pGuiColorText ); } else { // draw base without cursor pGuiColorText = pColorMode_->pGuiColorTextGet(pLocFrag, editCursor_.nConsPosGet() ); pGcw_->guiDrawReadColorWord( nScreenCharPos, nFragLine, soBase, 1, // number of chars to draw pGuiColorText ); if ( bMustLoadGuiColorTextArrayForTags() ) { loadGuiColorTextArrayForTags( pLocFrag ); GuiColorText* pGuiColorTextForTag = pGetGuiColorTextForTag( editCursor_.nConsPosGet() ); if ( pGuiColorTextForTag ) { pGcw_->guiDrawHalfCharacterTag( true, // on read nScreenCharPos, nFragLine, 1, // 1 character pGuiColorTextForTag ); pGcw_->guiDrawBasesWithoutBackground( true, // on read nScreenCharPos, nFragLine, soBase, pGuiColorText ); } } // if ( bMustLoadGuiColorTextArrayForTags() ) } // if (bMakeVisible && ... ) else } else { // on consensus // get the char representation char cBase; // and draw it on the consensus line as cursor or background if ( bMakeVisible && editCursor_.bGetBlinkState() ) { GuiColorText* pGctToUse = pGcw_->pGetGctConsensusCursor(); Ntide nt = pContig_->ntGetCons(editCursor_.nConsPosGet()); cBase = nt.cGetBaseUpperOrLower(); pGcw_->guiDrawOneConsensusChar(cBase, nScreenCharPos, pGctToUse ); } else { // draw base without cursor int nConsensusPosition = editCursor_.nConsPosGet(); GuiColorText* pGctForBaseWithoutTag; GetColorAndBaseForConsensus( nConsensusPosition, pGctForBaseWithoutTag, cBase); pGcw_->guiDrawOneConsensusChar(cBase, nScreenCharPos, pGctForBaseWithoutTag ); if ( pColorMode_ != GAPP->pColorMeansQuality_ ) { loadGuiColorTextArrayForConsensusTags(); GuiColorText* pGuiColorTextForTag = pGetGuiColorTextForTag( editCursor_.nConsPosGet() ); if ( pGuiColorTextForTag ) { pGcw_->guiDrawHalfCharacterTag( false, // on consensus nScreenCharPos, 0, // ignored for consensus 1, // 1 character pGuiColorTextForTag ); pGcw_->guiDrawBasesWithoutBackground( false, // on consensus nScreenCharPos, 0, // ignored for consensus cBase, pGctForBaseWithoutTag ); } } } // if ( bMakeVisible && editCursor_.bGetBlinkState() ) { else } // if (bOnFrag) { else } void ContigWin :: popupTracesByConsensusPosition( LocatedFragment* pLocatedFragment, const int nConsensusPosition ) { if ( bErrorMessageIfNoPhd() ) return; try { // read ABI file (if it hasn't already been read ) pLocatedFragment->readTraces( true ); // ask user for pathname of traces // if can't find them } catch(SysRequestFailed srf ) { throw srf; } catch (ExceptionBase eb) { // failed for whatever reason. tell the user popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), eb.szGetDesc()); eb.setUserNotified(); // will not be reported again throw eb; // in case anybody else cares } // if there is a teditor up that has a scrolling list of all traces, // bring it down for now and recreate it with just the trace we // are trying to bring up if ( pTeditor_ ) { if ( pTeditor_->pGuiTeditor_->bShowTracesInScrollingWindow_ ) delete pTeditor_; } if (pTeditor_ == NULL ) { // this exception handling is to catch the case of // the user trying to bring up a trace when he started // consed -nophd try { pTeditor_ = new Teditor( this, 1, // number of traces for teditor false // not in scrolling window ); } catch( ExceptionBase eb ) { // failed for whatever reason. tell the user if ( !eb.bUserNotified() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), eb.szGetDesc()); eb.setUserNotified(); // will not be reported again } throw eb; // in case anybody else cares } } else { const int nNumberOfTracesToAdd = 1; pTeditor_->deleteTedWinsIfTooMany( nNumberOfTracesToAdd ); pTeditor_->pGuiTeditorGet()->enlargeTeditor( nNumberOfTracesToAdd ); pTeditor_->pGuiTeditorGet()->repartitionTraceWindow( nNumberOfTracesToAdd ); pTeditor_->pGuiTeditorGet()->moveDownExistingTraces( nNumberOfTracesToAdd ); } TedWin* pNewTedWin; try { pNewTedWin = new TedWin( pTeditor_, nConsensusPosition, pLocatedFragment, 0, // position this trace at the top false ); // bAddToScrollingWindow } catch (...) { // failed for any reason // do not re-throw. assume it's been dealt with and carry on. // if we just brought up a Teditor for this failed TedWin, // the bring down the Teditor if (pTeditor_->nNumberOfTedWins() == 0 ) delete pTeditor_; } pTeditor_->alignToThisTraceIfScrollingTogether( pNewTedWin ); pTeditor_->raiseTracesWindow(); } //////////////////////////////////////////////////////////// // // PURPOSE: to popup the traces for a particular fragment // // // HOW TO USE IT: called from gui side, which translates all // pixel coordinates to character positions // // // INPUTS: 0-based x and y character positions within the // fragment bases portion of the screen // // OUTPUTS: nix // // REV: Feb 28, 1995 (David Gordon) // //////////////////////////////////////////////////////////// void ContigWin :: popupTracesByCursorPosition( const int nScreenCharX, const int nReadLine) { LocatedFragment *pLocatedFragment; int nConsensusPosition; pLocatedFragment = pContigView_->pLocatedFragmentGet( nReadLine ); // did they miss the fragment? i.e. there is a fragment on that // line but no base at that position? nConsensusPosition = nScreenCharToConsensusPosition( nScreenCharX ); if ((nConsensusPosition < pLocatedFragment->nGetAlignStart()) || (nConsensusPosition > pLocatedFragment->nGetAlignEnd())) { return; } // whether or not they get the trace file, the cursor is moved here moveCursorToFragChar(nScreenCharX, nReadLine ); scrollExistingTracesOrPopupIfNecessary( pLocatedFragment, nConsensusPosition ); } void ContigWin :: popup4BestTracesByCursorPosition( const int nScreenCharX ) { int nConsensusPosition; // did they miss the fragment? i.e. there is a fragment on that // line but no base at that position? nConsensusPosition = nScreenCharToConsensusPosition( nScreenCharX ); if ( !pContig_->bIsOnConsensus( nConsensusPosition ) ) { return; } // whether or not they get the trace file, the cursor is moved here moveCursorToConsPos( nConsensusPosition ); popup4BestTracesByConsensusPosition( nConsensusPosition ); } void ContigWin :: popup4BestTracesByConsensusPosition( const int nConsPos ) { if ( bErrorMessageIfNoPhd() ) return; LocatedFragment* pLocFrag[4]; find4BestReads( nConsPos, pLocFrag[0], pLocFrag[1], pLocFrag[2], pLocFrag[3] ); int nNumberOfTracesToAdd = 0; try { for( int nRead = 0; nRead < 4; ++nRead ) { // read ABI file (if it hasn't already been read ) if (pLocFrag[ nRead ] ) { pLocFrag[ nRead ]->readTraces( true ); // ask user for pathname if can't open traces ++nNumberOfTracesToAdd; } } } catch(SysRequestFailed srf ) { throw srf; } catch (ExceptionBase eb) { // failed for whatever reason. tell the user popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), eb.szGetDesc()); eb.setUserNotified(); // will not be reported again throw eb; // in case anybody else cares } // if there is a teditor up that has a scrolling list of all traces, // bring it down for now and recreate it with just the trace we // are trying to bring up if ( pTeditor_ ) { if ( pTeditor_->pGuiTeditor_->bShowTracesInScrollingWindow_ ) delete pTeditor_; } if (pTeditor_ == NULL ) { // this exception handling is to catch the case of // the user trying to bring up a trace when he started // consed -nophd try { pTeditor_ = new Teditor( this, nNumberOfTracesToAdd, false ); // not in scrolling window } catch( ExceptionBase eb ) { // failed for whatever reason. tell the user if ( !eb.bUserNotified() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), eb.szGetDesc()); eb.setUserNotified(); // will not be reported again } throw eb; // in case anybody else cares } } else { pTeditor_->deleteTedWinsIfTooMany( nNumberOfTracesToAdd ); pTeditor_->pGuiTeditorGet()->enlargeTeditor( nNumberOfTracesToAdd ); pTeditor_->pGuiTeditorGet()->repartitionTraceWindow( nNumberOfTracesToAdd ); pTeditor_->pGuiTeditorGet()->moveDownExistingTraces( nNumberOfTracesToAdd ); pTeditor_->raiseTracesWindow(); } TedWin* pNewTedWin[4]; int nPositionOnScreen = nNumberOfTracesToAdd - 1; for( int nRead = 3; nRead >= 0; --nRead ) { // there may be some reads that don't exist (e.g., there may // be no read that disagrees with the consensus on the top strand ) if (pLocFrag[ nRead ] ) { try { pNewTedWin[ nRead ] = new TedWin( pTeditor_, nConsPos, pLocFrag[nRead], nPositionOnScreen, // position here false ); // bAddToScrollingWindow --nPositionOnScreen; } catch (...) { // failed for any reason // do not re-throw. assume it's been dealt with and carry on. } } } // set cursor on one of the 4 reads if ( pLocFrag[0] && pLocFrag[0]->bIsInRead( nConsPos ) ) { moveCursorToFragPos( nConsPos, pLocFrag[0] ); pTeditor_->alignToThisTraceIfScrollingTogether( pNewTedWin[0] ); } else if ( pLocFrag[2] && pLocFrag[2]->bIsInRead( nConsPos ) ) { moveCursorToFragPos( nConsPos, pLocFrag[2] ); pTeditor_->alignToThisTraceIfScrollingTogether( pNewTedWin[2] ); } else if ( pLocFrag[1] && pLocFrag[1]->bIsInRead( nConsPos )) { moveCursorToFragPos( nConsPos, pLocFrag[1] ); pTeditor_->alignToThisTraceIfScrollingTogether( pNewTedWin[1] ); } else if ( pLocFrag[3] && pLocFrag[3]->bIsInRead( nConsPos )) { moveCursorToFragPos( nConsPos, pLocFrag[3] ); pTeditor_->alignToThisTraceIfScrollingTogether( pNewTedWin[3] ); } // if we just brought up a Teditor for this failed TedWin, // the bring down the Teditor if (pTeditor_->nNumberOfTedWins() == 0 ) delete pTeditor_; } void ContigWin :: scrollExistingTracesOrPopupIfNecessary( LocatedFragment* pLocatedFragment, const int nConsensusPosition ) { bool bPopupTraces = false; if ( pTeditor_ ) { if ( pTeditor_->pGuiTeditor_->bShowTracesInScrollingWindow_ ) bPopupTraces = true; else { TedWin* pTedWin = pGetTedWinByLocatedFragment( pLocatedFragment ); if ( pTedWin ) { pTeditor_->raiseTracesWindow(); pTedWin->scrollToConsPosAndRefresh(nConsensusPosition - nOffsetToPutBaseInTheMiddle ); bPopupTraces = false; } else bPopupTraces = true; } } // if ( pTeditor_ ) { else bPopupTraces = true; if ( bPopupTraces ) popupTracesByConsensusPosition( pLocatedFragment, nConsensusPosition ); } TedWin* ContigWin :: pGetTedWinByLocatedFragment( LocatedFragment* pLocatedFragment ) { TedWin* pTedWin = NULL; if (pTeditor_ ) { // NULL is returned if no TedWin contains this located fragment pTedWin = pTeditor_->pGetTedWinByLocatedFragment( pLocatedFragment ); } // return NULL if no TedWin contains this located fragment return( pTedWin ); } //////////////////////////////////////////////////////////// // // PURPOSE: // // HOW TO USE IT: must be called whenever a new contig view is created // // INPUTS: nix // // OUTPUTS: nix // // REV: (David Gordon) // //////////////////////////////////////////////////////////// void ContigWin :: setTopAndBottomVisibleFragments() { nIndexOfTopVisibleRead_ = 0; } // this is called as a result of the comp contig button being pressed. // affects the Contig, LocatedFragments, etc. but does not // cause refresh or repositioning. that gets done when a refresh // message comes back from the ConsEd. void ContigWin :: complementContig() { EditAction *pEditAction = new EditComplementContig( pContig_ ); PleaseWait* pPleaseWait = new PleaseWait( pGcw_->widGetGuiContigWinTopLevel() ); ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); delete pPleaseWait; } // called by the ConsEd to inform the ContigWin of edit action // that has completed and will now (most likely) require a // refresh of the ContigWin and its child teditor // // now deactivates undo button on any windows other than // the one the editaction came from void ContigWin :: editNotify(EditAction* pEdAct) { // call the virtual function to refresh a ContigWin // this does seem a little strange... pEdAct->refreshContigWin(this); if (pTeditor_ ) { pEdAct->refreshTeditor( pTeditor_ ); // tell the Teditor to appropriately set the undo buttons on // all its child tedwins to be active or not, according // to whether or not they were the one that initiated the // edit action pTeditor_->setTedWinsUndoButtonState(); } // that didn't hurt a bit, now did it? } void ContigWin :: refreshContigWinAndTeditor() { drawBasesAndConsensus( true ); // erase first if (pTeditor_ ) pTeditor_->refreshAllTedWins( false ); // no need to recalculate // base positions } // called by the complement edit action's refresh routine. // scroll the contig win so that it points to the same // strech of dna (now at the other "end") after complementation. void ContigWin :: refreshAfterCompContig() { // right edge becomes left edge // int nNewLeftEdgeConsPos = nGetRightEdgeConsensusPosition(); // this didn't work because nGetRightEdgeConsensusPosition() uses // pContig_->nGetLastDisplayableContigPos() which has already been // modified and thus is no longer valid. So I will have to calculate // directly: int nNewLeftEdgeConsPos = nLeftEdgeConsensusPosition_ + nGetDisplayedBasesWide() - 1; // this might be further to the // right than any read, so need to do a check below after complementing // this coordinate. // transform the coordinate pContig_->complement_coordinate(nNewLeftEdgeConsPos); // now check that this is within the range of // nFirstDisplayableContigPos_ to nLastDisplayableContigPos_ if ( nNewLeftEdgeConsPos < pContig_->nFirstDisplayableContigPos_ ) nNewLeftEdgeConsPos = pContig_->nFirstDisplayableContigPos_; if ( pContig_->nLastDisplayableContigPos_ < nNewLeftEdgeConsPos ) nNewLeftEdgeConsPos = pContig_->nLastDisplayableContigPos_; // transform the cursor position editCursor_.complementPosition(); // since slider positions are done in terms of the consensus // positions and not 0 based, the slider must be reset to // reflect the new max and min vals, etc. setSliderForNewContig(); // now scroll to the new location. // scrolling routine will make sure we're not off either edge. scrollToConsensusPos(nNewLeftEdgeConsPos); } int ContigWin :: nGetDisplayedBasesWide() const { return pGcw_->nGetDisplayedBasesWide(); } // moves the cursor to the passed consensus relative position // or as close to it as can get. Sets the editCursor_ // member to reflect the new position. void ContigWin :: moveCursorToConsPos(const int nConsPos ) { if ( !pContig_->bIsOnConsensus( nConsPos ) ) return; // clear the cursor from all child tedwins prior to move drawTeditorCursors(false); // remove old cursor from this ContigWin drawCursor(false); // move the cursor to its new position editCursor_.setCursorOnCons(pContig_, nConsPos); pContigView_->maybeSortReadsAtCursor( nConsPos ); displayHowReadsAreSorted(); // also scroll traces if move the cursor if ( pTeditor_ ) { // don't scroll the teditor if it contains all the traces--it // will take forever. Instead, recreate it. if ( ! pTeditor_->pGuiTeditor_->bShowTracesInScrollingWindow_ ) { // pTeditor_->drawVerticalLineThroughTracesOfAllTedWins( nConsPos ); TedWin* pTedWin = pTeditor_->pGetGuiTedWinScrollMaster()->pTedWinGet(); pTedWin->scrollToConsPosAndRefresh(nConsPos - nOffsetToPutBaseInTheMiddle ); } } // if there is a vertical line, when the cursor is moved, we must // erase the window first and redraw all of the reads if ( pCP->bPutVerticalLineAtCursor_ ) { drawBasesAndConsensus( true ); } // draw it on this ContigWin drawCursor(true); // and draw it on all child tedwins, if appropriate drawTeditorCursors(true); drawVerticalLineAtCursorIfNecessary(); } // moves the cursor to the passed screen relative position // or as close to it as can get. Sets the editCursor_ // member to reflect the new position. void ContigWin :: moveCursorToConsCharXPos(const int nScreenCharXPos) { // convert screen coordinate to consensus position int nConsPos = nScreenCharToConsensusPosition(nScreenCharXPos); // and call above if (! pContig_->bIsOnConsensus( nConsPos ) ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "Cursor must be set on consensus or fragment bases" ); return; } moveCursorToConsPos(nConsPos ); } // moves the cursor to the passed screen relative position // or as close to it as can get. // Sets // the editCursor_ member to reflect the new position. void ContigWin :: moveCursorToFragChar(const int nScreenCharXPos, const int nFragLine) { // convert screen coordinate to consensus position int nConsPos = nScreenCharToConsensusPosition(nScreenCharXPos); // get the located fragment pointer for that screen line if (nFragLine >= pContigView_->nGetNumberOfFragments()) { return; // do nothing } LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet(nFragLine); // does the frag have a base at that location ? if ((nConsPos < pLocFrag->nGetAlignStart()) || (nConsPos > pLocFrag->nGetAlignEnd())) { return; } // clear the cursor from all child tedwins prior to move drawTeditorCursors(false); // remove old cursor from this ContigWin drawCursor(false); // move the cursor to its new position editCursor_.setCursorOnFrag(pLocFrag, nConsPos); // also scroll traces if move the cursor if ( pTeditor_ ) { pTeditor_->reAlignTracesSinceCursorChanged( pLocFrag ); TedWin* pTedWin = pTeditor_->pGetGuiTedWinScrollMaster()->pTedWinGet(); pTedWin->scrollToConsPosAndRefresh(nConsPos - nOffsetToPutBaseInTheMiddle ); } // if there is a vertical line, when the cursor is moved, we must // erase the window first and redraw all of the reads if ( pCP->bPutVerticalLineAtCursor_ ) { drawBasesAndConsensus( true ); } // draw it on this ContigWin drawCursor(editCursor_.bGetBlinkState()); // and draw it on all child tedwins drawTeditorCursors(true); drawVerticalLineAtCursorIfNecessary(); } // this version of above is called by the child TedWins, // and does the same thing only takes arguments of // the pointer to the located fragment and the // consensus relative position in the fragment void ContigWin :: moveCursorToFragPos(const int nConsPos, LocatedFragment* pLocFrag) { // does the frag have a base at that location ? if ((nConsPos < pLocFrag->nGetAlignStart()) || (nConsPos > pLocFrag->nGetAlignEnd())) { assert (false); } scrollToConsensusPosInCenter( nConsPos ); verticalScrollToMakeThisReadVisible( pLocFrag ); // clear the cursor from all child tedwins prior to move drawTeditorCursors(false); // remove old cursor from this ContigWin drawCursor(false); // move the cursor to its new position editCursor_.setCursorOnFrag(pLocFrag, nConsPos); // draw it on this ContigWin drawCursor( true ); if ( pTeditor_ ) { // do *NOT* change the master trace just because the cursor // moves if the user moves the cursor in the // show all traces modeu if ( !pTeditor_->pGuiTeditor_->bShowTracesInScrollingWindow_ ) pTeditor_->reAlignTracesSinceCursorChanged( pLocFrag ); } // and draw it on all child tedwins drawTeditorCursors(true); drawVerticalLineAtCursorIfNecessary(); } // this version of above is called by the child TedWins, // and does the same thing only takes arguments of // the pointer to the located fragment and the // consensus relative position in the fragment void ContigWin :: moveCursorToNextReadPos( LocatedFragment* pLocFrag ) { // clear the cursor from all child tedwins prior to move drawTeditorCursors(false); // remove old cursor from this ContigWin drawCursor(false); // move the cursor to its new position editCursor_.advanceCursorAlongRead(); // draw it on this ContigWin drawCursor( true ); if ( pTeditor_ ) { pTeditor_->reAlignTracesSinceCursorChanged( pLocFrag ); } // and draw it on all child tedwins drawTeditorCursors(true); drawVerticalLineAtCursorIfNecessary(); } // sends a message to Teditor to draw // its cursor if appropriate void ContigWin :: drawTeditorCursors(const bool bMakeVisible) { if (pTeditor_ ) pTeditor_->drawCursors(bMakeVisible); } void ContigWin :: clearAllCursors() { drawCursor( false ); // redraw base without red // redraw all these bases without the red if ( pTeditor_ ) { for( int nTw = 0; nTw < pTeditor_->dapTedWin_.length(); ++nTw ) { pTeditor_->dapTedWin_[ nTw ]->drawCursor( false ); } } // there is only one EditCursor object for the Aligned Reads Window // and all trace windows editCursor_.unsetCursor(); // clear cursor so subsequent blinks have no effect } void ContigWin :: setAceFileLabel( const RWCString& soAssemblyName ) { pGcw_->setAceFileLabel( soAssemblyName ); } // given a pixel value that we already know falls in // one of the fragment base lines, which line is it? // does not include separator between for and rev, // first visible line is 0 // chrisa 8-mar-95 // // dg: // // the plus 1 is so that it starts on the next pixel // // pixel // ------------------------- // // descent // descent + 1 (so zero starts here) // // // ------------------------- nFragmentBasesBaselinePixelY_ // // // descent (and goes to here) // descent + 1 (and 1 starts here) int ContigWin :: nFragLineFromPixelY(const int nPixelY) const { int nReadLine = nIndexOfTopVisibleRead_; bool bFound = false; while(! bFound && nReadLine < pContigView_->nGetNumberOfFragments() ) { if ( nPixelY <= ( pGcw_->nFragLineToPixelY( nReadLine ) + GuiApp::pGetGuiApp()->nGetFontDescent() - 1 ) ) { bFound = true; } else ++nReadLine; } if (bFound) { return( nReadLine ); } else return( -1 ); } int ContigWin :: nGetFragmentBasesMaxPixelY() { int nIndexOfBottomRead = pContigView_->nGetNumberOfFragments() - 1; int nPixelBaseline = pGcw_->nFragLineToPixelY( nIndexOfBottomRead ); int nPixelBottom = nPixelBaseline + GuiApp::nGetFontDescent() - 1; return( nPixelBottom ); } bool ContigWin :: bTagIsOnScreen( tag* pTag, LocatedFragment* pLocFrag, int& nLeftIntersectConsPos, int& nRightIntersectConsPos ) { int nLeftConsPos = pTag->nPaddedConsPosStart_; int nRightConsPos = pTag->nPaddedConsPosEnd_; return( bIsOnScreen( nLeftConsPos, nRightConsPos, nLeftIntersectConsPos, nRightIntersectConsPos ) ); } // checks whether a segment, from nLeftConsPos to nRightConsPos, is // on the screen bool ContigWin :: bIsOnScreen( const int nLeftConsPos, const int nRightConsPos, int& nLeftIntersectConsPos, int& nRightIntersectConsPos ) { int nLeftConsPos2 = nLeftEdgeConsensusPosition_; int nRightConsPos2 = nGetRightEdgeConsensusPosition(); bool bIsOnScreenn = bIntersect( nLeftConsPos, nRightConsPos, nLeftConsPos2, nRightConsPos2, nLeftIntersectConsPos, nRightIntersectConsPos ); return( bIsOnScreenn ); } void ContigWin :: popupTagInfoForTagsAtThisLocation( const int nScreenCharX, const int nFragLine ) { int nConsPos = nScreenCharToConsensusPosition( nScreenCharX ); LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet(nFragLine); int nNumberOfTagsPoppedUp = 0; for( int n = 0; n < pLocFrag->nGetNumberOfTags(); ++n ) { tag* pTag = pLocFrag->pGetTag( n ); if (pTag->bTouchesThisConsPos( nConsPos ) ) { pTag->popupTagInfoForOneTag( nNumberOfTagsPoppedUp, (void*) pGcw_, true); // bIsGuiContigWin ++nNumberOfTagsPoppedUp; } } } void ContigWin :: popupTagInfoForConsensusTagsAtThisLocation( const int nScreenCharX ) { int nConsPos = nScreenCharToConsensusPosition( nScreenCharX ); int nNumberOfTagsPoppedUp = 0; for( int n = 0; n < pContig_->nGetNumberOfTags(); ++n ) { tag* pTag = pContig_->pGetTag( n ); if (pTag->bTouchesThisConsPos( nConsPos ) ) { pTag->popupTagInfoForOneTag( nNumberOfTagsPoppedUp, (void*) pGcw_, true); // bIsGuiContigWin ++nNumberOfTagsPoppedUp; } } } void ContigWin :: loadGuiColorTextArrayForTags( LocatedFragment* pLocFrag ) { int nScreenConsPosMin = nLeftEdgeConsensusPosition_; int nScreenConsPosMax = nGetRightEdgeConsensusPosition(); aGuiColorTextArray_.resize( nScreenConsPosMax - nScreenConsPosMin + 1 ); for( int nConsPos = nScreenConsPosMin; nConsPos <= nScreenConsPosMax; ++nConsPos ) { aGuiColorTextArray_[ nConsPos - nScreenConsPosMin ] = 0; } for( int nTag = 0; nTag < pLocFrag->nGetNumberOfTags(); ++nTag ) { tag* pTag = pLocFrag->pGetTag( nTag ); if ( !tagTypes::pGetTagTypes()->bCurrentlyShowAllTagTypes_ ) { if ( tagTypes::pGetTagTypes()->bAreTagsOfThisTypeHidden( pTag->soType_ ) ) continue; } int nDrawTagConsPosMin; int nDrawTagConsPosMax; if (pTag->bTagIsOnScreen( nScreenConsPosMin, nScreenConsPosMax, nDrawTagConsPosMin, nDrawTagConsPosMax ) ) { GuiColorText* pGctToUse = tagTypes::pGetTagTypes()->pGetGuiColorTextForTag( pTag ); for( int nConsPos = nDrawTagConsPosMin; nConsPos <= nDrawTagConsPosMax; ++nConsPos ) { if ( aGuiColorTextArray_[ nConsPos - nScreenConsPosMin ] ) aGuiColorTextArray_[ nConsPos - nScreenConsPosMin ] = tagTypes::pGetTagTypes()->pGetGuiColorTextForTagsOverlap(); else aGuiColorTextArray_[ nConsPos - nScreenConsPosMin ] = pGctToUse; } } // if (bTagIsOnScreen ... } // for (nTag = 0 ... } void ContigWin :: loadGuiColorTextArrayForConsensusTags( ) { int nScreenConsPosMin = nLeftEdgeConsensusPosition_; int nScreenConsPosMax = nGetRightEdgeConsensusPosition(); aGuiColorTextArray_.resize( nScreenConsPosMax - nScreenConsPosMin + 1 ); for( int nConsPos = nScreenConsPosMin; nConsPos <= nScreenConsPosMax; ++nConsPos ) { aGuiColorTextArray_[ nConsPos - nScreenConsPosMin ] = 0; } for( int nTag = 0; nTag < pContig_->nGetNumberOfTags(); ++nTag ) { tag* pTag = pContig_->pGetTag( nTag ); if ( !tagTypes::pGetTagTypes()->bCurrentlyShowAllTagTypes_ ) { if ( tagTypes::pGetTagTypes()->bAreTagsOfThisTypeHidden( pTag->soType_ ) ) continue; } int nDrawTagConsPosMin; int nDrawTagConsPosMax; if (pTag->bTagIsOnScreen( nScreenConsPosMin, nScreenConsPosMax, nDrawTagConsPosMin, nDrawTagConsPosMax ) ) { for( int nConsPos = nDrawTagConsPosMin; nConsPos <= nDrawTagConsPosMax; ++nConsPos ) { if ( aGuiColorTextArray_[ nConsPos - nScreenConsPosMin ] ) aGuiColorTextArray_[ nConsPos - nScreenConsPosMin ] = tagTypes::pGetTagTypes()->pGetGuiColorTextForTagsOverlap(); else { bool bLoadedBase = false; if ( pTag->soType_ == "oligo" ) { if ( ((oligoTag*) pTag)->bIsThisThe3PrimeEnd( nConsPos ) ) { aGuiColorTextArray_[ nConsPos - nScreenConsPosMin ] = tagTypes::pGetTagTypes()->pGetGuiColorTextForTagType( "oligo3PrimeEnd" ); bLoadedBase = true; } } if ( !bLoadedBase ) { aGuiColorTextArray_[ nConsPos - nScreenConsPosMin ] = tagTypes::pGetTagTypes()->pGetGuiColorTextForTag( pTag ); } } } } // if (bTagIsOnScreen ... } // for (nTag = 0 ... } GuiColorText* ContigWin :: pGetGuiColorTextForTag( const int nConsPos ) { int nScreenChar = nConsensusPositionToScreenChar( nConsPos ); return( aGuiColorTextArray_[ nScreenChar ] ); } bool ContigWin :: bGetNextTagOnLine( const bool bReadNotConsensusTag, LocatedFragment* pLocFrag, int& nTryScreenCharStart, const int nRightMostScreenChar, int& nActualScreenCharStart, int& nNumberOfCharsWide, GuiColorText*& pGctToUseForTag ) { int nScreenCharSequenceStart; int nScreenCharSequenceEnd; if ( bReadNotConsensusTag ) { nScreenCharSequenceStart = nConsensusPositionToScreenChar( pLocFrag->nGetAlignStart() ); nScreenCharSequenceEnd = nConsensusPositionToScreenChar( pLocFrag->nGetAlignEnd() ); } else { nScreenCharSequenceStart = nConsensusPositionToScreenChar( pContig_->nGetStartConsensusIndex() ); nScreenCharSequenceEnd = nConsensusPositionToScreenChar( pContig_->nGetEndConsensusIndex() ); } int nLeftIntersectScreenChar; int nRightIntersectScreenChar; bool bThereIsAnotherColorWord = bIntersect( nTryScreenCharStart, nRightMostScreenChar, nScreenCharSequenceStart, nScreenCharSequenceEnd, nLeftIntersectScreenChar, nRightIntersectScreenChar ); if (!bThereIsAnotherColorWord) return( false ); // find first base for which there is a tag nActualScreenCharStart = nLeftIntersectScreenChar; bool bFound = false; while( !bFound && nActualScreenCharStart <= nRightIntersectScreenChar ) { if ( aGuiColorTextArray_[ nActualScreenCharStart ] ) bFound = true; else ++nActualScreenCharStart; } // return if no more tags on this line if (!bFound ) return( false ); pGctToUseForTag = aGuiColorTextArray_[ nActualScreenCharStart ]; // now see how long this tag color lasts int nCurrentScreenPosition = nActualScreenCharStart + 1; bool bSame = true; while( bSame && nCurrentScreenPosition <= nRightIntersectScreenChar ) { if ( aGuiColorTextArray_[ nCurrentScreenPosition ] == pGctToUseForTag ) ++nCurrentScreenPosition; else bSame = false; } // nCurrentScreenPosition is now 1 too big--it is either on a different // tag color, or else it is past the rightmost position on the screen nNumberOfCharsWide = nCurrentScreenPosition - nActualScreenCharStart; // set up for next time nTryScreenCharStart = nCurrentScreenPosition; return( true ); } bool ContigWin :: bGetNextTaggedBasesForRead( LocatedFragment* pLocFrag, int& nTryScreenCharStart, const int nRightMostScreenChar, int& nActualScreenCharStart, RWCString& soBasesToDraw, GuiColorText*& pGctToUse ) { int nLeftIntersectScreenChar; int nRightIntersectScreenChar; bool bThereIsAnotherColorWord = bIntersect( nTryScreenCharStart, nRightMostScreenChar, nConsensusPositionToScreenChar( pLocFrag->nGetAlignStart() ), nConsensusPositionToScreenChar( pLocFrag->nGetAlignEnd() ), nLeftIntersectScreenChar, nRightIntersectScreenChar ); if (!bThereIsAnotherColorWord) return( false ); // find first base for which there is a tag nActualScreenCharStart = nLeftIntersectScreenChar; bool bFound = false; while( !bFound && nActualScreenCharStart <= nRightIntersectScreenChar ) { if ( aGuiColorTextArray_[ nActualScreenCharStart ] ) bFound = true; else ++nActualScreenCharStart; } // return if no more tags on this line if (!bFound ) return( false ); int nConsPos = nScreenCharToConsensusPosition( nActualScreenCharStart ); pGctToUse = pColorMode_->pGuiColorTextGetForeground( pLocFrag, nConsPos ); soBasesToDraw = pLocFrag->ntGetFragFromConsPos( nConsPos ).cGetBaseUpperOrLower(); // now see how long this tag color lasts int nCurrentScreenPosition = nActualScreenCharStart + 1; bool bSame = true; while( bSame && nCurrentScreenPosition <= nRightIntersectScreenChar ) { if ( aGuiColorTextArray_[ nCurrentScreenPosition ] ) { nConsPos = nScreenCharToConsensusPosition( nCurrentScreenPosition ); GuiColorText* pGctTemp = pColorMode_->pGuiColorTextGetForeground( pLocFrag, nConsPos ); if ( pGctToUse == pGctTemp ) { soBasesToDraw += pLocFrag->ntGetFragFromConsPos( nConsPos ).cGetBaseUpperOrLower(); ++nCurrentScreenPosition; } else bSame = false; } else bSame = false; } // set up for next time nTryScreenCharStart = nCurrentScreenPosition; return( true ); } void ContigWin :: userReleasedMouseButton1( const int nPixelX, const int nPixelY ) { // must stop automatic scrolling, if it is still going on pGcw_->stopAutomaticScrollingIfNecessary(); selection* pSelection = ConsEd::pGetConsEd()->pGetSelection(); int nConsPosLeft; int nConsPosRight; LocatedFragment* pLocFrag; bool bSelectionActive; Contig* pContig; pSelection->getSelection(nConsPosLeft, nConsPosRight, pLocFrag, pContig, bSelectionActive); if ( !bSelectionActive ) return; if ( pSelection->bIsOnConsensusNotRead() ) { makeSelectionFromConsensus( nConsPosLeft, nConsPosRight ); } else { makeSelectionFromARead( pLocFrag, nConsPosLeft, nConsPosRight ); } } void ContigWin :: clearHighlight() { selection* pSelection = ConsEd::pGetConsEd()->pGetSelection(); if ( pSelection->bSelectionActive_ ) { if ( pSelection->bIsOnConsensusNotRead() ) drawConsensus(); else drawBases(); } pSelection->bSelectionActive_ = false; } void ContigWin :: startHighlight( const int nScreenCharX, const bool bConsensusNotRead, const int nReadLine ) { // unhighlight any old highlighted bases: clearHighlight(); int nConsPos = nScreenCharToConsensusPosition( nScreenCharX ); if (bConsensusNotRead ) { if ( nConsPos < pContig_->nGetStartIndex() || pContig_->nGetEndIndex() < nConsPos ) { popupErrorMessage( "If you are highlighting the consensus, you must be on the consensus" ); return; } ConsEd::pGetConsEd()->pGetSelection()->startSelection( NULL, pContig_, nConsPos ); } else { LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet(nReadLine); if ( !pLocFrag->bIsInRead( nConsPos ) ) { popupErrorMessage( "If you are highlighting the read, you must be on the read bases" ); return; } ConsEd::pGetConsEd()->pGetSelection()->startSelection( pLocFrag, NULL, nConsPos ); } } // just called via a motion event void ContigWin :: continueHighlight( const int nPixelX, const int nPixelY ) { pGcw_->handleMovingMouseOffOrBackIntoWindow( nPixelX ); int nScreenCharX = pGcw_->nCharXFromPixel( nPixelX ); // if ( nScreenCharX == nButton1PressedScreenX_ ) return; int nConsPos = nScreenCharToConsensusPosition( nScreenCharX ); continueHighlight3( nConsPos ); } // can be called either via a motion event or a timer expiring void ContigWin :: continueHighlight3( const int nConsPos ) { selection* pSelection = ConsEd::pGetConsEd()->pGetSelection(); if ( !pSelection->bSelectionActive_ ) return; if ( pSelection->bIsOnConsensusNotRead() ) { // do not extend consensus selections beyond the end of the consensus if ( nConsPos < pContig_->nGetStartIndex() || pContig_->nGetEndIndex() < nConsPos ) { GuiApp::beep(); return; } } else { // do not extend consensus selections beyond the end of the read if ( nConsPos < pSelection->pLocatedFragment_->nGetAlignStart() || pSelection->pLocatedFragment_->nGetAlignEnd() < nConsPos ) { GuiApp::beep(); return; } } if ( pSelection->nExtendSelection( nConsPos ) != ERR_NO_NEED_TO_EXTEND ) { if ( pSelection->bIsOnConsensusNotRead() ) { drawConsensus(); } else { drawBases(); } drawHighlightedBases(); } } void ContigWin :: highlightFinished() { int nConsensusPosLeft; int nConsensusPosRight; LocatedFragment* pDummyLocatedFragment; bool bSelectionActive; Contig* pContig; // must stop automatic scrolling, if it is still going on pGcw_->stopAutomaticScrollingIfNecessary(); ConsEd::pGetConsEd()->pGetSelection()->getSelection(nConsensusPosLeft, nConsensusPosRight, pDummyLocatedFragment, pContig, bSelectionActive); // case in which someone presses down button outside the consensus and // then finishes inside the consensus if ( ! bSelectionActive ) return; if ( ConsEd::pGetConsEd()->pGetSelection()->bIsOnConsensusNotRead() ) { assert( pContig ); guiGetTagType* pGuiGetTagType = new guiGetTagType(); bool bUserPushedCancel; RWCString soComment; RWCString soContigName; RWCString soTagType; tagType::readOrConsensusType readOrConsensusTypeUserWants; pGuiGetTagType->popupBoxAndWaitForUserToSelectTagType2( soTagType, bUserPushedCancel, true, // only tag types // that can be // created by swiping readOrConsensusTypeUserWants, true, // bAllowUserToEnterComment soComment, soContigName ); delete pGuiGetTagType; if ( bUserPushedCancel ) { // clear selection and unhighlight the region ConsEd::pGetConsEd()->pGetSelection()->unsetSelection(); drawConsensus(); return; } if ( readOrConsensusTypeUserWants == tagType::consensus ) { tag* pTag = tagTypes::pGetTagTypes()->pCreateConsensusTag( soTagType, soComment, nConsensusPosLeft, nConsensusPosRight, pContig, false, // no NoTrans bUserPushedCancel, soContigName ); if ( bUserPushedCancel ) { ConsEd::pGetConsEd()->pGetSelection()->unsetSelection(); drawConsensus(); return; } ConsEd::pGetConsEd()->pGetSelection()->unsetSelection(); EditAction* pEditAction = new editAddConsensusTag( pTag ); ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); } // if ( readOrConsensusTypeUserWants == readType::consensus ) { else { // tag all reads ConsEd::pGetConsEd()->pGetSelection()->unsetSelection(); EditAction* pEditAction = new editAddTagsToAllReadsAtConsPos( pContig, nConsensusPosLeft, nConsensusPosRight, soTagType, soComment ); ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); } // if ( readOrConsensusTypeUserWants == readType::consensus ) { else } } // what happens when scrolling timer expires void ContigWin :: automaticScrollingTimer() { automaticallyScroll(); int nExtendToConsPos; if ( pGcw_->bAutomaticallyScrollLeftNotRight_ ) nExtendToConsPos = nLeftEdgeConsensusPosition_; else nExtendToConsPos = nGetRightEdgeConsensusPosition(); continueHighlight3( nExtendToConsPos ); } void ContigWin :: automaticallyScroll() { // where is the mouse? Can I interrogate it to make sure it is still // off the window? It must be, or else I would have received a motion // event. The button must still be pressed down, or else I would // have received a button release event. int nNewConsPos = nLeftEdgeConsensusPosition_ + ( pGcw_->bAutomaticallyScrollLeftNotRight_ ? -pCP->nWhenUserScrollsOffWindowBasesToScrollEachTime_ : pCP->nWhenUserScrollsOffWindowBasesToScrollEachTime_ ); scrollToConsensusPos( nNewConsPos ); } void ContigWin :: makeSelectionFromConsensus( const int nConsPosLeft, const int nConsPosRight ) { RWCString soSelectedBases; for( int nConsPos = nConsPosLeft; nConsPos <= nConsPosRight; ++nConsPos ) { Ntide nt = pContig_->ntGetCons( nConsPos ); if ( !nt.bIsPad() ) { RWCString soBase( nt.cGetBase() ); soSelectedBases += soBase; } } GuiApp::pGetGuiApp()->makeSelectionForPasting( soSelectedBases ); } void ContigWin :: makeSelectionFromARead( LocatedFragment* pLocFrag, const int nConsPosLeft, const int nConsPosRight ) { RWCString soSelectedBases; for( int nConsPos = nConsPosLeft; nConsPos <= nConsPosRight; ++nConsPos ) { Ntide nt = pLocFrag->ntGetFragFromConsPos( nConsPos ); if ( !nt.bIsPad() ) { RWCString soBase( nt.cGetBase() ); soSelectedBases += soBase; } } GuiApp::pGetGuiApp()->makeSelectionForPasting( soSelectedBases ); } void ContigWin :: toggleHighlightOfReadName( const int nPixelX, const int nPixelY ) { // find which read has been clicked int nReadLine = nFragLineFromPixelY( nPixelY ); LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet( nReadLine ); // 1-based position starting at left column int nScreenCharX = (nPixelX + GuiApp::nGetFontWidth() - 1) / GuiApp::nGetFontWidth(); RWCString soReadName = pLocFrag->soGetFragmentName(); // cursor wasn't on the name after all if ( soReadName.length() < nScreenCharX ) return; pLocFrag->bReadCurrentlyHighlighted_ = ! pLocFrag->bReadCurrentlyHighlighted_; drawFragmentNames(); GuiApp::pGetGuiApp()->makeSelectionForPasting( soReadName ); } void ContigWin :: find4BestReads( const int nConsPos, LocatedFragment*& pLocFrag1, LocatedFragment*& pLocFrag2, LocatedFragment*& pLocFrag3, LocatedFragment*& pLocFrag4 ) { pLocFrag1 = 0; pLocFrag2 = 0; pLocFrag3 = 0; pLocFrag4 = 0; int nBestQual1 = -1000; int nBestQual2 = -1000; int nBestQual3 = -1000; int nBestQual4 = -1000; for(int nRead = 0; nRead < pContigView_->nGetNumberOfFragments(); ++nRead ) { LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet( nRead ); if ( pLocFrag->bIsInRead( nConsPos ) && !pLocFrag->bIsClipped( nConsPos )) { Ntide nt = pLocFrag->ntGetFragFromConsPos( nConsPos ); int nQual = nt.qualGetQuality(); if ( ! pLocFrag->bComp() ) { if ( tolower( nt.cGetBase() ) == tolower( pContig_->ntGetCons( nConsPos ).cGetBase() ) ) { // top strand, agrees with consensus if (nQual > nBestQual1 ) { nBestQual1 = nQual; pLocFrag1 = pLocFrag; } } else { // top strand, disagrees with consensus if (nQual > nBestQual2 ) { nBestQual2 = nQual; pLocFrag2 = pLocFrag; } } } else { if ( tolower( nt.cGetBase() ) == tolower( pContig_->ntGetCons( nConsPos ).cGetBase() ) ) { // bottom strand, agrees with consensus if (nQual > nBestQual3 ) { nBestQual3 = nQual; pLocFrag3 = pLocFrag; } } else { // bottom strand, disagrees with consensus if (nQual > nBestQual4 ) { nBestQual4 = nQual; pLocFrag4 = pLocFrag; } } } } } } void ContigWin :: showBaseQuality(const int nScreenCharXPos, const int nReadIndex, const bool bReadBaseNotContigBase ) { // convert screen coordinate to consensus position int nConsPos = nScreenCharToConsensusPosition(nScreenCharXPos); Ntide nt; LocatedFragment* pLocFrag = NULL; if ( bReadBaseNotContigBase ) { // get the located fragment pointer for that screen line if (nReadIndex >= pContigView_->nGetNumberOfFragments()) { return; // do nothing } pLocFrag = pContigView_->pLocatedFragmentGet( nReadIndex ); // does the frag have a base at that location ? if ((nConsPos < pLocFrag->nGetAlignStart()) || (nConsPos > pLocFrag->nGetAlignEnd())) { return; } nt = pLocFrag->ntGetFragFromConsPos( nConsPos ); } else { if ( ( nConsPos < pContig_->nGetStartConsensusIndex() ) || ( pContig_->nGetEndConsensusIndex() < nConsPos ) ) return; nt = pContig_->ntGetCons( nConsPos ); } int nUnpadded = pContig_->nUnpaddedIndexStartingAtUserDefinedPosition( nConsPos ); int nQuality = nt.qualGetQuality(); RWCString soLine = "qual: " + RWCString( (long) nQuality ); if ( pContig_->bSetStartNumberingUnpaddedConsensusAtUserDefined_ && ( pContig_->nStartNumberingUnpaddedConsensusAtUserDefined_ != 1 ) ) soLine += ", cons pos (user-defined): "; else soLine += ", cons pos: "; soLine += ( soAddCommas( nUnpadded ) + ", diff from last: " + soAddCommas( ABS( nUnpadded - nLastUsedUnpaddedConsPos ) ) ); // display unpadded read position in direction of sequencing if ( bReadBaseNotContigBase ) { soLine += ", read pos: "; soLine += RWCString( (long) pLocFrag->nOrientedUnpaddedFragPosFromConsPos( nConsPos ) ); } soLine += ", "; soLine += pContigView_->soGetHowReadsAreSorted(); pGcw_->displayMessageAtBottom( (char*) soLine.data() ); nLastUsedUnpaddedConsPos = nUnpadded; } void ContigWin :: scrollLeft() { int nNewLeftEdgeConsPos = nLeftEdgeConsensusPosition_ - nGetDisplayedBasesWide()/2; scrollToConsensusPos( nNewLeftEdgeConsPos ); } void ContigWin :: scrollLeftLeft() { int nNewLeftEdgeConsPos = nLeftEdgeConsensusPosition_ - nGetDisplayedBasesWide() + nNumberOfBasesToOverlapWhenPaging; scrollToConsensusPos( nNewLeftEdgeConsPos ); } void ContigWin :: scrollRight() { int nNewLeftEdgeConsPos = nLeftEdgeConsensusPosition_ + nGetDisplayedBasesWide()/2; scrollToConsensusPos( nNewLeftEdgeConsPos ); } void ContigWin :: scrollRightRight() { int nNewLeftEdgeConsPos = nLeftEdgeConsensusPosition_ + nGetDisplayedBasesWide() - nNumberOfBasesToOverlapWhenPaging; scrollToConsensusPos( nNewLeftEdgeConsPos ); } void ContigWin :: userTypedInConsPos( const RWCString& soConsPos ) { // remove any embedded commas RWCString soConsPosTemp = soConsPos; soConsPosTemp.removeAllCommas(); bool bPaddedNotUnpaddedPos = false; if ( soConsPosTemp.bStartsWithAndRemove( "p" ) || soConsPosTemp.bStartsWithAndRemove( "P" ) || soConsPosTemp.bStartsWithAndRemove( "*" ) ) { bPaddedNotUnpaddedPos = true; } int nUserTypedUnpaddedConsPos; if (!bIsNumericMaybeWithWhitespace( soConsPosTemp, nUserTypedUnpaddedConsPos ) ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "consensus position must be numeric, not %s", soConsPosTemp.data() ); return; } int nConsPosPadded; if ( !bPaddedNotUnpaddedPos ) { int nConsPosMin = pGetContig()->nGetFirstDisplayableContigPos(); int nConsPosMax = pGetContig()->nGetLastDisplayableContigPos(); int nConsPosMinUnpaddedUserDefined = pContig_->nUnpaddedIndexStartingAtUserDefinedPosition( nConsPosMin ); int nConsPosMaxUnpaddedUserDefined = pContig_->nUnpaddedIndexStartingAtUserDefinedPosition( nConsPosMax ); if (! (nConsPosMinUnpaddedUserDefined <= nUserTypedUnpaddedConsPos && nUserTypedUnpaddedConsPos <= nConsPosMaxUnpaddedUserDefined ) ) { RWCString soError = "consensus position must be between "; soError += RWCString( (long) nConsPosMinUnpaddedUserDefined ); soError += " and "; soError += RWCString( (long) nConsPosMaxUnpaddedUserDefined ); if ( pContig_->nStartNumberingUnpaddedConsensusAtUserDefined_ != 1 ) { soError += " (note that positions on this contig start at "; soError += RWCString( (long) pContig_->nStartNumberingUnpaddedConsensusAtUserDefined_ ); soError += " according to a startNumberingConsensus tag"; } popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), soError ); return; } int nUnpadded; if ( pCP->bNumberUnpaddedConsensusAtUserDefined_ ) nUnpadded = nUserTypedUnpaddedConsPos - pContig_->nStartNumberingUnpaddedConsensusAtUserDefined_ + 1; else nUnpadded = nUserTypedUnpaddedConsPos; nConsPosPadded = pContig_->nPaddedIndex( nUnpadded ); } // if ( !bPaddedNotUnpaddedPos ) { else { nConsPosPadded = nUserTypedUnpaddedConsPos; } scrollToConsensusPosInCenter( nConsPosPadded ); moveCursorToConsPos( nConsPosPadded ); } void ContigWin :: pickPrimer( const int nScreenCharX, const bool bForwardNotReversePrimer, const bool bCloneNotSubcloneTemplate) { int nConsPos = nScreenCharToConsensusPosition( nScreenCharX ); pickPrimers( pContig_, nConsPos, bForwardNotReversePrimer, /* forward primer */ bCloneNotSubcloneTemplate, this ); } bool ContigWin :: bGetEntireVisibleConsensusBases( RWCString& soBasesToDraw, int& nActualScreenCharStart ) { int nLeftIntersectScreenChar; int nRightIntersectScreenChar; bool bThereIsAnotherColorWord = bIntersect( 0, // left-most screen char nGetDisplayedBasesWide() - 1, // right-most screen char nConsensusPositionToScreenChar( pContig_->nGetStartConsensusIndex() ), nConsensusPositionToScreenChar( pContig_->nGetEndConsensusIndex() ), nLeftIntersectScreenChar, nRightIntersectScreenChar ); if (!bThereIsAnotherColorWord ) return( false ); nActualScreenCharStart = nLeftIntersectScreenChar; int nConsPosStart = nScreenCharToConsensusPosition( nActualScreenCharStart ); int nConsPosEnd = nScreenCharToConsensusPosition( nRightIntersectScreenChar ); soBasesToDraw = pContig_->soGetPartOfConsensusUpperOrLower( nConsPosStart, nConsPosEnd ); return true; } void ContigWin :: drawHighlightedBases() { selection* pSelection = ConsEd::pGetConsEd()->pGetSelection(); if ( !pSelection->bSelectionActive_ ) return; Contig* pContig; LocatedFragment* pLocFrag; int nConsPosSelectionStart; int nConsPosSelectionEnd; bool bSelectionActive; ConsEd::pGetConsEd()->pGetSelection()->getSelection( nConsPosSelectionStart, nConsPosSelectionEnd, pLocFrag, pContig, bSelectionActive ); int nConsPosVisibleHighlightedMin; int nConsPosVisibleHighlightedMax; if ( !bIntersect( nLeftEdgeConsensusPosition_, nGetRightEdgeConsensusPosition(), nConsPosSelectionStart, nConsPosSelectionEnd, nConsPosVisibleHighlightedMin, nConsPosVisibleHighlightedMax ) ) return; if ( pSelection->bIsOnConsensusNotRead() ) { // We now have found a range of consensus positions that are // visible on the screen and are highlighted. Get the sequence. RWCString soHighlightedBases = pContig_->soGetPartOfConsensusUpperOrLower( nConsPosVisibleHighlightedMin, nConsPosVisibleHighlightedMax ); int nScreenCharStart = nConsensusPositionToScreenChar( nConsPosVisibleHighlightedMin ); pGcw_->guiDrawConsensusColorWord( nScreenCharStart, (char*) soHighlightedBases.data(), soHighlightedBases.length(), pGcw_->pGuiColorTextForHighlightedBases_ ); } // if ( pSelection->bIsOnConsensusNotRead() ) { else { int nConsPosStart; int nConsPosEnd; if ( !bIntersect( nConsPosVisibleHighlightedMin, nConsPosVisibleHighlightedMax, pLocFrag->nGetAlignStart(), pLocFrag->nGetAlignEnd(), nConsPosStart, nConsPosEnd ) ) return; RWCString soHighlightedBases = pLocFrag->soGetPartOfReadUpperOrLower( nConsPosStart, nConsPosEnd ); int nScreenCharStart = nConsensusPositionToScreenChar( nConsPosStart ); int nReadLine = pContigView_->nWhatLineIsReadOn( pLocFrag ); // should never happen if ( nReadLine == RW_NPOS ) return; pGcw_->guiDrawReadColorWord( nScreenCharStart, nReadLine, soHighlightedBases.data(), soHighlightedBases.length(), pGcw_->pGuiColorTextForHighlightedBases_ ); } } bool ContigWin :: bIsThisTraceDisplayed( const LocatedFragment* pLocFrag ) { // first check if no reads at all are displayed if (! pTeditor_ ) return( false ); if ( pTeditor_->pGetTedWinByLocatedFragment( pLocFrag ) ) return( true ); else return( false ); } int ContigWin :: nGetReadLineFromLocatedFragment( const LocatedFragment* pLocFrag ) { for(int nReadLine = 0; nReadLine < pContigView_->nGetNumberOfFragments(); ++nReadLine) { if ( pLocFrag == pContigView_->pLocatedFragmentGet( nReadLine ) ) return( nReadLine ); } // indicator that LocatedFragment wasn't found return( -1 ); } void ContigWin :: drawSequencingDirectionArrow( const LocatedFragment* pLocFrag ) { int nReadLine = nGetReadLineFromLocatedFragment( pLocFrag ); if (nReadLine < nIndexOfTopVisibleRead_ ) return; bool bThisReadsTraceIsUp = bIsThisTraceDisplayed( pLocFrag ); int nError = pGcw_->nGuiDrawSequencingDirectionArrow( nReadLine, pLocFrag->bComp(), bThisReadsTraceIsUp ); } void ContigWin :: getContigErrorRate( char* szErrors ) { // handle case in which the contigwin doesn't have a contig in it if (! pContig_ ) { szErrors[0] = '\0'; return; } double dErrorsPerMegabase = pContig_->dGetExpectedNumberOfErrorsPerMegabaseForConsensus(); double dErrorsPer10Kb = dErrorsPerMegabase / 100.0; if ( dErrorsPer10Kb > 999) { sprintf( szErrors, "%6.0f", dErrorsPer10Kb ); } else if (dErrorsPer10Kb < 0 ) { strcpy( szErrors, "???" ); } else { sprintf( szErrors, "%6.2f", dErrorsPer10Kb ); } } void ContigWin :: displayContigErrorRate() { char szErrors[100]; getContigErrorRate( szErrors ); pGcw_->displayErrorRate( szErrors ); } void ContigWin :: tellPhrapNotToOverlapReadsDiscrepantAtThisLocation( const int nCharX ) { int nConsPosWhereToSplit = nScreenCharToConsensusPosition( nCharX ); pContigView_->tellPhrapNotToOverlapReadsDiscrepantAtThisLocation( nConsPosWhereToSplit, true, // using Gui this ); } void ContigWin :: makeAllReadsNAtThisLocation( const int nCharX ) { int nConsPos = nScreenCharToConsensusPosition( nCharX ); for( int nRead = 0; nRead < pContigView_->nGetNumberOfFragments(); ++nRead ) { LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet( nRead ); // reads that aren't aligned against the consensus at this point // are not considered by phrap in making joins so don't bother // with their quality if ( !pLocFrag->bIsInAlignedPartOfRead( nConsPos ) ) continue; EditAction* pEditAction = new editChangeToNs( pLocFrag, nConsPos, nConsPos ); ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); } } void ContigWin :: tearContigs( const int nScreenCharX ) { int nConsPosWhereToTear = nScreenCharToConsensusPosition( nScreenCharX ); // make consed read-only right now // put up dialog box for user to select reads new guiTearContig( this, pContig_, pContigView_, nConsPosWhereToTear ); // now it is the job of the guiAskUserToSelectWhichReadsShouldGoInWhichContig // to actually make the tear } void ContigWin :: showAllTraces( const int nScreenCharX ) { int nConsPos = nScreenCharToConsensusPosition( nScreenCharX ); showAllTracesByConsensusPosition( nConsPos ); } void ContigWin :: showAllTracesByConsensusPosition( const int nConsPosOfCursor ) { if ( pTeditor_ ) { if ( !pTeditor_->pGuiTeditor_->bShowTracesInScrollingWindow_ ) delete pTeditor_; else pTeditor_->deleteAllTedWins(); } if ( pContig_->bIsOnConsensus( nConsPosOfCursor ) ) { moveCursorToConsPos( nConsPosOfCursor ); } const int nNumberOfTracesToAdd = 3; if ( !pTeditor_ ) { pTeditor_ = new Teditor( this, nNumberOfTracesToAdd, true ); // in scrolling window pTeditor_->pGuiTeditor_->createScrollingWindowForTraces(); } pTeditor_->pContigView_ = new ContigView( *pContigView_ ); pTeditor_->showAllTraces( nConsPosOfCursor ); } void ContigWin :: navigateToNextOrPreviousItem( const bool bNextNotPrevious ) { if ( pGuiMultiContigNav_ ) pGuiMultiContigNav_->gotoNextOrPreviousItem( bNextNotPrevious ); else if ( ConsEd::pGetConsEd()->aGuiMultiContigNavigator_.length() > 0 ) ConsEd::pGetConsEd()->aGuiMultiContigNavigator_.last()->gotoNextOrPreviousItem( bNextNotPrevious ); else popupErrorMessage( "There is no active navigator window for this contig" ); } void ContigWin :: raiseWindow() { XRaiseWindow( XtDisplay( pGcw_->widGetGuiContigWinTopLevel() ), XtWindow( pGcw_->widGetGuiContigWinTopLevel() ) ); } void ContigWin :: scrollToLeftOrRightEndOfConsensus( const bool bLeftNotRight ) { int nConsPos; if ( bLeftNotRight ) nConsPos = pContig_->nGetStartIndex(); else nConsPos = pContig_->nGetEndIndex(); scrollToConsensusPosInCenter( nConsPos ); } void ContigWin :: scrollToCursor() { if (! editCursor_.bCursorValid()) { popupErrorMessage( "the cursor is not set" ); return; } scrollToConsensusPosInCenter( editCursor_.nConsPosGet() ); } void ContigWin :: userPushedControlA() { if ( ! editCursor_.bCursorValid() ) { popupErrorMessage( "please set the cursor first so I know whether you want to go to the beginning of the consensus or a read and which read" ); return; } if (editCursor_.bCursorOnFrag()) { LocatedFragment* pLocFrag = editCursor_.pLocFragGet(); // // to deliberately force an exception // int nPeakPos = pLocFrag->nGetPointPos( -1667 ); // cerr << nPeakPos << endl; int nConsPos = pLocFrag->nGetAlignStart(); scrollToConsensusPosInCenter( nConsPos ); moveCursorToFragPos( nConsPos, pLocFrag ); } else if ( editCursor_.bCursorOnCons() ) { scrollToLeftOrRightEndOfConsensus( true ); // left } } void ContigWin :: userPushedControlE() { if ( ! editCursor_.bCursorValid() ) { popupErrorMessage( "please set the cursor first so I know whether you want to go to the end of the consensus or the end of a read and which read" ); return; } if ( editCursor_.bCursorOnFrag() ) { LocatedFragment* pLocFrag = editCursor_.pLocFragGet(); int nConsPos = pLocFrag->nGetAlignEnd(); scrollToConsensusPosInCenter( nConsPos ); moveCursorToFragPos( nConsPos, pLocFrag ); } else if ( editCursor_.bCursorOnCons() ) { scrollToLeftOrRightEndOfConsensus( false ); // right } } const int nHowCloseToEdgeCanCursorGet = 10; void ContigWin :: userPushedLeftArrow() { if ( !editCursor_.bCursorValid() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "please set the cursor first so I know where to move from" ); return; } if ( editCursor_.nConsPosGet() < nLeftEdgeConsensusPosition_ || nGetRightEdgeConsensusPosition() < editCursor_.nConsPosGet() ) { GuiApp::beep(); return; } int nNewConsPos = editCursor_.nConsPosGet() - 1; if ( editCursor_.bCursorOnFrag() ) { LocatedFragment* pLocFrag = editCursor_.pLocFragGet(); if ( nNewConsPos < pLocFrag->nGetAlignStart() ) { GuiApp::beep(); return; } moveCursorToFragPos( nNewConsPos, pLocFrag ); } else { if ( nNewConsPos < pContig_->nGetStartConsensusIndex() ) { GuiApp::beep(); return; } moveCursorToConsPos( nNewConsPos ); } // now scroll the window if necessary if ( editCursor_.nConsPosGet() < nLeftEdgeConsensusPosition_ + nHowCloseToEdgeCanCursorGet ) { // scroll. scrollToConsensusPos( nLeftEdgeConsensusPosition_ - 1 ); } } void ContigWin :: userPushedLeftArrowAboveComma() { if ( !editCursor_.bCursorValid() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "please set the cursor first so I know where to move from" ); return; } if ( editCursor_.nConsPosGet() < nLeftEdgeConsensusPosition_ || nGetRightEdgeConsensusPosition() < editCursor_.nConsPosGet() ) { GuiApp::beep(); return; } int nNewConsPos = editCursor_.nConsPosGet() - pCP->nAmountToMoveWithBigLeftAndRightArrows_; if (editCursor_.bCursorOnFrag() ) { LocatedFragment* pLocFrag = editCursor_.pLocFragGet(); if ( nNewConsPos < pLocFrag->nGetAlignStart() ) { GuiApp::beep(); return; } moveCursorToFragPos( nNewConsPos, pLocFrag ); } else { if ( nNewConsPos < pContig_->nGetStartConsensusIndex() ) { GuiApp::beep(); return; } moveCursorToConsPos( nNewConsPos ); } // now scroll the window if necessary if ( editCursor_.nConsPosGet() < nLeftEdgeConsensusPosition_ + nHowCloseToEdgeCanCursorGet ) { // scroll scrollToConsensusPos( nLeftEdgeConsensusPosition_ - pCP->nAmountToMoveWithBigLeftAndRightArrows_ ); } } void ContigWin :: userPushedRightArrow() { if ( !editCursor_.bCursorValid() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "please set the cursor first so I know where to move from" ); return; } if ( editCursor_.nConsPosGet() < nLeftEdgeConsensusPosition_ || nGetRightEdgeConsensusPosition() < editCursor_.nConsPosGet() ) { GuiApp::beep(); return; } int nNewConsPos = editCursor_.nConsPosGet() + 1; if ( editCursor_.bCursorOnFrag() ) { LocatedFragment* pLocFrag = editCursor_.pLocFragGet(); if ( pLocFrag->nGetAlignEnd() < nNewConsPos ) { GuiApp::beep(); return; } moveCursorToFragPos( nNewConsPos, pLocFrag ); } else { if ( pContig_->nGetEndConsensusIndex() < nNewConsPos ) { GuiApp::beep(); return; } moveCursorToConsPos( nNewConsPos ); } // now scroll the window if necessary if ( nGetRightEdgeConsensusPosition() - nHowCloseToEdgeCanCursorGet < editCursor_.nConsPosGet() ) { scrollToConsensusPos( nLeftEdgeConsensusPosition_ + 1 ); } } void ContigWin :: userPushedRightArrowAbovePeriod() { if ( !editCursor_.bCursorValid() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "please set the cursor first so I know where to move from" ); return; } if ( editCursor_.nConsPosGet() < nLeftEdgeConsensusPosition_ || nGetRightEdgeConsensusPosition() < editCursor_.nConsPosGet() ) { GuiApp::beep(); return; } int nNewConsPos = editCursor_.nConsPosGet() + pCP->nAmountToMoveWithBigLeftAndRightArrows_; if ( editCursor_.bCursorOnFrag() ) { LocatedFragment* pLocFrag = editCursor_.pLocFragGet(); if ( pLocFrag->nGetAlignEnd() < nNewConsPos ) { GuiApp::beep(); return; } moveCursorToFragPos( nNewConsPos, pLocFrag ); } else { if ( pContig_->nGetEndConsensusIndex() < nNewConsPos ) { GuiApp::beep(); return; } moveCursorToConsPos( nNewConsPos ); } // now scroll the window if necessary if ( nGetRightEdgeConsensusPosition() - nHowCloseToEdgeCanCursorGet < editCursor_.nConsPosGet() ) { scrollToConsensusPos( nLeftEdgeConsensusPosition_ + pCP->nAmountToMoveWithBigLeftAndRightArrows_ ); } } void ContigWin :: userPushedDownArrow() { if ( !editCursor_.bCursorValid() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "please set the cursor first so I know where to move from" ); return; } // check that the cursor is in the window we are currently seeing if ( editCursor_.nConsPosGet() < nLeftEdgeConsensusPosition_ || nGetRightEdgeConsensusPosition() < editCursor_.nConsPosGet() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "please set the cursor first in this window so I know where to move from" ); return; } int nNewReadLine = -666; if ( editCursor_.bCursorOnFrag() ) { LocatedFragment* pPreviousRead = editCursor_.pLocFragGet(); // where is this read in the list of reads displayed? int nPreviousReadLine; bool bFoundReadLine = false; int nReadLine; for( nReadLine = 0; nReadLine < pContigView_->nGetNumberOfFragments() && !bFoundReadLine; ++nReadLine ) { if ( pContigView_->pLocatedFragmentGet( nReadLine ) == pPreviousRead ) { nPreviousReadLine = nReadLine; bFoundReadLine = true; } } assert( bFoundReadLine ); nNewReadLine = MIN( nPreviousReadLine + 1, pContigView_->nGetNumberOfFragments() - 1 ); } else { nNewReadLine = 0; } // let's see if this read (or any subsequent read) has bases at // this position LocatedFragment* pNewAcceptableRead = NULL; bool bFoundAcceptableRead = false; for( int nReadLine = nNewReadLine; nReadLine < pContigView_->nGetNumberOfFragments() && !bFoundAcceptableRead; ++nReadLine ) { LocatedFragment* pNextRead = pContigView_->pLocatedFragmentGet( nReadLine ); if ( pNextRead->nGetAlignStart() <= editCursor_.nConsPosGet() && editCursor_.nConsPosGet() <= pNextRead->nGetAlignEnd() ) { bFoundAcceptableRead = true; pNewAcceptableRead = pNextRead; } } if ( !bFoundAcceptableRead ) { return; } // move cursor to this read moveCursorToFragPos( editCursor_.nConsPosGet(), pNewAcceptableRead ); } void ContigWin :: userPushedUpArrow() { if ( !editCursor_.bCursorValid() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "please set the cursor first so I know where to move from" ); return; } // check that the cursor is in the window we are currently seeing if ( editCursor_.nConsPosGet() < nLeftEdgeConsensusPosition_ || nGetRightEdgeConsensusPosition() < editCursor_.nConsPosGet() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "please set the cursor first in this window so I know where to move from" ); return; } if ( !editCursor_.bCursorOnFrag() ) return; LocatedFragment* pPreviousRead = editCursor_.pLocFragGet(); // where is this read in the list of reads displayed? int nPreviousReadLine; bool bFoundReadLine = false; int nReadLine; for( nReadLine = 0; nReadLine < pContigView_->nGetNumberOfFragments() && !bFoundReadLine; ++nReadLine ) { if ( pContigView_->pLocatedFragmentGet( nReadLine ) == pPreviousRead ) { nPreviousReadLine = nReadLine; bFoundReadLine = true; } } assert( bFoundReadLine ); // see if we can move up to find a read line that has bases // at the same consensus position as the cursor LocatedFragment* pNewAcceptableRead = NULL; bool bFoundAcceptableRead = false; for( nReadLine = nPreviousReadLine - 1; nReadLine >= 0 && !bFoundAcceptableRead; --nReadLine ) { LocatedFragment* pNextRead = pContigView_->pLocatedFragmentGet( nReadLine ); if ( pNextRead->nGetAlignStart() <= editCursor_.nConsPosGet() && editCursor_.nConsPosGet() <= pNextRead->nGetAlignEnd() ) { bFoundAcceptableRead = true; pNewAcceptableRead = pNextRead; } } if ( bFoundAcceptableRead ) { moveCursorToFragPos( editCursor_.nConsPosGet(), pNewAcceptableRead ); } else { // let's see if we can move to the consensus if ( pContig_->nGetStartIndex() <= editCursor_.nConsPosGet() && editCursor_.nConsPosGet() <= pContig_->nGetEndIndex() ) { moveCursorToConsPos( editCursor_.nConsPosGet() ); } // otherwise do nothing } } static RWTPtrOrderedVector aTagsAtThisLocation; static RWCString soToDisplay( (size_t) 200 ); void ContigWin :: pointerMoved( const int nPixelX, const int nPixelY ) { int nScreenCharX = pGcw_->nCharXFromPixel( nPixelX ); int nConsPos = nScreenCharToConsensusPosition( nScreenCharX ); int nReadLine; if ( pGcw_->bIsInFragmentBasesArea( nPixelX, nPixelY ) ) nReadLine = nFragLineFromPixelY( nPixelY ); else if ( pGcw_->bIsInConsensusBasesArea( nPixelX, nPixelY ) ) nReadLine = -2; else nReadLine = -3; // means not in either fragment bases area or // consensus bases area bool bSameScreenChar = ( nConsPos == nOldConsPosOfPointer_ && nReadLine == nOldReadLineOfPointer_ ) ? true : false; nOldConsPosOfPointer_ = nConsPos; nOldReadLineOfPointer_ = nReadLine; if ( bSameScreenChar ) return; if ( nReadLine == -3 ) return; // no tag here aTagsAtThisLocation.clear(); if ( pGcw_->bIsInFragmentBasesArea( nPixelX, nPixelY ) ) { LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet( nReadLine ); for( int n = 0; n < pLocFrag->nGetNumberOfTags(); ++n ) { tag* pTag = pLocFrag->pGetTag( n ); if (pTag->bTouchesThisConsPos( nConsPos ) ) { aTagsAtThisLocation.append( pTag ); } } } else if ( pGcw_->bIsInConsensusBasesArea( nPixelX, nPixelY ) ) { nOldReadLineOfPointer_ = -2; for( int nTag = 0; nTag < pContig_->nGetNumberOfTags(); ++nTag ) { tag* pTag = pContig_->pGetTag( nTag ); if ( pTag->bTouchesThisConsPos( nConsPos ) ) aTagsAtThisLocation.append( pTag ); } } if ( aTagsAtThisLocation.length() ) { soToDisplay = "tag types: "; int nTag; for( nTag = 0; nTag < aTagsAtThisLocation.length(); ++nTag ) { tag* pTag = aTagsAtThisLocation[ nTag ]; soToDisplay += pTag->soType_; soToDisplay += " "; } soToDisplay += "tag data:"; for( nTag = 0; nTag < aTagsAtThisLocation.length(); ++nTag ) { tag* pTag = aTagsAtThisLocation[ nTag ]; if ( !pTag->soComment_.isNull() ) { soToDisplay += " "; soToDisplay += pTag->soComment_; } if ( !pTag->soMiscData_.isNull() ) { soToDisplay += " "; soToDisplay += pTag->soMiscData_; } if ( pTag->soType_ == "oligo" ) { oligoTag* pOligoTag = (oligoTag*) pTag; soToDisplay += " "; soToDisplay += pOligoTag->soName_; } } pGcw_->displayMessageAtBottom( soToDisplay.data() ); } else { bool bLeave = ( ( pGcw_->soDisplayedMessageAtBottom_.length() > 6 ) && ( pGcw_->soDisplayedMessageAtBottom_( 0, 6) == "qual: " ) ) || ( ( pGcw_->soDisplayedMessageAtBottom_.length() > 12 ) && ( pGcw_->soDisplayedMessageAtBottom_( 0, 12 ) == "reads sorted" ) ) || ( pGcw_->soDisplayedMessageAtBottom_.bIsNull() ); if ( !bLeave ) { pGcw_->displayMessageAtBottom(""); } } } void ContigWin :: refreshContigName() { pGcw_->setContigLabel( pContig_->soGetFancyName() ); } void ContigWin :: showTemplateInfo() { PleaseWait* pPleaseWait = new PleaseWait( GuiApp::pGetGuiApp()->widGetTopLevel() ); ConsEd::pGetAssembly()->setContigTemplateArrays(); const int nNumberOfRowsVisible = 35; TextBox* pTextBox = new TextBox( "Template Info", nNumberOfRowsVisible ); pTextBox->append( "\n\n" ); pTextBox->append( "Name Left Right Size Library Def size\n" ); pTextBox->append( " of templ of lib " ); pTextBox->append( "\n" ); for( int nTemplate = 0; nTemplate < pContig_->aSubcloneTemplates_.entries(); ++nTemplate ) { subcloneTTemplate* pSub = pContig_->aSubcloneTemplates_[ nTemplate ]; pTextBox->appendWithArgs( "%-15s %7d %7d %5d %15s %-5d\n", pSub->soTemplateName_.data(), pSub->nUnpaddedStart_, pSub->nUnpaddedEnd_, pSub->nUnpaddedEnd_ - pSub->nUnpaddedStart_ + 1, pSub->pLibrary_->soName_.data(), pSub->pLibrary_->nAverageInsertSizeToUse_ ); for( int nRead = 0; nRead < pSub->aReads_.length(); ++nRead ) { LocatedFragment* pLocFrag = pSub->aReads_[ nRead ]; pTextBox->appendWithArgs( " %s %s from %d to %d in %s\n", pLocFrag->soGetName().data(), ( pLocFrag->bComp() ? "bottom" : "top " ), pLocFrag->nGetAlignStartUnpadded(), pLocFrag->nGetAlignEndUnpadded(), pLocFrag->pContig_->soGetName().data() ); } } delete pPleaseWait; pTextBox->makeVisible(); } void ContigWin :: changeToXsToLeftInAllReads() { changeToXsInAllReads( 'l' ); } void ContigWin :: changeToXsToRightInAllReads() { changeToXsInAllReads( 'r' ); } void ContigWin :: changeToXsInAllReads( const char cRightOrLeft ) { if ( !editCursor_.bCursorValid() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "you must first set the cursor by clicking on a consensus base" ); return; } PleaseWait* pPleaseWait = new PleaseWait( pGcw_->widGetGuiContigWinTopLevel() ); int nCursorPosition = editCursor_.nConsPosGet(); int nLeftMostPosition; int nRightMostPosition; if ( cRightOrLeft == 'r' ) { // find all read from the cursor position to the end of the contig // (including reads that stick out to the right) nLeftMostPosition = nCursorPosition; nRightMostPosition = pContig_->nGetLastDisplayableContigPos(); } else if ( cRightOrLeft == 'l' ) { nLeftMostPosition = pContig_->nGetFirstDisplayableContigPos(); nRightMostPosition = nCursorPosition; } else assert( false ); ContigView* pContigView = pContig_->pGetContigView( nLeftMostPosition, nRightMostPosition ); // I don't think so--DG, Sept 2008 since the displayed reads // are not changing. Notice that pContigView above is not changing // pContigView_ // resetRoomForReadNames(); for( int nRead = 0; nRead < pContigView->nGetNumberOfFragments(); ++nRead ) { LocatedFragment* pLocFrag = pContigView->pLocatedFragmentGet( nRead ); int nConsPosLeftInRead; int nConsPosRightInRead; if ( !bIntersect( nLeftMostPosition, nRightMostPosition, pLocFrag->nGetAlignStart(), pLocFrag->nGetAlignEnd(), nConsPosLeftInRead, nConsPosRightInRead ) ) continue; // I don't see how this could ever happen editChangeToXs* pEditChange = new editChangeToXs( pLocFrag, nConsPosLeftInRead, nConsPosRightInRead, cRightOrLeft ); ConsEd::pGetConsEd()->doEditActionNoRefresh( pEditChange, true ); // bWriteToEditHistoryFile } ConsEd::pGetConsEd()->refreshAllContigWinsAndAllTeditors(); delete pContigView; delete pPleaseWait; } void ContigWin :: createCloneEndTag( const bool bInsertToRight ) { if ( !editCursor_.bCursorValid() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "you must first set the cursor by clicking on a consensus or read base" ); return; } EditAction* pEditAction = NULL; bool bUserPushedCancel; // not used if ( editCursor_.bCursorOnFrag() ) { tag* pTag = tagTypes::pGetTagTypes()->pCreateReadTag( "cloneEnd", "", // soTagComment editCursor_.nConsPosGet(), editCursor_.nConsPosGet(), editCursor_.pLocFragGet(), true, // bWriteToPhdFileNotAceFile bUserPushedCancel ); if ( bInsertToRight ) pTag->soMiscData_ = "->"; else pTag->soMiscData_ = "<-"; pEditAction = new editAddReadTag( pTag ); } else { tag* pTag = tagTypes::pGetTagTypes()->pCreateConsensusTag( "cloneEnd", "", // soComment editCursor_.nConsPosGet(), editCursor_.nConsPosGet(), pContig_, false, // bNoTrans bUserPushedCancel, pContig_->soGetName() ); if ( bInsertToRight ) pTag->soMiscData_ = "->"; else pTag->soMiscData_ = "<-"; pEditAction = new editAddConsensusTag( pTag ); } ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); // bWriteToEditHistoryFile } void ContigWin :: resetRoomForReadNames() { if ( pCP->bAlignedReadsWindowAutomaticallyExpandRoomForReadNames_ ) { pGcw_->nRoomForReadNames_ = 0; for( int nRead = 0; nRead < pContigView_->nGetNumberOfFragments(); ++nRead ) { LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet( nRead ); pGcw_->nRoomForReadNames_ = MAX( pGcw_->nRoomForReadNames_, pLocFrag->soGetName().length() ); } // but in no circumstances do we want to allow the read names // to take up more than the width of the screen. In fact, we // need some room for the bases, so only allow it to take up, // say, 3/4 of the room on the screen // I think I will just give a warning and tell the user what to do: if ( pGcw_->nRoomForReadNames_ * GuiApp::pGetGuiApp()->nGetFontWidth() + pGcw_->nFragmentNameXPixelPosition() + nPixelMarginAfterFragmentName > pGcw_->nGetContigWindowPixelWidth() ) { RWCString soError = "your read names are very long and will cause no bases to be displayed. If you want to have read names this long, then you should set the following in your .consedrc file: consed.alignedReadsWindowAutomaticallyExpandRoomForReadNames: false\nIf you want more room for your read names, then increase consed.alignedReadsWindowMaxCharsForReadNames: 20"; cerr << soError << endl; popupErrorMessage( soError ); } } // if ( pCP->bAlignedReadsWindowAutomaticallyExpandRoomForReadNames_ ) else { pGcw_->nRoomForReadNames_ = pCP->nAlignedReadsWindowMaxCharsForReadNames_; } } void ContigWin :: compareReadsToReference() { guiGetReferenceRead* pRefRead = new guiGetReferenceRead( pGcw_->widGetGuiContigWinTopLevel(), pContig_, this ); pRefRead->createWindow(); } void ContigWin :: userPressedUserDefinedKey( const RWCString& soProgram, const RWCString& soArgument, const RWCString& soTagToApply ) { if ( !editCursor_.bCursorValid() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "You must first set the cursor before pressing this key" ); return; } // pick up the cursor location from the EditCursor LocatedFragment* pLocFrag = ( editCursor_.bCursorOnCons() ? NULL : editCursor_.pLocFragGet() ); // the cursor may not be visible. In this case do not let the // user apply the user-defined key. int nConsPos = editCursor_.nConsPosGet(); if ( nConsPos < nLeftEdgeConsensusPosition_ || nGetRightEdgeConsensusPosition() < nConsPos ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "use the left mouse button to set the cursor in the aligned reads window before striking this key" ); return; } // see if there is a tag to be applied if ( soTagToApply != "none" && !tagTypes::pGetTagTypes()->bIsAValidTagType( soTagToApply ) ) { RWCString soError = "unrecognized tag type for user defined key: \""; soError += soTagToApply; soError += "\nSee Info/Show Current Consed Resources:\nconsed.tagsToApplyWithUserDefinedKeys\nTo define tags, click on \"Help\" and look for \"CREATING CUSTOM TAG TYPES\""; THROW_ERROR( soError ); } int nUnpaddedSeqPosInDirectionOfSequencing; if ( editCursor_.bCursorOnCons() ) { nUnpaddedSeqPosInDirectionOfSequencing = -1; } else { nUnpaddedSeqPosInDirectionOfSequencing = pLocFrag->nOrientedUnpaddedFragPosFromConsPos( nConsPos ); } assert( editCursor_.pGetContigEvenIfCursorIsOnRead() == pContig_ ); int nUnpadded = pContig_->nUnpaddedIndex( nConsPos ); char cBase; int nQuality; if ( editCursor_.bCursorOnCons() ) { cBase = pContig_->ntGetCons( nConsPos ).cGetBase(); nQuality = pContig_->ntGetCons( nConsPos ).qualGetQuality(); } else { cBase = pLocFrag->ntGetFragFromConsPos( nConsPos ).cGetBase(); nQuality = pLocFrag->ntGetFragFromConsPos( nConsPos ).qualGetQuality(); } RWCString soCommandLine = soProgram + " " + soArgument + " " + ( editCursor_.bCursorOnCons() ? RWCString( "consensus" ) : pLocFrag->soGetName() ) + " " + RWCString( (long) nUnpaddedSeqPosInDirectionOfSequencing ) + " " + pContig_->soGetName() + " " + RWCString( (long) nUnpadded ) + " " + RWCString( (long) nConsPos ) + " " + RWCString( cBase ) + " " + RWCString( (long) nQuality ) + " " + ConsEd::pGetAssembly()->filGetAceFileFullPathname() + " " + "a.r.window"; int nReturnStatus = system( soCommandLine.data() ); if ( nReturnStatus != 0 ) { RWCString soErrorMessage = "unable to run command "; soErrorMessage += soCommandLine; soErrorMessage += " because of return status "; soErrorMessage += RWCString( (long) nReturnStatus ); soErrorMessage += " meaning "; soErrorMessage += soGetErrno(); THROW_ERROR( soErrorMessage ); } if ( soTagToApply != "none" ) { EditAction* pEditAction = NULL; if ( editCursor_.bCursorOnCons() ) { bool bUserPushedCancel = false; tag* pTag = tagTypes::pGetTagTypes()->pCreateConsensusTag( soTagToApply, "", // soComment nConsPos, nConsPos, pContig_, false, // bNoTrans bUserPushedCancel, "" ); // only used for contigName tags if ( bUserPushedCancel ) return; // I don't think this code // path will ever be taken because the user will never be given // a chance to cancel pEditAction = new editAddConsensusTag( pTag ); } else { bool bUserPushedCancel = false; tag* pTag = tagTypes::pGetTagTypes()->pCreateReadTag( soTagToApply, "", // soComment nConsPos, nConsPos, pLocFrag, true, // bWriteToPhdFileNotAceFile bUserPushedCancel ); if ( bUserPushedCancel ) return; // I don't think this code // path will ever be taken because the user will never be given // a chance to cancel pEditAction = new editAddReadTag( pTag ); } ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); } } void ContigWin :: turnOnOrOffStartNumberingConsensusStartingAtUserDefinedPosition() { pCP->bNumberUnpaddedConsensusAtUserDefined_ = !pCP->bNumberUnpaddedConsensusAtUserDefined_; // redraw everything ConsEd::pGetConsEd()->refreshAllContigWinsAndAllTeditors(); } void ContigWin :: showUncalledPeakInfo() { if ( !editCursor_.bCursorValid() ) { popupErrorMessage2( pGcw_->widGetGuiContigWinTopLevel(), "You must first set the cursor before pressing this key" ); return; } PleaseWait* pPleaseWait = new PleaseWait( pGcw_->widGetGuiContigWinTopLevel() ); RWCString soMessage( (size_t) 10000 ); // get all reads at the cursor position int nConsPos = editCursor_.nConsPosGet(); soMessage = "unpadded pos: "; soMessage += RWCString( (long) pContig_->nUnpaddedIndex( nConsPos ) ); soMessage += "\nread rel area qual high quality segment\n"; for( int nRead = 0; nRead < pContigView_->nGetNumberOfFragments(); ++nRead ) { LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet( nRead ); if ( pLocFrag->bIsInAlignedPartOfRead( nConsPos ) ) { mbtValVector* pRelativeAreasOfUncalledBases = NULL; if ( !pLocFrag->bGetSingleSignalRelativeAreas( pRelativeAreasOfUncalledBases ) ) { soMessage += pLocFrag->soGetName(); soMessage += " no chromat\n"; continue; } int n1UnpaddedReadPos = pLocFrag->nOrientedUnpaddedFragPosFromConsPos( nConsPos ); float fRelativeArea = (*pRelativeAreasOfUncalledBases)[ n1UnpaddedReadPos ]; delete pRelativeAreasOfUncalledBases; RWCString soHQS; if ( pLocFrag->bIsInHighQualitySegmentOfRead( nConsPos ) ) { soHQS = "hqs"; } else { soHQS = "lqs"; } RWCString soLine( (size_t) 1000 ); sprintf( soLine.data(), "%-30s %6.3f %2d %3s\n", pLocFrag->soGetName().data(), fRelativeArea, pLocFrag->ntGetFragFromConsPos( nConsPos ).qualGetQuality(), soHQS.data() ); soLine.nCurrentLength_ = strlen( soLine.data() ); soMessage += soLine; } else { soMessage += pLocFrag->soGetName(); soMessage += " unaligned at this cons pos\n"; } } soMessage.stripTrailingWhitespaceFast(); int nRowsNeeded = 2 + pContigView_->nGetNumberOfFragments(); if ( nRowsNeeded > 50 ) nRowsNeeded = 50; TextBox* pTextBox = new TextBox( "quality and uncalled peaks of reads", nRowsNeeded ); pTextBox->append( soMessage ); pTextBox->makeVisible(); delete pPleaseWait; } void ContigWin :: editAllReads( LocatedFragment* pMasterLocFrag, const int nConsPos ) { bool bGoAhead = true; if ( pCP->bWarnUserWhenTryingToEditAllReads_ ) { RWCString soWarning = "Warning: You are attempting to change all of the reads at this position at once. We suggest that you do not do this, but instead open each trace and edit it there. Do you still want to edit all reads at once? (y/n)"; bGoAhead = bGuiGetAnswerYesNo( soWarning ); if ( bGoAhead ) { bool bTurnOffWarning = bGuiGetAnswerYesNo( "would you prefer to not get this warning in the future?" ); if ( bTurnOffWarning ) { popupInfoMessage( pGcw_->widMainWinTopLevelShell_, "Warning turned off. If you want to turn it off forever, you can set the .consedrc resource consed.warnUserWhenTryingToEditAllReads: false" ); pCP->bWarnUserWhenTryingToEditAllReads_ = false; } } } if ( !bGoAhead ) return; RWTPtrOrderedVector aReadsToChange( (size_t) pContigView_->nGetNumberOfFragments() ); for( int nRead = 0; nRead < pContigView_->nGetNumberOfFragments(); ++nRead ) { LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet( nRead ); if ( pLocFrag->bIsInAlignedPartOfRead( nConsPos ) ) { aReadsToChange.insert( pLocFrag ); } } editOverstrikeAllReadsAtConsPos* pEdit = new editOverstrikeAllReadsAtConsPos( nConsPos, pMasterLocFrag, aReadsToChange ); ConsEd::pGetConsEd()->doEditAction( pEdit, true ); } // the reason for have 2 drawVerticalLineAtCursor routines instead of 1 is // to prevent drawBasesAndConsensus calling drawVerticalLineAtCursor which // calls drawBasesAndConsensus... // So current drawBasesAndConsensus calls drawVerticalLineAtCursorNoRedraw // which does *not* call drawBasesAndConsensus void ContigWin :: drawVerticalLineAtCursorNoRedraw() { if ( !pCP->bPutVerticalLineAtCursor_ ) return; if (! editCursor_.bCursorValid()) return; // is the cursor in the current view, and if so where int nScreenCharPos; int nFragLine; bool bOnFrag; bool bCursorInView = editCursor_.bGetViewPos(this, nScreenCharPos, bOnFrag, nFragLine); if (! bCursorInView) return; // done pGcw_->guiDrawVerticalLineAtCursor( nScreenCharPos ); nCurrentVerticalLineScreenCharPos_ = nScreenCharPos; bDrewEverythingSinceLastDrewVerticalLine_ = false; } void ContigWin :: drawVerticalLineAtCursorIfNecessary() { if ( !pCP->bPutVerticalLineAtCursor_ ) return; if (! editCursor_.bCursorValid()) return; int nScreenCharPos; int nFragLine; bool bOnFrag; bool bCursorInView = editCursor_.bGetViewPos(this, nScreenCharPos, bOnFrag, nFragLine); if ( !bCursorInView ) return; if ( !bDrewEverythingSinceLastDrewVerticalLine_ && nScreenCharPos != nCurrentVerticalLineScreenCharPos_ ) { drawBasesAndConsensus( true ); return; // drawBasesAndConsensus will call drawVerticalLineAtCursorNoRedraw } drawVerticalLineAtCursorNoRedraw(); } void ContigWin :: toggleHorizontalLineAtCursor() { pCP->bPutHorizontalLineAtCursor_ = !pCP->bPutHorizontalLineAtCursor_; if ( pCP->bPutHorizontalLineAtCursor_ ) { if ( editCursor_.bCursorValid() ) { int nScreenCharPos; int nFragLine; bool bOnFrag; bool bCursorInView = editCursor_.bGetViewPos( this, nScreenCharPos, bOnFrag, nFragLine ); if ( bCursorInView && bOnFrag ) { pGcw_->guiDrawHorizontalLineAtCursor( nFragLine ); } } } else { ConsEd::pGetConsEd()->refreshAllContigWins(); } } void ContigWin :: toggleVerticalLineAtCursor() { pCP->bPutVerticalLineAtCursor_ = !pCP->bPutVerticalLineAtCursor_; ConsEd::pGetConsEd()->refreshAllContigWins(); } bool ContigWin :: bDrawSeparatorBetweenTopAndBottomStrandReads() { // nGetForFragsVisible() == 0 is // case in which there are only reverse frag lines // Thus there is also no forward/reverse separator, // so the positions of the reverse lines is just like that // for forward reads if ( ( pContigView_->cHowAreReadsSorted_ == ContigView::cSTRAND_AND_POSITION ) && ( nGetForFragsVisible() > 0 ) ) return true; else return false; } bool ContigWin :: bIsEditCursorVisible() { if ( !editCursor_.bCursorValid() ) return false; int nConsPosOfCursor = editCursor_.nConsPosGet(); if ( nLeftEdgeConsensusPosition_ <= nConsPosOfCursor && nConsPosOfCursor <= nGetRightEdgeConsensusPosition() ) { return true; } else return false; } // just used by horizontalScrollBarMoved( void ContigWin :: maybeSortReadsAtCursor() { if ( !bIsEditCursorVisible() ) return; if ( pCP->soShowReadsAtCursorSortedHow_ == "none" ) return; int nConsPosAtCursor = editCursor_.nConsPosGet(); if ( pCP->soShowReadsAtCursorSortedHow_ == "quality" ) { pContigView_->sortReadsByQualityAtConsPos( nConsPosAtCursor ); } else if ( pCP->soShowReadsAtCursorSortedHow_ == "base" ) { pContigView_->sortReadsByBaseAtConsPos( nConsPosAtCursor ); } } void ContigWin :: sortByQualityValuesAtCursor( const bool b ) { if ( b ) { pCP->soShowReadsAtCursorSortedHow_ = "quality"; } else { pCP->soShowReadsAtCursorSortedHow_ = "none"; } // get cursor, if it is available if ( !bIsEditCursorVisible() ) return; int nConsPosAtCursor = editCursor_.nConsPosGet(); if ( pCP->soShowReadsAtCursorSortedHow_ == "quality" ) { pContigView_->sortReadsByQualityAtConsPos( nConsPosAtCursor ); } else { pContigView_->sortReads(); } displayHowReadsAreSorted(); // now redisplay reads drawBasesAndConsensus( true ); // erase first } void ContigWin :: userOverstrikingConsensus( const int nConsPos, const char cNewBaseLower ) { // check if this base agrees with any read--allow ambiguity codes setNumberFromBase4(); int nNewBase = nNumberFromBase4[ cNewBaseLower ]; bool bAReadMatches = false; for( int nRead = 0; nRead < pContigView_->nGetNumberOfFragments(); ++nRead ) { LocatedFragment* pLocFrag = pContigView_->pLocatedFragmentGet( nRead ); // commented out Oct 2009 since when extending consensus, // most reads are unaligned and thus it will give a warning // that no read has this base // if ( !pLocFrag->bIsInAlignedPartOfRead( nConsPos ) ) continue; if ( !pLocFrag->bIsInRead( nConsPos ) ) continue; if ( nNumberFromBase4[ pLocFrag->ntGetFragFromConsPos( nConsPos ).cGetBase() ] & nNewBase ) { bAReadMatches = true; break; } } if ( !bAReadMatches ) { RWCString soQuestion = "There is no read that has base " + RWCString( cNewBaseLower ) + ". Are you sure?"; if ( !bGuiGetAnswerYesNo( soQuestion ) ) { return; } } EditAction* pEditAction = new editOverstrikeConsensus( pContig_, nConsPos, cNewBaseLower ); ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); } void ContigWin :: displayHowReadsAreSorted() { RWCString soHowSorted = pContigView_->soGetHowReadsAreSorted(); pGcw_->displayMessageAtBottom( soHowSorted.data() ); }