/***************************************************************************** # 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. # #*****************************************************************************/ #include "assemblyView.h" #include #include #include #include #include #include #include #include #include #include #include #include "guiapp.h" #include "handleWindowManagerDelete2.h" #include #include "consed.h" #include "hp_exception_kludge.h" #include using namespace std; #include #include "contig.h" #include "assembly.h" #include "consedParameters.h" #include #include "clScaffold.h" #include "please_wait.h" #include "readTypes.h" #include "fwdRevPair.h" #include "fwdRevPairTriangle.h" #include "fwdRevPairSquare.h" #include "fGetDistanceFromPointToLine.h" #include "popupErrorMessage.h" #include "colorDefaults.h" #include "guiAssemblyViewWhatToShow.h" #include "fGetDistanceFromPointToPoint.h" #include "guiMultiContigNavigator.h" #include "library.h" #include "textbox.h" #include "rwcregexp.h" #include "assemblyViewRemoveReads.h" #include "guiChoiceOfSeqMatches.h" #include "guiReorderContigs.h" #include "guiReorientContigs.h" #include "guiAssemblyViewIncludeContigs.h" #include "guiAssemblyViewReadDepth.h" #include "guiAssemblyViewShowTags.h" #include "bForwardReversePairIsConsistentWithContigOrder.h" #include "popupErrorMessage2.h" #include "digestForOneEnzyme.h" #include #include "waitUntilDialogIsVisible.h" #include "assert.h" #include "bGuiGetAnswerYesNo.h" #include "editAddConsensusTag.h" #include "editDeleteConsensusTag.h" #include "printTime.h" #include "printPS.h" #include "mbtValVectorOfBool.h" #include "soAddCommas.h" #include "rwcregexp.h" static void cbFindContig( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->findContig() ); } static void cbUserPushedFindMainWindow( Widget wid, XtPointer pClientData, XtPointer pCallData ) { TRY_CATCH_WRAPPER( GuiApp::pGetGuiApp()->findTopWindow() ); } static void cbUserPushedHideOrShowTags( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->userPushedHideOrShowTags() ); } static void cbUserPushedDigestCutSites( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->userPushedDigestCutSites() ); } static void cbUserPushedGotoAlignedReadsWindow( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->userPushedGotoAlignedReadsWindow() ); } static void cbUserPushedGotoTagInAlignedReadsWindow( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->userPushedGotoTagInAlignedReadsWindow() ); } static void cbUserPushedGotoFragmentInDigestWindow( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->userPushedGotoFragmentInDigestWindow() ); } static void cbUserPushedWhatToShow( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; XmPushButtonCallbackStruct* pPushButtonCallbackStruct = (XmPushButtonCallbackStruct*) pCallData; TRY_CATCH_WRAPPER( pAssemblyView->userPushedWhatToShow( pPushButtonCallbackStruct->event ) ); } static void cbUserPushedWhichTagsToShow( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->userPushedWhichTagsToShow() ); } static void cbUserPushedIncludeContigs( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->userPushedIncludeContigs() ); } static void cbUserPushedReorderContigs( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->userPushedReorderContigs() ); } static void cbUserPushedReorientContigs( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->userPushedReorientContigs() ); } static void cbUserPushedFreezeContigOrder( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->userPushedFreezeContigOrder() ); } static void cbAssemblyViewExposure( Widget wid, assemblyView* pAssemblyView, XmDrawingAreaCallbackStruct* xmDrawStruct) { TRY_CATCH_WRAPPER( pAssemblyView->drawEverything( false, false ) ); // bCalculate } static void cbDismissAssemblyView( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( delete pAssemblyView; ); } static void cbGuiShowDocumentationForAssemblyView( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAV = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAV->showDocumentationForAssemblyView() ); } static void cbResize( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->userResizedWindow() ); } static void cbInput( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; XmDrawingAreaCallbackStruct* pDAC = (XmDrawingAreaCallbackStruct*) pCallData; TRY_CATCH_WRAPPER( pAssemblyView->userClickedOrSomething( pDAC ) ); } static void pointerMotionEventHandler( Widget wid, XtPointer pClientData, XEvent* pEvent, Boolean* ) { int nPixelX = pEvent->xmotion.x; int nPixelY = pEvent->xmotion.y; assemblyView* pAssemblyView = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pAssemblyView->pointerMoved( nPixelX, nPixelY ) ); } static void cbVerticalScrollBar( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pASV = (assemblyView*) pClientData; XmScrollBarCallbackStruct* pCbStruct = (XmScrollBarCallbackStruct*) pCallData; TRY_CATCH_WRAPPER( pASV->verticalScrollBarMoved( pCbStruct->value ) ); } static void cbHorizontalScrollBar( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pASV = (assemblyView*) pClientData; XmScrollBarCallbackStruct* pCbStruct = (XmScrollBarCallbackStruct*) pCallData; TRY_CATCH_WRAPPER( pASV->horizontalScrollBarMoved( pCbStruct->value ) ); } static void cbUserPushedZoomIn( Widget wid, XtPointer pClientData, XtPointer pCallCata ) { assemblyView* pASV = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pASV->userZoomed( assemblyView::nZOOM_IN ) ); } static void cbUserPushedZoomOut( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pASV = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pASV->userZoomed( assemblyView::nZOOM_OUT ) ); } static void cbUserPushedZoomOriginal( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pASV = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( pASV->userZoomed( assemblyView::nZOOM_ORIGINAL ) ); } static void cbUserPushedFwdRevPairsWhatToShow( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView *pASV = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( guiAssemblyViewWhatToShow* pGuiShow = new guiAssemblyViewWhatToShow( pASV, guiAssemblyViewWhatToShow::cFWD_REV_PAIRS ); pGuiShow->popup() ); } static void cbUserPushedReadDepth( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView *pASV = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( guiAssemblyViewReadDepth* pGuiReadDepth = new guiAssemblyViewReadDepth( pASV ); pGuiReadDepth->createWindow(); ); } static void cbUserPushedSequenceMatchesWhatToShow( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pASV = (assemblyView*) pClientData; TRY_CATCH_WRAPPER( guiAssemblyViewWhatToShow* pGuiShow = new guiAssemblyViewWhatToShow( pASV, guiAssemblyViewWhatToShow::cSEQUENCE_MATCHES ); pGuiShow->popup() ); } static void cbUserPushedContigArrangement( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyView* pASV = (assemblyView*) pClientData; XmPushButtonCallbackStruct* pPushButtonCallbackStruct = (XmPushButtonCallbackStruct*) pCallData; TRY_CATCH_WRAPPER( pASV->userPushedContigArrangement( pPushButtonCallbackStruct->event ) ); } const int nSpacingBetweenButtons = 5; assemblyView :: assemblyView( ) : bFinishedComingUp_( false ), pGuiNav_( NULL ), pGuiChoiceOfSeqMatches_( NULL ), pAssemblyViewRemoveReads_( NULL ), bAlreadyReadCrossMatchOutput_( false ), p2DArrayOfArrayOfSeqMatches_( NULL ), pGuiReorderContigs_( NULL ), pGuiReorientContigs_( NULL ), bDoNotDeleteGuiReorderContigs_( false ), bDoNotDeleteGuiReorientContigs_( false ) { aSeqMatches_.soName_ = "assemblyView::aSeqMatches_"; aScaffoldRowTagBars_.soName_ = "assemblyView::aScaffoldRowTagBars_"; } void assemblyView :: createWindow( Assembly* pAssembly ) { nHeightOfAreaForFwdRevPairsInSameScaffold_ = 100; dPixelWidthOfBase_ = 0.004; nVerticalPixelsPerContig_ = 3; nPixelIncrementToScroll_ = 30; nLeftMarginPixelsWide_ = 100; nLeftMarginBeforeName_ = 5; nLeftEdgeScaffoldPos_ = 0; nTopEdgeVirtualPixelPosition_ = 0; bShowDepth_ = pCP->bAssemblyViewShowConsistentFwdRevPairDepth_; bShowEachConsistentFwdRevPair_ = pCP->bAssemblyViewShowConsistentFwdRevPairs_; bShowGapSpanningFwdRevPairs_ = pCP->bAssemblyViewShowGapSpanningFwdRevPairs_; bShowConsistentFwdRevPairsBetweenDifferentScaffolds_ = pCP->bAssemblyViewShowConsistentFwdRevPairsBetweenDifferentScaffolds_; bShowLegsOnSquaresForConsistentFwdRevPairs_ = pCP->bAssemblyViewShowLegsOnSquaresForConsistentFwdRevPairs_; bShowDigest_ = pCP->bAssemblyViewShowRestrictionDigestCutSites_; nNumberOfHighlightedPairsLastTime_ = -666; // forces display the // first time if ( pCP->soAssemblyViewShowWhichInconsistentFwdRevPairs_ == "filtered" ) { nShowWhichInconsistentFwdRevPairs_ = nFILTERED_INCONSISTENT_FWD_REV_PAIRS; } else if ( pCP->soAssemblyViewShowWhichInconsistentFwdRevPairs_ == "none" ) { nShowWhichInconsistentFwdRevPairs_ = nNO_INCONSISTENT_FWD_REV_PAIRS; } else if ( pCP->soAssemblyViewShowWhichInconsistentFwdRevPairs_ == "all" ) { nShowWhichInconsistentFwdRevPairs_ = nALL_INCONSISTENT_FWD_REV_PAIRS; } else { RWCString soError = "consed.assemblyViewShowWhichInconsistentFrwdRevPairs is "; soError += pCP->soAssemblyViewShowWhichInconsistentFwdRevPairs_; soError += " but must be filtered, none, or all"; THROW_ERROR( soError ); } // if there is a file, use it. Only don't use it if the user // specifically says to not use it using guiAssemblyViewWhatToShow // Rachel Maupin, Sept 2002, says that she wants the default to // be to show everything. Thus changing this to false bDoNotShowTemplatesInDoNotShowTemplatesFile_ = false; aArrayOfFwdRevPairTriangles_.soName_ = "assemblyView::aArrayOfFwdRevPairTriangles_"; aArrayOfFwdRevPairLines_.soName_ = "assemblyView::aArrayOfFwdRevPairLines_"; aArrayOfFwdRevPairSquares_.soName_ = "assemblyView::aArrayOfFwdRevPairSquares_"; aScaffolds_.soName_ = "assemblyView::aScaffolds_"; aCurrentlyHighlightedFwdRevPairs_.soName_ = "assemblyView::aCurrentlyHighlightedFwdRevPairs_"; aCurrentlyHighlightedTags_.soName_ = "assemblyView::aCurrentlyHighlightedTags_"; aCurrentlyHighlightedFragments_.soName_ = "assemblyView::aCurrentlyHighlightedFragments_"; aClickedFwdRevPairs_.soName_ = "assemblyView::aClickedFwdRevPairs_"; widPopupShell_ = XtVaCreatePopupShell( "Assembly View", topLevelShellWidgetClass, GuiApp::pGetGuiApp()->widGetTopLevel(), XmNtransient, False, XmNdeleteResponse, XmDO_NOTHING, NULL ); handleWindowManagerDelete2( widPopupShell_, cbDismissAssemblyView, this ); // the immediate child of the application shell is a main window widMainWin_ = XtVaCreateManagedWidget( "mainwin", xmMainWindowWidgetClass, widPopupShell_, XmNancestorSensitive, True, NULL ); // put menu bar on the main window int nArgs = 0; Arg aArg[30]; widMenuBar_ = XmCreateMenuBar( widMainWin_, "menubar", aArg, nArgs ); XtManageChild( widMenuBar_ ); // create help menu button nArgs = 0; Widget widHelpMenu = XmCreatePulldownMenu( widMenuBar_, "Help", aArg, nArgs ); nArgs = 0; XtSetArg( aArg[nArgs], XmNsubMenuId, widHelpMenu ); ++nArgs; Widget widHelpCascade = XmCreateCascadeButton( widMenuBar_, "Help", aArg, nArgs ); XtManageChild( widHelpCascade ); XtVaSetValues( widMenuBar_, XmNmenuHelpWidget, widHelpCascade, NULL ); // now add help menu item Widget widShowDocumentation = XtVaCreateManagedWidget( "Show Documentation for Assembly View", xmPushButtonWidgetClass, widHelpMenu, NULL ); XtAddCallback( widShowDocumentation, XmNactivateCallback, cbGuiShowDocumentationForAssemblyView, this ); widForm_ = XtVaCreateManagedWidget( "form", xmFormWidgetClass, widMainWin_, XmNshadowThickness, 0, XmNborderWidth, 0, NULL ); widDismissButton_ = XtVaCreateManagedWidget( "Dismiss", xmPushButtonWidgetClass, widForm_, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 40, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 60, NULL ); Widget widToBeAttachedTo = widDismissButton_; XtAddCallback( widDismissButton_, XmNactivateCallback, (XtCallbackProc) cbDismissAssemblyView, this ); widZoomIn_ = XtVaCreateManagedWidget( "Zoom In", xmPushButtonWidgetClass, widForm_, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widToBeAttachedTo, XmNbottomOffset, 10, XmNleftAttachment, XmATTACH_FORM, NULL ); widToBeAttachedTo = widZoomIn_; XtAddCallback( widZoomIn_, XmNactivateCallback, cbUserPushedZoomIn, this ); widZoomOut_ = XtVaCreateManagedWidget( "Zoom Out", xmPushButtonWidgetClass, widForm_, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widToBeAttachedTo, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widZoomIn_, XmNleftOffset, nSpacingBetweenButtons, NULL ); widToBeAttachedTo = widZoomOut_; XtAddCallback( widZoomOut_, XmNactivateCallback, cbUserPushedZoomOut, this ); widZoomOriginal_ = XtVaCreateManagedWidget( "Zoom Orig", xmPushButtonWidgetClass, widForm_, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widToBeAttachedTo, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widZoomOut_, XmNleftOffset, nSpacingBetweenButtons, NULL ); widToBeAttachedTo = widZoomOriginal_; XtAddCallback( widZoomOriginal_, XmNactivateCallback, cbUserPushedZoomOriginal, this ); Widget widWhatToShow = XtVaCreateManagedWidget( "What to Show", xmPushButtonWidgetClass, widForm_, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widToBeAttachedTo, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widToBeAttachedTo, XmNleftOffset, 30, NULL ); widToBeAttachedTo = widWhatToShow; XtAddCallback( widWhatToShow, XmNactivateCallback, cbUserPushedWhatToShow, this ); widContigArrangement_ = XtVaCreateManagedWidget( "Contig Arrangement", xmPushButtonWidgetClass, widForm_, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widToBeAttachedTo, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widToBeAttachedTo, XmNleftOffset, nSpacingBetweenButtons, NULL ); XtAddCallback( widContigArrangement_, XmNactivateCallback, cbUserPushedContigArrangement, this ); widToBeAttachedTo = widContigArrangement_; Widget widFindMainWindow = XtVaCreateManagedWidget( "Find Main Win", xmPushButtonWidgetClass, widForm_, XmNalignment, XmALIGNMENT_BEGINNING, XmNtraversalOn, False, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widToBeAttachedTo, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widToBeAttachedTo, XmNleftOffset, nSpacingBetweenButtons, NULL ); XtAddCallback( widFindMainWindow, XmNactivateCallback, cbUserPushedFindMainWindow, this ); widToBeAttachedTo = widFindMainWindow; Widget widFindContig = XtVaCreateManagedWidget( "Find Contig", xmPushButtonWidgetClass, widForm_, XmNtraversalOn, False, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widToBeAttachedTo, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widToBeAttachedTo, XmNleftOffset, nSpacingBetweenButtons, NULL ); XtAddCallback( widFindContig, XmNactivateCallback, cbFindContig, this ); widToBeAttachedTo = widFindContig; widContigName_ = XtVaCreateManagedWidget( "Contig Name", xmTextFieldWidgetClass, widForm_, // XmNtraversalOn, False, (if this is uncommented, you can't // edit the field!) XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, widToBeAttachedTo, XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, nSpacingBetweenButtons, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widToBeAttachedTo, XmNleftOffset, nSpacingBetweenButtons, NULL ); XtAddCallback( widContigName_, XmNactivateCallback, cbFindContig, this ); widToBeAttachedTo = widContigName_; // now row above widMessageWindowAtBottom_ = XtVaCreateManagedWidget( "messagebox", xmTextWidgetClass, widForm_, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widToBeAttachedTo, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtraversalOn, False, XmNeditable, False, XmNeditMode, XmSINGLE_LINE_EDIT, XmNcursorPositionVisible, False, XmNmarginHeight, 0, NULL ); widToBeAttachedTo = widMessageWindowAtBottom_; widScrolledWin_ = XtVaCreateManagedWidget( "scrolled", xmScrolledWindowWidgetClass, widForm_, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, widToBeAttachedTo, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL ); widHorizontalScrollBar_ = XtVaCreateManagedWidget( "horizontalScrollBar", xmScrollBarWidgetClass, widScrolledWin_, XmNorientation, XmHORIZONTAL, XmNminimum, 0, NULL ); XtAddCallback( widHorizontalScrollBar_, XmNvalueChangedCallback, cbHorizontalScrollBar, this ); XtAddCallback( widHorizontalScrollBar_, XmNdragCallback, cbHorizontalScrollBar, this ); widVerticalScrollBar_ = XtVaCreateManagedWidget( "verticalScrollBar", xmScrollBarWidgetClass, widScrolledWin_, XmNorientation, XmVERTICAL, XmNminimum, 0, NULL ); XtAddCallback( widVerticalScrollBar_, XmNvalueChangedCallback, cbVerticalScrollBar, this ); XtAddCallback( widVerticalScrollBar_, XmNdragCallback, cbVerticalScrollBar, this ); widDrawingArea_ = XtVaCreateManagedWidget( "assemblyViewDrawingArea", xmDrawingAreaWidgetClass, widScrolledWin_, XmNwidth, (Dimension) pCP->nAssemblyViewWindowInitialPixelWidth_, XmNheight, (Dimension) pCP->nAssemblyViewWindowInitialPixelHeight_, NULL ); XtAddCallback( widDrawingArea_, XmNinputCallback, (XtCallbackProc )cbInput, this); XtAddCallback( widDrawingArea_, XmNresizeCallback, cbResize, this ); pGctContigs_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewContigs_, "black" ); pGctContigNames_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewContigNamesForeground_, ColorDefaults::pGetColorDefaults()->soColorAssemblyViewContigNamesBackground_ ); pGctConsistentFwdRevPairs_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentFwdRevPairs_, "black" ); pGctTooFewConsistentFwdRevPairs_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewTooFewConsistentFwdRevPairs_, "black" ); pGctConsistentFwdRevPairDepth_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentFwdRevPairDepth_, "black" ); pGctReadDepth_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewReadDepth_, "black" ); pGctDiscrepanciesNotIndels_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewDiscrepanciesNotIndels_, "black" ); pGctDiscrepanciesIndels_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewDiscrepanciesIndels_, "black" ); pGctInconsistentFwdRevPair_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewInconsistentFwdRevPair_, "black" ); pGctScale_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewScaleNumbers_, "black" ); pGctScaleNumbers_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewScaleNumbers_, "black" ); pGctConsistentGapSpanningFwdRevPair_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentGapSpanningFwdRevPair_, "black" ); pGctHighlight_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewHighlight_, "black" ); pGctMultipleItemsOnTopOfEachOther_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewMultipleItemsOnTopOfEachOther_, "black" ); pGctDirectSequenceMatches_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewDirectSequenceMatches_, "black" ); pGctInvertedSequenceMatches_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewInvertedSequenceMatches_, "black" ); for( int nEnzyme = 0; nEnzyme < nMaxNumberOfRestrictionEnzymeLines; ++nEnzyme ) { int n1Enzyme = nEnzyme + 1; RWCString soColor; if ( n1Enzyme == 1 ) soColor = ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentRestrictionDigestFragment1_; else if ( n1Enzyme == 2 ) soColor = ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentRestrictionDigestFragment2_; else if ( n1Enzyme == 3 ) soColor = ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentRestrictionDigestFragment3_; else if ( n1Enzyme == 4 ) soColor = ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentRestrictionDigestFragment4_; else if ( n1Enzyme == 5 ) soColor = ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentRestrictionDigestFragment5_; else if ( n1Enzyme == 6 ) soColor = ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentRestrictionDigestFragment6_; else if ( n1Enzyme == 7 ) soColor = ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentRestrictionDigestFragment7_; else if ( n1Enzyme == 8 ) soColor = ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentRestrictionDigestFragment8_; else if ( n1Enzyme == 9 ) soColor = ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentRestrictionDigestFragment9_; else if ( n1Enzyme == 10) soColor = ColorDefaults::pGetColorDefaults()->soColorAssemblyViewConsistentRestrictionDigestFragment10_; else assert( false ); pGctConsistentRestrictionDigestFragment_[ nEnzyme ] = new GuiColorText( soColor, "black" ); } pGctInconsistentRestrictionDigestFragment_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewInconsistentRestrictionDigestFragment_, "black" ); pGctCloneEnd_ = new GuiColorText( ColorDefaults::pGetColorDefaults()->soColorAssemblyViewCloneEnd_, "black" ); XtPopup( widPopupShell_, XtGrabNone ); PleaseWait* pPleaseWait = new PleaseWait( widPopupShell_ ); pCP->bPrintInFigureOutContigOrderAndOrientation_ = false; ConsEd::pGetAssembly()->getScaffolds( aScaffolds_ ); // need to set to true for other uses pCP->bPrintInFigureOutContigOrderAndOrientation_ = true; setContigScaffolds( aScaffolds_ ); // this does a huge amount of work: // calls figureOutContigOrderAndOrientation() which calls // setContigTemplateArrays // this is called by getScaffolds (above) // ConsEd::pGetAssembly()->figureOutContigOrderAndOrientation(); // this will // call setContigTemplateArrays readFileOfTemplatesToNotShowIfItExists(); if ( aScaffolds_.length() == 0 ) { delete this; guiAssemblyViewIncludeContigs* pGuiAssemblyViewIncludeContigs = new guiAssemblyViewIncludeContigs(); pGuiAssemblyViewIncludeContigs->createWindow(); popupErrorMessage( "All contigs were excluded by user-settable criteria so there are no scaffolds. Use the \"Which Contigs to Show in Assembly View\" window to change the parameters" ); return; } pAssembly->setAllPaddedPositionsArrays(); if ( bShowDepth_ ) pAssembly->figureOutConsistentForwardReversePairDepthOfAllContigs( bDoNotShowTemplatesInDoNotShowTemplatesFile_ ); pAssembly->filterInconsistentFwdRevPairs(); nLongestScaffoldLength_ = aScaffolds_[0]->nScaffoldLength_; dPixelWidthOfBase_ = dCalculateInitialZoomFactor(); lBasesPerScaleTick_ = lCalculateWidthOfScaleTicks(); arrangeScaffoldsOnScreen(); setHorizontalScrollBar(); setVerticalScrollBar(); delete pPleaseWait; bFinishedComingUp_ = true; drawEverything( true, // bFirstCalculate false ); // first erase ConsEd::pGetConsEd()->pAssemblyView_ = this; // the reason I've added these after everything else is calculated and // created is to avoid the following bug: // // an exception is thrown during the calculations. Thus the ctor // is exited, probably releasing the memory. However, the // pointerMotionEventHandler is still registered. The user moves // the pointer over the area, this handler runs, and gets a // segmentation fault since the data is no longer there. XtAddEventHandler( widDrawingArea_, PointerMotionMask, False, (XtEventHandler) pointerMotionEventHandler, this ); XtAddCallback( widDrawingArea_, XmNexposeCallback, (XtCallbackProc ) cbAssemblyViewExposure, this ); // prepare for the user pushing the Contig Arrangement button // create popup menu before-hand widContigArrangementPopupMenu_ = XmCreatePopupMenu( widDrawingArea_, // tried widPopupShell_, widContigArrangement_, and widForm_ and all have problems "popup", NULL, 0 ); Widget widReorderContigs = XtVaCreateManagedWidget( "Reorder Contigs", xmPushButtonWidgetClass, widContigArrangementPopupMenu_, NULL ); XtAddCallback( widReorderContigs, XmNactivateCallback, cbUserPushedReorderContigs, this ); Widget widReorientContigs = XtVaCreateManagedWidget( "Reorient Contigs", xmPushButtonWidgetClass, widContigArrangementPopupMenu_, NULL ); XtAddCallback( widReorientContigs, XmNactivateCallback, cbUserPushedReorientContigs, this ); Widget widFixContigOrder = XtVaCreateManagedWidget( "Freeze Contig Order", xmPushButtonWidgetClass, widContigArrangementPopupMenu_, NULL ); XtAddCallback( widFixContigOrder, XmNactivateCallback, cbUserPushedFreezeContigOrder, this ); // prepare with "WhatToShow" popup menu beforehand widWhatToShowPopupMenu_ = XmCreatePopupMenu( widDrawingArea_, "popup", NULL, 0 ); widSequenceMatchesWhatToShow_ = XtVaCreateManagedWidget( "Sequence Matches", xmPushButtonWidgetClass, widWhatToShowPopupMenu_, NULL ); XtAddCallback( widSequenceMatchesWhatToShow_, XmNactivateCallback, cbUserPushedSequenceMatchesWhatToShow, this ); widFwdRevPairsWhatToShow_ = XtVaCreateManagedWidget( "Fwd/Rev Pairs", xmPushButtonWidgetClass, widWhatToShowPopupMenu_, NULL ); XtAddCallback( widFwdRevPairsWhatToShow_, XmNactivateCallback, cbUserPushedFwdRevPairsWhatToShow, this ); widIncludeContigs_ = XtVaCreateManagedWidget( "In/exclude Contigs", xmPushButtonWidgetClass, widWhatToShowPopupMenu_, NULL ); XtAddCallback( widIncludeContigs_, XmNactivateCallback, cbUserPushedIncludeContigs, this ); widReadDepth_ = XtVaCreateManagedWidget( "Read Depth/Multiple Discrepancies", xmPushButtonWidgetClass, widWhatToShowPopupMenu_, NULL ); XtAddCallback( widReadDepth_, XmNactivateCallback, cbUserPushedReadDepth, this ); widTags_ = XtVaCreateManagedWidget( "Which Tags To Show", xmPushButtonWidgetClass, widWhatToShowPopupMenu_, NULL ); XtAddCallback( widTags_, XmNactivateCallback, cbUserPushedWhichTagsToShow, this ); widHideOrShowTags_ = XtVaCreateManagedWidget( ( pCP->bAssemblyViewShowTags_ ? "Hide All Tags" : "Show Selected Tags" ), xmPushButtonWidgetClass, widWhatToShowPopupMenu_, NULL ); XtAddCallback( widHideOrShowTags_, XmNactivateCallback, cbUserPushedHideOrShowTags, this ); widDigestCutSites_ = XtVaCreateManagedWidget( ( bShowDigest_ ? "Hide Digest Fragments" : "Digest Fragments" ), xmPushButtonWidgetClass, widWhatToShowPopupMenu_, NULL ); XtAddCallback( widDigestCutSites_, XmNactivateCallback, cbUserPushedDigestCutSites, this ); // prepare popup menu for "goto contig pos" widMouseButton3PopupMenu_ = XmCreatePopupMenu( widDrawingArea_, "popup", NULL, 0 ); widGotoAlignedReadsWindow_ = XtVaCreateManagedWidget( "Goto Aligned Reads Window", xmPushButtonWidgetClass, widMouseButton3PopupMenu_, NULL ); XtAddCallback( widGotoAlignedReadsWindow_, XmNactivateCallback, cbUserPushedGotoAlignedReadsWindow, this ); widGotoTag_ = XtVaCreateManagedWidget( "Show tag(s)", xmPushButtonWidgetClass, widMouseButton3PopupMenu_, NULL ); XtAddCallback( widGotoTag_, XmNactivateCallback, cbUserPushedGotoTagInAlignedReadsWindow, this ); widGotoFragment_ = XtVaCreateManagedWidget( "Goto fragment in digest window", xmPushButtonWidgetClass, widMouseButton3PopupMenu_, NULL ); XtAddCallback( widGotoFragment_, XmNactivateCallback, cbUserPushedGotoFragmentInDigestWindow, this ); } void assemblyView :: drawScaffolds() { for ( int nScaffold = 0; nScaffold < aScaffolds_.length(); nScaffold++) { drawScaffold( nScaffold ); } } void assemblyView :: drawScaffold( const int nScaffold ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; for( int nContig = 0; nContig < pScaffold->aContigs_.length(); ++nContig ) { drawContigBar( nContig, nScaffold ); } drawScaleForEachContigInScaffold( nScaffold ); drawContigLabels( nScaffold ); } // draws the grey bar for a contig void assemblyView :: drawContigBar( const int nContig, const int nScaffold ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; Contig* pContig = pScaffold->aContigs_[ nContig ]; int nPixelXLeft = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosLeft_ ); int nPixelXRight = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosRight_ ); const int nMinimumWidthOfAGap = 10; // shrink the contig so that the gaps are at least 5 pixels wide if ( nContig > 0 ) { Contig* pContigLeft = pScaffold->aContigs_[ nContig - 1 ]; int nPixelContigLeft = nGetPixelXFromScaffoldPos( nScaffold, pContigLeft->nClonePosRight_ ); int nGapSizeInPixels = ABS( nPixelXLeft - nPixelContigLeft ); if ( nGapSizeInPixels < nMinimumWidthOfAGap ) { nPixelXLeft += ( nMinimumWidthOfAGap - nGapSizeInPixels ) / 2; } } if ( nContig < ( pScaffold->aContigs_.length() - 1) ) { Contig* pContigRight = pScaffold->aContigs_[ nContig + 1 ]; int nPixelContigRight = nGetPixelXFromScaffoldPos( nScaffold, pContigRight->nClonePosLeft_ ); int nGapSizeInPixels = ABS( nPixelContigRight - nPixelXRight ); if ( nGapSizeInPixels < nMinimumWidthOfAGap ) { nPixelXRight -= ( nMinimumWidthOfAGap - nGapSizeInPixels ) / 2; } } // however, after shrinking both ends, little contigs might now have // disappeared altogether. In such cases, just can't show the gap. if ( nPixelXLeft > nPixelXRight ) { nPixelXLeft = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosLeft_ ); nPixelXRight = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosRight_ ); } int nPixelYTop = nGetPixelYOfScaffoldBaseline( nScaffold ); // the -1 is so that there is no overlap between the contig bar // and the tags or inconsistent fwd/rev pairs int nPixelYBottom = nGetPixelYOfTopOfAreaForInconsistentFwdRevPairs( nScaffold ) - 1; XFillRectangle( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGctContigs_->gcGet(), nPixelXLeft, nPixelYTop, nPixelXRight - nPixelXLeft + 1, nPixelYBottom - nPixelYTop + 1 ); } const int nPixelSpacingBetweenNames = 0; void assemblyView :: drawContigLabels( const int nScaffold ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; for( int nContig = 0; nContig < pScaffold->aContigs_.length(); ++nContig ) { Contig* pContig = pScaffold->aContigs_[ nContig ]; int nContigPixelXLeft = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosLeft_ ); int nContigPixelXRight = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosRight_ ); int nPixelXWindowLeft = 0; int nPixelXWindowRight = nGetAssemblyViewWindowWidth() - 1; int nContigOnScreenPixelXLeft; int nContigOnScreenPixelXRight; if ( !bIntersect( nContigPixelXLeft, nContigPixelXRight, nPixelXWindowLeft, nPixelXWindowRight, nContigOnScreenPixelXLeft, nContigOnScreenPixelXRight ) ) { // offscreen continue; } if ( nPixelXWindowRight < nContigPixelXLeft ) { // all other contigs are off the right edge of the screen break; } int nPixelXCenterOfContigName = ( nContigOnScreenPixelXLeft + nContigOnScreenPixelXRight ) / 2; RWCString soContigName = pContig->soGetAbbreviatedName(); if ( pScaffold->aIfContigsAreComplemented_[ nContig ] ) soContigName += "c"; int nWhereWeWouldLikeToStartTheName = nPixelXCenterOfContigName - soContigName.length() * GuiApp::nGetFontWidth() / 2; // ok to write name int nPixelY = nGetPixelYOfContigName( nScaffold ); XDrawImageString( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGctContigNames_->gcGet(), nWhereWeWouldLikeToStartTheName, nPixelY, soContigName.data(), soContigName.length() ); } } // call this whenever zoom or when start up long assemblyView :: lCalculateWidthOfScaleTicks() { // this doesn't depend on the scaffold or contig--just on the zoom. // Make the tick marks so they are a minimum distance apart. Let's // say a minimum of a font character width int nMinimumPixelSeparation = GuiApp::nGetFontWidth() / 3; long lBasesPerScaleTick = 1; while( 1 ) { int nPixelSeparation = dPixelWidthOfBase_ * lBasesPerScaleTick; if ( nPixelSeparation > nMinimumPixelSeparation ) { return( lBasesPerScaleTick ); } lBasesPerScaleTick *= 10; } } void assemblyView :: drawScaleForEachContigInScaffold( const int nScaffold ) { int nRightmostUsedPixelForNumber = -666; clScaffold* pScaffold = aScaffolds_[ nScaffold ]; for( int nContig = 0; nContig < pScaffold->aContigs_.length(); ++nContig ) { Contig* pContig = pScaffold->aContigs_[ nContig ]; int nPixelXLeft = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosLeft_ ); int nPixelXRight = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosRight_ ); if ( nPixelXRight < 0 ) { // offscreen. continue; } if ( nGetAssemblyViewWindowWidth() < nPixelXLeft ) break; // no more contigs can be seen // if reached here, then we are considering a contig that // is partly on the screen bool bComplementedContig = pScaffold->aIfContigsAreComplemented_[ nContig ]; int nUnpaddedStart; int nUnpaddedEnd; if ( bComplementedContig ) { nUnpaddedStart = pContig->nGetHighQualitySegmentEnd(); // round down int nTemp = nUnpaddedStart / lBasesPerScaleTick_; nUnpaddedStart = nTemp * lBasesPerScaleTick_; nUnpaddedEnd = pContig->nGetHighQualitySegmentStart(); } else { nUnpaddedStart = pContig->nGetHighQualitySegmentStart(); // round up int nTemp = ( nUnpaddedStart + lBasesPerScaleTick_ - 1 ) / lBasesPerScaleTick_; nUnpaddedStart = nTemp * lBasesPerScaleTick_; nUnpaddedEnd = pContig->nGetHighQualitySegmentEnd(); } int nAmountToAdd = ( bComplementedContig ? -lBasesPerScaleTick_ : lBasesPerScaleTick_ ); for( int nUnpaddedBase = nUnpaddedStart; ( bComplementedContig && ( nUnpaddedBase >= nUnpaddedEnd ) ) || ( !bComplementedContig && ( nUnpaddedBase <= nUnpaddedEnd ) ); nUnpaddedBase += nAmountToAdd ) { // convert to scaffold position int nScaffoldPos = pContig->nGetScaffoldPosFromUnpaddedConsPos( nUnpaddedBase ); drawScaleTick( nScaffold, nScaffoldPos, nUnpaddedBase, nRightmostUsedPixelForNumber ); } } } void assemblyView :: drawScaleTick( const int nScaffold, const int nScaffoldPos, const int nUnpaddedBase, int& nRightmostUsedPixelForNumber ) { int nPixelX = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPos ); int nPixelYTop = nGetPixelYOfScaleTickTop( nScaffold ); // int nPixelYBottom = nGetPixelYOfScaleTickBottom( nScaffold ); // will the number fit? RWCString soNumber = soAddCommas( nUnpaddedBase ); int nPixelXLeftOfNumber = nPixelX - soNumber.length() * GuiApp::nGetFontWidth() / 2; int nPixelSpaceBetweenNumbers = GuiApp::nGetFontWidth() / 2; bool bDrawNumber = ( nPixelXLeftOfNumber > ( nRightmostUsedPixelForNumber + nPixelSpaceBetweenNumbers ) && ( ( nUnpaddedBase / lBasesPerScaleTick_ ) % 10 == 0 ) ) ? true : false; eScaleTickType eTickType; int nTicks = nUnpaddedBase / lBasesPerScaleTick_; if ( nTicks % 10 == 0 ) eTickType = eBigTick; else if ( nTicks % 5 == 0 ) eTickType = eMediumSizedTick; else eTickType = eLittleTick; int nPixelYBottom = nGetPixelYOfScaleTickBottom( nScaffold, eTickType ); XDrawLine( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGctScale_->gcGet(), nPixelX, nPixelYTop, nPixelX, nPixelYBottom ); if ( bDrawNumber ) { int nPixelYForScaleNumber = nGetPixelYOfScaleNumber( nScaffold ); XDrawString( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGctScaleNumbers_->gcGet(), nPixelXLeftOfNumber, nPixelYForScaleNumber, soNumber.data(), soNumber.length() ); nRightmostUsedPixelForNumber = nPixelXLeftOfNumber + soNumber.length() * GuiApp::nGetFontWidth(); } } int assemblyView :: nGetTopOfScaffold( const int nScaffold ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; return( nHeightOfMarginAtTopOfScreen - nTopEdgeVirtualPixelPosition_ + pScaffold->nScaffoldRow_ * nGetHeightOfOneScaffold() ); } int assemblyView :: nGetPixelXFromScaffoldPos( const int nScaffold, const int nScaffoldPos ) { // what is the scaffold row position? clScaffold* pScaffold = aScaffolds_[ nScaffold ]; // first convert the clone position to the screen position, // which takes into account scrolling int nScreenScaffoldPos = nScaffoldPos - nLeftEdgeScaffoldPos_ + pScaffold->nScaffoldPositionsBeforeItOnScaffoldRow_; int nPixelX = nGetPixelXFromScreenScaffoldPos( nScreenScaffoldPos ); return( nPixelX ); } const int nLeftEdgePixelMargin = 20; const int nRightEdgePixelMargin = 20; int assemblyView :: nGetPixelXFromScreenScaffoldPos( const int nScreenScaffoldPos ) { return( (int) ( nScreenScaffoldPos * dPixelWidthOfBase_ ) + nLeftEdgePixelMargin ); } void assemblyView :: drawEverything( const bool bFirstCalculatePositions, const bool bFirstErase ) { if ( !bFinishedComingUp_ ) return; if ( bFirstErase ) { XClearArea( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), 0, 0, 0, 0, false ); } drawFwdRevPairs( bFirstCalculatePositions ); if ( bShowDepth_ ) drawFwdRevPairDepth(); drawRepeats( bFirstCalculatePositions ); drawScaffolds(); drawCloneEnds(); if ( pCP->bAssemblyViewShowReadDepth_ ) drawReadDepth(); if ( pCP->bAssemblyViewShowMultipleHighQualityDiscrepancies_ ) drawMultipleDiscrepancies(); if ( pCP->bAssemblyViewShowTags_ ) { if ( bFirstCalculatePositions ) calculateTagLines(); drawTags(); } if ( bShowDigest_ && ConsEd::pGetConsEd()->aGuiDisplayDigest_.length() > 0 ) { drawRestrictionDigestFragments(); } } void assemblyView :: drawFwdRevPairDepth() { for ( int nScaffold = 0; nScaffold < aScaffolds_.length(); nScaffold++) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; for( int nContig = 0; nContig < pScaffold->aContigs_.length(); ++nContig ) { drawFwdRevPairDepthForOneContig( nScaffold, nContig ); } } } void assemblyView :: drawFwdRevPairDepthForOneContig( const int nScaffold, const int nContig ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; Contig* pContig = pScaffold->aContigs_[ nContig ]; int nPixelY = nGetPixelYOfConsistentFwdRevPairBaseline( nScaffold ); int nNumberOfBasesPerFwdRevPairPoint = nGetNumberOfBasesPerFwdRevPairPoint(); if ( pContig->aConsistentFwdRevPairDepth_.nGetEndIndex() != pContig->nGetUnpaddedEndIndex() ) { // do all contigs at once. Presumably that will fix this for all contigs. ConsEd::pGetAssembly()->figureOutConsistentForwardReversePairDepthOfAllContigs( bDoNotShowTemplatesInDoNotShowTemplatesFile_ ); assert( pContig->aConsistentFwdRevPairDepth_.nGetEndIndex() == pContig->nGetUnpaddedEndIndex() ); } const char cSTART = 's'; const char cTOO_FEW = 't'; const char cENOUGH = 'e'; const int nEnoughFwdRevPairs = 2; char cOldState = cSTART; char cNewState; const int nMaxPoints = 2000; XPoint xpoints[ nMaxPoints ]; int nXPointIndex = -1; // ++ will start this at 0 bool bLastPoint = false; for( int nUnpadded = pContig->nGetUnpaddedStartIndex(); !bLastPoint; nUnpadded += nNumberOfBasesPerFwdRevPairPoint ) { int nSum = 0; int nBases = 0; for( int nUnpadded1 = nUnpadded; nUnpadded1 <= nUnpadded + nNumberOfBasesPerFwdRevPairPoint - 1 && nUnpadded1 <= pContig->nGetUnpaddedEndIndex(); ++nUnpadded1 ) { nSum += (int) pContig->aConsistentFwdRevPairDepth_[ nUnpadded1 ]; ++nBases; } // round assert( nBases != 0 ); int nAverage = ( nSum + nBases/2 ) / nBases; if ( nAverage < pCP->nAssemblyViewShowFwdRevPairDepthsInRedIfOnlyThisMany_ ) cNewState = cTOO_FEW; else cNewState = cENOUGH; // if we just had a state change and there are points from // the old state that haven't yet been written out, write // them out now. if ( cNewState != cOldState && cOldState != cSTART && nXPointIndex > -1 ) { // write out the xpoints so far GuiColorText* pGCT = ( cOldState == cENOUGH ? pGctConsistentFwdRevPairDepth_ : pGctTooFewConsistentFwdRevPairs_ ); XDrawLines( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGCT->gcGet(), xpoints, nXPointIndex + 1, // 0 to nXPointIndex has // nXPointIndex + 1 entries CoordModeOrigin ); nXPointIndex = -1; // set up for next time around } cOldState = cNewState; ++nXPointIndex; xpoints[ nXPointIndex].y = nGetPixelYFromNumberOfFwdRevPairs( nAverage, nScaffold ); xpoints[ nXPointIndex].x = nGetPixelXFromContigBase( nScaffold, pContig, nUnpadded ); if ( nUnpadded >= pContig->nGetUnpaddedEndIndex() - nNumberOfBasesPerFwdRevPairPoint + 1 ) bLastPoint = true; if ( ( nXPointIndex >= ( nMaxPoints - 1 ) ) || bLastPoint ) { GuiColorText* pGCT = ( cOldState == cENOUGH ? pGctConsistentFwdRevPairDepth_ : pGctTooFewConsistentFwdRevPairs_ ); XDrawLines( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGCT->gcGet(), xpoints, nXPointIndex + 1, // 0 to nXPointIndex has // nXPointIndex + 1 entries CoordModeOrigin ); nXPointIndex = -1; // set up for next time around } } } int assemblyView :: nGetNumberOfBasesPerFwdRevPairPoint() { // this depends on the zoom, dPixelWidthOfBase_ const int nPixelsPerFwdRevPairPoint = 1; int nBasesPerFwdRevPairPoint = nPixelsPerFwdRevPairPoint / dPixelWidthOfBase_; if ( nBasesPerFwdRevPairPoint < 1 ) nBasesPerFwdRevPairPoint = 1; return( nBasesPerFwdRevPairPoint ); } const int nVerticalSpacingBetweenContigBaselineAndFwdRevPairGraph = 2; int assemblyView :: nGetPixelYFromNumberOfFwdRevPairs( const int nNumberOfFwdRevPairs, const int nScaffold ) { int nPixelY = nGetPixelYOfConsistentFwdRevPairBaseline( nScaffold ); // how many fwd/rev pairs should we put between contigs? // 200,000 bp with 3000 3000bp subclones, means that 9Mb is the // sum of the bases in subclones, so 9Mb/200,00bp = 4.5 subclones deep, // on average. So if we make the distance 20 between contigs, we will // have lots of room. const int nNumberOfFwdRevPairsBetweenContigs = 255; // if the # is <= 30, fit it into the 75% of the region. If it // is 31 to 255, then fit it into the remaining 1/4 of the vertical // region. int nThreeQuarterPixel = nHeightOfAreaForFwdRevPairsInSameScaffold_ * 3 / 4; int nPixelsAboveBaseline; if ( nNumberOfFwdRevPairs <= 30 ) { nPixelsAboveBaseline = nNumberOfFwdRevPairs * nThreeQuarterPixel / 30; } else { int nOneQuarterPixel = nHeightOfAreaForFwdRevPairsInSameScaffold_ / 4; nPixelsAboveBaseline = nThreeQuarterPixel + nOneQuarterPixel * ( nNumberOfFwdRevPairs - 30 ) / (255 - 30 ); } // should always be able to see the graph (Nov 2008) if ( nPixelsAboveBaseline == 0 ) { nPixelsAboveBaseline = 1; } nPixelY -= nPixelsAboveBaseline; return( nPixelY ); } // int assemblyView :: nGetPixelYOfContigBaseline( // const int nZeroBasedContigOrderFromTop ) { // return( nVerticalPixelSpacingAboveTopContig_ + // ( nZeroBasedContigOrderFromTop * // ( nVerticalPixelsPerContig_ + nHeightOfAreaForFwdRevPairsInSameScaffold_ ) // ) ); // } // int assemblyView :: nGetPixelXFromBase( const int nBase ) { // // this depends on zoom, dPixelWidthOfBase_ // return( nLeftMarginPixelsWide_ + nBase * dPixelWidthOfBase_ ); // } void assemblyView :: calculateWhereFwdRevPairsAre() { // fixes bug in which the user moves the pointer so fast to click // "apply" in the "What to show" box that some fwdRev pairs are // still highlighted. The // aArrayOfFwdRevPairTriangles_.clearAndDestroy runs, deleting // these objects. Then the pointer motion event is handled and // consed attempts to unhighlight the deleted fwdRev pairs getting // a segmentation fault. Fixed July 2005. if ( aCurrentlyHighlightedFwdRevPairs_.nCurrentLength_ > 0 ) { unhighlightCurrentFwdRevPairs(); } aArrayOfFwdRevPairTriangles_.clearAndDestroy(); aArrayOfFwdRevPairLines_.clearAndDestroy(); aArrayOfFwdRevPairSquares_.clearAndDestroy(); Assembly* pAssembly = ConsEd::pGetAssembly(); for( int nSub = 0; nSub < pAssembly->subcloneTTemplateArray_.length(); ++nSub ) { subcloneTTemplate* pSub = pAssembly->subcloneTTemplateArray_[ nSub ]; if ( !pSub->bHasForwardAndReversePair_ ) continue; if ( bDoNotShowTemplatesInDoNotShowTemplatesFile_ && pSub->bDoNotShowInAssemblyView_ ) continue; // get the forward and reverse reads. If there is more than one // of either, which should we use? The best of each. LocatedFragment* pForwardLocFrag = NULL; LocatedFragment* pReverseLocFrag = NULL; char cProblem = ' '; bool bHasAFwdRevPair; bool bIsConsistent = pSub->bHasAConsistentFwdRevPair( pForwardLocFrag, pReverseLocFrag, bHasAFwdRevPair, cProblem); if ( !bHasAFwdRevPair ) continue; // redundant, I think // special check to handle case (hitherto unchecked) that // a forward/reverse pair are in different contigs, they // are pointing in a manner that is consistent with the // contig order/orientation if ( bIsConsistent && pForwardLocFrag->pGetContig() != pReverseLocFrag->pGetContig() ) { bIsConsistent = bForwardReversePairIsConsistentWithContigOrder( pForwardLocFrag, pReverseLocFrag, cProblem ); } fwdRevPair2* pFwdRevPair = pCalculateWhereSingleFwdRevPairIs( pForwardLocFrag, pReverseLocFrag, bIsConsistent, cProblem ); if ( !pFwdRevPair ) continue; if ( pFwdRevPair->cGetType() == cTRIANGLE ) aArrayOfFwdRevPairTriangles_.insert( (fwdRevPairTriangle*) pFwdRevPair ); else if ( pFwdRevPair->cGetType() == cSQUARE ) aArrayOfFwdRevPairSquares_.insert( (fwdRevPairSquare*) pFwdRevPair ); else if ( pFwdRevPair->cGetType() == cLINE ) aArrayOfFwdRevPairLines_.insert( (fwdRevPairLine*) pFwdRevPair ); else assert( false ); } // for( int nSub = 0; if ( nShowWhichInconsistentFwdRevPairs_ == nFILTERED_INCONSISTENT_FWD_REV_PAIRS ) filteredBadFwdRevPairs(); // now sort the lists and mark the ones that are coincident aArrayOfFwdRevPairTriangles_.resort(); aArrayOfFwdRevPairLines_.resort(); aArrayOfFwdRevPairSquares_.resort(); aArrayOfFwdRevPairTriangles_.markCoincidentItems( this ); aArrayOfFwdRevPairLines_.markCoincidentItems( this ); aArrayOfFwdRevPairSquares_.markCoincidentItems( this ); // special handling of clicked objects: RWTPtrOrderedVector aTempClickedFwdRevPairs = aClickedFwdRevPairs_; aClickedFwdRevPairs_.clear(); // do not destroy at this point, // because we are going to access the objects themselves for( int nPair = 0; nPair < aTempClickedFwdRevPairs.length(); ++nPair ) { fwdRevPair2* pFwdRevPair = aTempClickedFwdRevPairs[ nPair ]; // consider putting both the calculating routines as well as the // routines for drawing into the derived classes of the fwdRevPair2 // class. fwdRevPair2* pNewFwdRevPair = pCalculateWhereSingleFwdRevPairIs( pFwdRevPair->pLeftLocFrag_, pFwdRevPair->pRightLocFrag_, pFwdRevPair->bIsConsistent(), pFwdRevPair->cProblem_ ); // this could happen if the user has just switched what is to // be displayed, and this particular clicked-on fwd/rev pair // is no longer displayed if ( !pNewFwdRevPair ) continue; assert( pNewFwdRevPair->cGetType() == cSQUARE || pNewFwdRevPair->cGetType() == cTRIANGLE || pNewFwdRevPair->cGetType() == cLINE ); aClickedFwdRevPairs_.insert( pNewFwdRevPair ); delete pFwdRevPair; } } fwdRevPair2* assemblyView :: pCalculateWhereSingleFwdRevPairIs( LocatedFragment* pLocFrag1, LocatedFragment* pLocFrag2, const bool bIsConsistent, const char cProblem ) { fwdRevPair2* pFwdRevPairToReturn = NULL; int nScaffold1 = nGetScaffoldForContig( pLocFrag1->pContig_ ); int nScaffold2 = nGetScaffoldForContig( pLocFrag2->pContig_ ); // handle the case of the contig not being displayed if ( nScaffold1 == -1 || nScaffold2 == -1 ) { return( NULL ); } if ( !bIsConsistent ) { if ( nShowWhichInconsistentFwdRevPairs_ == nALL_INCONSISTENT_FWD_REV_PAIRS ) { if ( nScaffold1 == nScaffold2 ) pFwdRevPairToReturn = pBadFwdRevPairInSameScaffold( pLocFrag1, pLocFrag2, nScaffold1, cProblem ); else pFwdRevPairToReturn = pBadFwdRevPairInDifferentScaffolds( pLocFrag1, pLocFrag2, nScaffold1, nScaffold2, cProblem ); } } // if ( !bIsConsistent ) else { if ( pLocFrag1->pContig_ == pLocFrag2->pContig_ ) { if ( bShowEachConsistentFwdRevPair_ ) pFwdRevPairToReturn = pConsistentFwdRevPairWithinSingleContig( pLocFrag1, pLocFrag2, nScaffold1 ); } else if ( nScaffold1 == nScaffold2 ) { if ( bShowGapSpanningFwdRevPairs_ ) pFwdRevPairToReturn = pConsistentGapSpanningPair( pLocFrag1, pLocFrag2, nScaffold1 ); } else { if ( bShowConsistentFwdRevPairsBetweenDifferentScaffolds_ ) pFwdRevPairToReturn = pConsistentPairBetweenDifferentScaffolds( pLocFrag1, pLocFrag2, nScaffold1, nScaffold2 ); } } // if ( pSub->bReadsAreInconsistent_ ) { return( pFwdRevPairToReturn ); } fwdRevPair2* assemblyView :: pConsistentFwdRevPairWithinSingleContig( LocatedFragment* pLocFrag1, LocatedFragment* pLocFrag2, const int nScaffold ) { int nScaffoldPos1 = pLocFrag1->pContig_->nGetScaffoldPosFromUnpaddedConsPos( pLocFrag1->nGetConsPosOfBeginningOfReadUnpadded() ); int nScaffoldPos2 = pLocFrag2->pContig_->nGetScaffoldPosFromUnpaddedConsPos( pLocFrag2->nGetConsPosOfBeginningOfReadUnpadded() ); int nSizeOfInsert = ABS( nScaffoldPos1 - nScaffoldPos2 ) + 1; int nHeight = nGetHeightFromSize( nSizeOfInsert ); int nPixelYBaseline = nGetPixelYOfConsistentFwdRevPairBaseline( nScaffold ); int nY = nPixelYBaseline - nHeight; int nX = nGetPixelXFromScaffoldPos( nScaffold, ( nScaffoldPos1 + nScaffoldPos2 )/2 ); LocatedFragment* pLeftLocFrag; LocatedFragment* pRightLocFrag; if ( nScaffoldPos1 < nScaffoldPos2 ) { pLeftLocFrag = pLocFrag1; pRightLocFrag = pLocFrag2; } else { pLeftLocFrag = pLocFrag2; pRightLocFrag = pLocFrag1; int nTemp = nScaffoldPos1; nScaffoldPos1 = nScaffoldPos2; nScaffoldPos2 = nTemp; } XPoint xpoints[3]; xpoints[0].x = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPos1 ); xpoints[0].y = nPixelYBaseline; xpoints[1].x = nX; xpoints[1].y = nY; xpoints[2].x = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPos2 ); xpoints[2].y = nPixelYBaseline; fwdRevPairSquare* pSquare = new fwdRevPairSquare( nX, nY, xpoints, pLeftLocFrag, pRightLocFrag, pGctConsistentFwdRevPairs_, fwdRevPair2::cCONSISTENT_WITHIN_SAME_CONTIG, fwdRevPair2::cNO_PROBLEM ); return( pSquare ); } fwdRevPair2* assemblyView :: pBadFwdRevPairInSameScaffold( LocatedFragment* pLocFrag1, LocatedFragment* pLocFrag2, const int nScaffold, const char cProblem ) { int nScaffoldPos1 = pLocFrag1->pContig_->nGetScaffoldPosFromUnpaddedConsPos( pLocFrag1->nGetConsPosOfBeginningOfReadUnpadded() ); int nScaffoldPos2 = pLocFrag2->pContig_->nGetScaffoldPosFromUnpaddedConsPos( pLocFrag2->nGetConsPosOfBeginningOfReadUnpadded() ); // it is important for sorting the fwdRevPairTriangles that // xpoint[0].x <= xpoint[2].x LocatedFragment* pLeftLocFrag; LocatedFragment* pRightLocFrag; if ( nScaffoldPos1 < nScaffoldPos2 ) { pLeftLocFrag = pLocFrag1; pRightLocFrag = pLocFrag2; } else { pLeftLocFrag = pLocFrag2; pRightLocFrag = pLocFrag1; int nTemp = nScaffoldPos1; nScaffoldPos1 = nScaffoldPos2; nScaffoldPos2 = nTemp; } int nSizeOfInsert = ABS( nScaffoldPos1 - nScaffoldPos2 ) + 1; int nHeight = nGetHeightFromSize( nSizeOfInsert ); int nPixelYBaseline = nGetPixelYOfTopOfAreaForInconsistentFwdRevPairs( nScaffold ); XPoint xpoints[3]; xpoints[0].x = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPos1 ); xpoints[0].y = nPixelYBaseline; xpoints[1].x = nGetPixelXFromScaffoldPos( nScaffold, ( nScaffoldPos1 + nScaffoldPos2 ) / 2 ); xpoints[1].y = nPixelYBaseline + nHeight; xpoints[2].x = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPos2 ); xpoints[2].y = nPixelYBaseline; // I don't think this will ever happen if ( xpoints[0].x > xpoints[2].x ) { cerr << "xpoints[0].x = " << xpoints[0].x << " and xpoints[2].x = " << xpoints[2].x << endl; } assert( xpoints[0].x <= xpoints[2].x ); fwdRevPairTriangle* pTriangle = new fwdRevPairTriangle( xpoints, pLeftLocFrag, pRightLocFrag, pGctInconsistentFwdRevPair_, fwdRevPair2::cINCONSISTENT_SAME_SCAFFOLD, cProblem ); return( pTriangle ); } fwdRevPair2* assemblyView :: pBadFwdRevPairInDifferentScaffolds( LocatedFragment* pLocFrag1, LocatedFragment* pLocFrag2, const int nScaffold1, const int nScaffold2, const char cProblem ) { int nPixelY1 = nGetPixelYOfTopOfAreaForInconsistentFwdRevPairs( nScaffold1 ); int nPixelY2 = nGetPixelYOfTopOfAreaForInconsistentFwdRevPairs( nScaffold2 ); int nScaffoldPos1 = pLocFrag1->pContig_->nGetScaffoldPosFromUnpaddedConsPos( pLocFrag1->nGetConsPosOfBeginningOfReadUnpadded() ); int nScaffoldPos2 = pLocFrag2->pContig_->nGetScaffoldPosFromUnpaddedConsPos( pLocFrag2->nGetConsPosOfBeginningOfReadUnpadded() ); int nPixelX1 = nGetPixelXFromScaffoldPos( nScaffold1, nScaffoldPos1 ); int nPixelX2 = nGetPixelXFromScaffoldPos( nScaffold2, nScaffoldPos2 ); if ( nPixelY1 == nPixelY2 ) { // case in which they are different scaffolds, but they // are put into the same scaffold row XPoint xpoints[3]; xpoints[0].x = MIN( nPixelX1, nPixelX2 ); xpoints[0].y = nPixelY1; xpoints[2].x = MAX( nPixelX1, nPixelX2 ); xpoints[2].y = nPixelY2; xpoints[1].x = ( nPixelX1 + nPixelX2 ) / 2; int nPixelSeparation = ABS( nPixelX1 - nPixelX2 ) + 1; int nBasesSeparation = nPixelSeparation / dPixelWidthOfBase_; int nHeight = nGetHeightFromSize( nBasesSeparation ); xpoints[1].y = nPixelY1 + nHeight; fwdRevPairTriangle* pTriangle = new fwdRevPairTriangle( xpoints, pLocFrag1, pLocFrag2, pGctInconsistentFwdRevPair_, fwdRevPair2::cINCONSISTENT_BETWEEN_SCAFFOLDS, cProblem ); return( pTriangle ); } else { // case in which they are different scaffolds, and they // are in different scaffold rows XPoint xpoints[2]; xpoints[0].x = nPixelX1; xpoints[0].y = nPixelY1; xpoints[1].x = nPixelX2; xpoints[1].y = nPixelY2; fwdRevPair2* pLine = new fwdRevPairLine( xpoints, pLocFrag1, pLocFrag2, pGctInconsistentFwdRevPair_, fwdRevPair2::cINCONSISTENT_BETWEEN_SCAFFOLDS, cProblem ); return( pLine ); } } fwdRevPair2* assemblyView :: pConsistentPairBetweenDifferentScaffolds( LocatedFragment* pLocFrag1, LocatedFragment* pLocFrag2, const int nScaffold1, const int nScaffold2 ) { int nScaffoldPos1 = pLocFrag1->pContig_->nGetScaffoldPosFromUnpaddedConsPos( pLocFrag1->nGetConsPosOfBeginningOfReadUnpadded() ); int nScaffoldPos2 = pLocFrag2->pContig_->nGetScaffoldPosFromUnpaddedConsPos( pLocFrag2->nGetConsPosOfBeginningOfReadUnpadded() ); clScaffold* pScaffold1 = aScaffolds_[ nScaffold1 ]; clScaffold* pScaffold2 = aScaffolds_[ nScaffold2 ]; if ( pScaffold1->nScaffoldRow_ == pScaffold2->nScaffoldRow_ ) { // same scaffold-row, so use a triangle int nPixelX1 = nGetPixelXFromScaffoldPos( nScaffold1, nScaffoldPos1 ); int nPixelX2 = nGetPixelXFromScaffoldPos( nScaffold2, nScaffoldPos2 ); int nPixelY = nGetPixelYOfConsistentFwdRevPairBaseline( nScaffold1 ); XPoint xpoints[3]; xpoints[0].x = MIN( nPixelX1, nPixelX2 ); xpoints[0].y = nPixelY; xpoints[2].x = MAX( nPixelX1, nPixelX2 ); xpoints[2].y = nPixelY; xpoints[1].x = ( nPixelX1 + nPixelX2 ) / 2; // to use nGetHeightFromSize, just convert pixel distance // to # of bases between int nPixelSize = ABS( nPixelX1 - nPixelX2 ) + 1; int nBasesSize = nPixelSize / dPixelWidthOfBase_; int nHeight = nGetHeightFromSize( nBasesSize ); int nPixelYTopOfTriangle = nPixelY - nHeight; xpoints[1].y = nPixelYTopOfTriangle; fwdRevPairTriangle* pTriangle = new fwdRevPairTriangle( xpoints, pLocFrag1, pLocFrag2, pGctConsistentGapSpanningFwdRevPair_, fwdRevPair2::cCONSISTENT_BETWEEN_SCAFFOLDS, fwdRevPair2::cNO_PROBLEM ); return( pTriangle ); } else { // different scaffold-rows, so just use a line XPoint xpoint[2]; xpoint[0].x = nGetPixelXFromScaffoldPos( nScaffold1, nScaffoldPos1 ); xpoint[0].y = nGetPixelYOfConsistentFwdRevPairBaseline( nScaffold1 ); xpoint[1].x = nGetPixelXFromScaffoldPos( nScaffold2, nScaffoldPos2 ); xpoint[1].y = nGetPixelYOfConsistentFwdRevPairBaseline( nScaffold2 ); fwdRevPairLine* pLine = new fwdRevPairLine( xpoint, pLocFrag1, pLocFrag2, pGctConsistentGapSpanningFwdRevPair_, fwdRevPair2::cCONSISTENT_BETWEEN_SCAFFOLDS, fwdRevPair2::cNO_PROBLEM ); return( pLine ); } } fwdRevPair2* assemblyView :: pConsistentGapSpanningPair( LocatedFragment* pLocFrag1, LocatedFragment* pLocFrag2, const int nScaffold ) { int nScaffoldPos1 = pLocFrag1->pContig_->nGetScaffoldPosFromUnpaddedConsPos( pLocFrag1->nGetConsPosOfBeginningOfReadUnpadded() ); int nScaffoldPos2 = pLocFrag2->pContig_->nGetScaffoldPosFromUnpaddedConsPos( pLocFrag2->nGetConsPosOfBeginningOfReadUnpadded() ); int nSizeOfInsert = ABS( nScaffoldPos1 - nScaffoldPos2 ) + 1; int nHeight = nGetHeightFromSize( nSizeOfInsert ); int nPixelYBaseline = nGetPixelYOfConsistentFwdRevPairBaseline( nScaffold ); XPoint xpoint[3]; xpoint[0].x = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPos1 ); xpoint[0].y = nPixelYBaseline; xpoint[2].x = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPos2 ); xpoint[2].y = nPixelYBaseline; xpoint[1].x = nGetPixelXFromScaffoldPos( nScaffold, ( nScaffoldPos1 + nScaffoldPos2 )/2 ); xpoint[1].y = nPixelYBaseline - nHeight; if ( xpoint[0].x > xpoint[2].x ) { XPoint xtemp = xpoint[0]; xpoint[0] = xpoint[2]; xpoint[2] = xtemp; } fwdRevPairTriangle* pTriangle = new fwdRevPairTriangle( xpoint, pLocFrag1, pLocFrag2, pGctConsistentGapSpanningFwdRevPair_, fwdRevPair2::cCONSISTENT_GAP_SPANNING, fwdRevPair2::cNO_PROBLEM ); return( pTriangle ); } void assemblyView :: drawFwdRevPairs( const bool bCalculateFirst ) { if ( bCalculateFirst ) calculateWhereFwdRevPairsAre(); // A subcloneTTemplate in Assembly::aSubcloneTemplateArray_ is not // in a Contig if and only if the flag bOKToUseThisTemplate_ is false. // Thus I can find all of the other templates by looking through this // list for these. Shall all of these be shown in red? Let's start // out by saying "yes"--short insert, bUnalignedHighQualityRegionTooLong_, // bIsChimeric_, bHasSeriousHighQualityDiscrepancies_, // bReadsAreInconsistent_ // Perhaps there should be a different color for those that are // inconsistent from the others. for( int nTriangle = 0; nTriangle < aArrayOfFwdRevPairTriangles_.length(); ++nTriangle ) { fwdRevPairTriangle* pTriangle = aArrayOfFwdRevPairTriangles_[ nTriangle ]; pTriangle->drawThyself( this, false ); } for( int nLine = 0; nLine < aArrayOfFwdRevPairLines_.length(); ++nLine ) { fwdRevPairLine* pFwdRevPairLine = aArrayOfFwdRevPairLines_[ nLine ]; pFwdRevPairLine->drawThyself( this, false ); } for( int nSquare = 0; nSquare < aArrayOfFwdRevPairSquares_.length(); ++nSquare ) { fwdRevPairSquare* pSquare = aArrayOfFwdRevPairSquares_[ nSquare ]; pSquare->drawThyself( this, false ); } highlightClickedFwdRevPairs(); } int assemblyView :: nGetHeightFromSize( const int nSizeOfInsert ) { // convert size of insert into a vertical height // 0 -> 0 // infinity -> nHeightOfAreaForFwdRevPairsInSameScaffold_ // The formula that will do this is: 2/pi * nVertical.. arctan( insert) double dHeight = atan( nSizeOfInsert/3000.0 ) * 2.0 / 3.14159264 * ( nHeightOfAreaForFwdRevPairsInSameScaffold_ / 2 ); return( (int) dHeight ); } void assemblyView :: userZoomed( const int nZoomHow ) { zoomVertically( nZoomHow ); zoomHorizontally( nZoomHow ); lBasesPerScaleTick_ = lCalculateWidthOfScaleTicks(); adjustScrollBarsWhenZoom( true, // bMoveHorizontalSlider, true ); // bMoveVerticalSlider ); drawEverything( true, // bCalculatePositions true ); // bFirstErase } double assemblyView :: dCalculateInitialZoomFactor() { // find the size of the largest scaffold and make it fit in // roughly 600 pixels // since the scaffolds are sorted with the longest first, // the longest scaffold is the first one. int nAssemblyViewPixelWidth; if ( bFinishedComingUp_ ) { nAssemblyViewPixelWidth = nGetAssemblyViewWindowWidth(); } else nAssemblyViewPixelWidth = pCP->nAssemblyViewWindowInitialPixelWidth_; return( (double) ( nAssemblyViewPixelWidth - nLeftEdgePixelMargin - nRightEdgePixelMargin ) / (double) nLongestScaffoldLength_ ); } // why is this needed when we have Contig::nScaffold_ ? (DG, Jan 2004) int assemblyView :: nGetScaffoldForContig( Contig* pContigToFind ) { // now have a lookup for finding which scaffold corresponds // to a particular contig for( int nScaffold = 0; nScaffold < aScaffolds_.length(); ++nScaffold ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; for( int nContig = 0; nContig < pScaffold->aContigs_.length(); ++nContig ) { if ( pContigToFind == pScaffold->aContigs_[ nContig ] ) return( nScaffold ); } } return( -1 ); } int assemblyView :: nGetAssemblyViewWindowWidth() { Dimension nPixelsWide; XtVaGetValues( widDrawingArea_, XmNwidth, &nPixelsWide, NULL ); return( nPixelsWide ); } int assemblyView :: nGetAssemblyViewWindowHeight() { Dimension nPixelsHigh; XtVaGetValues( widDrawingArea_, XmNheight, &nPixelsHigh, NULL ); return( nPixelsHigh ); } int assemblyView :: nGetPixelXFromContigBase( const int nScaffold, Contig* pContig, const int nUnpadded ) { int nScaffoldPos = pContig->nGetScaffoldPosFromUnpaddedConsPos( nUnpadded ); return( nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPos ) ); } void assemblyView :: horizontalScrollBarMoved( const int nNewScrollBarPosition ) { nLeftEdgeScaffoldPos_ = nNewScrollBarPosition; drawEverything( true, // bCalculatePositions true ); // bFirstErase } void assemblyView :: programMovedHorizontalScrollBar( const int nNewScrollBarPosition ) { nLeftEdgeScaffoldPos_ = nNewScrollBarPosition; drawEverything( true, // bCalculatePositions true ); // bFirstErase } const int nHorizontalScrollBarPixelsPerClick = 20; void assemblyView :: setHorizontalScrollBar() { int nIncrementInScaffoldPositions = nHorizontalScrollBarPixelsPerClick / dPixelWidthOfBase_; int nScaffoldPositionsDisplayedAtOnce = ( nGetAssemblyViewWindowWidth() - nLeftEdgePixelMargin - nRightEdgePixelMargin ) / dPixelWidthOfBase_; if ( nScaffoldPositionsDisplayedAtOnce > nLongestScaffoldLength_ ) nScaffoldPositionsDisplayedAtOnce = nLongestScaffoldLength_; int nScrollBarMax = nLongestScaffoldLength_; int nSliderSize = nScaffoldPositionsDisplayedAtOnce; if ( nLeftEdgeScaffoldPos_ > ( nScrollBarMax - nSliderSize ) ) { nSliderSize = nScrollBarMax - nLeftEdgeScaffoldPos_; } XtVaSetValues( widHorizontalScrollBar_, XmNmaximum, nLongestScaffoldLength_, XmNminimum, 0, XmNincrement, nIncrementInScaffoldPositions, XmNsliderSize, nSliderSize, XmNpageIncrement, nScaffoldPositionsDisplayedAtOnce, NULL ); } void assemblyView :: adjustScrollBarsWhenZoom( const bool bMoveHorizontalSlider, const bool bMoveVerticalSlider ) { adjustHorizontalScrollBarWhenZoom( bMoveHorizontalSlider); adjustVerticalScrollBarWhenZoom( bMoveVerticalSlider ); } void assemblyView :: adjustHorizontalScrollBarWhenZoom( const bool bMoveSlider ) { int nScaffoldPositionsPerScrollBarClick = nHorizontalScrollBarPixelsPerClick / dPixelWidthOfBase_; int nScaffoldPositionsDisplayedAtOnce = ( nGetAssemblyViewWindowWidth() - nLeftEdgePixelMargin - nRightEdgePixelMargin ) / dPixelWidthOfBase_; int nScrollBarMax = nLongestScaffoldLength_; if ( nScaffoldPositionsDisplayedAtOnce > nScrollBarMax ) nScaffoldPositionsDisplayedAtOnce = nScrollBarMax; if ( bMoveSlider ) { XtVaSetValues( widHorizontalScrollBar_, XmNincrement, nScaffoldPositionsPerScrollBarClick, XmNsliderSize, nScaffoldPositionsDisplayedAtOnce, XmNpageIncrement, nScaffoldPositionsDisplayedAtOnce, XmNvalue, nLeftEdgeScaffoldPos_, NULL ); } else { XtVaSetValues( widHorizontalScrollBar_, XmNincrement, nScaffoldPositionsPerScrollBarClick, XmNsliderSize, nScaffoldPositionsDisplayedAtOnce, XmNpageIncrement, nScaffoldPositionsDisplayedAtOnce, NULL ); } } const int nVerticalScrollBarPixelsPerClick = 100; void assemblyView :: adjustVerticalScrollBarWhenZoom( const bool bMoveSlider ) { int nVirtualPixelPositionsDisplayedAtOnce = nGetAssemblyViewWindowHeight(); int nMaximumVirtualPixelPosition = nGetHeightOfOneScaffold() * nNumberOfScaffoldRows_ + nHeightOfMarginAtTopOfScreen; if ( nVirtualPixelPositionsDisplayedAtOnce > nMaximumVirtualPixelPosition ) nVirtualPixelPositionsDisplayedAtOnce = nMaximumVirtualPixelPosition; if ( bMoveSlider ) { XtVaSetValues( widVerticalScrollBar_, XmNmaximum, nMaximumVirtualPixelPosition, XmNminimum, 0, XmNincrement, nVerticalScrollBarPixelsPerClick, XmNsliderSize, nVirtualPixelPositionsDisplayedAtOnce, XmNpageIncrement, nVirtualPixelPositionsDisplayedAtOnce, XmNvalue, nTopEdgeVirtualPixelPosition_, NULL ); } else { XtVaSetValues( widVerticalScrollBar_, XmNmaximum, nMaximumVirtualPixelPosition, XmNminimum, 0, XmNincrement, nVerticalScrollBarPixelsPerClick, XmNsliderSize, nVirtualPixelPositionsDisplayedAtOnce, XmNpageIncrement, nVirtualPixelPositionsDisplayedAtOnce, NULL ); } } void assemblyView :: verticalScrollBarMoved( const int nNewScrollBarPosition ) { nTopEdgeVirtualPixelPosition_ = nNewScrollBarPosition; drawEverything( true, // bCalculatePositions true ); // bFirstErase } void assemblyView :: programScrollVertically( const int nNewTopEdgePixelY2 ) { int nNewTopEdgePixelY = nNewTopEdgePixelY2; int nVirtualPixelPositionsDisplayedAtOnce = nGetAssemblyViewWindowHeight(); int nMaximumVirtualPixelPosition = nGetHeightOfOneScaffold() * nNumberOfScaffoldRows_ + nHeightOfMarginAtTopOfScreen; if ( nNewTopEdgePixelY > ( nMaximumVirtualPixelPosition - nVirtualPixelPositionsDisplayedAtOnce ) ) { nNewTopEdgePixelY = nMaximumVirtualPixelPosition - nVirtualPixelPositionsDisplayedAtOnce; } // however, don't let it be negative: if ( nNewTopEdgePixelY < 0 ) nNewTopEdgePixelY = 0; nTopEdgeVirtualPixelPosition_ = nNewTopEdgePixelY; drawEverything( true, // bCalculatePositions true ); // bFirstErase XtVaSetValues( widVerticalScrollBar_, XmNvalue, nNewTopEdgePixelY, NULL ); } void assemblyView :: setVerticalScrollBar() { int nVirtualPixelPositionsDisplayedAtOnce = nGetAssemblyViewWindowHeight(); int nMaximumVirtualPixelPosition = nGetHeightOfOneScaffold() * nNumberOfScaffoldRows_ + nHeightOfMarginAtTopOfScreen; if ( nVirtualPixelPositionsDisplayedAtOnce > nMaximumVirtualPixelPosition ) nVirtualPixelPositionsDisplayedAtOnce = nMaximumVirtualPixelPosition; XtVaSetValues( widVerticalScrollBar_, XmNmaximum, nMaximumVirtualPixelPosition, XmNminimum, 0, XmNincrement, nVerticalScrollBarPixelsPerClick, XmNsliderSize, nVirtualPixelPositionsDisplayedAtOnce, XmNpageIncrement, nVirtualPixelPositionsDisplayedAtOnce, NULL ); } void assemblyView :: userResizedWindow() { // There is an initial resize event before getting scaffolds // so the setVerticalScrollBar uses bad values. if ( !bFinishedComingUp_ ) return; setVerticalScrollBar(); setHorizontalScrollBar(); int nScrollBarMax; int nSliderSize; int nValue; XtVaGetValues( widHorizontalScrollBar_, XmNmaximum, &nScrollBarMax, XmNsliderSize, &nSliderSize, XmNvalue, &nValue, NULL ); // the grid also must be re-created clearOldGridTable(); } void assemblyView :: filteredBadFwdRevPairs() { Assembly* pAssembly = ConsEd::pGetAssembly(); for( int nPair = 0; nPair < pAssembly->pArrayOfConfirmedInconsistentFwdRevPairs_->length(); ++nPair ) { fwdRevPair* pFwdRevPair = (*pAssembly->pArrayOfConfirmedInconsistentFwdRevPairs_)[ nPair ]; // See if this template is in the list of reads to not be shown. // This would open the possibility that one pair would be shown, // while the confirming pair would not be shown. if ( bDoNotShowTemplatesInDoNotShowTemplatesFile_ && pFwdRevPair->pLocFrag1_->pSub_->bDoNotShowInAssemblyView_ ) continue; int nScaffold1 = nGetScaffoldForContig( pFwdRevPair->pLocFrag1_->pContig_ ); int nScaffold2 = nGetScaffoldForContig( pFwdRevPair->pLocFrag2_->pContig_ ); // handle case of the contig not being displayed if ( nScaffold1 == -1 || nScaffold2 == -1 ) continue; fwdRevPair2* pFwdRevPair2; if ( nScaffold1 == nScaffold2 ) pFwdRevPair2 = pBadFwdRevPairInSameScaffold( pFwdRevPair->pLocFrag1_, pFwdRevPair->pLocFrag2_, nScaffold1, pFwdRevPair->cProblem_ ); else pFwdRevPair2 = pBadFwdRevPairInDifferentScaffolds( pFwdRevPair->pLocFrag1_, pFwdRevPair->pLocFrag2_, nScaffold1, nScaffold2, pFwdRevPair->cProblem_ ); if ( pFwdRevPair2->cGetType() == cTRIANGLE ) aArrayOfFwdRevPairTriangles_.insert( (fwdRevPairTriangle*) pFwdRevPair2 ); else if ( pFwdRevPair2->cGetType() == cSQUARE ) aArrayOfFwdRevPairSquares_.insert( (fwdRevPairSquare*) pFwdRevPair2 ); else if ( pFwdRevPair2->cGetType() == cLINE ) aArrayOfFwdRevPairLines_.insert( (fwdRevPairLine*) pFwdRevPair2 ); } } assemblyView :: ~assemblyView() { if ( this == ConsEd::pGetConsEd()->pAssemblyView_ ) ConsEd::pGetConsEd()->pAssemblyView_ = NULL; XtRemoveCallback( widDrawingArea_, XmNexposeCallback, (XtCallbackProc) cbAssemblyViewExposure, this ); XtRemoveEventHandler( widDrawingArea_, PointerMotionMask, False, (XtEventHandler) pointerMotionEventHandler, this ); XtPopdown( widPopupShell_ ); XtDestroyWidget( widPopupShell_ ); if ( pGuiNav_ ) delete pGuiNav_; aScaffolds_.clearAndDestroy(); ConsEd::pGetConsEd()->pAssemblyView_ = NULL; if ( pGuiReorientContigs_ ) { if ( bDoNotDeleteGuiReorientContigs_ ) { pGuiReorientContigs_->pAssemblyView_ = NULL; } else { delete pGuiReorientContigs_; } } if ( pGuiReorderContigs_ ) { if ( bDoNotDeleteGuiReorderContigs_ ) { pGuiReorderContigs_->pAssemblyView_ = NULL; } else { delete pGuiReorderContigs_; } } } void assemblyView :: pointerMoved( const int nPixelX, const int nPixelY ) { if ( !bFinishedComingUp_ ) return; // I've noticed that after resizing the window smaller, it // is possible for motion events to still come in that are // from positions outside the window. So eliminate those: int nMaxPixelBottom = nGetAssemblyViewWindowHeight() - 1; if ( nPixelY < 0 || nPixelY > nMaxPixelBottom ) return; int nMaxPixelRight = nGetAssemblyViewWindowWidth() - 1; if ( nPixelX < 0 || nPixelX > nMaxPixelRight ) return; unhighlightCurrentFwdRevPairs(); // if the user has recently resized or done something to invalidate // the positions, then we need to first recalculate the grid if ( !p2DArrayOfArrayOfSeqMatches_ ) { drawRepeats( true ); } // which grid cells is the pointer near? // remember that pixels increase downwards RWTPtrOrderedVector aOldHighlightedSeqMatches( aCurrentlyHighlightedSeqMatches_ ); aCurrentlyHighlightedSeqMatches_.clear(); int nYPixelTop = nPixelY - pCP->nAssemblyViewCursorSensitivityInPixels_ / 2; int nYPixelBottom = nYPixelTop + pCP->nAssemblyViewCursorSensitivityInPixels_ - 1; int nXPixelLeft = nPixelX - pCP->nAssemblyViewCursorSensitivityInPixels_ / 2; int nXPixelRight = nPixelX + pCP->nAssemblyViewCursorSensitivityInPixels_ - 1; // it is possible for the cursor sensitivity box to stick out // below the bottom of the window. This would cause subscript errors, // so truncate it at the bottom of the window. if ( nYPixelBottom > nMaxPixelBottom ) nYPixelBottom = nMaxPixelBottom; // similarly, it is possible for the cursor sensitivity window to stick // out to the right of the window. This would also cause subscript errors, // so truncate it at the right of the window. if ( nXPixelRight > nMaxPixelRight ) nXPixelRight = nMaxPixelRight; // similarly, it is possible for the sensitivity box to stick out // beyond the top or left of the window. So truncate it. if ( nYPixelTop < 0 ) nYPixelTop = 0; if ( nXPixelLeft < 0 ) nXPixelLeft = 0; if ( nYPixelTop > nYPixelBottom ) { RWCString soError = "file: "; soError += __FILE__; soError += " line: "; soError += RWCString( (long) __LINE__ ); soError += " nYPixelTop = "; soError += RWCString( (long) nYPixelTop ); soError += " nYPixelBottom = "; soError += RWCString( (long) nYPixelBottom ); soError += " but should be nYPixelTop <= nYPixelBottom. nMaxPixelBottom = "; soError += RWCString( (long) nMaxPixelBottom ); soError += " (nX, nY) of cursor = "; soError += RWCString( (long) nPixelX ); soError += ", "; soError += RWCString( (long) nPixelY ); soError += ")"; THROW_ERROR( soError ); } assert( nXPixelLeft <= nXPixelRight ); int nYIndexTop = nYPixelTop / pCP->dAssemblyViewGridCellWidthInPixels_; int nYIndexBottom = nYPixelBottom / pCP->dAssemblyViewGridCellWidthInPixels_; int nXIndexLeft = nXPixelLeft / pCP->dAssemblyViewGridCellWidthInPixels_; int nXIndexRight = nXPixelRight / pCP->dAssemblyViewGridCellWidthInPixels_; for( int nXIndex = nXIndexLeft; nXIndex <= nXIndexRight; ++nXIndex ) { for( int nYIndex = nYIndexTop; nYIndex <= nYIndexBottom; ++nYIndex ) { RWTPtrOrderedVector* pSeqMatchArray = p2DArrayOfArrayOfSeqMatches_->pGetElement( nXIndex, nYIndex ); if ( pSeqMatchArray ) { for( int nSeqMatchInSquare = 0; nSeqMatchInSquare < pSeqMatchArray->length(); ++nSeqMatchInSquare ) { seqMatch* pSeqMatch = (*pSeqMatchArray)[ nSeqMatchInSquare ]; if ( aCurrentlyHighlightedSeqMatches_.index( pSeqMatch ) == RW_NPOS ) { highlightSeqMatch( pSeqMatch ); aCurrentlyHighlightedSeqMatches_.insert( pSeqMatch ); } } } } } RWTPtrOrderedVector aSeqMatchesToUnhighlight; for( int nSeqMatch = 0; nSeqMatch < aOldHighlightedSeqMatches.length(); ++nSeqMatch ) { seqMatch* pSeqMatchWasHighlighted = aOldHighlightedSeqMatches[ nSeqMatch ]; if ( aCurrentlyHighlightedSeqMatches_.index( pSeqMatchWasHighlighted ) == RW_NPOS ) { // this is a seqMatch that was highlighted, but shouldn't be // any longer so turn off highlighting for it drawOneRepeat( pSeqMatchWasHighlighted, false, // bSavePositionsInGrid false ); // bHighlighted } } // see if we can find a triangle that is close by for( int nTriangle = 0; nTriangle < aArrayOfFwdRevPairTriangles_.length(); ++nTriangle ) { fwdRevPairTriangle* pTriangle = aArrayOfFwdRevPairTriangles_[ nTriangle ]; // if ( !pTriangle->bOKToShow_ ) continue; // We want to show information on triangles that are not // shown because they are coincident with some other triangle if ( pTriangle->xpoints_[0].x > nPixelX ) break; if ( pTriangle->xpoints_[0].x <= nPixelX && nPixelX <= pTriangle->xpoints_[2].x ) { // must handle both upwards pointing and downwards pointing // triangles if ( ( pTriangle->xpoints_[0].y <= nPixelY && nPixelY <= pTriangle->xpoints_[1].y ) || ( pTriangle->xpoints_[0].y >= nPixelY && nPixelY >= pTriangle->xpoints_[1].y ) ) { // the pointer is within the rectangle bounding the triangle if ( fGetDistanceFromPointToLine( nPixelX, nPixelY, pTriangle->xpoints_[0].x, pTriangle->xpoints_[0].y, pTriangle->xpoints_[1].x, pTriangle->xpoints_[1].y ) < 5 || fGetDistanceFromPointToLine( nPixelX, nPixelY, pTriangle->xpoints_[1].x, pTriangle->xpoints_[1].y, pTriangle->xpoints_[2].x, pTriangle->xpoints_[2].y ) < 5 ) { highlightNewObject( pTriangle ); } } } } for( int nLine = 0; nLine < aArrayOfFwdRevPairLines_.length(); ++nLine ) { fwdRevPairLine* pLine = aArrayOfFwdRevPairLines_[ nLine ]; if ( ( pLine->xpoints_[0].x <= nPixelX && nPixelX <= pLine->xpoints_[1].x ) || ( pLine->xpoints_[1].x <= nPixelX && nPixelX <= pLine->xpoints_[0].x ) ) { if ( ( pLine->xpoints_[0].y <= nPixelY && nPixelY <= pLine->xpoints_[1].y ) || ( pLine->xpoints_[1].y <= nPixelY && nPixelY <= pLine->xpoints_[0].y ) ) { if ( fGetDistanceFromPointToLine( nPixelX, nPixelY, pLine->xpoints_[0].x, pLine->xpoints_[0].y, pLine->xpoints_[1].x, pLine->xpoints_[1].y ) < 5 ) { highlightNewObject( pLine ); } } } } for( int nSquare = 0; nSquare < aArrayOfFwdRevPairSquares_.length(); ++nSquare ) { fwdRevPairSquare* pSquare = aArrayOfFwdRevPairSquares_[ nSquare ]; if ( fGetDistanceFromPointToPoint( nPixelX, nPixelY, pSquare->nX_, pSquare->nY_ ) < 5 ) { highlightNewObject( pSquare ); } } highlightTags( nPixelX, nPixelY ); highlightRestrictionDigestFragments( nPixelX, nPixelY ); RWCString soMessage( (size_t) 2000 ); bool bIsOnAContig; Contig* pContig; int nUnpadded; displayContigLocation( nPixelX, nPixelY, soMessage, bIsOnAContig, pContig, nUnpadded ); if ( bIsOnAContig ) { displayReadDepth( soMessage, pContig, nUnpadded ); displayFwdRevPairDepth( soMessage, pContig, nUnpadded ); } checkIfOnATag( nPixelX, nPixelY, soMessage ); displayHighlightedRestrictionDigestCutSites( soMessage ); displayHighlightedObjects( soMessage ); displayMessageAtBottom( soMessage ); } void assemblyView :: unhighlightCurrentObjects() { unhighlightCurrentFwdRevPairs(); unhighlightCurrentSeqMatches(); } void assemblyView :: unhighlightCurrentFwdRevPairs() { for( int nObject = 0; nObject < aCurrentlyHighlightedFwdRevPairs_.length(); ++nObject ) { fwdRevPair2* pPair = aCurrentlyHighlightedFwdRevPairs_[ nObject ]; // check that this object is not currently clicked before unhighlighting // it. bool bFound = false; for( int nClickedObject = 0; nClickedObject < aClickedFwdRevPairs_.length(); ++nClickedObject ) { fwdRevPair2* pClickedPair = aClickedFwdRevPairs_[ nClickedObject ]; if ( pClickedPair->pLeftLocFrag_ == pPair->pLeftLocFrag_ ) { bFound = true; break; } } if ( !bFound ) { pPair->drawThyself( this, false ); } } aCurrentlyHighlightedFwdRevPairs_.clear(); } void assemblyView :: highlightNewObject( fwdRevPair2* pPairToHighlight ) { aCurrentlyHighlightedFwdRevPairs_.insert( pPairToHighlight ); pPairToHighlight->drawThyself( this, true ); } void assemblyView :: displayHighlightedObjects( RWCString& soMessage ) { // to get rid of annoying flicker of objects: 0 // if ( aCurrentlyHighlightedFwdRevPairs_.length() == 0 && // nNumberOfHighlightedPairsLastTime_ == 0 ) return; soMessage.increaseMaxLengthIfNecessary( 2000 ); if ( aCurrentlyHighlightedFwdRevPairs_.length() > 0 ) { soMessage += RWCString( (long) aCurrentlyHighlightedFwdRevPairs_.length() ); soMessage += " subclones: "; } for( int nObject = 0; nObject < aCurrentlyHighlightedFwdRevPairs_.length(); ++nObject ) { if ( nObject > 0 ) soMessage += ", "; fwdRevPair2* pPair = aCurrentlyHighlightedFwdRevPairs_[ nObject ]; bool bLeftReadComplemented = pPair->pLeftLocFrag_->bComp(); if ( pPair->pLeftLocFrag_->pGetContig()->bThisContigIsComplementedInTheScaffold_ ) { bLeftReadComplemented = !bLeftReadComplemented; } bool bRightReadComplemented = pPair->pRightLocFrag_->bComp(); if ( pPair->pRightLocFrag_->pGetContig()->bThisContigIsComplementedInTheScaffold_ ) { bRightReadComplemented = !bRightReadComplemented; } RWCString soLeftReadDirection; if ( bLeftReadComplemented ) soLeftReadDirection = "<-"; else soLeftReadDirection = "->"; RWCString soRightReadDirection; if ( bRightReadComplemented ) soRightReadDirection = "<-"; else soRightReadDirection = "->"; // cerr << "left: " << pPair->pLeftLocFrag_->soGetName() << " " << // pPair->pLeftLocFrag_->nGetAlignStartUnpadded() << "-" << // pPair->pLeftLocFrag_->nGetAlignEndUnpadded() << " " << // soLeftReadDirection << " " << szPrintBool( pPair->pLeftLocFrag_->bComp() ) << endl; // cerr << "left read comp: " << szPrintBool( pPair->pLeftLocFrag_->bComp() ) << " contig comp: " << szPrintBool( pPair->pLeftLocFrag_->pGetContig()->bThisContigIsComplementedInTheScaffold_ ) << endl; // cerr << "right: " << pPair->pRightLocFrag_->soGetName() << " " << // pPair->pRightLocFrag_->nGetAlignStartUnpadded() << "-" << // pPair->pRightLocFrag_->nGetAlignEndUnpadded() << " " << // soRightReadDirection << " " << szPrintBool( pPair->pRightLocFrag_->bComp() ) << endl; // cerr << "right read comp: " << szPrintBool( pPair->pRightLocFrag_->bComp() ) << " contig comp: " << szPrintBool( pPair->pRightLocFrag_->pGetContig()->bThisContigIsComplementedInTheScaffold_ ) << endl; soMessage += pPair->pLeftLocFrag_->pSub_->soGetName(); soMessage += " "; soMessage += soLeftReadDirection; soMessage += soRightReadDirection; } if ( aCurrentlyHighlightedSeqMatches_.length() > 0 ) { soMessage += " "; soMessage += RWCString( (long) aCurrentlyHighlightedSeqMatches_.length() ); soMessage += " seq match(es): "; } for( int nSeqMatch = 0; nSeqMatch < aCurrentlyHighlightedSeqMatches_.length(); ++nSeqMatch ) { seqMatch* pSeqMatch = aCurrentlyHighlightedSeqMatches_[ nSeqMatch ]; for( int nCopy = 0; nCopy <= 1; ++nCopy ) { soMessage += pSeqMatch->pContig_[nCopy]->soGetName(); soMessage += " "; soMessage += RWCString( (long) pSeqMatch->nUnpaddedStartConsPos_[nCopy] ); soMessage += "-"; soMessage += RWCString( (long) pSeqMatch->nUnpaddedEndConsPos_[nCopy] ); if ( nCopy == 0 ) { soMessage += " to "; } } if ( pSeqMatch->bComplemented_ ) soMessage += " (comp)"; else soMessage += " (not comp)"; soMessage.increaseMaxLengthIfNecessary( 30 ); soMessage.appendFormat( " size: %d sim: %4.1f", ABS( pSeqMatch->nUnpaddedEndConsPos_[1] - pSeqMatch->nUnpaddedStartConsPos_[1] ), pSeqMatch->fPercentSimilar_ ); if ( nSeqMatch != ( aCurrentlyHighlightedSeqMatches_.length() - 1 ) ) { soMessage += " "; } } nNumberOfHighlightedPairsLastTime_ = aCurrentlyHighlightedFwdRevPairs_.length(); } void assemblyView :: displayMessageAtBottom( const RWCString& soMessage ) { XtVaSetValues( widMessageWindowAtBottom_, XmNvalue, soMessage.data(), NULL ); } void assemblyView :: userClickedOrSomething( XmDrawingAreaCallbackStruct* pDAC ) { if ( pDAC->event->xany.type == ButtonPress ) { nLastButtonPressPixelX_ = pDAC->event->xbutton.x; nLastButtonPressPixelY_ = pDAC->event->xbutton.y; if ( pDAC->event->xbutton.button == Button1 ) { unhighlightClickedObjects(); if ( aClickedFwdRevPairs_.length() > 0 ) aClickedFwdRevPairs_.clearAndDestroy(); for( int nObject = 0; nObject < aCurrentlyHighlightedFwdRevPairs_.length(); ++nObject ) { fwdRevPair2* pPair = (fwdRevPair2*) aCurrentlyHighlightedFwdRevPairs_[ nObject ]; fwdRevPair2* pNewPair; if ( pPair->cGetType() == cSQUARE ) { pNewPair = new fwdRevPairSquare( ((fwdRevPairSquare*) pPair)->nX_, ((fwdRevPairSquare*) pPair)->nY_, ((fwdRevPairSquare*) pPair)->xpoints_, pPair->pLeftLocFrag_, pPair->pRightLocFrag_, pPair->pGctToUse_, pPair->cType_, pPair->cProblem_ ); } else if ( pPair->cGetType() == cLINE ) { pNewPair = new fwdRevPairLine( ((fwdRevPairLine*) pPair)->xpoints_, pPair->pLeftLocFrag_, pPair->pRightLocFrag_, pPair->pGctToUse_, pPair->cType_, pPair->cProblem_ ); } else if ( pPair->cGetType() == cTRIANGLE ) { pNewPair = new fwdRevPairTriangle( ((fwdRevPairTriangle*) pPair)->xpoints_, pPair->pLeftLocFrag_, pPair->pRightLocFrag_, pPair->pGctToUse_, pPair->cType_, pPair->cProblem_ ); } else assert( false ); aClickedFwdRevPairs_.insert( pNewPair ); } // do this so that when the user moves the pointer, // the clicked objects are not unhighlighted aCurrentlyHighlightedFwdRevPairs_.clear(); // now do the same with repeats aClickedSeqMatches_.clear(); for( int nSeqMatch = 0; nSeqMatch < aCurrentlyHighlightedSeqMatches_.length(); ++nSeqMatch ) { seqMatch* pSeqMatch = aCurrentlyHighlightedSeqMatches_[ nSeqMatch ]; aClickedSeqMatches_.insert( pSeqMatch ); } // do this so that when the user moves the pointer, // the clicked seqMatches do not unhighlight aCurrentlyHighlightedSeqMatches_.clear(); // do this for both highlightClickedObjects(); displayPopupBoxForClickedObjects(); } // if ( pDAC->event->xbutton.button == Button1 ) { else if ( pDAC->event->xbutton.button == Button3 ) { userPushedMouseButton3InDrawingArea( (XButtonPressedEvent*) (pDAC->event) ); } } } void assemblyView :: unhighlightClickedObjects() { for( int nPair = 0; nPair < aClickedFwdRevPairs_.length(); ++nPair ) { fwdRevPair2* pPair = aClickedFwdRevPairs_[ nPair ]; pPair->drawThyself( this, false ); } for( int nSeqMatch = 0; nSeqMatch < aClickedSeqMatches_.length(); ++nSeqMatch ) { seqMatch* pSeqMatch = aClickedSeqMatches_[ nSeqMatch ]; drawOneRepeat( pSeqMatch, false, // bSavePositionsInGrids false ); // bHighlight } } void assemblyView :: highlightClickedFwdRevPairs() { for( int nPair = 0; nPair < aClickedFwdRevPairs_.length(); ++nPair ) { fwdRevPair2* pPair = aClickedFwdRevPairs_[ nPair ]; pPair->drawThyself( this, true ); // bHighlight } } void assemblyView :: highlightClickedSeqMatches() { for( int nSeqMatch = 0; nSeqMatch < aClickedSeqMatches_.length(); ++nSeqMatch ) { seqMatch* pSeqMatch = aClickedSeqMatches_[ nSeqMatch ]; drawOneRepeat( pSeqMatch, false, // bSavePositionsInGrids true ); // bHighlight } } void assemblyView :: highlightClickedObjects() { highlightClickedFwdRevPairs(); highlightClickedSeqMatches(); } void assemblyView :: drawClickedObjects( const bool bBlinkState ) { if ( bBlinkState ) { highlightClickedObjects(); } else { unhighlightClickedObjects(); } } void cbAddToAssemblyViewRemoveReadsWindow( const gotoItem* pGotoItem, void* pClientData ) { assemblyView* pAssemblyView = (assemblyView*) pClientData; pAssemblyView->userClickedButtonInNavigatorWindow(); } void assemblyView :: userClickedButtonInNavigatorWindow() { // if the pullout window is already up, just add to it. // if it is not already up, then create it. if ( !pAssemblyViewRemoveReads_ ) { pAssemblyViewRemoveReads_ = new assemblyViewRemoveReads( this ); } // now, one way or another, the pullout window exists. So add to it for( int nGotoItem = 0; nGotoItem < pGuiNav_->pGotoList_->nGetNumGotoItems(); ++nGotoItem ) { gotoItem* pGotoItem = pGuiNav_->pGotoList_->pGetGotoItem( nGotoItem ); // make a new gotoItem since the old ones will be clearAndDestroy'd // (see in displayPopupBoxForClickedObjects ) when the user clicks // the new time // I'll need to make a new copy constructor for this. gotoItem* pNewGotoItem = new gotoItem( pGotoItem ); pAssemblyViewRemoveReads_->appendToList( pNewGotoItem ); } pAssemblyViewRemoveReads_->displayList( true ); } void assemblyView :: displayPopupBoxForClickedObjects() { displayPopupBoxForClickedFwdRevPairs(); displayPopupBoxForClickedSeqMatches(); } void assemblyView :: displayPopupBoxForClickedFwdRevPairs() { bool bAlreadyExisted = false; if ( !pGuiNav_ ) { if ( aClickedFwdRevPairs_.length() == 0 ) return; // don't create a box if there is nothing to put in it. pGuiNav_ = new guiMultiContigNavigator( "Clicked Forward/Reverse Pairs", "read strand left right", "", 75, "Pull Out Reads", cbAddToAssemblyViewRemoveReadsWindow, this, NULL, NULL ); pGuiNav_->pAssemblyView_ = this; } else { bAlreadyExisted = true; // clear the old goto list pGuiNav_->pGotoList_->apGotoItem_.clearAndDestroy(); } for( int nPair = 0; nPair < aClickedFwdRevPairs_.length(); ++nPair ) { fwdRevPair2* pPair = aClickedFwdRevPairs_[ nPair ]; // make 2 lines: one for the one read and the other for // the other read makeGotoItemsForSubclone( pPair ); } pGuiNav_->displayList( false ); if ( bAlreadyExisted ) pGuiNav_->raiseWindow(); } void assemblyView :: displayPopupBoxForClickedSeqMatches() { bool bSeqMatchesBoxAlreadyExisted = false; if ( ! pGuiChoiceOfSeqMatches_ ) { if ( aClickedSeqMatches_.length() == 0 ) return; pGuiChoiceOfSeqMatches_ = new guiChoiceOfSeqMatches( this ); pGuiChoiceOfSeqMatches_->createWindow(); } else bSeqMatchesBoxAlreadyExisted = true; pGuiChoiceOfSeqMatches_->loadWindowWithClickedSeqMatches(); if ( bSeqMatchesBoxAlreadyExisted ) pGuiChoiceOfSeqMatches_->raiseWindow(); } void assemblyView :: makeGotoItemsForSubclone( fwdRevPair2* pPair ) { // what is the insert size? What is the library? (maybe) If the // fwd/rev pair is no good, why not? RWCString soDescriptionForTemplate = ( pPair->bIsConsistent() ? "consistent" : "inconsistent" ); subcloneTTemplate* pSub = pPair->pLeftLocFrag_->pSub_; if ( pPair->cType_ == fwdRevPair2::cCONSISTENT_WITHIN_SAME_CONTIG ) { // find the position of the insert (chopping off the vector) Contig* pContig = pPair->pLeftLocFrag_->pContig_; int nContig = pSub->aContigs_.index( pContig ); if ( nContig != RW_NPOS ) { int nUnpaddedLeft = pSub->aUnpaddedLeft_[ nContig ]; int nUnpaddedRight = pSub->aUnpaddedRight_[ nContig ]; if ( !( ( pSub->aFlags_[ nContig ] & RIGHT_CONS_POS_SET ) && ( pSub->aFlags_[ nContig ] & LEFT_CONS_POS_SET ) ) ) { cerr << "problem finding insert for " << pSub->soTemplateName_ << endl; } else { soDescriptionForTemplate += " insert at "; soDescriptionForTemplate += RWCString( (long) nUnpaddedLeft ); soDescriptionForTemplate += "-"; soDescriptionForTemplate += RWCString( (long) nUnpaddedRight ); soDescriptionForTemplate += " size: "; soDescriptionForTemplate += RWCString( (long) nUnpaddedRight - nUnpaddedLeft + 1 ); } } else { cerr << "problem (b) finding insert for " << pSub->soTemplateName_ << endl; } } else if ( pPair->bIsConsistent() ) { // do nothing } else { // inconsistent fwd/rev pair soDescriptionForTemplate += " because: "; soDescriptionForTemplate += pPair->soGetProblem(); if ( pPair->cProblem_ == fwdRevPair2::cTOO_FAR_APART ) { // find the position of the insert (chopping off the vector) Contig* pContig = pPair->pLeftLocFrag_->pContig_; int nContig = pSub->aContigs_.index( pContig ); if ( nContig != RW_NPOS ) { int nUnpaddedLeft = pSub->aUnpaddedLeft_[ nContig ]; int nUnpaddedRight = pSub->aUnpaddedRight_[ nContig ]; if ( !( ( pSub->aFlags_[ nContig ] & RIGHT_CONS_POS_SET ) && ( pSub->aFlags_[ nContig ] & LEFT_CONS_POS_SET ) ) ) { cerr << "problem c finding insert for " << pSub->soTemplateName_ << endl; } else { int nInsertSize = nUnpaddedRight - nUnpaddedLeft + 1; soDescriptionForTemplate += " size: "; soDescriptionForTemplate += RWCString( (long) nInsertSize ); soDescriptionForTemplate += " but lib max is "; soDescriptionForTemplate += RWCString( (long) pSub->pLibrary_->nMaxInsertSize_ ); } } else { cerr << "problem d finding insert for " << pSub->soTemplateName_ << endl; } } // if ( pPair->cType_ == fwdRevPair2::cTOO_FAR_APART ) { } soDescriptionForTemplate += ". lib: "; if ( pSub->pLibrary_ ) { soDescriptionForTemplate += pSub->pLibrary_->soName_; } else { soDescriptionForTemplate += "?"; } for( int nRead = 0; nRead < pSub->aReads_.length(); ++nRead ) { LocatedFragment* pLocFrag = pSub->aReads_[ nRead ]; RWCString soDescription2 = pLocFrag->soGetName(); if ( pLocFrag->bComp() ) soDescription2 += " <- "; else soDescription2 += " -> "; soDescription2 += pLocFrag->pContig_->soGetName(); soDescription2 += " "; soDescription2 += RWCString( (long) pLocFrag->nGetAlignStartUnpadded() ); soDescription2 += "-"; soDescription2 += RWCString( (long) pLocFrag->nGetAlignEndUnpadded() ); soDescription2 += " "; soDescription2 += soDescriptionForTemplate; if ( pPair->cProblem_ == fwdRevPair2::cTOO_FAR_FROM_END_OF_CONTIG ) { int nDistanceFromEnd = -666; if ( pLocFrag->bComp() ) { nDistanceFromEnd = pLocFrag->nGetAlignEndUnpadded() - 1; } else { nDistanceFromEnd = pLocFrag->pContig_->nGetUnpaddedEndIndex() - pLocFrag->nGetAlignStartUnpadded(); } soDescription2 += " "; soDescription2 += RWCString( (long) nDistanceFromEnd ); soDescription2 += " from end"; } gotoItem* pGotoItem = new gotoItem( pLocFrag->pContig_, pLocFrag, pLocFrag->nGetConsPosOfBeginningOfRead(), pLocFrag->nGetConsPosOfBeginningOfRead(), pLocFrag->nGetConsPosOfBeginningOfReadUnpadded(), pLocFrag->nGetConsPosOfBeginningOfReadUnpadded(), soDescription2, false, // bPrefixContigToDescription NULL ); pGuiNav_->appendToList( pGotoItem ); } } void assemblyView :: programHighlightsRead( LocatedFragment* pLocFrag ) { // see if we can find a read pair that comes from the same template subcloneTTemplate* pSub = pLocFrag->pSub_; bool bFound = false; fwdRevPair2* pFwdRevPairToHighlight = NULL; for( int nTriangle = 0; nTriangle < aArrayOfFwdRevPairTriangles_.length() && !bFound; ++nTriangle ) { fwdRevPairTriangle* pTriangle = aArrayOfFwdRevPairTriangles_[ nTriangle ]; if ( pTriangle->pLeftLocFrag_->pSub_ == pSub ) { bFound = true; pFwdRevPairToHighlight = pTriangle; break; } } for( int nLine = 0; nLine < aArrayOfFwdRevPairLines_.length() && !bFound; ++nLine ) { fwdRevPairLine* pFwdRevPairLine = aArrayOfFwdRevPairLines_[ nLine ]; if ( pFwdRevPairLine->pLeftLocFrag_->pSub_ == pSub ) { bFound = true; pFwdRevPairToHighlight = pFwdRevPairLine; break; } } for( int nSquare = 0; nSquare < aArrayOfFwdRevPairSquares_.length() && !bFound; ++nSquare ) { fwdRevPairSquare* pSquare = aArrayOfFwdRevPairSquares_[ nSquare ]; if ( pSquare->pLeftLocFrag_->pSub_ == pSub ) { bFound = true; pFwdRevPairToHighlight = pSquare; break; } } if ( bFound ) { unhighlightClickedObjects(); if ( aClickedFwdRevPairs_.length() > 0 ) aClickedFwdRevPairs_.clearAndDestroy(); fwdRevPair2* pNewPair = NULL; if ( pFwdRevPairToHighlight->cGetType() == cSQUARE ) { pNewPair = new fwdRevPairSquare( ((fwdRevPairSquare*) pFwdRevPairToHighlight)->nX_, ((fwdRevPairSquare*) pFwdRevPairToHighlight)->nY_, ((fwdRevPairSquare*) pFwdRevPairToHighlight)->xpoints_, pFwdRevPairToHighlight->pLeftLocFrag_, pFwdRevPairToHighlight->pRightLocFrag_, pFwdRevPairToHighlight->pGctToUse_, pFwdRevPairToHighlight->cType_, pFwdRevPairToHighlight->cProblem_ ); } else if ( pFwdRevPairToHighlight->cGetType() == cLINE ) { pNewPair = new fwdRevPairLine( ((fwdRevPairLine*) pFwdRevPairToHighlight)->xpoints_, pFwdRevPairToHighlight->pLeftLocFrag_, pFwdRevPairToHighlight->pRightLocFrag_, pFwdRevPairToHighlight->pGctToUse_, pFwdRevPairToHighlight->cType_, pFwdRevPairToHighlight->cProblem_ ); } else if ( pFwdRevPairToHighlight->cGetType() == cTRIANGLE ) { pNewPair = new fwdRevPairTriangle( ((fwdRevPairTriangle*) pFwdRevPairToHighlight)->xpoints_, pFwdRevPairToHighlight->pLeftLocFrag_, pFwdRevPairToHighlight->pRightLocFrag_, pFwdRevPairToHighlight->pGctToUse_, pFwdRevPairToHighlight->cType_, pFwdRevPairToHighlight->cProblem_ ); } else assert( false ); aClickedFwdRevPairs_.insert( pNewPair ); pNewPair->drawThyself( this, true ); displayPopupBoxForClickedObjects(); } else { popupErrorMessage( "could not find read %s subclone %s in Assembly View probably because this subclone has no aligned fwd/rev pair", pLocFrag->soGetName().data(), pLocFrag->pSub_->soTemplateName_.data() ); } } void assemblyView :: raiseWindow() { XtMapWidget( widPopupShell_ ); XRaiseWindow( XtDisplay( widPopupShell_ ), XtWindow( widPopupShell_ ) ); } void assemblyView :: showDocumentationForAssemblyView() { TextBox* pTB = new TextBox( "Documentation", 30, // rows visible pCP->soGetDocumentation() ); pTB->makeVisible(); // want to find the ASSEMBLY VIEW section // do not want: // 3.35) TESTING RUNNING CROSS_MATCH FROM ASSEMBLY VIEW // 9.89) ASSEMBLY VIEW // 13.15) RESTRICTION DIGEST AND ASSEMBLY VIEW // But want: // 9.89) ASSEMBLY VIEW // They key is that the 9.89 (or some other number) starts immediately // after the new line. RWCRegexp regNumberAtBeginning( "^[0-9]+\\.?[0-9]*\\)$" ); int nAssemblyViewPos; bool bFound = false; int nStartLookingHere = 0; while( !bFound ) { nAssemblyViewPos = pCP->soGetDocumentation().index("ASSEMBLY VIEW", nStartLookingHere ); if ( nAssemblyViewPos == RW_NPOS ) { popupErrorMessage( "Internal program error finding ASSEMBLY VIEW in documentation." ); return; } // set up for next iteration nStartLookingHere = nAssemblyViewPos + 1; // look backwards to previous \n int nNewLine = -666; bool bFoundNewLine = false; for( int n = nAssemblyViewPos - 1; n >= 0; --n ) { if ( pCP->soGetDocumentation()[n] == '\n' ) { nNewLine = n; bFoundNewLine = n; break; } } if ( !bFoundNewLine ) { continue; } RWCString soNumber = pCP->soGetDocumentation()( nNewLine + 1, nAssemblyViewPos - nNewLine - 1 ); soNumber.stripTrailingWhitespaceFast(); if ( soNumber.bContains( regNumberAtBeginning ) ) { bFound = true; } } assert( bFound ); XmTextSetHighlight( pTB->widScrolledText_, nAssemblyViewPos, nAssemblyViewPos + strlen( "ASSEMBLY VIEW" ), XmHIGHLIGHT_SELECTED ); pTB->scrollWindowToLocation( nAssemblyViewPos ); } void assemblyView :: readFileOfTemplatesToNotShowIfItExists() { if ( pCP->filAssemblyViewFileOfTemplatesToNotShow_.bFileByThisNameExists() ) { cerr << "reading file " << pCP->filAssemblyViewFileOfTemplatesToNotShow_ << endl; readFileOfTemplatesToNotShow( pCP->filAssemblyViewFileOfTemplatesToNotShow_ ); markFwdRevPairsForThoseNotToShow(); } else { cerr << "not reading file " << pCP->filAssemblyViewFileOfTemplatesToNotShow_ << " because can't find it--that's ok" << endl; } } void assemblyView :: readFileOfTemplatesToNotShow( const FileName& filTemplatesToNotShow ) { FILE* pFOF = fopen( filTemplatesToNotShow.data(), "r" ); if ( !pFOF ) { RWCString soError = "could not open file "; soError += filTemplatesToNotShow; soError += " because of error: "; soError += strerror( errno ); soError += " or "; soError += RWCString( (long) errno ); popupErrorMessage( soError ); return; } const int nMaxLineSize = 1000; RWCString soLine( (size_t) ( nMaxLineSize + 1 ) ); int nNumberOfTemplates = 0; while( fgets( soLine.data(), nMaxLineSize, pFOF ) != NULL ) { ++nNumberOfTemplates; } // the c (rather than c++ method: now that we know how much // space we need, allocate it and read the file again aTemplatesToNotShow_.clear(); aTemplatesToNotShow_.resize( (size_t) nNumberOfTemplates ); rewind( pFOF ); while( fgets( soLine.data(), nMaxLineSize, pFOF ) != NULL ) { soLine.nCurrentLength_ = strlen( soLine.data() ); // there might be leading and/or trailing whitespace soLine.stripAllWhitespaceIncludingInternal(); aTemplatesToNotShow_.insert( soLine ); } fclose( pFOF ); } void assemblyView :: markFwdRevPairsForThoseNotToShow() { Assembly* pAssembly = ConsEd::pGetAssembly(); int nSub; for( nSub = 0; nSub < pAssembly->subcloneTTemplateArray_.length(); ++nSub ) { subcloneTTemplate* pSub = pAssembly->subcloneTTemplateArray_[ nSub ]; pSub->bDoNotShowInAssemblyView_ = false; } for( int nTemplateToNotShow = 0; nTemplateToNotShow < aTemplatesToNotShow_.length(); ++nTemplateToNotShow ) { RWCString soTemplateName = aTemplatesToNotShow_[ nTemplateToNotShow ]; // two ways of looking for templates: // 1) if the name is a wildcard, then go through all templates // 2) if the name is not a wildcard, do a binary search for it. if ( soTemplateName.index( "*" ) != RW_NPOS ) { // case 1. Change globbing syntax to regular expression // syntax and then use RWCRegexp for( int n = soTemplateName.length() - 1; n >= 0; --n ) { if ( soTemplateName[ n ] == '*' ) { soTemplateName.insert( n, "." ); } } // put ^ and $ around the pattern (it must fit precisely--not // just found internally // e.g., abc123* would not match the template M02abc1234 soTemplateName.insert(0, "^" ); soTemplateName.append( "$" ); RWCRegexp regTemplate( soTemplateName ); for( nSub = 0; nSub < pAssembly->subcloneTTemplateArray_.length(); ++nSub ) { subcloneTTemplate* pSub = pAssembly->subcloneTTemplateArray_[ nSub ]; if ( pSub->soTemplateName_.index( regTemplate ) != RW_NPOS ) { pSub->bDoNotShowInAssemblyView_ = true; } // must continue in loop since this pattern may match some // other templates } } else { // case 2. Do a binary search: int nIndex = pAssembly->subcloneTTemplateArray_.nFindIndexOfMatchOrSuccessor2( soTemplateName ); if ( nIndex != RW_NPOS ) { subcloneTTemplate* pSub = pAssembly->subcloneTTemplateArray_[ nIndex ]; pSub->bDoNotShowInAssemblyView_ = true; } else { cerr << "could not find template " << soTemplateName << " in assembly but it was in the file" << endl; } } } } int assemblyView :: nGetRightEdgePixelX() { Dimension nPixelsWide; XtVaGetValues( widDrawingArea_, XtNwidth, &nPixelsWide, NULL ); return( nPixelsWide - 1 ); } int assemblyView :: nGetBottomEdgePixelY() { Dimension nPixelsHigh; XtVaGetValues( widDrawingArea_, XtNheight, &nPixelsHigh, NULL ); return( nPixelsHigh - 1 ); } bool assemblyView :: bIsOnScreen( const int nX, const int nY ) { return( 0 <= nX && 0 <= nY && nX <= nGetRightEdgePixelX() && nY <= nGetBottomEdgePixelY() ); } void assemblyView :: zoomVertically( const int nZoomHow ) { // now zoom verticallly: // first record the old virtual pixel coordinate of the middle of // the screen: int nOldHeightOfOneScaffold = nGetHeightOfOneScaffold(); int nYVirtualPixelOfMiddleOfScreenOldCoordinates = ( 2 * nTopEdgeVirtualPixelPosition_ + nGetBottomEdgePixelY() ) / 2; if ( nZoomHow == nZOOM_IN ) { nHeightOfAreaForFwdRevPairsInSameScaffold_ = nHeightOfAreaForFwdRevPairsInSameScaffold_ * pCP->dAssemblyViewZoomFactor_; } else if ( nZoomHow == nZOOM_OUT ) { nHeightOfAreaForFwdRevPairsInSameScaffold_ = nHeightOfAreaForFwdRevPairsInSameScaffold_ / pCP->dAssemblyViewZoomFactor_; if ( nHeightOfAreaForFwdRevPairsInSameScaffold_ < 1 ) nHeightOfAreaForFwdRevPairsInSameScaffold_ = 1; } else if ( nZoomHow == nZOOM_ORIGINAL ) { nHeightOfAreaForFwdRevPairsInSameScaffold_ = 100; } else assert( false ); // when zooming, let's make the middle location stay constant. // What is the virtual pixel location of the middle of the screen? // now convert nYVirtualPixelOfMiddleOfScreenOldCoordinates to // new coordinates int nNewHeightOfOneScaffold = nGetHeightOfOneScaffold(); int nYVirtualPixelOfMiddleOfScreenNewCoordinates = (float) nYVirtualPixelOfMiddleOfScreenOldCoordinates * (float) nNewHeightOfOneScaffold / (float) nOldHeightOfOneScaffold; // and what is the pixel coordinate of the top of the screen now? nTopEdgeVirtualPixelPosition_ = nYVirtualPixelOfMiddleOfScreenNewCoordinates - nGetAssemblyViewWindowHeight() / 2; int nVirtualPixelPositionsDisplayedAtOnce = nGetAssemblyViewWindowHeight(); int nMaximumVirtualPixelPosition = nGetHeightOfOneScaffold() * nNumberOfScaffoldRows_ + nHeightOfMarginAtTopOfScreen; if ( nTopEdgeVirtualPixelPosition_ > ( nMaximumVirtualPixelPosition - nVirtualPixelPositionsDisplayedAtOnce ) ) { nTopEdgeVirtualPixelPosition_ = nMaximumVirtualPixelPosition - nVirtualPixelPositionsDisplayedAtOnce; } // however, don't let it be negative: if ( nTopEdgeVirtualPixelPosition_ < 0 ) nTopEdgeVirtualPixelPosition_ = 0; } void assemblyView :: zoomHorizontally( const int nZoomHow ) { // before changing dPixelWidthOfBase_ or nLeftEdgeScaffoldPos_, // record middle of screen int nWidthOfScreenInScaffoldPositions = nGetAssemblyViewWindowWidth() / dPixelWidthOfBase_; int nScaffoldPosOfMiddleOfScreen = nLeftEdgeScaffoldPos_ + nWidthOfScreenInScaffoldPositions / 2; if ( nZoomHow == nZOOM_IN ) { double dTryThisPixelWidthOfBase = dPixelWidthOfBase_ * pCP->dAssemblyViewZoomFactor_; double dPixelXMax = nLongestScaffoldLength_ * dTryThisPixelWidthOfBase; if ( dPixelXMax > 32000 ) { popupErrorMessage( "Cannot zoom in further." ); return; } dPixelWidthOfBase_ = dTryThisPixelWidthOfBase; } else if ( nZoomHow == nZOOM_OUT ) { dPixelWidthOfBase_ /= pCP->dAssemblyViewZoomFactor_; } else if ( nZoomHow == nZOOM_ORIGINAL ) { dPixelWidthOfBase_ = dCalculateInitialZoomFactor(); } else assert( false ); // now attempt to scroll so whatever scaffold position // was in the middle of the screen stays there int nNewWidthOfScreenInScaffoldPositions = nGetAssemblyViewWindowWidth() / dPixelWidthOfBase_; nLeftEdgeScaffoldPos_ = nScaffoldPosOfMiddleOfScreen - nNewWidthOfScreenInScaffoldPositions / 2; // however, we need to be sure that we aren't too far to the right // (such as off the scaffold completely) int nScrollBarMaximum = nLongestScaffoldLength_; int nScaffoldPositionsDisplayedAtOnce = ( nGetAssemblyViewWindowWidth() - nLeftEdgePixelMargin - nRightEdgePixelMargin ) / dPixelWidthOfBase_; if ( nScaffoldPositionsDisplayedAtOnce > nLongestScaffoldLength_ ) nScaffoldPositionsDisplayedAtOnce = nLongestScaffoldLength_; // the slider size is nScaffoldPositionsDisplayedAtOnce if ( nLeftEdgeScaffoldPos_ > ( nScrollBarMaximum - nScaffoldPositionsDisplayedAtOnce ) ) nLeftEdgeScaffoldPos_ = nScrollBarMaximum - nScaffoldPositionsDisplayedAtOnce; if ( nLeftEdgeScaffoldPos_ < 0 ) nLeftEdgeScaffoldPos_ = 0; } void assemblyView :: userPushedContigArrangement( XEvent* pEvent ) { XButtonPressedEvent* pEvent2 = (XButtonPressedEvent*) pEvent; XmMenuPosition( widContigArrangementPopupMenu_, pEvent2 ); XtManageChild( widContigArrangementPopupMenu_ ); } void assemblyView :: userPushedReorientContigs() { if ( pGuiReorientContigs_ ) { pGuiReorientContigs_->raiseWindow(); } else { pGuiReorientContigs_ = new guiReorientContigs( this ); pGuiReorientContigs_->createWindow(); } } void assemblyView :: userPushedReorderContigs() { if ( pGuiReorderContigs_ ) { pGuiReorderContigs_->raiseWindow(); } else { pGuiReorderContigs_ = new guiReorderContigs( this ); pGuiReorderContigs_->createWindow(); } } void assemblyView :: userPushedFreezeContigOrder() { RWCString soQuestion = "This will cause contigEndPair or cloneEnd tags to be put on the end of every contig (unless there is already such a tag there). This will cause Assembly View to show the contigs in this order/orientation in the future. Is this what you want? (y/n)"; if ( !bGuiGetAnswerYesNo( soQuestion ) ) { return; } RWCString soQuestion2 = "Before doing this, do you want to delete all existing cloneEnd and contigEndPair tags? (y/n)"; bool bFirstDeleteTags = bGuiGetAnswerYesNo( soQuestion2 ); if ( bFirstDeleteTags ) { Assembly* pAssembly = ConsEd::pGetAssembly(); int nContig; for( nContig = 0; nContig < pAssembly->nNumContigs(); ++nContig ) { Contig* pContig = pAssembly->pGetContig( nContig ); for( int nConsensusTag = pContig->nGetNumberOfTags() - 1; nConsensusTag >= 0; --nConsensusTag ) { tag* pTag= pContig->pGetTag( nConsensusTag ); if ( ( pTag->soGetTagType() == "contigEndPair") || ( pTag->soGetTagType() == "cloneEnd" ) ) { EditAction* pEditAction = new editDeleteConsensusTag( pTag ); ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); // write to edit history file } } } } RWTPtrOrderedVector aUserDefinedContigEndPairs; ConsEd::pGetAssembly()->getUserDefinedContigEndPairs( aUserDefinedContigEndPairs ); // if reached here, the user wants to go ahead for( int nScaffold = 0; nScaffold < aScaffolds_.length(); ++nScaffold ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; for( int nContig = 0; nContig < ( pScaffold->aContigs_.length() - 1 ); ++nContig ) { // look just at the pairs of contigs nContig and nContig + 1 Contig* pLeftContig = pScaffold->aContigs_[ nContig ]; Contig* pRightContig = pScaffold->aContigs_[ nContig + 1 ]; bool bLeftContigComplemented = pScaffold->aIfContigsAreComplemented_[ nContig ]; bool bRightContigComplemented = pScaffold->aIfContigsAreComplemented_[ nContig + 1 ]; int nGapOfLeftContig = ( bLeftContigComplemented ? nLeftGap : nRightGap ); int nGapOfRightContig = ( bRightContigComplemented ? nRightGap : nLeftGap ); // see if there are already contigEnd tags linking these two // contig ends bool bAlreadyHasTags = false; for( int nContigEndPair = 0; nContigEndPair < aUserDefinedContigEndPairs.length(); ++nContigEndPair ) { contigEndPair* pCEP = aUserDefinedContigEndPairs[ nContigEndPair ]; if ( pLeftContig == pCEP->pContig_[0] && pRightContig == pCEP->pContig_[1] && nGapOfLeftContig == pCEP->nWhichEnd_[0] && nGapOfRightContig == pCEP->nWhichEnd_[1] ) { bAlreadyHasTags = true; } else if ( pLeftContig == pCEP->pContig_[1] && pRightContig == pCEP->pContig_[0] && nGapOfLeftContig == pCEP->nWhichEnd_[0] && nGapOfRightContig == pCEP->nWhichEnd_[1] ) { bAlreadyHasTags = true; } if ( bAlreadyHasTags ) break; } // for( int nContigEndPair = 0; if ( bAlreadyHasTags ) continue; // if reached here, this pair of contigs does not already has // tags, or else the tags it has are somehow corrupted (e.g., // doesn't match the sequence) RWCString soContigEndPairID = ConsEd::pGetAssembly()->soGetNextContigEndPairID(); for( int nContig0or1 = 0; nContig0or1 <= 1; ++nContig0or1 ) { Contig* pLeftOrRightContig; int nContigEnd; if ( nContig0or1 == 0 ) { pLeftOrRightContig = pLeftContig; nContigEnd = nGapOfLeftContig; } else { pLeftOrRightContig = pRightContig; nContigEnd = nGapOfRightContig; } int nConsPosForTag = pLeftOrRightContig->nGetGoodPlaceForContigEndPairTag( nContigEnd ); tag* pTag = new tag( NULL, // LocatedFragment pLeftOrRightContig, "contigEndPair", nConsPosForTag, nConsPosForTag, false, // bWriteToPhdFileNotAceFile "", // soComment soConsed, // "consed" soEmptyString, // current date/time false ); // bNoTrans int nUnpaddedStart = pLeftOrRightContig->nUnpaddedIndex( nConsPosForTag ); RWCString soBases; pLeftOrRightContig->getPartOfUnpaddedConsensus( nUnpaddedStart, 10, soBases, ( nContigEnd == nLeftGap ? true : false ), // bComplemented ( nContigEnd == nLeftGap ? false : true ) ); // bTowardsIncreasingUnpaddedPositions pTag->soMiscData_ = soContigEndPairID; pTag->soMiscData_ += "\n"; pTag->soMiscData_ += ( nContigEnd == nLeftGap ? "<-gap" : "gap->" ); pTag->soMiscData_ += "\n"; pTag->soMiscData_ += soBases; EditAction* pEditAction = new editAddConsensusTag( pTag ); ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); // bWriteToEditHistoryFile } // for( int nContig0or1 = 0; nContig0or1 <= 1; } // for( int nContig = 0; nContig < ( pScaffold->aContigs_.length() - 1 ); // now deal with the first and last contig (which might be the // same contigs. Put cloneEnd tags on both of them. Contig* pLeftmostContig = pScaffold->aContigs_[ 0 ]; Contig* pRightmostContig = pScaffold->aContigs_[ pScaffold->aContigs_.length() - 1 ]; // first check if there is already a cloneEnd tag in this contig pointing // in this direction: RWCString soArrowForLeftmostContig; if ( pLeftmostContig->bThisContigIsComplementedInTheScaffold_ ) soArrowForLeftmostContig = "<-"; else soArrowForLeftmostContig = "->"; bool bAlreadyCloneEndTagOnLeftmostContig = false; int nConsensusTag; for( nConsensusTag = 0; nConsensusTag < pLeftmostContig->nGetNumberOfTags(); ++nConsensusTag ) { tag* pTag = pLeftmostContig->pGetTag( nConsensusTag ); if ( pTag->soGetTagType() == "cloneEnd" && pTag->soMiscData_ == soArrowForLeftmostContig ) { bAlreadyCloneEndTagOnLeftmostContig = true; break; } } if ( !bAlreadyCloneEndTagOnLeftmostContig ) { // put cloneEnd tag on left of left-most contig // if the left-most contig is complemented in the scaffold, // then the tag will go on the right end of the contig (in // uncomplemented orientation) int nWhichGap = ( pLeftmostContig->bThisContigIsComplementedInTheScaffold_ ? nRightGap : nLeftGap ); int nConsPosForLeftmostContigEnd = pLeftmostContig->nGetGoodPlaceForContigEndPairTag( nWhichGap ); tag* pTag = new tag( NULL, // LocatedFragment pLeftmostContig, "cloneEnd", nConsPosForLeftmostContigEnd, nConsPosForLeftmostContigEnd, false, // bWriteToPhdFileNotAceFile soEmptyString, // soComment soConsed, // "consed" soEmptyString, // current date/time false ); // bNoTrans pTag->soMiscData_ = soArrowForLeftmostContig; EditAction* pEditAction = new editAddConsensusTag( pTag ); ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); // bWriteToEditHistoryFile } // do the same for the right-most contig RWCString soArrowForRightmostContig; if ( pRightmostContig->bThisContigIsComplementedInTheScaffold_ ) soArrowForRightmostContig = "->"; // in the scaffold, the insert // is to the left. But in the uncomplemented contig, the insert // is to the right. else soArrowForRightmostContig = "<-"; // points to insert bool bAlreadyCloneEndTagOnRightmostContig = false; for( nConsensusTag = 0; nConsensusTag < pRightmostContig->nGetNumberOfTags(); ++nConsensusTag ) { tag* pTag = pRightmostContig->pGetTag( nConsensusTag ); if ( pTag->soGetTagType() == "cloneEnd" && pTag->soMiscData_ == soArrowForRightmostContig ) { bAlreadyCloneEndTagOnRightmostContig = true; } } if ( !bAlreadyCloneEndTagOnRightmostContig ) { // if the rightmost contig is complemented in the scaffold, // then ask for position for the tag at the left end int nWhichGap = ( pRightmostContig->bThisContigIsComplementedInTheScaffold_ ? nLeftGap : nRightGap ); int nConsPosForRightMostContigEnd = pRightmostContig->nGetGoodPlaceForContigEndPairTag( nWhichGap ); tag* pTag = new tag( NULL, // LocatedFragment pRightmostContig, "cloneEnd", nConsPosForRightMostContigEnd, nConsPosForRightMostContigEnd, false, // bWriteToPhdFileNotAceFile soEmptyString, // soComment soConsed, // "consed" soEmptyString, // current date/time false ); // bNoTrans pTag->soMiscData_ = soArrowForRightmostContig; EditAction* pEditAction = new editAddConsensusTag( pTag ); ConsEd::pGetConsEd()->doEditAction( pEditAction, true ); // bWriteToEditHistoryFile } } // for( int nScaffold = 0; nScaffold < aScaffolds_.length(); // should redraw in case there are new cloneEnd tags to be shown drawEverything( true, // bFirstCalculatePositions true ); // bFirstErase } void assemblyView :: arrangeScaffoldsOnScreen() { clScaffold* pScaffold = aScaffolds_[ 0 ]; int nMaximumScaffoldPositionOnRow = pScaffold->nScaffoldLength_; // let's make it approximately 1/10 of the screen width int nScaffoldPosOfGapBetweenScaffolds = MAX( nMaximumScaffoldPositionOnRow / 10, 1 ); int nCurrentScaffoldRow = 0; int nCurrentScaffoldOnScaffoldRow = -1; int nScaffoldPositionsOnRowSoFar = 0; int nScaffold = 0; // the 0th scaffold goes alone on the top line while( nScaffold < aScaffolds_.length() ) { pScaffold = aScaffolds_[ nScaffold ]; if ( nScaffoldPositionsOnRowSoFar == 0 ) { // will always fit. Just add it. pScaffold->nScaffoldRow_ = nCurrentScaffoldRow; ++nCurrentScaffoldOnScaffoldRow; pScaffold->nScaffoldOnScaffoldRow_ = nCurrentScaffoldOnScaffoldRow; pScaffold->nScaffoldPositionsBeforeItOnScaffoldRow_ = 0; nScaffoldPositionsOnRowSoFar = pScaffold->nScaffoldLength_; ++nScaffold; // for next scaffold } else { // There is already a scaffold on the row--see if the next // scaffold will fit. int nLengthIfAddedToCurrentRow = nScaffoldPositionsOnRowSoFar + nScaffoldPosOfGapBetweenScaffolds + pScaffold->nScaffoldLength_; if ( nLengthIfAddedToCurrentRow <= nMaximumScaffoldPositionOnRow ) { // fine--add it to current row pScaffold->nScaffoldRow_ = nCurrentScaffoldRow; ++nCurrentScaffoldOnScaffoldRow; pScaffold->nScaffoldOnScaffoldRow_ = nCurrentScaffoldOnScaffoldRow; pScaffold->nScaffoldPositionsBeforeItOnScaffoldRow_ = nScaffoldPositionsOnRowSoFar + nScaffoldPosOfGapBetweenScaffolds; nScaffoldPositionsOnRowSoFar = nLengthIfAddedToCurrentRow; ++nScaffold; // for next loop } else { // did not fit. Do not increment the scaffold, but // increment the nScaffoldRow for next loop. ++nCurrentScaffoldRow; nScaffoldPositionsOnRowSoFar = 0; nCurrentScaffoldOnScaffoldRow = -1; } } } nNumberOfScaffoldRows_ = nCurrentScaffoldRow + 1; // convert to 1-based } void assemblyView :: userPushedIncludeContigs() { guiAssemblyViewIncludeContigs* pGuiAssemblyViewIncludeContigs = new guiAssemblyViewIncludeContigs(); pGuiAssemblyViewIncludeContigs->createWindow(); } void assemblyView :: userPushedWhatToShow( XEvent* pEvent ) { XButtonPressedEvent* pEvent2 = (XButtonPressedEvent*) pEvent; XmMenuPosition( widWhatToShowPopupMenu_, pEvent2 ); XtManageChild( widWhatToShowPopupMenu_ ); } void assemblyView :: drawReadDepth() { for( int nScaffold = 0; nScaffold < aScaffolds_.length(); ++nScaffold ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; for( int nContig = 0; nContig < pScaffold->aContigs_.length(); ++nContig ) { drawReadDepthForOneContig( nScaffold, nContig ); } } } void assemblyView :: drawReadDepthForOneContig( const int nScaffold, const int nContig ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; Contig* pContig = pScaffold->aContigs_[ nContig ]; pContig->calculateReadDepthIfNecessary(); int nPixelY = nGetPixelYOfConsistentFwdRevPairBaseline( nScaffold ); int nNumberOfBasesPerFwdRevPairPoint = nGetNumberOfBasesPerFwdRevPairPoint(); const int nMaxPoints = 2000; XPoint xpoints[ nMaxPoints ]; int nXPointIndex = -1; // ++ will start this at 0 bool bLastPoint = false; for( int nUnpadded = pContig->nGetUnpaddedStartIndex(); !bLastPoint; nUnpadded += nNumberOfBasesPerFwdRevPairPoint ) { // int nSum = 0; // int nBases = 0; int nMax = 0; for( int nUnpadded1 = nUnpadded; ( nUnpadded1 <= ( nUnpadded + nNumberOfBasesPerFwdRevPairPoint - 1 ) ) && nUnpadded1 <= pContig->nGetUnpaddedEndIndex(); ++nUnpadded1 ) { // nSum += (*pContig->pReadDepthArray_)[ nUnpadded1 ]; nMax = MAX( nMax, (*pContig->pReadDepthArray_)[ nUnpadded1 ] ); // ++nBases; } // round // assert( nBases != 0 ); // int nAverage = ( nSum + nBases/2 ) / nBases; ++nXPointIndex; xpoints[ nXPointIndex].y = nGetPixelYFromNumberOfFwdRevPairs( nMax, nScaffold ); xpoints[ nXPointIndex].x = nGetPixelXFromContigBase( nScaffold, pContig, nUnpadded ); if ( nUnpadded >= pContig->nGetUnpaddedEndIndex() - nNumberOfBasesPerFwdRevPairPoint + 1 ) bLastPoint = true; if ( nXPointIndex >= ( nMaxPoints - 1 ) || bLastPoint ) { XDrawLines( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGctReadDepth_->gcGet(), xpoints, nXPointIndex + 1, // 0 to nPointIndex has // nPointIndex + 1 entries CoordModeOrigin ); nXPointIndex = -1; // set up for next time around } } } void assemblyView :: drawMultipleDiscrepancies() { for( int nScaffold = 0; nScaffold < aScaffolds_.length(); ++nScaffold ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; for( int nContig = 0; nContig < pScaffold->aContigs_.length(); ++nContig ) { drawMultipleDiscrepanciesForOneContig( nScaffold, nContig ); } } } void assemblyView :: drawMultipleDiscrepanciesForOneContig( const int nScaffold, const int nContig ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; Contig* pContig = pScaffold->aContigs_[ nContig ]; pContig->navigateByHighlyDiscrepantPositions( pCP->nNavigateByHighlyDiscrepantPositionsMinDiscrepantReads_, pCP->nNavigateByHighlyDiscrepantPositionsMaxDepthOfCoverage_, pCP->nNavigateByHighlyDiscrepantPositionsIgnoreBasesBelowThisQuality_, pCP->bNavigateByHighlyDiscrepantPositionsJustListIndels_, pCP->bNavigateByHighlyDiscrepantPositionsIgnoreOtherReadsStartingAtSameLocation_, pCP->bNavigateByHighlyDiscrepantPositionsIgnoreIfListedBasesInConsensus_, pCP->soNavigateByHighlyDiscrepantPositionsIgnoreIfTheseBasesInConsensus_, false, // bGotoListNotArrays NULL ); int nPixelY = nGetPixelYOfConsistentFwdRevPairBaseline( nScaffold ); int nNumberOfBasesPerFwdRevPairPoint = nGetNumberOfBasesPerFwdRevPairPoint(); const int nMaxPoints = 2000; XPoint xpoints[ nMaxPoints ]; int nXPointIndex = -1; // ++ will start this at 0 bool bLastPoint = false; int nUnpadded; for( nUnpadded = pContig->nGetUnpaddedStartIndex(); !bLastPoint; nUnpadded += nNumberOfBasesPerFwdRevPairPoint ) { int nSum = 0; for( int nUnpadded1 = nUnpadded; ( nUnpadded1 <= ( nUnpadded + nNumberOfBasesPerFwdRevPairPoint - 1 ) ) && nUnpadded1 <= pContig->nGetUnpaddedEndIndex(); ++nUnpadded1 ) { int nConsPos = pContig->nPaddedIndexFast( nUnpadded1 ); if ( pContig->paDiscrepanciesNotIndels_->bGetValue( nConsPos ) ) ++nSum; } ++nXPointIndex; xpoints[ nXPointIndex].y = nGetPixelYFromNumberOfFwdRevPairs( nSum, nScaffold ); xpoints[ nXPointIndex].x = nGetPixelXFromContigBase( nScaffold, pContig, nUnpadded ); if ( nUnpadded >= pContig->nGetUnpaddedEndIndex() - nNumberOfBasesPerFwdRevPairPoint + 1 ) bLastPoint = true; if ( nXPointIndex >= ( nMaxPoints - 1 ) || bLastPoint ) { XDrawLines( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGctDiscrepanciesNotIndels_->gcGet(), xpoints, nXPointIndex + 1, // 0 to nPointIndex has // nPointIndex + 1 entries CoordModeOrigin ); nXPointIndex = -1; // set up for next time around } } nXPointIndex = -1; // ++ will start this at 0 bLastPoint = false; for( nUnpadded = pContig->nGetUnpaddedStartIndex(); !bLastPoint; nUnpadded += nNumberOfBasesPerFwdRevPairPoint ) { int nSum = 0; for( int nUnpadded1 = nUnpadded; ( nUnpadded1 <= ( nUnpadded + nNumberOfBasesPerFwdRevPairPoint - 1 ) ) && nUnpadded1 <= pContig->nGetUnpaddedEndIndex(); ++nUnpadded1 ) { int nConsPos = pContig->nPaddedIndexFast( nUnpadded1 ); if ( pContig->paDiscrepanciesJustIndels_->bGetValue( nConsPos ) ) ++nSum; } ++nXPointIndex; xpoints[ nXPointIndex].y = nGetPixelYFromNumberOfFwdRevPairs( nSum, nScaffold ); xpoints[ nXPointIndex].x = nGetPixelXFromContigBase( nScaffold, pContig, nUnpadded ); if ( nUnpadded >= pContig->nGetUnpaddedEndIndex() - nNumberOfBasesPerFwdRevPairPoint + 1 ) bLastPoint = true; if ( nXPointIndex >= ( nMaxPoints - 1 ) || bLastPoint ) { XDrawLines( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGctDiscrepanciesIndels_->gcGet(), xpoints, nXPointIndex + 1, // 0 to nPointIndex has // nPointIndex + 1 entries CoordModeOrigin ); nXPointIndex = -1; // set up for next time around } } } void assemblyView :: displayContigLocation( const int nPixelX, const int nPixelY, RWCString& soMessage, bool& bIsOnAContig, Contig*& pContig, int& nUnpadded ) { bIsOnAContig = false; pContig = NULL; nUnpadded = -666; int nFirstScaffoldOnScaffoldRow; if ( !bIsPointerYOnAScaffoldRowOrItsTags( nPixelY, nFirstScaffoldOnScaffoldRow ) ) return; bool bContigComplementedInScaffold; if ( !bIsPointerXOnAContig( nFirstScaffoldOnScaffoldRow, nPixelX, pContig, nUnpadded, bContigComplementedInScaffold ) ) return; soMessage += pContig->soGetName(); if ( bContigComplementedInScaffold ) soMessage += "c"; soMessage += ": "; soMessage += RWCString( (long) nUnpadded ); soMessage += " click MB3 "; bIsOnAContig = true; } int assemblyView :: nGetFirstScaffoldOnScaffoldRow( const int nScaffoldRow ) { for( int nScaffold = 0; nScaffold < aScaffolds_.length(); ++nScaffold ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; if ( pScaffold->nScaffoldRow_ == nScaffoldRow ) { return( nScaffold ); } } cerr << "Warning: bad nScaffoldRow" << endl; // if reached here, couldn't find it. So what shall we do? // return garbage return( 0 ); } bool assemblyView :: bIsPointerYOnAScaffoldRow( const int nPixelY, int& nFirstScaffoldOnScaffoldRow ) { int nLastScaffoldRow = -1; for( int nScaffold = 0; nScaffold < aScaffolds_.length(); ++nScaffold ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; if ( pScaffold->nScaffoldRow_ == nLastScaffoldRow ) { // no use checking since the pointer won't be in this // scaffold either (it wasn't in the last one) continue; } // ------------------- <- nGetPixelYOfScaffoldBaseline // | // | (grey contig bar) // | // ------------------- <- nGetPixelYOfTopOfAreaForInconsistentFwdRevPairs if ( nPixelY < nGetPixelYOfScaffoldBaseline( nScaffold ) ) { // pixel was above this scaffold return( false ); } if ( nPixelY < nGetPixelYOfTopOfAreaForInconsistentFwdRevPairs( nScaffold ) ) { nFirstScaffoldOnScaffoldRow = nScaffold; return( true ); } } // if reached here, have considered all scaffolds and none worked return( false ); } bool assemblyView :: bIsPointerYOnAScaffoldRowOrItsTags( const int nPixelY, int& nFirstScaffoldOnScaffoldRow ) { int nLastScaffoldRow = -1; for( int nScaffold = 0; nScaffold < aScaffolds_.length(); ++nScaffold ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; if ( pScaffold->nScaffoldRow_ == nLastScaffoldRow ) { // no use checking since the pointer won't be in this // scaffold either (it wasn't in the last one) continue; } // ------------------- <- nGetPixelYOfScaffoldBaseline // | // | (grey contig bar) // | // ------------------- <- nGetPixelYOfTopOfAreaForInconsistentFwdRevPairs if ( nPixelY < nGetPixelYOfScaffoldBaseline( nScaffold ) ) { // pixel was above this scaffold return( false ); } if ( nPixelY <= nGetPixelYBottomOfTagBar( nScaffold ) ) { nFirstScaffoldOnScaffoldRow = nScaffold; return( true ); } } // if reached here, have considered all scaffolds and none worked return( false ); } bool assemblyView :: bIsPointerXOnAContig( const int nFirstScaffoldOnScaffoldRow, const int nPixelX, Contig*& pContigOfPointer, int& nUnpaddedOfPointer, bool& bContigComplementedInScaffold ) { assert( 0 <= nFirstScaffoldOnScaffoldRow ); assert( nFirstScaffoldOnScaffoldRow < aScaffolds_.length() ); int nScaffoldRow = aScaffolds_[ nFirstScaffoldOnScaffoldRow ]->nScaffoldRow_; for( int nScaffold = nFirstScaffoldOnScaffoldRow; nScaffold < aScaffolds_.length(); ++nScaffold ) { clScaffold* pScaffold = aScaffolds_[ nScaffold ]; if ( pScaffold->nScaffoldRow_ != nScaffoldRow ) { // we have already examined all the scaffolds on the // scaffold row that the pointer is on return( false ); } for( int nContig = 0; nContig < pScaffold->aContigs_.length(); ++nContig ) { Contig* pContig = pScaffold->aContigs_[ nContig ]; int nContigPixelXLeft = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosLeft_ ); int nContigPixelXRight = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosRight_ ); if ( nPixelX < nContigPixelXLeft ) { // I believe that all other contigs will be further to the right // so the pointer will not intersect them. return( false ); } else { // case in which the contig starts to the left of the pointer // but does it end to the right of the pointer? if ( nPixelX <= nContigPixelXRight ) { // The pointer *is* within the contig. But where? pContigOfPointer = pContig; int nPointerClonePos; if ( nContigPixelXRight != nContigPixelXLeft ) { // assuming that clone pos always increase from // left to right nPointerClonePos = (double) ( pContig->nClonePosRight_ - pContig->nClonePosLeft_ ) * (double ) ( nPixelX - nContigPixelXLeft ) / (double) ( nContigPixelXRight - nContigPixelXLeft ) + pContig->nClonePosLeft_; } else { // pathological case in which the contig is a tiny // 1 pixel sliver. In this case, we really can't // resolve the contig position. nPointerClonePos = pContig->nClonePosLeft_; } // now convert clone pos to unpadded pos nUnpaddedOfPointer = pContigOfPointer->nGetUnpaddedConsPosFromScaffoldPos( nPointerClonePos ); bContigComplementedInScaffold = pScaffold->aIfContigsAreComplemented_[ nContig ]; return( true ); } // if ( nPixelX <= nContigPixelXRight ) { } } // for( int nContig = 0; nContig < pScaffold->aContigs_.length(); } // for( int nScaffold = nFirstScaffoldOnScaffoldRow; // if reached here, the pointer must be to the right of all the scaffolds // on this scaffold row return( false ); } void assemblyView :: userPushedMouseButton3InDrawingArea( XButtonPressedEvent* pEvent ) { XmString xms; int nFirstScaffoldOnScaffoldRow; if ( !bIsPointerYOnAScaffoldRowOrItsTags( nLastButtonPressPixelY_, nFirstScaffoldOnScaffoldRow ) ) { xms = XmStringCreateLocalized( "Move pointer to a grey contig bar before right mouse click" ); } else { xms = XmStringCreateLocalized( "Goto Aligned Reads Window" ); } XtVaSetValues( widGotoAlignedReadsWindow_, XmNlabelString, xms, NULL ); XmStringFree( xms ); XmMenuPosition( widMouseButton3PopupMenu_, pEvent ); XtManageChild( widMouseButton3PopupMenu_ ); } void assemblyView :: userPushedGotoAlignedReadsWindow() { // where is the pointer? // To get here, I believe it must be on a contig, but // handle case of it now anyway. int nFirstScaffoldOnScaffoldRow; if ( !bIsPointerYOnAScaffoldRowOrItsTags( nLastButtonPressPixelY_, nFirstScaffoldOnScaffoldRow ) ) return; Contig* pContig; int nUnpadded; bool bContigComplementedInScaffold; if ( !bIsPointerXOnAContig( nFirstScaffoldOnScaffoldRow, nLastButtonPressPixelX_, pContig, nUnpadded, bContigComplementedInScaffold ) ) return; int nConsPos = pContig->nPaddedIndexFast( nUnpadded ); ContigWin* pContigWin = ConsEd::pGetConsEd()->pScrollExistingContigWinOrMakeNewContigWin( pContig, nConsPos ); pContigWin->moveCursorToConsPos( nConsPos ); pContigWin->raiseWindow(); } void assemblyView :: displayReadDepth( RWCString& soMessage, Contig* pContig, const int nUnpadded ) { if ( !pCP->bAssemblyViewShowReadDepth_ ) return; // what is the unpadded positions? assert( pContig ); pContig->calculateReadDepthIfNecessary(); // it is possible for nUnpadded to be off the contig since // displayContigLocation and bIsPointerXOnAContig can return values // of nUnpadded that are not within the contig, at least Aug 2005. // Perhaps should change this. if ( nUnpadded < 1 || pContig->pReadDepthArray_->nGetEndIndex() < nUnpadded ) return; assert( pContig->pReadDepthArray_ ); int nReadDepth = (*pContig->pReadDepthArray_)[ nUnpadded ]; soMessage += "read depth: "; soMessage += RWCString( (long) nReadDepth ); soMessage += " "; } // for deliberate exception // static int nCounter = 0; // end deliberate exception void assemblyView :: displayFwdRevPairDepth( RWCString& soMessage, Contig* pContig, const int nUnpadded ) { if ( !bShowDepth_ ) return; assert( pContig ); // If the user has changed the consensus (such as changing pads to // bases), ConsistentFwdRevPairDepth_ can be shorter than the // unpadded contig. Aug 2005 if ( pContig->aConsistentFwdRevPairDepth_.nGetEndIndex() != pContig->nGetUnpaddedEndIndex() ) { ConsEd::pGetAssembly()->figureOutConsistentForwardReversePairDepthOfAllContigs( bDoNotShowTemplatesInDoNotShowTemplatesFile_ ); assert( pContig->aConsistentFwdRevPairDepth_.nGetEndIndex() == pContig->nGetUnpaddedEndIndex() ); } // it is possible for nUnpadded to be off the contig since // displayContigLocation and bIsPointerXOnAContig can return values // of nUnpadded that are not within the contig, at least Aug 2005. // Perhaps should change this. if ( nUnpadded < pContig->aConsistentFwdRevPairDepth_.nGetStartIndex() || pContig->aConsistentFwdRevPairDepth_.nGetEndIndex() < nUnpadded ) return; // for deliberate exception--this shows if exception handling is // working correctly at St Louis // ++nCounter; // if ( nCounter % 3 == 0 ) { // cerr << pContig->aConsistentFwdRevPairDepth_[ pContig->nGetUnpaddedEndIndex() + 10 ] << endl; // } // end deliberate exception int nFwdRevPairDepth = pContig->aConsistentFwdRevPairDepth_[ nUnpadded ]; soMessage += "fwd/rev pair depth: "; soMessage += RWCString( (long) nFwdRevPairDepth ); soMessage += " "; } void assemblyView :: userPushedWhichTagsToShow() { guiAssemblyViewShowTags* pGuiAssemblyViewShowTags = new guiAssemblyViewShowTags( this ); pGuiAssemblyViewShowTags->createWindow(); } void assemblyView :: userPushedGotoTagInAlignedReadsWindow() { RWTPtrOrderedVector aTags; if ( !bCheckIfOnATag( nLastButtonPressPixelX_, nLastButtonPressPixelY_, &aTags ) ) { popupErrorMessage( "You are not pointing to a tag." ); return; } if ( aTags.length() == 1 ) { // just go there without bringing up a navigate box tag* pTag = aTags[0]; int nConsPos = pTag->nPaddedConsPosStart_; Contig* pContig = pTag->pGetContig(); ContigWin* pContigWin = ConsEd::pGetConsEd()->pScrollExistingContigWinOrMakeNewContigWin( pContig, nConsPos ); if ( pTag->bReadTagNotConsensusTag_ ) { pContigWin->moveCursorToFragPos( nConsPos, pTag->pLocFrag_ ); } else { pContigWin->moveCursorToConsPos( nConsPos ); } pContigWin->raiseWindow(); } else { // more than 1 tag gotoList* pGotoList = new gotoList(); for( int nTag = 0; nTag < aTags.length(); ++nTag ) { tag* pTag = aTags[ nTag ]; LocatedFragment* pLocFrag; Contig* pContig; if ( !pTag->bReadTagNotConsensusTag_ ) pLocFrag = NULL; else pLocFrag = pTag->pLocFrag_; pContig = pTag->pGetContig(); int nUnpaddedStart = pContig->nUnpaddedIndex( pTag->nPaddedConsPosStart_ ); int nUnpaddedEnd = pContig->nUnpaddedIndex( pTag->nPaddedConsPosEnd_ ); const int nMaxLengthForDescription = 50; RWCString soDescription = pTag->soGetExtraInformationForNavigator( nMaxLengthForDescription ); if ( soDescription.isNull() ) { soDescription.increaseMaxLengthIfNecessary( 200 ); soDescription.nCurrentLength_ = sprintf( soDescription.data(), "%6d %s", ( nUnpaddedEnd - nUnpaddedStart + 1 ), pTag->soType_.data() ); } gotoItem* pGotoItem = new gotoItem( pContig, pLocFrag, pTag->nPaddedConsPosStart_, pTag->nPaddedConsPosEnd_, nUnpaddedStart, nUnpaddedEnd, soDescription, true ); // bPrefixContigToDescription pGotoList->addToList( pGotoItem ); } pGotoList->sortByPosition(); ConsEd::pGetConsEd()->addGuiMultiContigNavigator( new guiMultiContigNavigator( "Goto Which Tag?", "", // soTextForFirstLine "", // soTextForSecondLine 75, // nwidthInChars "", // soTitleOfSpecialPurposeButton NULL, // cbSpecialPurposeButton NULL, // pClientDataForCbSpecialPurposeButton NULL, // widTopLevelShellToBeConnectedTo pGotoList, NULL ) // pContigWin ); } // if ( aTags.length() == 1 ) { else } void assemblyView :: userPushedGotoFragmentInDigestWindow() { if ( aCurrentlyHighlightedFragments_.length() == 0 ) { popupErrorMessage2( widPopupShell_, "you must first point to a fragment" ); return; } restrictionFragment* pGotoRestrictionFragment = NULL; for( int nHighlightedFragment = 0 ; nHighlightedFragment < aCurrentlyHighlightedFragments_.length() && !pGotoRestrictionFragment; ++nHighlightedFragment ) { restrictionFragment* pResFrag = aCurrentlyHighlightedFragments_[ nHighlightedFragment ]; if ( pResFrag->pDigestForOneEnzyme_ == pResFrag->pDigestForOneEnzyme_->pGuiDisplayDigest_->pCurrentlyDisplayedDigest_ ) { pGotoRestrictionFragment = pResFrag; } } if ( !pGotoRestrictionFragment ) { // give a message saying that you must first switch // the digest window to the enzyme you want restrictionFragment* pRandomHighlightedFragment = aCurrentlyHighlightedFragments_[0]; popupErrorMessage2( widPopupShell_, "None of the highlighted fragments are for enzymes that are currently displayed in the digest windows. If you want to display the fragment for enzyme %s, switch the digest window to that enzyme", pRandomHighlightedFragment->pDigestForOneEnzyme_->soEnzymeName_.data() ); return; } guiDisplayDigest* pGuiDisplayDigest = pGotoRestrictionFragment->pDigestForOneEnzyme_->pGuiDisplayDigest_; pGuiDisplayDigest->highlightFragment( pGotoRestrictionFragment ); pGuiDisplayDigest->raiseWindow(); } void assemblyView :: setContigScaffolds( const RWTPtrOrderedVector& aScaffolds ) { // not all contigs will be shown in assemblyView so for those contigs, // set the scaffold to -1 Assembly* pAssembly = ConsEd::pGetAssembly(); for( int nContig = 0; nContig < pAssembly->nNumContigs(); ++nContig ) { Contig* pContig = pAssembly->pGetContig( nContig ); pContig->nScaffold_ = -1; } for( int nScaffold = 0; nScaffold < aScaffolds.length(); ++nScaffold ) { clScaffold* pScaffold = aScaffolds[ nScaffold ]; for( int nContig = 0; nContig < pScaffold->aContigs_.length(); ++nContig ) { Contig* pContig = pScaffold->aContigs_[ nContig ]; pContig->nScaffold_ = nScaffold; } } } void assemblyView :: userPushedDigestCutSites() { bShowDigest_ = !bShowDigest_; XmString xms; if ( bShowDigest_ ) xms = XmStringCreateLocalized( "Hide Digest Cut Sites" ); else xms = XmStringCreateLocalized( "Digest Cut Sites" ); XtVaSetValues( widDigestCutSites_, XmNlabelString, xms, NULL ); XmStringFree( xms ); drawEverything( false, // bFirstCalculatePositions true ); // bFirstErase } void assemblyView :: drawCloneEnds() { // find any clone end tags RWTPtrOrderedVector aCloneEndTags; ConsEd::pGetAssembly()->lookForCloneEndTags3( &aCloneEndTags ); for( int nTag = 0; nTag < aCloneEndTags.length(); ++nTag ) { tag* pCloneEndTag = aCloneEndTags[ nTag ]; drawCloneEndTag( pCloneEndTag ); } } void assemblyView :: drawCloneEndTag( tag* pCloneEndTag ) { Contig* pContig = pCloneEndTag->pGetContig(); int nScaffold = pContig->nScaffold_; // case in which the contig is not being displayed if ( nScaffold == -1 ) return; int nUnpadded = pContig->nUnpaddedIndex( pCloneEndTag->nPaddedConsPosStart_ ); int nScaffoldPos = pContig->nGetScaffoldPosFromUnpaddedConsPos( nUnpadded ); // which way should the clone end tag point? Must look at the // rest of the tag information bool bInsertToRight; if ( pCloneEndTag->soMiscData_ == "->" ) { bInsertToRight = true; } else { bInsertToRight = false; } // however, perhaps the contig is reversed in the scaffold... if ( pContig->bThisContigIsComplementedInTheScaffold_ ) bInsertToRight = !bInsertToRight; guiDrawCloneEndTag( nScaffold, nScaffoldPos, bInsertToRight ); } void assemblyView :: guiDrawCloneEndTag( const int nScaffold, const int nScaffoldPos, const bool bInsertToRight ) { int nPixelYTop = nGetPixelYOfScaffoldBaseline( nScaffold ); // the -1 is so that there is no overlap between the contig bar // and the tags or inconsistent fwd/rev pairs int nPixelYBottom = nGetPixelYOfTopOfAreaForInconsistentFwdRevPairs( nScaffold ) - 1; int nPixelX = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPos ); const int nNumberOfPoints = 3; XPoint aPoint[ nNumberOfPoints ]; aPoint[0].x = nPixelX; aPoint[0].y = nPixelYTop; aPoint[2].x = nPixelX; aPoint[2].y = nPixelYBottom; const int nPixelWidthOfCloneEndTag = 5; if ( bInsertToRight ) aPoint[1].x = nPixelX + nPixelWidthOfCloneEndTag; else aPoint[1].x = nPixelX - nPixelWidthOfCloneEndTag; aPoint[1].y = ( nPixelYTop + nPixelYBottom ) / 2; XFillPolygon( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGctCloneEnd_->gcGet(), aPoint, nNumberOfPoints, Convex, CoordModeOrigin ); } void assemblyView :: userPushedHideOrShowTags() { pCP->bAssemblyViewShowTags_ = !pCP->bAssemblyViewShowTags_; XmString xms; if ( pCP->bAssemblyViewShowTags_ ) xms = XmStringCreateLocalized( "Hide All Tags" ); else xms = XmStringCreateLocalized( "Show Selected Tags" ); XtVaSetValues( widHideOrShowTags_, XmNlabelString, xms, NULL ); XmStringFree( xms ); // fixed Nov 2006 bool bFirstCalculatePositions; if ( pCP->bAssemblyViewShowTags_ ) bFirstCalculatePositions = true; else bFirstCalculatePositions = false; drawEverything( bFirstCalculatePositions, // bFirstCalculatePositions true ); // bFirstErase } void assemblyView :: findContig() { char* szContig = XmTextGetString( widContigName_ ); RWCString soContig( szContig ); XtFree( szContig ); soContig.stripAllWhitespaceExceptInternal(); Contig* pContig = ConsEd::pGetAssembly()->pGetContigByVariousNamesCaseInsensitive( soContig ); if ( !pContig ) { popupErrorMessage2( widPopupShell_, "Could not find contig %s", soContig.data() ); return; } int nScaffold = nGetScaffoldForContig( pContig ); if ( nScaffold == -1 ) { popupErrorMessage2( widPopupShell_, "Could not find %s in assembly view", soContig.data() ); return; } clScaffold* pScaffold = aScaffolds_[ nScaffold ]; // find nContig int nContig; bool bFound = false; for( nContig = 0; nContig < pScaffold->aContigs_.length(); ++nContig ) { if ( pScaffold->aContigs_[ nContig ] == pContig ) { bFound = true; break; } } assert( bFound ); int nContigPixelXLeft = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosLeft_ ); int nContigPixelXRight = nGetPixelXFromScaffoldPos( nScaffold, pContig->nClonePosRight_ ); // check if these pixels are on the screen. If not, scroll. int nPixelXWindowLeft = 0; int nPixelXWindowRight = nGetAssemblyViewWindowWidth() - 1; int nContigOnScreenPixelXLeft; int nContigOnScreenPixelXRight; if ( !bIntersect( nContigPixelXLeft, nContigPixelXRight, nPixelXWindowLeft, nPixelXWindowRight, nContigOnScreenPixelXLeft, nContigOnScreenPixelXRight ) ) { // offscreen--should scroll, but no time to write this today return; } int nPixelYTopOfWindow = 0; int nPixelYBottomOfWindow = nGetAssemblyViewWindowHeight(); int nPixelYContigName = nGetPixelYOfContigName( nScaffold ); // check if should scroll window vertically if ( nPixelYContigName < nPixelYTopOfWindow || nPixelYBottomOfWindow < nPixelYContigName ) { // must scroll so that this contig is near the top of the // window, but not too close to top. Neha liked it in // this position int nNewTopOfWindow = nTopEdgeVirtualPixelPosition_ + nPixelYContigName - nGetHeightOfOneScaffold(); programScrollVertically( nNewTopOfWindow ); // this has now changed and is used by XDrawImageString below nPixelYContigName = nGetPixelYOfContigName( nScaffold ); } int nPixelXCenterOfContigName = ( nContigOnScreenPixelXLeft + nContigOnScreenPixelXRight ) / 2; RWCString soContigName = pContig->soGetAbbreviatedName(); if ( pScaffold->aIfContigsAreComplemented_[ nContig ] ) soContigName += "c"; int nWhereWeWouldLikeToStartTheName = nPixelXCenterOfContigName - soContigName.length() * GuiApp::nGetFontWidth() / 2; // ok to write name for( int n = 0; n < 2; ++n ) { XDrawImageString( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGctContigNames_->gcGetReverse(), nWhereWeWouldLikeToStartTheName, nPixelYContigName, soContigName.data(), soContigName.length() ); // need to delay less than a second waitUntilDialogIsVisible( widPopupShell_ ); sleep( 1 ); XDrawImageString( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGctContigNames_->gcGet(), nWhereWeWouldLikeToStartTheName, nPixelYContigName, soContigName.data(), soContigName.length() ); waitUntilDialogIsVisible( widPopupShell_ ); sleep( 1 ); } }