/***************************************************************************** # 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 #include #include #include #include #include #include using namespace std; #include "soGetErrno.h" #include "assert.h" #include "contigwin.h" #include "consed.h" #include "guicontigwin.h" #include "assemblyViewRemoveReads.h" #include "handleWindowManagerDelete2.h" #include "consedParameters.h" #include "hp_exception_kludge.h" #include "assemblyView.h" #include "soGetErrno.h" #include "breakIntoShorterLines.h" #include "popupErrorMessage.h" #include "guiRemoveReads.h" static void cbDismissPulloutWindow( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyViewRemoveReads* pAVRemoveReads = (assemblyViewRemoveReads*) pClientData; TRY_CATCH_WRAPPER( delete pAVRemoveReads ); } static void cbSaveHighlightedReads( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyViewRemoveReads* pAVRemoveReads = (assemblyViewRemoveReads*) pClientData; TRY_CATCH_WRAPPER( pAVRemoveReads->saveHighlightedReads() ); } static void cbRemoveHighlightedReads( Widget wid, XtPointer pClientData, XtPointer pCallData ) { assemblyViewRemoveReads* pAVRemoveReads = (assemblyViewRemoveReads*) pClientData; TRY_CATCH_WRAPPER( pAVRemoveReads->removeHighlightedReads() ); } assemblyViewRemoveReads :: assemblyViewRemoveReads( assemblyView* pAssemblyView ) : pAssemblyView_( pAssemblyView ) { pGotoList_ = new gotoList(); int nArgs; Arg aArg[500]; widPopupShell_ = XtVaCreatePopupShell( "Put Reads Into Their Own Contigs", topLevelShellWidgetClass, GAPP->widGetTopLevel(), // might be possible // to attach this to assemblyView, but // then if delete assemblyView before // deleting this window, might have problems. XmNnoResize, False, XmNautoUnmanage, False, XmNtransient, False, XmNdeleteResponse, XmDO_NOTHING, NULL ); handleWindowManagerDelete2( widPopupShell_, cbDismissPulloutWindow, this ); // // create the form widget // Widget widForm = XtVaCreateManagedWidget( "form", xmFormWidgetClass, widPopupShell_, XmNshadowThickness, 0, XmNborderWidth, 0, NULL ); RWCString soInstructions = "Help/Instructions:\nHighlight the reads you want to put into their own contigs. Then push \"Remove Highlighted\" to put these reads into their own contigs. In order to highlight the reads, you can left mouse click to start a group and then hold down the shift key and left mouse click to mark the end of a group of reads. Subsequent groups of reads can be started by holding down the control key and then left mouse clicking. Such a group is ended by holding down the shift key and left mouse clicking on the last read. If you want to add a single additional read, you can hold down the control key and left mouse click."; breakIntoShorterLines( soInstructions, 50 ); short shRowsVisible = 3; const int nWidthInChars = 50; nArgs = 0; XtSetArg(aArg[nArgs], XmNeditable, false); nArgs++; XtSetArg(aArg[nArgs], XmNcursorPositionVisible, false); nArgs++; XtSetArg(aArg[nArgs], XmNrows, shRowsVisible ); nArgs++; XtSetArg(aArg[nArgs], XmNtraversalOn, False); nArgs++; XtSetArg(aArg[nArgs], XmNvalue, (char*) soInstructions.data()); nArgs++; XtSetArg(aArg[nArgs], XmNtopAttachment, XmATTACH_FORM); nArgs++; XtSetArg(aArg[nArgs], XmNtopOffset, 0); nArgs++; XtSetArg(aArg[nArgs], XmNleftAttachment, XmATTACH_FORM); nArgs++; XtSetArg(aArg[nArgs], XmNrightAttachment, XmATTACH_FORM); nArgs++; XtSetArg( aArg[nArgs], XmNeditMode, XmMULTI_LINE_EDIT ); ++nArgs; XtSetArg( aArg[nArgs], XmNcolumns, nWidthInChars ); ++nArgs; // removing this method of setting fontList to fix SuSe bug // that gives dagger characters // XtSetArg( aArg[nArgs], XmNfontList, GuiApp::pGetGuiApp()->xmfontListGet() ); ++nArgs; widInstructions_ = XmCreateScrolledText(widForm, "instructions", aArg, nArgs); XtManageChild( widInstructions_); const int nSpacingBetweenButtons = 1; int nButtonLocationLeft[6]; int nButtonLocationRight[6]; int nNumberOfButtons = 3; double dWidthOfAButton = ( 100 - nSpacingBetweenButtons * ( nNumberOfButtons + 1) ) / (double) nNumberOfButtons; for( int nButton = 0; nButton < nNumberOfButtons; ++nButton ) { nButtonLocationLeft[ nButton ] = nSpacingBetweenButtons * ( nButton + 1 ) + (int) (dWidthOfAButton * nButton ); nButtonLocationRight[ nButton ] = nSpacingBetweenButtons * ( nButton + 1 ) + (int) (dWidthOfAButton * ( nButton + 1 )); } widRemoveReadsButton_ = XtVaCreateManagedWidget( "Remove Highlighted Reads", xmPushButtonWidgetClass, widForm, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 10, XmNtraversalOn, False, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, nButtonLocationLeft[0], XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, nButtonLocationRight[0], NULL ); XtAddCallback(widRemoveReadsButton_, XmNactivateCallback, (XtCallbackProc ) cbRemoveHighlightedReads, this); widSaveButton_ = XtVaCreateManagedWidget( "Save Highlight Reads To File", xmPushButtonWidgetClass, widForm, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, widRemoveReadsButton_, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 10, XmNtraversalOn, False, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, nButtonLocationLeft[1], XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, nButtonLocationRight[1], NULL ); XtAddCallback(widSaveButton_, XmNactivateCallback, (XtCallbackProc )cbSaveHighlightedReads, this); widDismissButton_ = XtVaCreateManagedWidget( "Dismiss", xmPushButtonWidgetClass, widForm, XmNtopAttachment, XmATTACH_OPPOSITE_WIDGET, XmNtopWidget, widRemoveReadsButton_, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 10, XmNtraversalOn, False, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, nButtonLocationLeft[2], XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, nButtonLocationRight[2], NULL ); XtAddCallback(widDismissButton_, XmNactivateCallback, (XtCallbackProc )cbDismissPulloutWindow, this); nArgs = 0; XtSetArg(aArg[nArgs], XmNselectionPolicy, XmEXTENDED_SELECT); nArgs++; // I'm not sure if I'll create the list empty or not // XtSetArg(aArg[nArgs], XmNlistItems, paXms); nArgs++; // XtSetArg(aArg[nArgs], XmNlistItemCount, nNumGotoItems); nArgs++; XtSetArg(aArg[nArgs], XmNtopAttachment, XmATTACH_WIDGET); nArgs++; XtSetArg(aArg[nArgs], XmNtopWidget, widInstructions_ ); nArgs++; XtSetArg(aArg[nArgs], XmNtopOffset, 0 ); nArgs++; XtSetArg(aArg[nArgs], XmNleftAttachment, XmATTACH_FORM); nArgs++; XtSetArg(aArg[nArgs], XmNrightAttachment, XmATTACH_FORM); nArgs++; XtSetArg(aArg[nArgs], XmNbottomAttachment, XmATTACH_WIDGET); nArgs++; XtSetArg(aArg[nArgs], XmNbottomWidget, widRemoveReadsButton_); nArgs++; XtSetArg(aArg[nArgs], XmNbottomOffset, 10 ); nArgs++; XtSetArg(aArg[nArgs], XmNmarginWidth, 0 ); nArgs++; XtSetArg(aArg[nArgs], XmNmarginHeight, 0 ); nArgs++; XtSetArg( aArg[nArgs], XmNtextColumns, (short) nWidthInChars ); ++nArgs; XtSetArg( aArg[nArgs], XmNvisibleItemCount, 20 ); ++nArgs; widScrolledList_ = XmCreateScrolledList( widForm, "reads to remove", aArg, nArgs); XtManageChild( widScrolledList_ ); XtPopup( widPopupShell_, XtGrabNone ); } void assemblyViewRemoveReads :: saveHighlightedReads() { RWCString soDirMask = "*.*"; RWCString soTryOutFileName = "list.txt"; FileName filUserOutFileName = GuiApp::popupFileSelector("Save list to file", soDirMask, soTryOutFileName); // if user cancelled or did not supply name, bail now if (filUserOutFileName.isNull()) { return; } bool bGoAhead = true; if (filUserOutFileName.bFileByThisNameExists()) { bGoAhead = GuiApp::popupDecisionMessage("File %s exists. Save anyway?", (const char*)filUserOutFileName); } if (! bGoAhead) return; saveHighlightedReads2( filUserOutFileName ); } void assemblyViewRemoveReads :: saveHighlightedReads2( const FileName& filOutputFile ) { int* pPositionList; int nNumberOfSelectedItems = 0; if ( !XmListGetSelectedPos( widScrolledList_, &pPositionList, &nNumberOfSelectedItems ) || nNumberOfSelectedItems == 0 ) { popupErrorMessage( "No reads were selected." ); return; } // open the output file FILE* pOutputFile = fopen( filOutputFile.data(), "w" ); if (! pOutputFile ) { // throw an exception with a detailed explanation RWCString soError = "Unable to open file "; soError += filOutputFile; soError += " for writing\n"; soError += soGetErrno(); THROW_ERROR( soError ); } for( int nSelected = 0; nSelected < nNumberOfSelectedItems; ++nSelected ) { int nPositionInDisplayedList = pPositionList[ nSelected ]; int nPositionInGotoList = nPositionInDisplayedList - 1; gotoItem* pGotoItem = pGotoList_->pGetGotoItem( nPositionInGotoList ); fprintf( pOutputFile, "read %s from %d to %d\n", pGotoItem->pLocFrag_->soGetName().data(), pGotoItem->nUnpaddedGotoItemStart_, pGotoItem->nUnpaddedGotoItemEnd_ ); } fclose( pOutputFile ); } void assemblyViewRemoveReads :: appendToList ( gotoItem* pGotoItemToAppend ) { // check that read is not already in the list LocatedFragment* pLocFragToAdd = pGotoItemToAppend->pLocFrag_; for( int nGotoItem = 0; nGotoItem < pGotoList_->nGetNumGotoItems(); ++nGotoItem ) { if ( pLocFragToAdd == pGotoList_->pGetGotoItem( nGotoItem )->pLocFrag_ ) { cerr << "read " << pLocFragToAdd->soGetName() << " is already in the list of reads to remove so not adding it again." << endl; return; } } pGotoList_->addToList( pGotoItemToAppend ); } void assemblyViewRemoveReads :: displayList( const bool bSortByStartPosition ) { if ( bSortByStartPosition ) pGotoList_->sortByPosition(); pGotoList_->removeDuplicates(); XmString* pXmStrings; pXmStrings = (XmString*) XtMalloc( sizeof( XmString ) * pGotoList_->nGetNumGotoItems() ); int nGotoItem; for( nGotoItem = 0; nGotoItem < pGotoList_->nGetNumGotoItems(); ++nGotoItem ) { gotoItem* pGotoItem = pGotoList_->pGetGotoItem( nGotoItem ); pXmStrings[ nGotoItem ] = XmStringCreateSimple( (char*) pGotoItem->soGetFullDesc().data() ); } XtVaSetValues( widScrolledList_, XmNitems, pXmStrings, XmNitemCount, pGotoList_->nGetNumGotoItems(), NULL ); for( nGotoItem = 0; nGotoItem < pGotoList_->nGetNumGotoItems(); ++nGotoItem ) XmStringFree( pXmStrings[ nGotoItem ] ); XtFree( (char*) pXmStrings ); } assemblyViewRemoveReads :: ~assemblyViewRemoveReads() { // We could be in this dtor due to user pushing "cancel" in // assemblyViewRemoveReads but assemblyView is still up. Or we could // be in this dtor because assemblyView is going down. In former case, // remove reference to this in assemblyView if ( ConsEd::pGetConsEd()->pAssemblyView_ == pAssemblyView_ ) { pAssemblyView_->pAssemblyViewRemoveReads_ = NULL; } XtPopdown( widPopupShell_ ); pGotoList_->apGotoItem_.clearAndDestroy(); delete pGotoList_; XtDestroyWidget( widPopupShell_ ); } void assemblyViewRemoveReads :: raiseWindow() { XtMapWidget( widPopupShell_ ); XRaiseWindow( XtDisplay( widPopupShell_ ), XtWindow( widPopupShell_ ) ); } void assemblyViewRemoveReads :: removeHighlightedReads() { // which reads are highlighted? int* pPositionList; int nNumberOfSelectedItems; if ( !XmListGetSelectedPos( widScrolledList_, &pPositionList, &nNumberOfSelectedItems ) ) { nNumberOfSelectedItems = 0; } if ( nNumberOfSelectedItems == 0 ) { popupErrorMessage( "You must select the reads you want to remove. See the instructions at the top" ); XtFree( (char*) pPositionList ); return; } guiRemoveReads* pGuiRemoveReads = new guiRemoveReads(); for( int nSelectedRead = 0; nSelectedRead < nNumberOfSelectedItems; ++nSelectedRead ) { int nOneBasedInXmList = pPositionList[ nSelectedRead ]; // convert to zero-based, which is the index of the pGotoList_ gotoItem* pGotoItem = pGotoList_->pGetGotoItem( nOneBasedInXmList - 1 ); pGuiRemoveReads->aReadsToRemove_.insert( pGotoItem->pLocFrag_ ); } XtFree( (char*) pPositionList ); pGuiRemoveReads->doItAlmostNoGui( widPopupShell_, false ); // bDeleteNotJustPutInOwnContig // tricky order delete this; // usually (always?), assemblyView will already have been deleted // since Contig::putReadsIntoTheirOwnAssembly calls // whatToDoBeforeModifyAssembly which deletes assemblyView if ( ConsEd::pGetConsEd()->pAssemblyView_ ) delete ConsEd::pGetConsEd()->pAssemblyView_; ConsEd::pGetConsEd()->pAssemblyView_ = new assemblyView( ); ConsEd::pGetConsEd()->pAssemblyView_->createWindow( ConsEd::pGetAssembly() ); }