/***************************************************************************** # 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 "oligoTag.h" #include "consed.h" #include "assembly.h" #include #include #include #include #include #include #include #include "hp_exception_kludge.h" #include #include "complement_so.h" #include "popupErrorMessage.h" #include "rwcregexp.h" #include "filename.h" #include "search_for_string.h" #include "searchMethods.h" #include "centerWidgetOnWidget.h" static void cbSearchForOligoBases( Widget wid, XtPointer pClientData, XtPointer pCallData ) { oligoTag* pOligoTag = (oligoTag*) pClientData; TRY_CATCH_WRAPPER( pOligoTag->searchForOligoBases() ); } void oligoTag :: writeToEditHistoryFileAnythingSpecialForThisTagType() { ConsEd :: pGetAssembly()->writeEditToEditHistoryFile( "{ %s %s %d %s\n%s\n}", soName_.data(), soBases_.data(), nMeltingTemperature_, ( bComplementedWithRespectToWayPhrapCreatedContig_ ? "C" : "U" ), soTemplates_.data() ); } // ctor used when getting info from ace file oligoTag :: oligoTag( Contig* pContig, const int nConsPosStart, const int nConsPosEnd, const RWCString& soSource, const RWCString& soDate, const bool bNoTrans, const RWCString& soName, const RWCString& soBases, const int nMeltingTemp, const bool bComplementedWithRespectToWayPhrapCreatedContig, const RWCString& soTemplates, const RWCString& soComment ) : tag( NULL, // LocatedFragment pContig, "oligo", nConsPosStart, nConsPosEnd, false, // bWriteToPhdFileNotAceFile since oligo tags are consensus tags soComment, soSource, soDate, bNoTrans ), soName_( soName ), soBases_( soBases ), nMeltingTemperature_( nMeltingTemp ), bComplementedWithRespectToWayPhrapCreatedContig_( bComplementedWithRespectToWayPhrapCreatedContig ), soTemplates_( soTemplates ) { // set everything else to 0 ucMinQuality_ = 0; ucMinQualityIn3Prime4Bases_ = 0; nScoreOfStickiestFalseMatch_ = 0; soContigOfStickiestFalseMatch_ = ""; nUnpaddedOfStickiestFalseMatch_ = 0; bContigOfStickiestFalseMatchIsComplemented_ = false; nSelfMatchScore_ = 0; nSelfMatchOffsetOfComplementedPrimer_ = 0; nSelfMatchPosOf3PrimeSubOligo_ = 0; nSequenceInFileStickiestScore_ = 0; nSequenceInFileSequenceNumber_ = 0; nSequenceInFileBasePosition_ = 0; bSequenceInFileIsComplemented_ = false; } oligoTag :: oligoTag( primerType* pPrimer, const bool bCloneNotSubcloneTemplate, const bool bComplementedWithRespectToWayPhrapCreatedContig, const int nPrimerID, const RWCString& soComment ) : tag( NULL, // LocatedFragment pPrimer->pContig_, "oligo", pPrimer->pContig_->nPaddedIndex( pPrimer->nUnpaddedStart_ ), pPrimer->pContig_->nPaddedIndex( pPrimer->nUnpaddedEnd_ ), false, // bWriteToPhdFileNotAceFile since oligo tags are consensus tags soComment, "consed", // soSource "", // current date false ), // bNoTrans bComplementedWithRespectToWayPhrapCreatedContig_( bComplementedWithRespectToWayPhrapCreatedContig ) { if ( nPrimerID == -1 ) soName_ = ConsEd::pGetAssembly()->soGetNextOligoName(); else soName_ = ConsEd::pGetAssembly()->soGetOligoNameFromOligoNumber( nPrimerID ); // in the case of reverse primer, from right to // left and complemented RWCString soTemp( pPrimer->szPrimer_, (size_t) pPrimer->nUnpaddedLength_ ); soBases_ = soTemp; nMeltingTemperature_ = (int) ( pPrimer->dMeltingTemperature_ + .5); ucMinQuality_ = pPrimer->ucMinQuality_; ucMinQualityIn3Prime4Bases_ = pPrimer->ucMinQualityIn3Prime4Bases_; nScoreOfStickiestFalseMatch_ = pPrimer->nScoreOfStickiestFalseMatch_; if ( pPrimer->pContigOfStickiestFalseMatch_ ) { soContigOfStickiestFalseMatch_ = pPrimer->pContigOfStickiestFalseMatch_->soGetName(); } nUnpaddedOfStickiestFalseMatch_ = pPrimer->nUnpaddedOfStickiestFalseMatch_; bContigOfStickiestFalseMatchIsComplemented_ = pPrimer->bContigOfStickiestFalseMatchIsComplemented_; nSelfMatchScore_ = pPrimer->nSelfMatchScore_; nSelfMatchOffsetOfComplementedPrimer_ = pPrimer->nSelfMatchOffsetOfComplementedPrimer_; nSelfMatchPosOf3PrimeSubOligo_ = pPrimer->nSelfMatchPosOf3PrimeSubOligo_; nSequenceInFileStickiestScore_ = pPrimer->nSequenceInFileStickiestScore_; nSequenceInFileSequenceNumber_ = pPrimer->nSequenceInFileSequenceNumber_; nSequenceInFileBasePosition_ = pPrimer->nSequenceInFileBasePosition_; bSequenceInFileIsComplemented_ = pPrimer->bSequenceInFileIsComplemented_; if ( bCloneNotSubcloneTemplate ) soTemplates_ = "clone"; else { soTemplates_ = ""; bool bFirstTime = true; for( int n = 0; n < nNUMBER_OF_TEMPLATES; ++n ) { if ( pPrimer->pSubcloneTemplate_[n] ) { if ( bFirstTime ) bFirstTime = false; else soTemplates_ += " "; soTemplates_ += pPrimer->pSubcloneTemplate_[n]->soTemplateName_; } } } } static const int nRightPositionOfLabels = 60; static const int nLeftPositionOfInputFields = 65; #define displayTagItem( parameterName, labelToDisplay, printfFormat ) \ \ Widget wid ## parameterName ## Form = XtVaCreateManagedWidget( "form", \ xmFormWidgetClass, \ widRowCol,\ XmNshadowThickness, 0,\ NULL );\ \ Widget wid ## parameterName ## Label = XtVaCreateManagedWidget( \ labelToDisplay, \ xmLabelWidgetClass, \ wid ## parameterName ## Form, \ XmNtopAttachment, XmATTACH_FORM, \ XmNbottomAttachment, XmATTACH_FORM, \ XmNleftAttachment, XmATTACH_FORM, \ XmNrightAttachment, XmATTACH_POSITION, \ XmNrightPosition, nRightPositionOfLabels, \ XmNalignment, XmALIGNMENT_END, \ NULL ); \ \ char sz ## parameterName[200]; \ sprintf( sz ## parameterName, printfFormat, \ parameterName ); \ \ \ Widget wid ## parameterName = XtVaCreateManagedWidget( \ #parameterName, \ xmTextFieldWidgetClass, \ wid ## parameterName ## Form, \ XmNtraversalOn, True, \ XmNtopAttachment, XmATTACH_FORM, \ XmNbottomAttachment, XmATTACH_FORM, \ XmNleftAttachment, XmATTACH_POSITION, \ XmNleftPosition, nLeftPositionOfInputFields, \ XmNrightAttachment, XmATTACH_FORM, \ XmNeditable, False, \ XmNcursorPositionVisible, False, \ XmNtraversalOn, False, \ XmNvalue, sz ## parameterName, \ NULL ); \ \ XtAddCallback( wid ## parameterName, \ XmNactivateCallback, \ (XtCallbackProc )XmProcessTraversal, \ (XtPointer) XmTRAVERSE_NEXT_TAB_GROUP ); void oligoTag :: guiDisplayExtraInformation( Widget widForm, Widget widAbove, Widget widBelow, bool& bExtraStuffDisplayed, Widget& widBottomOfExtraStuff ) { int nArgs; Arg aArg[50]; Widget widRowCol = XtVaCreateManagedWidget( "rowcol", xmRowColumnWidgetClass, widForm, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, widAbove, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, // XmNbottomAttachment, XmATTACH_WIDGET, // XmNbottomWidget, widBelow, XmNbottomOffset, 20, XmNorientation, XmVERTICAL, XmNnumColumns, 1, XmNpacking, XmPACK_COLUMN, NULL ); char* szName = (char*) soName_.data(); displayTagItem( szName, "Oligo name", "%s" ); char* szBases = (char*) soBases_.data(); displayTagItem( szBases, "oligo bases", "%s" ); bool bPrimerComplemented = bComplementedWithRespectToWayPhrapCreatedContig_; if ( pContig_->bIsComplementedFromWayPhrapCreated() ) bPrimerComplemented = !bPrimerComplemented; char* szOrientation = (char*) (bPrimerComplemented ? "<--" : "-->" ); displayTagItem( szOrientation, "orientation:", "%s" ); displayTagItem( nMeltingTemperature_, "melting temp", "%d" ); // char* szTemplates = (char*) soTemplates_.data(); // displayTagItem( szTemplates, "templates:", "%s" ); Widget widTemplatesForm = XtVaCreateManagedWidget( "form", xmFormWidgetClass, widRowCol, XmNshadowThickness, 0, NULL ); Widget widTemplatesLabel = XtVaCreateManagedWidget( "templates", xmLabelWidgetClass, widTemplatesForm, XmNtopAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_FORM, NULL ); Widget widTemplates = XtVaCreateManagedWidget( "templates", xmTextFieldWidgetClass, \ widTemplatesForm, XmNtraversalOn, True, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment, XmATTACH_WIDGET, XmNleftWidget, widTemplatesLabel, XmNrightAttachment, XmATTACH_FORM, XmNeditable, False, XmNcursorPositionVisible, False, XmNtraversalOn, False, XmNvalue, (char*) soTemplates_.data(), NULL ); XtAddCallback( widTemplates, XmNactivateCallback, (XtCallbackProc )XmProcessTraversal, (XtPointer) XmTRAVERSE_NEXT_TAB_GROUP ); Widget widSearchForOligoBasesForm = XtVaCreateManagedWidget( "form", xmFormWidgetClass, widRowCol, XmNshadowThickness, 0, NULL ); Widget widSearchForOligoBases = XtVaCreateManagedWidget( "search for oligo bases", xmPushButtonWidgetClass, widSearchForOligoBasesForm, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL ); // using widForm because widSearchForOligoBasesForm has width zero // at this point (probably resizes after pops up) centerWidgetOnWidget( widSearchForOligoBases, widForm ); XtAddCallback( widSearchForOligoBases, XmNactivateCallback, cbSearchForOligoBases, this ); // displayTagItem( ucMinQuality_, "min quality in oligo:", "%d" ); // displayTagItem( nScoreOfStickiestFalseMatch_, "max false anneal score:", // "%d" ); // char* szContig = (char*) soContigOfStickiestFalseMatch_.data(); // displayTagItem( szContig, "contig where max false anneal:", "%s" ); // displayTagItem( nUnpaddedOfStickiestFalseMatch_, "cons pos of false anneal:", // "%d" ); // char* szContigIsComplemented = bContigOfStickiestFalseMatchIsComplemented_ ? // "yes" : "no"; // displayTagItem( szContigIsComplemented, // "Is false anneal to complemented contig?", // "%s" ); // displayTagItem( nSelfMatchScore_, "self-anneal score", "%d" ); // displayTagItem( nSelfMatchOffsetOfComplementedPrimer_, // "offset of comp primer where max self-anneal score", "%d" ); // displayTagItem( nSelfMatchPosOf3PrimeSubOligo_, // "suboligo pos w/i primer where max self-anneal", "%d" ); // displayTagItem( nSequenceInFileStickiestScore_, // "max of anneal to vector", "%d" ); // displayTagItem( nSequenceInFileSequenceNumber_, // "vector seq # of max anneal", "%d" ); // displayTagItem( nSequenceInFileBasePosition_, // "base pos in vector where anneal", "%d" ); // char* szContigIsComplemented2 = bSequenceInFileIsComplemented_ ? // "yes" : "no"; // displayTagItem( szContigIsComplemented2, // "vector seq is complemented?", "%s" ); // char* szVectorFileUsed = "SubcloneVectorFile.seq"; // displayTagItem( szVectorFileUsed, // "vector file", "%s" ); widBottomOfExtraStuff = widRowCol; bExtraStuffDisplayed = true; } void oligoTag :: writeToAceFileAnythingSpecialForThisTagType( ofstream& ofsAceFile ) { ofsAceFile << soName_ << " " << soBases_ << " " << nMeltingTemperature_ << " " << ( bComplementedWithRespectToWayPhrapCreatedContig_ ? "C" : "U" ) << endl << soTemplates_ << endl; } const int nSIZE_OF_COMMENT_FIELD = 18; RWCString oligoTag :: soGetExtraInformationForNavigator(const int nMaxLength ) { RWCString soDescription( (size_t) 1000 ); soDescription = soComment_.soPadOrTruncate( nSIZE_OF_COMMENT_FIELD ); soDescription += " "; // tricky and dangerous soDescription.nCurrentLength_ += sprintf( soDescription.sz_ + soDescription.nCurrentLength_, "%-15s %-15s", soName_.data(), soTemplates_.data() ); // remove trailing blanks, often inserted by the sprintf above soDescription = soDescription.strip( RWCString::TRAILING ); if ( soDescription.length() <= nMaxLength ) return( soDescription ); else { if ( nMaxLength < 4 ) return( "" ); else return( soDescription(0, nMaxLength - 3 ) + "..." ); } } void oligoTag :: writeToEditHistoryFileAnythingSpecialForThisTagTypeForDeleteTag() { ConsEd :: pGetAssembly()->writeEditToEditHistoryFile( "{ %s %s %d %s\n%s\n}", soName_.data(), soBases_.data(), nMeltingTemperature_, ( bComplementedWithRespectToWayPhrapCreatedContig_ ? "C" : "U" ), soTemplates_.data() ); } bool oligoTag :: bIsThisThe3PrimeEnd( const int nConsPos ) { bool bPrimerComplemented = bComplementedWithRespectToWayPhrapCreatedContig_; if ( pContig_->bIsComplementedFromWayPhrapCreated() ) bPrimerComplemented = !bPrimerComplemented; if ( bPrimerComplemented ) { if ( nConsPos == nPaddedConsPosStart_ ) return( true ); } else { if ( nConsPos == nPaddedConsPosEnd_ ) return( true ); } return( false ); } gotoItem* oligoTag :: pGetGotoItemForThisTag() { int nUnpaddedConsPosStart = pContig_->nUnpaddedIndex( nPaddedConsPosStart_ ); int nUnpaddedConsPosEnd = pContig_->nUnpaddedIndex( nPaddedConsPosEnd_ ); const int nMaxLengthForDescription = 1000; RWCString soDescription = soGetExtraInformationForNavigator( nMaxLengthForDescription ); // is this code path ever taken? if ( soDescription.isNull() ) { char szTemp[500]; sprintf( szTemp, "%6d %s", ( nUnpaddedConsPosEnd - nUnpaddedConsPosStart + 1 ), "oligo" ); soDescription = szTemp; } gotoItem* pGotoItem = new gotoItem( pContig_, pLocFrag_, nPaddedConsPosStart_, nPaddedConsPosEnd_, nUnpaddedConsPosStart, nUnpaddedConsPosEnd, soDescription ); return pGotoItem; } void oligoTag :: searchForOligoBases() { // what are the bases? Let's use soBases_ from the tag since // presumably that is what the tag is made of. Warn user if these // bases don't match the position. // guess at the singlets filename FileName filSingletsFile = ConsEd::pGetAssembly()->soGetAceFileName(); // chop off everything starting with .fasta.screen. RWCRegexp regFasta( "\\.fasta\\.screen\\..*$" ); filSingletsFile( regFasta ) = ""; filSingletsFile += ".fasta.screen.singlets"; popupOutputWindowAndDoSearch( this->soBases_, nExact, // search method ignored true, // search contigs, not reads 0, // per cent mismatch ignored filSingletsFile ); // check if bases mismatch Contig* pContig = this->pContig_; RWCString soConsensusBases; pContig->getPartOfConsensus( this->nPaddedConsPosStart_, this->nPaddedConsPosEnd_ - this->nPaddedConsPosStart_ + 1, soConsensusBases ); // get rid of pads soConsensusBases.removeSingleCharacterAllOccurrences( '*' ); if ( this->soBases_ != soConsensusBases ) { if ( this->soBases_ != soComplementSO( soConsensusBases ) ) { RWCString soErrorMessage = "warning: oligo bases " + this->soBases_ + " do not match the sequence bases which are " + soConsensusBases + " in either orientation. Will search with "+ this->soBases_; popupErrorMessage( soErrorMessage ); } } }