/***************************************************************************** # 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 "pickPCRPrimers.h" #include "contig.h" #include "createPrimerCandidates.h" #include "findPrimerMatchesElsewhere.h" #include "findPrimerSelfMatches.h" #include "whichPrimersAreAcceptable.h" #include "findPrimerMatchesAgainstSequencesInFile.h" #include "copyPrimerMatchesFromShorterToLongerPrimers.h" #include "consedParameters.h" #include "checkPrimersForMononucleotideRepeats.h" #include "assembly.h" #include "matchScores.h" #include "consed.h" #include "calculatePrimerMeltingTemperatures.h" #include "popupErrorMessage.h" #include "textbox.h" #include "whyIsPrimerNotAcceptableTypes.h" #include "please_wait.h" #include "contigwin.h" #include "guicontigwin.h" #include "popupInfoMessage.h" #include "guiMultiContigNavigator.h" #include "oligoTag.h" #include "editAddConsensusTag.h" #include "groupOfPrimers.h" #include "bIsPCRPrimerPairOK.h" #include "checkPrimersForACGT.h" #include "bIsPrimerStale.h" static void acceptPrimerPair( const gotoItem* pGotoItem, void* pPickPCRPrimersVoid ) { pickPCRPrimers* pPCR = (pickPCRPrimers*) pPickPCRPrimersVoid; pPCR->acceptPrimerPair2( pGotoItem ); } pickPCRPrimers :: pickPCRPrimers( Contig* pContig, const int nConsPos, const bool bTopStrandNotBottomStrand, ContigWin* pContigWin ) : pContigWin1_( pContigWin ), pContigForFirstPCRPrimer_( pContig ), nConsPosForFirstPCRPrimer_( nConsPos ), bTopStrandNotBottomStrandForFirstPCRPrimer_( bTopStrandNotBottomStrand ), pFirstPrimerArray_( 0 ), pSecondPrimerArray_( 0 ), nNumberOfFirstPrimers_( 0 ), nNumberOfSecondPrimers_( 0 ), nNumberOfAcceptableFirstPrimers_( 0 ), nNumberOfAcceptableSecondPrimers_( 0 ), pGuiMultiContigNav_( 0 ) { PleaseWait* pPleaseWait = new PleaseWait( pContigWin1_->pGcw_->widGetGuiContigWinTopLevel() ); // pick two lists of whole clone reads ConsEd::pGetAssembly()->setContigMatchTablesInAllContigs(); ConsEd::pGetAssembly()->setAllPaddedPositionsArrays(); pCP->setParametersForSequencingPrimersNotPCRPrimers( false ); createPrimerCandidates( pContigForFirstPCRPrimer_, nConsPosForFirstPCRPrimer_, bTopStrandNotBottomStrandForFirstPCRPrimer_, &pFirstPrimerArray_, nNumberOfFirstPrimers_ ); findPrimerMatchesElsewhere( pFirstPrimerArray_, nNumberOfFirstPrimers_, bTopStrandNotBottomStrandForFirstPCRPrimer_, true ); // bCloneNotSubcloneTemplate if (consedParameters::pGetConsedParameters()->bPrimersScreenForVector_ ) { findPrimerMatchesAgainstSequencesInFile( pFirstPrimerArray_, nNumberOfFirstPrimers_, true ); // bCloneNotSubcloneTemplate } copyPrimerMatchesFromShorterToLongerPrimers( pFirstPrimerArray_, nNumberOfFirstPrimers_, bTopStrandNotBottomStrandForFirstPCRPrimer_ ); calculatePrimerMeltingTemperatures( pFirstPrimerArray_, nNumberOfFirstPrimers_ ); findPrimerSelfMatches( pFirstPrimerArray_, nNumberOfFirstPrimers_ ); checkPrimersForMononucleotideRepeats( pFirstPrimerArray_, nNumberOfFirstPrimers_, nNumberOfAcceptableFirstPrimers_ ); checkPrimersForACGT( pFirstPrimerArray_, nNumberOfFirstPrimers_, nNumberOfAcceptableFirstPrimers_ ); whichPrimersAreAcceptable( pFirstPrimerArray_, nNumberOfFirstPrimers_, nNumberOfAcceptableFirstPrimers_ ); delete pPleaseWait; if ( nNumberOfAcceptableFirstPrimers_ == 0 ) { displayErrorMessageIfNoPrimersFound( pFirstPrimerArray_, nNumberOfFirstPrimers_, "Sorry--there are no acceptable first primers so \nthere won't be any PCR primer pairs\n" ); delete this; return; } else { popupInfoMessage( pContigWin1_->pGcw_->widGetGuiContigWinTopLevel(), "Now Pick 2nd PCR Primer\n\nFound %d first PCR primers\nGo to the location for the 2nd PCR primer, press down the right mouse button and release either on \"pick top strand Second PCR primer\" \nor on \n\"pick bottom strand Second PCR primer\"", nNumberOfAcceptableFirstPrimers_ ); } pCP->bReadyToPickSecondPCRPrimer_ = true; } void pickPCRPrimers :: userPickedSecondPCRPrimerSite( Contig* pContigForSecondPCRPrimer, const int nConsPosForSecondPCRPrimer, const bool bTopStrandNotBottomStrandForSecondPCRPrimer, ContigWin* pContigWin ) { pContigWin2_ = pContigWin; PleaseWait* pPleaseWait = new PleaseWait( pContigWin->pGcw_->widGetGuiContigWinTopLevel() ); // whatever happens, whether successful or fails, // set this so that the user can start over pCP->bReadyToPickSecondPCRPrimer_ = false; pContigForSecondPCRPrimer_ = pContigForSecondPCRPrimer; nConsPosForSecondPCRPrimer_ = nConsPosForSecondPCRPrimer; bTopStrandNotBottomStrandForSecondPCRPrimer_ = bTopStrandNotBottomStrandForSecondPCRPrimer; pCP->pPickPCRPrimers_ = NULL; // now find array of second primers pCP->setParametersForSequencingPrimersNotPCRPrimers( false ); createPrimerCandidates( pContigForSecondPCRPrimer_, nConsPosForSecondPCRPrimer, bTopStrandNotBottomStrandForSecondPCRPrimer_, &pSecondPrimerArray_, nNumberOfSecondPrimers_ ); findPrimerMatchesElsewhere( pSecondPrimerArray_, nNumberOfSecondPrimers_, bTopStrandNotBottomStrandForSecondPCRPrimer_, true ); // bCloneNotSubcloneTemplate if (consedParameters::pGetConsedParameters()->bPrimersScreenForVector_ ) { findPrimerMatchesAgainstSequencesInFile( pSecondPrimerArray_, nNumberOfSecondPrimers_, true ); // bCloneNotSubcloneTemplate } copyPrimerMatchesFromShorterToLongerPrimers( pSecondPrimerArray_, nNumberOfSecondPrimers_, bTopStrandNotBottomStrandForSecondPCRPrimer_ ); calculatePrimerMeltingTemperatures( pSecondPrimerArray_, nNumberOfSecondPrimers_ ); findPrimerSelfMatches( pSecondPrimerArray_, nNumberOfSecondPrimers_ ); checkPrimersForMononucleotideRepeats( pSecondPrimerArray_, nNumberOfSecondPrimers_, nNumberOfAcceptableSecondPrimers_ ); checkPrimersForACGT( pSecondPrimerArray_, nNumberOfSecondPrimers_, nNumberOfAcceptableSecondPrimers_ ); whichPrimersAreAcceptable( pSecondPrimerArray_, nNumberOfSecondPrimers_, nNumberOfAcceptableSecondPrimers_ ); delete pPleaseWait; if ( nNumberOfAcceptableSecondPrimers_ == 0 ) { displayErrorMessageIfNoPrimersFound( pSecondPrimerArray_, nNumberOfSecondPrimers_, "Sorry--there are no acceptable second primers so there won't be any PCR primer pairs\n" ); delete this; return; } // break them into groups RWTPtrOrderedVector aGroupOfFirstPCRPrimers_; RWTPtrOrderedVector aGroupOfSecondPCRPrimers_; dividePrimersIntoGroups( aGroupOfFirstPCRPrimers_, pFirstPrimerArray_, nNumberOfFirstPrimers_ ); dividePrimersIntoGroups( aGroupOfSecondPCRPrimers_, pSecondPrimerArray_, nNumberOfSecondPrimers_ ); // for( int nGroup = 0; nGroup < aGroupOfFirstPCRPrimers_.length(); ++nGroup ) { // groupOfPrimersForPCR* pGroup1 = aGroupOfFirstPCRPrimers_[ nGroup ]; // printf( "group from index %d to %d and from unpadded %d to %d with starting unpadded %d\n", // pGroup1->nStartIndex_, // pGroup1->nEndIndex_, // pGroup1->nRangeLeft_, // pGroup1->nRangeRight_, // pGroup1->nLeftMostUnpaddedConsPos_ ); // } // printf( "second pcr primers:\n" ); // for( nGroup = 0; nGroup < aGroupOfSecondPCRPrimers_.length(); ++nGroup ) { // groupOfPrimersForPCR* pGroup2 = aGroupOfSecondPCRPrimers_[ nGroup ]; // printf( "with group from index %d to %d and from unpadded %d to %d with starting unpadded %d\n", // pGroup2->nStartIndex_, // pGroup2->nEndIndex_, // pGroup2->nRangeLeft_, // pGroup2->nRangeRight_, // pGroup2->nLeftMostUnpaddedConsPos_ ); // } // now compare them, finding the best 100 pairs printf( "nNumberOfAcceptableFirstPrimers_ = %d and nNumberOfAcceptableSecondPrimers_ = %d\n", nNumberOfAcceptableFirstPrimers_, nNumberOfAcceptableSecondPrimers_ ); aAcceptablePCRPrimerPairs_.resize( aGroupOfFirstPCRPrimers_.length() * aGroupOfSecondPCRPrimers_.length() * pCP->nPrimersLookForThisManyPCRPrimerPairsPerPairOfGroups_ ); // now compare each window of first PCR primers to each window // of second PCR primers nPairsTried_ = 0; nTempDiffTooGreat_ = 0; nPrimersStickToEachOther_ = 0; nPairsOK_ = 0; for( int nGroup1 = 0; nGroup1 < aGroupOfFirstPCRPrimers_.length(); ++nGroup1 ) { for( int nGroup2 = 0; nGroup2 < aGroupOfSecondPCRPrimers_.length(); ++nGroup2 ) { groupOfPrimersForPCR* pGroup1 = aGroupOfFirstPCRPrimers_[ nGroup1 ]; groupOfPrimersForPCR* pGroup2 = aGroupOfSecondPCRPrimers_[ nGroup2 ]; findAcceptablePrimersInThisPairOfGroups( pGroup1, pGroup2 ); } } if ( aAcceptablePCRPrimerPairs_.length() == 0 ) { popupErrorMessage( "Sorry--of the %d pairs of acceptable primers, there were none that were compatible. %d did not have compatible melting temperatures and %d stuck to each other", nPairsTried_, nTempDiffTooGreat_, nPrimersStickToEachOther_ ); delete this; return; } // if reached here, there are some acceptable PCR primer pairs printf( "primer pairs found: %d\n", nPairsOK_ ); displayAcceptablePCRPrimerPairs(); } pickPCRPrimers :: ~pickPCRPrimers() { // deallocate arrays free( pFirstPrimerArray_ ); free( pSecondPrimerArray_ ); if ( pGuiMultiContigNav_ ) { pGuiMultiContigNav_->popDownAndDestroy(); } } void pickPCRPrimers :: addPCRPrimerPairIfPossible( primerType* pFirstPCRPrimer, primerType* pSecondPCRPrimer ) { if ( aAcceptablePCRPrimerPairs_.length() >= pCP->nPrimersMaxPCRPrimerPairsToDisplay_ ) return; int nDistance; if ( pContigForFirstPCRPrimer_ == pContigForSecondPCRPrimer_ ) { int n3PrimeBaseOfPrimer1 = pFirstPCRPrimer->bTopStrandNotBottomStrand_ ? pFirstPCRPrimer->nUnpaddedEnd_ : pFirstPCRPrimer->nUnpaddedStart_; int n3PrimeBaseOfPrimer2 = pSecondPCRPrimer->bTopStrandNotBottomStrand_ ? pSecondPCRPrimer->nUnpaddedEnd_ : pSecondPCRPrimer->nUnpaddedStart_; nDistance = ABS( n3PrimeBaseOfPrimer1 - n3PrimeBaseOfPrimer2 ); } else { int nPrimer1DistanceToEndOfContig1; if ( pFirstPCRPrimer->bTopStrandNotBottomStrand_ ) { nPrimer1DistanceToEndOfContig1 = pContigForFirstPCRPrimer_->nGetUnpaddedEndIndex() - pFirstPCRPrimer->nUnpaddedEnd_; } else { nPrimer1DistanceToEndOfContig1 = pFirstPCRPrimer->nUnpaddedStart_; } int nPrimer2DistanceToEndOfContig2; if ( pSecondPCRPrimer->bTopStrandNotBottomStrand_ ) { nPrimer2DistanceToEndOfContig2 = pContigForSecondPCRPrimer_->nGetUnpaddedEndIndex() - pSecondPCRPrimer->nUnpaddedEnd_; } else { nPrimer2DistanceToEndOfContig2 = pSecondPCRPrimer->nUnpaddedStart_; } nDistance = nPrimer1DistanceToEndOfContig1 + nPrimer2DistanceToEndOfContig2 + pCP->nAutoFinishNumberOfBasesBetweenContigsAssumed_; } pcrPrimerPair* pPCR = new pcrPrimerPair( pFirstPCRPrimer, pSecondPCRPrimer, nDistance ); aAcceptablePCRPrimerPairs_.insert( pPCR ); } void pickPCRPrimers :: displayErrorMessageIfNoPrimersFound( primerType* pPrimerArray, const int nNumberOfPrimers, const RWCString& soAdditionalErrorMessage ) { int nPrimersStickToSequenceInFiles = 0; int nPrimersStickToSomewhereElse = 0; int nPrimersStickToSelf = 0; int nPrimersMeltingTemperatureTooLow = 0; int nPrimersMeltingTemperatureTooHigh = 0; int nPrimersTooLowQuality = 0; int nPrimersWithMononucleotideRepeat = 0; int nPrimersWithNoTemplate = 0; int nUnacceptablePrimers = 0; for( int nPrimer = 0; nPrimer < nNumberOfPrimers; ++nPrimer ) { primerType* pPrimer = pPrimerArray + nPrimer; if (! pPrimer->bAcceptable_ ) { ++nUnacceptablePrimers; switch( pPrimer->nWhyIsPrimerNotAcceptable_ ) { case BAD_PRIMER_STICKS_TO_SEQUENCE_IN_FILE: ++nPrimersStickToSequenceInFiles; break; case BAD_PRIMER_STICKS_TO_SOMEWHERE_ELSE: ++nPrimersStickToSomewhereElse; break; case BAD_PRIMER_STICKS_TO_SELF: ++nPrimersStickToSelf; break; case BAD_PRIMER_MELTING_TEMPERATURE_TOO_LOW: ++nPrimersMeltingTemperatureTooLow; break; case BAD_PRIMER_MELTING_TEMPERATURE_TOO_HIGH: ++nPrimersMeltingTemperatureTooHigh; break; case BAD_PRIMER_TOO_LOW_QUALITY: ++nPrimersTooLowQuality; break; case BAD_PRIMER_MONONUCLEOTIDE_REPEAT: ++nPrimersWithMononucleotideRepeat; break; case BAD_PRIMER_HAS_NO_TEMPLATE: ++nPrimersWithNoTemplate; break; } } } TextBox* pTextBox = new TextBox("Why There Are No Acceptable Primers", 20 ); pTextBox->append( soAdditionalErrorMessage ); pTextBox->append("\n\n\n" ); pTextBox->append("You may want to relax the primer picking requirements.\nTo do this, in the main window, click on\nOptions/Primer Picking Preferences\nConsider raising the PrimersMaxLengthOfMononucleotideRepeat\nConsider increasing the PrimersMaxMatchElsewhereScore. If you do choose to increase the PrimersMaxMatchElsewhereScore, and you find primers, see the xterm for the alignments of those primers against possible false priming sites.\n\n\n" ); pTextBox->appendWithArgs("primers tried: %d\n", nNumberOfPrimers ); pTextBox->appendWithArgs("primers anneal to sequences in file: %6.2f%%\n", (float) nPrimersStickToSequenceInFiles * 100 / nNumberOfPrimers ); pTextBox->appendWithArgs( "primers too low quality: %6.2f%%\n", (float) nPrimersTooLowQuality * 100 / nNumberOfPrimers ); pTextBox->appendWithArgs( "primers anneal to somewhere else in assembly: %6.2f%%\n", (float) nPrimersStickToSomewhereElse * 100 / nNumberOfPrimers ); pTextBox->appendWithArgs( "primers anneal to self: %6.2f%%\n", (float) nPrimersStickToSelf * 100 / nNumberOfPrimers ); pTextBox->appendWithArgs( "primers melting temp too low: %6.2f%%\n", (float) nPrimersMeltingTemperatureTooLow * 100 / nNumberOfPrimers ); pTextBox->appendWithArgs( "primers melting temp too high: %6.2f%%\n", (float) nPrimersMeltingTemperatureTooHigh * 100 / nNumberOfPrimers ); pTextBox->appendWithArgs( "primers with mononucleotide repeats: %6.2f%%\n", (float) nPrimersWithMononucleotideRepeat * 100 / nNumberOfPrimers ); pTextBox->appendWithArgs( "primers with no template: %6.2f%%\n", (float) nPrimersWithNoTemplate * 100 / nNumberOfPrimers ); pTextBox->makeVisible(); } void pickPCRPrimers :: displayAcceptablePCRPrimerPairs() { RWCString soColumnHeadings1 = "pair distance primer1 primer2 melting primer1 primer2"; RWCString soColumnHeadings2 = "# between contig left right contig left right p1 p2"; pGuiMultiContigNav_ = new guiMultiContigNavigator( "PCR Primer Pairs", soColumnHeadings1, soColumnHeadings2, 100, "Accept Pair", acceptPrimerPair, (void*) this, pContigWin2_->pGcw_->widGetGuiContigWinTopLevel(), NULL, // pGotoList NULL ); for( int nPrimerPair = 0; nPrimerPair < aAcceptablePCRPrimerPairs_.length(); ++nPrimerPair ) { pcrPrimerPair* pPCR = aAcceptablePCRPrimerPairs_[ nPrimerPair ]; primerType* pPrimer1 = pPCR->pPrimer1_; primerType* pPrimer2 = pPCR->pPrimer2_; RWCString soDescription( (size_t) 1000 ); soDescription.nCurrentLength_ = sprintf( soDescription.sz_, "%3d %5d %9s %6d %6d %9s %6d %6d %d %d ", nPrimerPair + 1, // want this to start at 1 pPCR->nDistance_, pPrimer1->pContig_->soGetName().data(), pPrimer1->nUnpaddedStart_, pPrimer1->nUnpaddedEnd_, pPrimer2->pContig_->soGetName().data(), pPrimer2->nUnpaddedStart_, pPrimer2->nUnpaddedEnd_, (int) pPrimer1->dMeltingTemperature_, (int) pPrimer2->dMeltingTemperature_ ); int n; for( n = 0; n < pPrimer1->nUnpaddedLength_; ++n ) soDescription.append( pPrimer1->szPrimer_[ n ] ); soDescription.append( " " ); for( n = 0; n < pPrimer2->nUnpaddedLength_; ++n ) soDescription.append( pPrimer2->szPrimer_[ n ] ); RWCString soDescription2( (size_t) 1000 ); soDescription2.nCurrentLength_ = sprintf( soDescription2.data(), " primer1: %2d %2d %2d %2d primer2: %2d %2d %2d %2d", pPrimer1->nSelfMatchScore_, pPrimer1->nScoreOfStickiestFalseMatch_, pPrimer1->nSequenceInFileStickiestScore_, (int) pPrimer1->ucMinQuality_, pPrimer2->nSelfMatchScore_, pPrimer2->nScoreOfStickiestFalseMatch_, pPrimer2->nSequenceInFileStickiestScore_, (int) pPrimer2->ucMinQuality_ ); soDescription += soDescription2; int nPaddedConsPosStart = pPrimer1->pContig_->nPaddedIndexFast( pPrimer1->nUnpaddedStart_ ); int nPaddedConsPosEnd = pPrimer1->pContig_->nPaddedIndexFast( pPrimer1->nUnpaddedEnd_ ); gotoItem* pGotoItem = new gotoItem( pPrimer1->pContig_, NULL, // LocatedFragment nPaddedConsPosStart, nPaddedConsPosEnd, pPrimer1->nUnpaddedStart_, pPrimer1->nUnpaddedEnd_, soDescription.data(), false, // do not prefix consensus to description (void*) pPCR ); pGuiMultiContigNav_->appendToList( pGotoItem ); } pGuiMultiContigNav_->displayList( false ); // don't re-sort the primers } void pickPCRPrimers :: acceptPrimerPair2( const gotoItem* pGotoItem ) { pcrPrimerPair* pPCR = (pcrPrimerPair*) pGotoItem->pOtherData_; primerType* pPrimer1 = pPCR->pPrimer1_; primerType* pPrimer2 = pPCR->pPrimer2_; // check that both primers still point to the original memory RWCString soErrorMessage; if ( bIsPrimerStale( pPrimer1, soErrorMessage ) ) { popupErrorMessage( soErrorMessage ); return; } if ( bIsPrimerStale( pPrimer2, soErrorMessage ) ) { popupErrorMessage( soErrorMessage ); return; } // create oligo tags for both of these primers RWCString soTagComment( (size_t) 2000); soTagComment.nCurrentLength_ = sprintf( soTagComment.sz_, "pcr primer pair with primers at \n%s %d to %d with sequence\n", pPrimer1->pContig_->soGetName().data(), pPrimer1->nUnpaddedStart_, pPrimer1->nUnpaddedEnd_ ); int n; for( n = 0; n < pPrimer1->nUnpaddedLength_; ++n ) { soTagComment.append( pPrimer1->szPrimer_[ n ] ); } soTagComment.append( '\n' ); soTagComment.nCurrentLength_ += sprintf( soTagComment.sz_ + soTagComment.nCurrentLength_, "and at \n%s %d to %d with sequence\n", pPrimer2->pContig_->soGetName().data(), pPrimer2->nUnpaddedStart_, pPrimer2->nUnpaddedEnd_ ); for( n = 0; n < pPrimer2->nUnpaddedLength_; ++n ) { soTagComment.append( pPrimer2->szPrimer_[ n ] ); } bool bPrimer1ComplementedWithRespectToWayPhrapCreatedContig = ! pPrimer1->bTopStrandNotBottomStrand_; if ( pPrimer1->pContig_->bIsComplementedFromWayPhrapCreated() ) bPrimer1ComplementedWithRespectToWayPhrapCreatedContig = ! bPrimer1ComplementedWithRespectToWayPhrapCreatedContig; oligoTag* pOligo1Tag = new oligoTag( pPrimer1, true, // clone template, not subclone template bPrimer1ComplementedWithRespectToWayPhrapCreatedContig, -1 , // create new oligo name soTagComment ); EditAction* pEditAction1 = new editAddConsensusTag( pOligo1Tag ); // the edit action, once formed, goes all the way up to // the consed. any in-between objects will get notified // on the way back down by the refresh message (if the edit // completes successfully ConsEd::pGetConsEd()->doEditAction( pEditAction1, true ); bool bPrimer2ComplementedWithRespectToWayPhrapCreatedContig = ! pPrimer2->bTopStrandNotBottomStrand_; if ( pPrimer2->pContig_->bIsComplementedFromWayPhrapCreated() ) bPrimer2ComplementedWithRespectToWayPhrapCreatedContig = ! bPrimer2ComplementedWithRespectToWayPhrapCreatedContig; oligoTag* pOligo2Tag = new oligoTag( pPrimer2, true, // bCloneNotSubcloneTemplate bPrimer2ComplementedWithRespectToWayPhrapCreatedContig, -1, // create new oligo name soTagComment ); EditAction* pEditAction2 = new editAddConsensusTag( pOligo2Tag ); ConsEd::pGetConsEd()->doEditAction( pEditAction2, true ); // now scroll both contigwin's ContigWin* pContigWin1 = ConsEd::pGetConsEd()->pGetContigWinByContig( pPrimer1->pContig_ ); ContigWin* pContigWin2 = ConsEd::pGetConsEd()->pGetContigWinByContig( pPrimer2->pContig_ ); if ( pContigWin1 ) { int nConsPos1 = pPrimer1->pContig_->nPaddedIndex( pPrimer1->nUnpaddedStart_ ); pContigWin1->scrollToConsensusPosInCenter( nConsPos1 ); pContigWin1->moveCursorToConsPos( nConsPos1 ); } if ( pContigWin2 && pContigWin2 != pContigWin1 ) { int nConsPos2 = pPrimer2->pContig_->nPaddedIndex( pPrimer2->nUnpaddedStart_ ); pContigWin2->scrollToConsensusPosInCenter( nConsPos2 ); pContigWin2->moveCursorToConsPos( nConsPos2 ); } delete this; } void pickPCRPrimers :: dividePrimersIntoGroups( RWTPtrOrderedVector& aGroups, primerType* pPrimerArray, const int nNumberOfPrimersInPrimerArray ) { int nBeginningOfNextGroup; bool bNeedFirstAcceptablePrimer = true; groupOfPrimersForPCR* pPreviousGroup = NULL; int nPrimer; for( nPrimer = 0; nPrimer < nNumberOfPrimersInPrimerArray; ++nPrimer ) { primerType* pPCRPrimer = pPrimerArray + nPrimer; if ( !pPCRPrimer->bAcceptable_ ) continue; if ( !bNeedFirstAcceptablePrimer && ( pPCRPrimer->nUnpaddedStart_ >= nBeginningOfNextGroup ) ) { // finish off the previous group pPreviousGroup->nEndIndex_ = nPrimer - 1; // start new group // skip over 100 base areas with no primers do { nBeginningOfNextGroup += pCP->nPrimersPCRPrimersGroupedIntoWindowOfThisManyBases_; } while( nBeginningOfNextGroup <= pPCRPrimer->nUnpaddedStart_ ); groupOfPrimersForPCR* pGroupOfPrimersForPCR = new groupOfPrimersForPCR; pGroupOfPrimersForPCR->nStartIndex_ = nPrimer; pGroupOfPrimersForPCR->nLeftMostUnpaddedConsPos_ = pPCRPrimer->nUnpaddedStart_; pGroupOfPrimersForPCR->nRangeLeft_ = nBeginningOfNextGroup - pCP->nPrimersPCRPrimersGroupedIntoWindowOfThisManyBases_; pGroupOfPrimersForPCR->nRangeRight_ = nBeginningOfNextGroup - 1; aGroups.insert( pGroupOfPrimersForPCR ); pPreviousGroup = pGroupOfPrimersForPCR; } else if ( bNeedFirstAcceptablePrimer ) { bNeedFirstAcceptablePrimer = false; nBeginningOfNextGroup = pPCRPrimer->nUnpaddedStart_ + pCP->nPrimersPCRPrimersGroupedIntoWindowOfThisManyBases_; groupOfPrimersForPCR* pGroupOfPrimersForPCR = new groupOfPrimersForPCR; pGroupOfPrimersForPCR->nStartIndex_ = nPrimer; pGroupOfPrimersForPCR->nLeftMostUnpaddedConsPos_ = pPCRPrimer->nUnpaddedStart_; pGroupOfPrimersForPCR->nRangeLeft_ = pPCRPrimer->nUnpaddedStart_; pGroupOfPrimersForPCR->nRangeRight_ = pPCRPrimer->nUnpaddedStart_ + pCP->nPrimersPCRPrimersGroupedIntoWindowOfThisManyBases_ - 1; aGroups.insert( pGroupOfPrimersForPCR ); pPreviousGroup = pGroupOfPrimersForPCR; } } // finish the last group. pPreviousGroup->nEndIndex_ = nNumberOfPrimersInPrimerArray - 1; } void pickPCRPrimers :: findAcceptablePrimersInThisPairOfGroups( groupOfPrimersForPCR* pGroup1, groupOfPrimersForPCR* pGroup2 ) { int nPairsOKThisPairOfWindows = 0; for( int nFirstPrimer = pGroup1->nStartIndex_; nFirstPrimer <= pGroup1->nEndIndex_; ++nFirstPrimer ) { primerType* pFirstPCRPrimer = pFirstPrimerArray_ + nFirstPrimer; if ( !pFirstPCRPrimer->bAcceptable_ ) continue; for( int nSecondPrimer = pGroup2->nStartIndex_; nSecondPrimer <= pGroup2->nEndIndex_; ++nSecondPrimer ) { primerType* pSecondPCRPrimer = pSecondPrimerArray_ + nSecondPrimer; if ( !pSecondPCRPrimer->bAcceptable_ ) continue; ++nPairsTried_; bool bTempDiffTooGreat; bool bPrimersStickToEachOther; if ( bIsPCRPrimerPairOK( pFirstPCRPrimer, pSecondPCRPrimer, bTempDiffTooGreat, bPrimersStickToEachOther ) ) { ++nPairsOK_; ++nPairsOKThisPairOfWindows; addPCRPrimerPairIfPossible( pFirstPCRPrimer, pSecondPCRPrimer ); if ( pCP->bPrimersCheckJustSomePCRPrimerPairsRatherThanAll_ && ( nPairsOKThisPairOfWindows >= pCP->nPrimersLookForThisManyPCRPrimerPairsPerPairOfGroups_ ) ) return; } else { if ( bTempDiffTooGreat ) ++nTempDiffTooGreat_; else if ( bPrimersStickToEachOther ) ++nPrimersStickToEachOther_; } } } }