/***************************************************************************** # 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 "restrictionFragment.h" #include #include "arrayOfRestrictionFragments.h" #include "contig.h" #include "guiDisplayDigest.h" #include "clScaffold.h" #include "digestForOneEnzyme.h" #include "popupErrorMessage.h" #include "consed.h" void assemblyView :: assignEnzymeLinesToFragments() { if ( ConsEd::pGetConsEd()->aGuiDisplayDigest_.length() == 0 ) return; int nEnzymeLine = 0; for( int nGuiDisplayDigest = 0; nGuiDisplayDigest < ConsEd::pGetConsEd()->aGuiDisplayDigest_.length(); ++nGuiDisplayDigest ) { guiDisplayDigest* pGuiDisplayDigest = ConsEd::pGetConsEd()->aGuiDisplayDigest_[ nGuiDisplayDigest ]; for( int nEnzyme = 0; nEnzyme < pGuiDisplayDigest->aDigests_.length(); ++nEnzyme ) { digestForOneEnzyme* pDigestForOneEnzyme = pGuiDisplayDigest->aDigests_[ nEnzyme ]; if ( nEnzymeLine >= nMaxNumberOfRestrictionEnzymeLines ) { // means that this enzyme will not be shown pDigestForOneEnzyme->nAssemblyViewEnzymeLine_ = -2; } else pDigestForOneEnzyme->nAssemblyViewEnzymeLine_ = nEnzymeLine; ++nEnzymeLine; } } } void assemblyView :: drawRestrictionDigestFragments() { if ( ConsEd::pGetConsEd()->aGuiDisplayDigest_.length() == 0 ) return; assignEnzymeLinesToFragments(); for( int nWindow = 0; nWindow < ConsEd::pGetConsEd()->aGuiDisplayDigest_.length(); ++nWindow ) { guiDisplayDigest* pGuiDisplayDigest = ConsEd::pGetConsEd()->aGuiDisplayDigest_[ nWindow ]; // each digest window may have several enzyme domains. Display them all. for( int nEnzyme = 0; nEnzyme < pGuiDisplayDigest->aDigests_.length(); ++nEnzyme ) { digestForOneEnzyme* pDigestForOneEnzyme = pGuiDisplayDigest->aDigests_[ nEnzyme ]; // check if there are too many enzymes to display them all if ( pDigestForOneEnzyme->nAssemblyViewEnzymeLine_ < 0 ) continue; arrayOfRestrictionFragments* pPredictedFragmentsArray = &(pDigestForOneEnzyme->aPredictedResFragsByConsPos_ ); int nPredictedFragment; for( nPredictedFragment = 0; nPredictedFragment < pPredictedFragmentsArray->length(); ++nPredictedFragment ) { restrictionFragment* pResFrag = (*pPredictedFragmentsArray)[ nPredictedFragment ]; drawRestrictionEnzymeFragment( pResFrag, false ); } } } } void assemblyView :: drawRestrictionEnzymeFragment( restrictionFragment* pResFrag, const bool bHighlight ) { int nScaffold; int nScaffoldPosLeft; int nScaffoldPosRight; if ( !bIsFragmentDisplayed( pResFrag, nScaffold, nScaffoldPosLeft, nScaffoldPosRight ) ) return; int nPixelYTop = nGetPixelYTopOfAreaForRestrictionDigestEnzyme( nScaffold, pResFrag->pDigestForOneEnzyme_->nAssemblyViewEnzymeLine_ ); int nPixelXLeft = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPosLeft ); int nPixelXRight = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPosRight ); int nWidth = nPixelXRight - nPixelXLeft + 1; XDrawRectangle( XtDisplay( widDrawingArea_ ), XtWindow( widDrawingArea_ ), pGetGuiColorTextForRestrictionFragment( pResFrag, bHighlight )->gcGet(), nPixelXLeft, nPixelYTop, nWidth, nThicknessOfARestrictionDigestFragment ); } bool assemblyView :: bIsFragmentDisplayed( restrictionFragment* pResFrag, int& nScaffold, int& nScaffoldPosLeft, int& nScaffoldPosRight ) { Contig* pContig; int nUnpaddedConsPos; if ( pResFrag->fragLeft_ != restrictionFragment::IN_CONTIG && pResFrag->fragRight_ != restrictionFragment::IN_CONTIG ) return( false ); // special cases: only one end in a contig (the other in vector) // both ends in contigs, but in different scaffolds int nScaffoldLeft; if ( pResFrag->fragLeft_ == restrictionFragment::IN_CONTIG ) { nScaffoldLeft = pResFrag->pLeftContig_->nScaffold_; if ( nScaffoldLeft < 0 ) { return( false ); } nScaffoldPosLeft = pResFrag->pLeftContig_->nGetScaffoldPosFromUnpaddedConsPos( pResFrag->nUnpaddedLeft_ ); } else { // the possibilities for fragLeft_ are IN_VECTOR, // AT_VECTOR_INSERT_JUNCTION, and UNKNOWN // I'm going to draw the vector as though it goes to // the vector-insert junction. So I will draw it to // the extreme left position (1) of the scaffold. Which scaffold? // The only way to know that is by the scaffold of the other end // of the fragment. nScaffoldLeft = pResFrag->pRightContig_->nScaffold_; nScaffoldPosLeft = 0; } int nScaffoldRight; if ( pResFrag->fragRight_ == restrictionFragment::IN_CONTIG ) { nScaffoldRight = pResFrag->pRightContig_->nScaffold_; if ( nScaffoldRight < 0 ) { return( false ); } nScaffoldPosRight = pResFrag->pRightContig_->nGetScaffoldPosFromUnpaddedConsPos( pResFrag->nUnpaddedRight_ ); } else { // case in which the fragment goes to the extreme right end of the // scaffold. Which scaffold? Go by fragLeft_ nScaffoldRight = pResFrag->pLeftContig_->nScaffold_; // scaffold positions are 0-based nScaffoldPosRight = aScaffolds_[ nScaffoldRight ]->nScaffoldLength_ - 1; } if ( nScaffoldLeft != nScaffoldRight ) { // can't show such a fragment. But also don't want to // display this error message over and over. // Fixed for Nancy Hansen, March 3, 2006 //popupErrorMessage( "in different scaffolds %d and %d\n", //nScaffoldLeft, //nScaffoldRight ); return( false ); } nScaffold = nScaffoldLeft; if ( nScaffold < 0 ) { // setContigScaffolds has determined that these contigs are not // displayed return( false ); } return( true ); } void assemblyView :: highlightRestrictionDigestFragments( const int nCursorPixelX, const int nCursorPixelY ) { if ( ( ConsEd::pGetConsEd()->aGuiDisplayDigest_.length() == 0 ) || !bShowDigest_ ) return; RWTPtrOrderedVector aOldHighlightedFragments( aCurrentlyHighlightedFragments_ ); aCurrentlyHighlightedFragments_.clear(); int nCursorPixelXLeft = nCursorPixelX - pCP->nAssemblyViewCursorSensitivityInPixels_/2; int nCursorPixelRight = nCursorPixelX + pCP->nAssemblyViewCursorSensitivityInPixels_/2; int nCursorPixelYTop = nCursorPixelY - pCP->nAssemblyViewCursorSensitivityInPixels_/2; int nCursorPixelYBottom = nCursorPixelY + pCP->nAssemblyViewCursorSensitivityInPixels_/2; for( int nWindow = 0; nWindow < ConsEd::pGetConsEd()->aGuiDisplayDigest_.length(); ++nWindow ) { guiDisplayDigest* pGuiDisplayDigest = ConsEd::pGetConsEd()->aGuiDisplayDigest_[ nWindow ]; // each digest window may have several enzyme domains. Display them all. for( int nEnzyme = 0; nEnzyme < pGuiDisplayDigest->aDigests_.length(); ++nEnzyme ) { digestForOneEnzyme* pDigestForOneEnzyme = pGuiDisplayDigest->aDigests_[ nEnzyme ]; // check if this is an enzyme that is not being displayed if ( pDigestForOneEnzyme->nAssemblyViewEnzymeLine_ < 0 ) continue; arrayOfRestrictionFragments* pPredictedFragmentsArray = &(pDigestForOneEnzyme->aPredictedResFragsByConsPos_ ); int nPredictedFragment; for( nPredictedFragment = 0; nPredictedFragment < pPredictedFragmentsArray->length(); ++nPredictedFragment ) { restrictionFragment* pResFrag = (*pPredictedFragmentsArray)[ nPredictedFragment ]; int nScaffold; int nScaffoldPosLeft; int nScaffoldPosRight; if ( !bIsFragmentDisplayed( pResFrag, nScaffold, nScaffoldPosLeft, nScaffoldPosRight ) ) continue; int nFragmentPixelXLeft = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPosLeft ); int nFragmentPixelXRight = nGetPixelXFromScaffoldPos( nScaffold, nScaffoldPosRight ); if ( !bIntervalsIntersect( nCursorPixelXLeft, nCursorPixelRight, nFragmentPixelXLeft, nFragmentPixelXRight ) ) continue; int nPixelYTop = nGetPixelYTopOfAreaForRestrictionDigestEnzyme( nScaffold, pResFrag->pDigestForOneEnzyme_->nAssemblyViewEnzymeLine_ ); int nPixelYBottom = nGetPixelYBottomOfAreaForRestrictionDigestEnzyme( nScaffold, pResFrag->pDigestForOneEnzyme_->nAssemblyViewEnzymeLine_ ); if ( !bIntervalsIntersect( nPixelYTop, nPixelYBottom, nCursorPixelYTop, nCursorPixelYBottom ) ) continue; // if reached here, the restriction digest cut site intersects // the area of tolerance of the cursor aCurrentlyHighlightedFragments_.insert( pResFrag ); } } // for( int nEnzyme = 0; } // for( int nWindow = 0; // for each cut site we have determined should be highlighted, see // if it is already highlighted for( int nFragment = 0; nFragment < aCurrentlyHighlightedFragments_.length(); ++nFragment ) { restrictionFragment* pResFrag = aCurrentlyHighlightedFragments_[ nFragment ]; bool bFound = false; int nOldFragment; for( nOldFragment = 0; nOldFragment < aOldHighlightedFragments.length() && !bFound; ++nOldFragment ) { if ( pResFrag == aOldHighlightedFragments[ nOldFragment ] ) { bFound = true; } } if ( !bFound ) { // this means it isn't currently highlighted, so highlight it drawRestrictionEnzymeFragment( pResFrag, true ); // bHighlight } } // for each old cut site, see if it needs to be unhighlighted for( int nOldFragment = 0; nOldFragment < aOldHighlightedFragments.length(); ++nOldFragment ) { restrictionFragment* pResFrag = aOldHighlightedFragments[ nOldFragment ]; bool bFound = false; for( int nNewCutSite = 0; nNewCutSite < aCurrentlyHighlightedFragments_.length() && !bFound; ++nNewCutSite ) { if ( pResFrag == aCurrentlyHighlightedFragments_[ nNewCutSite ] ) { bFound = true; } } if ( !bFound ) { // should no longer be highlighted, so unhighlight it drawRestrictionEnzymeFragment( pResFrag, false ); // bHighlight } } } void assemblyView :: displayHighlightedRestrictionDigestCutSites( RWCString& soMessage ) { if ( aCurrentlyHighlightedFragments_.length() == 0 ) return; soMessage.increaseMaxLengthIfNecessary( aCurrentlyHighlightedFragments_.length() * 100 ); for( int nFragment = 0; nFragment < aCurrentlyHighlightedFragments_.length(); ++nFragment ) { restrictionFragment* pResFrag = aCurrentlyHighlightedFragments_[ nFragment ]; soMessage += pResFrag->pDigestForOneEnzyme_->soEnzymeName_; soMessage += ": "; if ( pResFrag->bCombinedVectorAndInsertPartialFragments_ ) { soMessage += "vector/insert frag sz: "; soMessage += RWCString( (long) pResFrag->nSize_ ); soMessage += " "; } else { soMessage += "frag "; soMessage += " sz: "; soMessage += RWCString( (long) pResFrag->nSize_ ); soMessage += " "; } } } GuiColorText* assemblyView :: pGetGuiColorTextForRestrictionFragment( restrictionFragment* pResFrag, const bool bHighlight ) { if ( bHighlight ) { return pGctHighlight_; } else { if ( pResFrag->bIsProblemFragment() ) { return( GuiApp::pGetGuiApp()->pColorOfRestrictionFragmentPairTooFarApart_ ); } else { int nEnzymeLine = pResFrag->pDigestForOneEnzyme_->nAssemblyViewEnzymeLine_; assert( 0 <= nEnzymeLine && nEnzymeLine <= nMaxNumberOfRestrictionEnzymeLines ); return pGctConsistentRestrictionDigestFragment_[ nEnzymeLine ]; } } } int assemblyView :: nGetNumberOfDisplayedRestrictionEnzymes() { int nNumberOfEnzymeLinesDisplayed = 0; for( int nGuiDisplayDigest = 0; nGuiDisplayDigest < ConsEd::pGetConsEd()->aGuiDisplayDigest_.length(); ++nGuiDisplayDigest ) { guiDisplayDigest* pGuiDisplayDigest = ConsEd::pGetConsEd()->aGuiDisplayDigest_[ nGuiDisplayDigest ]; nNumberOfEnzymeLinesDisplayed += pGuiDisplayDigest->aDigests_.length(); } if ( nNumberOfEnzymeLinesDisplayed > nMaxNumberOfRestrictionEnzymeLines ) nNumberOfEnzymeLinesDisplayed = nMaxNumberOfRestrictionEnzymeLines; return( nNumberOfEnzymeLinesDisplayed ); }