omssa.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:32k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: omssa.cpp,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 18:09:10  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* $Id: omssa.cpp,v 1000.4 2004/06/01 18:09:10 gouriano Exp $
  10. * ===========================================================================
  11. *
  12. *                            PUBLIC DOMAIN NOTICE
  13. *               National Center for Biotechnology Information
  14. *
  15. *  This software/database is a "United States Government Work" under the
  16. *  terms of the United States Copyright Act.  It was written as part of
  17. *  the author's official duties as a United States Government employee and
  18. *  thus cannot be copyrighted.  This software/database is freely available
  19. *  to the public for use. The National Library of Medicine and the U.S.
  20. *  Government have not placed any restriction on its use or reproduction.
  21. *
  22. *  Although all reasonable efforts have been taken to ensure the accuracy
  23. *  and reliability of the software and data, the NLM and the U.S.
  24. *  Government do not and cannot warrant the performance or results that
  25. *  may be obtained by using this software or data. The NLM and the U.S.
  26. *  Government disclaim all warranties, express or implied, including
  27. *  warranties of performance, merchantability or fitness for any particular
  28. *  purpose.
  29. *
  30. *  Please cite the authors in any work or product based on this material.
  31. *
  32. * ===========================================================================
  33. *
  34. * Author:  Lewis Y. Geer
  35. *  
  36. * File Description:
  37. *    code to do the ms/ms search and score matches
  38. *
  39. * ===========================================================================
  40. */
  41. #include <ncbi_pch.hpp>
  42. #include <corelib/ncbistd.hpp>
  43. #include <corelib/ncbiargs.hpp>
  44. #include <corelib/ncbiapp.hpp>
  45. #include <corelib/ncbienv.hpp>
  46. #include <corelib/ncbidiag.hpp>
  47. #include <corelib/ncbi_limits.hpp>
  48. #include <fstream>
  49. #include <string>
  50. #include <list>
  51. #include <deque>
  52. #include <algorithm>
  53. #include <math.h>
  54. #include "SpectrumSet.hpp"
  55. #include "omssa.hpp"
  56. #include "nrutil.h"
  57. #include <ncbimath.h>
  58. USING_NCBI_SCOPE;
  59. USING_SCOPE(objects);
  60. USING_SCOPE(omssa);
  61. /////////////////////////////////////////////////////////////////////////////
  62. //
  63. //  CSearch::
  64. //
  65. //  Performs the ms/ms search
  66. //
  67. CSearch::CSearch(void): rdfp(0)
  68. {
  69. }
  70. int CSearch::InitBlast(const char *blastdb, bool InitDb)
  71. {
  72.     if(!blastdb) return 0;
  73.     if(rdfp) readdb_destruct(rdfp);
  74.     rdfp = readdb_new_ex2((char *)blastdb,TRUE, READDB_NEW_DO_TAXDB | 
  75.   READDB_NEW_INDEX, NULL, NULL);
  76.     if(!rdfp) return 1;
  77.     numseq = readdb_get_num_entries(rdfp);
  78.     if(InitDb) {
  79. int iSearch, length;
  80. char testchar;
  81. unsigned char *Sequence;
  82. for(iSearch = 0; iSearch < numseq; iSearch++) {
  83.     length = readdb_get_sequence(rdfp, iSearch, &Sequence);
  84.     testchar = Sequence[0];
  85. }
  86.     }
  87.     return 0;
  88. }
  89. // create the ladders from sequence
  90. int CSearch::CreateLadders(unsigned char *Sequence, int iSearch, int position,
  91.    int endposition,
  92.    int *Masses, int iMissed, CAA& AA, 
  93.    CLadder& BLadder,
  94.    CLadder& YLadder, CLadder& B2Ladder,
  95.    CLadder& Y2Ladder,
  96.    unsigned ModMask,
  97.    const char **Site,
  98.    int *DeltaMass,
  99.    int NumMod)
  100. {
  101.     if(!BLadder.CreateLadder(kBIon, 1, (char *)Sequence, iSearch,
  102.      position, endposition, Masses[iMissed], 
  103.      MassArray, AA, ModMask, Site, DeltaMass,
  104.      NumMod)) return 1;
  105.     if(!YLadder.CreateLadder(kYIon, 1, (char *)Sequence, iSearch,
  106.  position, endposition, Masses[iMissed], 
  107.      MassArray, AA, ModMask, Site, DeltaMass,
  108.      NumMod)) return 1;
  109.     B2Ladder.CreateLadder(kBIon, 2, (char *)Sequence, iSearch,
  110.   position, endposition, 
  111.   Masses[iMissed], 
  112.   MassArray, AA, ModMask, Site, DeltaMass,
  113.   NumMod);
  114.     Y2Ladder.CreateLadder(kYIon, 2, (char *)Sequence, iSearch,
  115.   position, endposition,
  116.   Masses[iMissed], 
  117.   MassArray, AA, ModMask, Site, DeltaMass,
  118.   NumMod);
  119.     
  120.     return 0;
  121. }
  122. // compare ladders to experiment
  123. int CSearch::CompareLadders(CLadder& BLadder,
  124.     CLadder& YLadder, CLadder& B2Ladder,
  125.     CLadder& Y2Ladder, CMSPeak *Peaks,
  126.     bool OrLadders,  TMassPeak *MassPeak)
  127. {
  128.     if(MassPeak && MassPeak->Charge >= kConsiderMult) {
  129. Peaks->CompareSorted(BLadder, MSCULLED2, 0); 
  130. Peaks->CompareSorted(YLadder, MSCULLED2, 0); 
  131. Peaks->CompareSorted(B2Ladder, MSCULLED2, 0); 
  132. Peaks->CompareSorted(Y2Ladder, MSCULLED2, 0);
  133. if(OrLadders) {
  134.     BLadder.Or(B2Ladder);
  135.     YLadder.Or(Y2Ladder);
  136. }
  137.     }
  138.     else {
  139. Peaks->CompareSorted(BLadder, MSCULLED1, 0); 
  140. Peaks->CompareSorted(YLadder, MSCULLED1, 0); 
  141.     }
  142.     return 0;
  143. }
  144. // compare ladders to experiment
  145. bool CSearch::CompareLaddersTop(CLadder& BLadder,
  146.     CLadder& YLadder, CLadder& B2Ladder,
  147.     CLadder& Y2Ladder, CMSPeak *Peaks,
  148.     TMassPeak *MassPeak)
  149. {
  150.     if(MassPeak && MassPeak->Charge >=  kConsiderMult ) {
  151. if(Peaks->CompareTop(BLadder)) return true; 
  152. if(Peaks->CompareTop(YLadder)) return true; 
  153. if(Peaks->CompareTop(B2Ladder)) return true; 
  154. if(Peaks->CompareTop(Y2Ladder)) return true;
  155.     }
  156.     else {
  157. if(Peaks->CompareTop(BLadder)) return true; 
  158. if(Peaks->CompareTop(YLadder)) return true; 
  159.     }
  160.     return false;
  161. }
  162. #ifdef _DEBUG
  163. #define CHECKGI
  164. #ifdef CHECKGI
  165. bool CheckGi(int gi)
  166. {
  167.     if(gi == 21742354) {
  168. ERR_POST(Info << "test seq");
  169. return true;
  170.     }
  171.     return false;
  172. }
  173. #endif
  174. #endif
  175. // loads spectra into peaks
  176. void CSearch::Spectrum2Peak(CMSRequest& MyRequest, CMSPeakSet& PeakSet)
  177. {
  178.     CSpectrumSet::Tdata::const_iterator iSpectrum;
  179.     CMSPeak* Peaks;
  180.     iSpectrum = MyRequest.GetSpectra().Get().begin();
  181.     for(; iSpectrum != MyRequest.GetSpectra().Get().end(); iSpectrum++) {
  182. CRef <CMSSpectrum> Spectrum =  *iSpectrum;
  183. if(!Spectrum) {
  184.     ERR_POST(Error << "omssa: unable to find spectrum");
  185.     return;
  186. }
  187. Peaks = new CMSPeak(MyRequest.GetHitlistlen());
  188. if(!Peaks) {
  189.     ERR_POST(Error << "omssa: unable to allocate CMSPeak");
  190.     return;
  191. }
  192. if(Peaks->Read(*Spectrum, MyRequest.GetMsmstol()) != 0) {
  193.     ERR_POST(Error << "omssa: unable to read spectrum into CMSPeak");
  194.     return;
  195. }
  196. if(Spectrum->CanGetName()) Peaks->SetName() = Spectrum->GetName();
  197. if(Spectrum->CanGetNumber())
  198.     Peaks->SetNumber() = Spectrum->GetNumber();
  199. Peaks->Sort();
  200. Peaks->SetComputedCharge(3);
  201. Peaks->InitHitList();
  202. Peaks->CullAll(MyRequest.GetCutlo(), MyRequest.GetSinglewin(),
  203.        MyRequest.GetDoublewin(), MyRequest.GetSinglenum(),
  204.        MyRequest.GetDoublenum());
  205. if(Peaks->GetNum(MSCULLED1) < MSPEAKMIN)  {
  206.     ERR_POST(Info << "omssa: not enough peaks in spectra");
  207.     Peaks->SetError(eMSHitError_notenuffpeaks);
  208. }
  209. PeakSet.AddPeak(Peaks);
  210.     }
  211.     PeakSet.SortPeaks(static_cast <int> (MyRequest.GetPeptol()*MSSCALE));
  212. }
  213. // compares TMassMasks.  Lower m/z first in sort.
  214. struct CMassMaskCompare {
  215.     bool operator() (const TMassMask& x, const TMassMask& y)
  216.     {
  217. if(x.Mass < y.Mass) return true;
  218. return false;
  219.     }
  220. };
  221. // update sites and masses for new peptide
  222. void CSearch::UpdateWithNewPep(int Missed,
  223.        const char *PepStart[],
  224.        const char *PepEnd[], 
  225.        int NumMod[], 
  226.        const char *Site[][MAXMOD],
  227.        int DeltaMass[][MAXMOD],
  228.        int Masses[],
  229.        int EndMasses[])
  230. {
  231.     // iterate over missed cleavages
  232.     int iMissed;
  233.     // maximum mods allowed
  234.     int ModMax; 
  235.     // iterate over mods
  236.     int iMod;
  237.     
  238.     // update the longer peptides to add the new peptide (Missed-1) on the end
  239.     for(iMissed = 0; iMissed < Missed - 1; iMissed++) {
  240. // skip start
  241. if(PepStart[iMissed] == (const char *)-1) continue;
  242. // reset the end sequences
  243. PepEnd[iMissed] = PepEnd[Missed - 1];
  244. // update new mod masses to add in any new mods from new peptide
  245. // first determine the maximum value for updated mod list
  246. if(NumMod[iMissed] + NumMod[Missed-1] >= MAXMOD)
  247.     ModMax = MAXMOD - NumMod[iMissed];
  248. else ModMax = NumMod[Missed-1];
  249. // now interatu thru the new entries
  250. for(iMod = NumMod[iMissed]; 
  251.     iMod < NumMod[iMissed] + ModMax;
  252.     iMod++) {
  253.     Site[iMissed][iMod] = 
  254. Site[Missed-1][iMod - NumMod[iMissed]];
  255.     DeltaMass[iMissed][iMod] = 
  256. DeltaMass[Missed-1][iMod - NumMod[iMissed]];
  257.     //     Masses[iMissed][iMod] = 
  258.     // Masses[Missed-1][iMod - NumMod[iMissed] + 1] +
  259.     // Masses[iMissed][NumMod[iMissed] - 1];
  260. }
  261. // update old masses
  262. Masses[iMissed] += Masses[Missed - 1];
  263. // update end masses
  264. EndMasses[iMissed] = EndMasses[Missed - 1];
  265. // update number of Mods
  266. NumMod[iMissed] += ModMax;
  267.     }     
  268. }
  269. // create the various combinations of mods
  270. void CSearch::CreateModCombinations(int Missed,
  271.     const char *PepStart[],
  272.     TMassMask MassAndMask[][MAXMOD2],
  273.     int Masses[],
  274.     int EndMasses[],
  275.     int NumMod[],
  276.     int DeltaMass[][MAXMOD],
  277.     unsigned NumMassAndMask[])
  278. {
  279.     // need to iterate thru combinations that have iMod.
  280.     // i.e. iMod = 3 and NumMod=5
  281.     // 00111, 01011, 10011, 10101, 11001, 11010, 11100, 01101,
  282.     // 01110
  283.     // i[0] = 0 --> 5-3, i[1] = i[0]+1 -> 5-2, i[3] = i[1]+1 -> 5-1
  284.     // then construct bool mask
  285.     
  286.     // holders for calculated modification mask and modified peptide masses
  287.     unsigned Mask, MassOfMask;
  288.     // iterate thru active mods
  289.     int iiMod;
  290.     // keep track of the number of unique masks created.  each corresponds to a ladder
  291.     int iModCount;
  292.     // missed cleavage
  293.     int iMissed;
  294.     // number of mods to consider
  295.     int iMod;
  296.     // positions of mods
  297.     int ModIndex[MAXMOD];
  298.     // go thru missed cleaves
  299.     for(iMissed = 0; iMissed < Missed; iMissed++) {
  300. // skip start
  301. if(PepStart[iMissed] == (const char *)-1) continue;
  302. iModCount = 0;
  303. // set up non-modified mass
  304. MassAndMask[iMissed][iModCount].Mass = 
  305.     Masses[iMissed] + EndMasses[iMissed];
  306. MassAndMask[iMissed][iModCount].Mask = 0;
  307. iModCount++;
  308. // go thru number of mods allowed
  309. for(iMod = 0; iMod < NumMod[iMissed] && iModCount < MAXMOD2; iMod++) {
  310.     
  311.     // initialize ModIndex that points to mod sites
  312.     InitModIndex(ModIndex, iMod);
  313.     do {
  314. // calculate mass
  315. MassOfMask = Masses[iMissed] + EndMasses[iMissed];
  316. for(iiMod = 0; iiMod <= iMod; iiMod++ ) 
  317.     MassOfMask += DeltaMass[iMissed][ModIndex[iiMod]];
  318. // make bool mask
  319. Mask = MakeBoolMask(ModIndex, iMod);
  320. // put mass and mask into storage
  321. MassAndMask[iMissed][iModCount].Mass = MassOfMask;
  322. MassAndMask[iMissed][iModCount].Mask = Mask;
  323. // keep track of the  number of ladders
  324. iModCount++;
  325.     } while(iModCount < MAXMOD2 &&
  326.     CalcModIndex(ModIndex, iMod, NumMod[iMissed]));
  327. } // iMod
  328. // sort mask and mass by mass
  329. sort(MassAndMask[iMissed], MassAndMask[iMissed] + iModCount,
  330.      CMassMaskCompare());
  331. // keep track of number of MassAndMask
  332. NumMassAndMask[iMissed] = iModCount;
  333.     } // iMissed
  334. }
  335. //#define MSSTATRUN
  336. int CSearch::Search(CMSRequest& MyRequest, CMSResponse& MyResponse)
  337. {
  338.     try {
  339. int length;
  340. CTrypsin trypsin;
  341. unsigned header;
  342. #ifdef CHECKGI
  343. char *blastdefline;
  344. SeqId *sip;
  345. #endif
  346. CLadder BLadder[MAXMOD2], YLadder[MAXMOD2], B2Ladder[MAXMOD2],
  347.     Y2Ladder[MAXMOD2];
  348. bool LadderCalc[MAXMOD2];  // have the ladders been calculated?
  349. CAA AA;
  350. int Missed = MyRequest.GetMissedcleave()+1;  // number of missed cleaves allowed + 1
  351. int iMissed; // iterate thru missed cleavages
  352.     
  353. int iSearch, hits;
  354. unsigned char *Sequence;  // start position
  355. int endposition, position;
  356. MassArray.Init(MyRequest.GetFixed(), MyRequest.GetSearchtype());
  357. VariableMods.Init(MyRequest.GetVariable());
  358. const int *IntMassArray = MassArray.GetIntMass();
  359. const char *PepStart[MAXMISSEDCLEAVE];
  360. const char *PepEnd[MAXMISSEDCLEAVE];
  361. // the position within the peptide of a variable modification
  362. const char *Site[MAXMISSEDCLEAVE][MAXMOD];
  363. // the modification mass at the Site
  364. int DeltaMass[MAXMISSEDCLEAVE][MAXMOD];
  365. // the number of modified sites + 1 unmodified
  366. int NumMod[MAXMISSEDCLEAVE];
  367. // calculated masses and masks
  368. TMassMask MassAndMask[MAXMISSEDCLEAVE][MAXMOD2];
  369. // the number of masses and masks for each peptide
  370. unsigned NumMassAndMask[MAXMISSEDCLEAVE];
  371. // set up mass array, indexed by missed cleavage
  372. // note that EndMasses is the end mass of peptide, kept separate to allow
  373. // reuse of Masses array in missed cleavage calc
  374. int Masses[MAXMISSEDCLEAVE];
  375. int EndMasses[MAXMISSEDCLEAVE];
  376. int iMod;   // used to iterate thru modifications
  377. bool SequenceDone;  // are we done iterating through the sequences?
  378. int taxid;
  379. const CMSRequest::TTaxids& Tax = MyRequest.GetTaxids();
  380. CMSRequest::TTaxids::const_iterator iTax;
  381. CMSHit NewHit;  // a new hit of a ladder to an m/z value
  382. CMSHit *NewHitOut;  // copy of new hit
  383. CMSPeakSet PeakSet;
  384. TMassPeak *MassPeak; // peak currently in consideration
  385. CMSPeak* Peaks;
  386. Spectrum2Peak(MyRequest, PeakSet);
  387. #ifdef MSSTATRUN
  388. ofstream charge1("charge1.txt");
  389. ofstream charge2("charge2.txt");
  390. ofstream charge3("charge3.txt");
  391. #endif
  392. // iterate through sequences
  393. for(iSearch = 0; iSearch < numseq; iSearch++) {
  394.     if(iSearch/10000*10000 == iSearch) ERR_POST(Info << "sequence " << 
  395. iSearch);
  396.     header = 0;
  397. #ifdef CHECKGI
  398.     int testgi;
  399. #endif 
  400.     if(MyRequest.IsSetTaxids()) {
  401. while(readdb_get_header_ex(rdfp, iSearch, &header, 
  402. #ifdef CHECKGI
  403.    &sip, &blastdefline,
  404. #else
  405.    NULL, NULL,
  406. #endif
  407.    &taxid, NULL, NULL)) {
  408. #ifdef CHECKGI
  409.     SeqId *bestid = SeqIdFindBest(sip, SEQID_GI);
  410.     CheckGi(bestid->data.intvalue);
  411.     testgi = bestid->data.intvalue;
  412.     //     cout << testgi << endl;
  413. #endif 
  414. #ifdef CHECKGI
  415.     MemFree(blastdefline);
  416.     SeqIdSetFree(sip);
  417. #endif
  418.     for(iTax = Tax.begin(); iTax != Tax.end(); iTax++) {
  419. if(taxid == *iTax) goto TaxContinue;
  420.     } 
  421.     //else goto TaxContinue;
  422. }
  423. continue;
  424.     }
  425. TaxContinue:
  426.     length = readdb_get_sequence(rdfp, iSearch, &Sequence);
  427.     SequenceDone = false;
  428.     // PepStart = (const char *)Sequence[0];
  429.     // initialize missed cleavage matrix
  430.     for(iMissed = 0; iMissed < Missed; iMissed++) {
  431. PepStart[iMissed] = (const char *)-1; // mark start
  432. PepEnd[iMissed] = (const char *)Sequence;
  433. Masses[iMissed] = 0;
  434. EndMasses[iMissed] = 0;
  435. NumMod[iMissed] = 0;
  436. DeltaMass[iMissed][0] = 0;
  437. Site[iMissed][0] = (const char *)-1;
  438.     }
  439.     PepStart[Missed - 1] = (const char *)Sequence;
  440.     // iterate thru the sequence by digesting it
  441.     while(!SequenceDone) {
  442. // zero out no missed cleavage peptide mass and mods
  443. // note that Masses and EndMass are separate to reuse
  444. // masses during the missed cleavage calculation
  445. Masses[Missed - 1] = 0;
  446. EndMasses[Missed - 1] = 0;
  447. NumMod[Missed - 1] = 0;
  448. // init no modification elements
  449. Site[Missed - 1][0] = (const char *)-1;
  450. DeltaMass[Missed - 1][0] = 0;
  451. // calculate new stop and mass
  452. SequenceDone = 
  453.     trypsin.CalcAndCut((const char *)Sequence,
  454.        (const char *)Sequence + length - 1, 
  455.        &(PepEnd[Missed - 1]),
  456.        &(Masses[Missed - 1]),
  457.        NumMod[Missed - 1],
  458.        MAXMOD,
  459.        &(EndMasses[Missed - 1]),
  460.        VariableMods,
  461.        Site[Missed - 1],
  462.        DeltaMass[Missed - 1],
  463.        IntMassArray);
  464. UpdateWithNewPep(Missed, PepStart, PepEnd, NumMod, Site,
  465.  DeltaMass, Masses, EndMasses);
  466. CreateModCombinations(Missed, PepStart, MassAndMask, Masses,
  467.       EndMasses, NumMod, DeltaMass, NumMassAndMask);
  468. int OldMass;  // keeps the old peptide mass for comparison
  469. bool NoMassMatch;  // was there a match to the old mass?
  470. for(iMissed = 0; iMissed < Missed; iMissed++) {     
  471.     if(PepStart[iMissed] == (const char *)-1) continue;  // skip start
  472.     // get the start and stop position, inclusive, of the peptide
  473.     position =  PepStart[iMissed] - (const char *)Sequence;
  474.     endposition = PepEnd[iMissed] - (const char *)Sequence;
  475.     // init bool for "Has ladder been calculated?"
  476.     for(iMod = 0; iMod < MAXMOD2; iMod++) LadderCalc[iMod] = false;
  477.     OldMass = 0;
  478.     NoMassMatch = true;
  479.     // go thru total number of mods
  480.     for(iMod = 0; iMod < NumMassAndMask[iMissed]; iMod++) {
  481.     
  482. // have we seen this mass before?
  483. if(MassAndMask[iMissed][iMod].Mass == OldMass &&
  484.    NoMassMatch) continue;
  485. NoMassMatch = true;
  486. OldMass = MassAndMask[iMissed][iMod].Mass;
  487. // return peak where theoretical mass is < precursor mass + tol
  488. MassPeak = PeakSet.GetIndexLo(OldMass);
  489. for(;MassPeak < PeakSet.GetEndMassPeak() && 
  490. OldMass > MassPeak->Mass - MassPeak->Peptol;
  491.     MassPeak++) {
  492.     Peaks = MassPeak->Peak;
  493.     // make sure we look thru other mod masks with the same mass
  494.     NoMassMatch = false;
  495. #ifdef CHECKGI
  496.     SeqId *bestid;
  497.     header = 0;
  498.     readdb_get_header(rdfp, iSearch, &header, &sip, &blastdefline);
  499.     bestid = SeqIdFindBest(sip, SEQID_GI);
  500.     if(/*Peaks->GetNumber() == 245 && */CheckGi(bestid->data.intvalue))
  501. cerr << "hello" << endl;
  502.     // int testgi = bestid->data.intvalue;
  503.     MemFree(blastdefline);
  504.     SeqIdSetFree(sip);
  505. #endif
  506.     if(!LadderCalc[iMod]) {
  507. LadderCalc[iMod] = true;
  508. if(CreateLadders(Sequence, iSearch, position,
  509.  endposition,
  510.  Masses,
  511.  iMissed, AA,
  512.  BLadder[iMod],
  513.  YLadder[iMod],
  514.  B2Ladder[iMod],
  515.  Y2Ladder[iMod],
  516.  MassAndMask[iMissed][iMod].Mask,
  517.  Site[iMissed],
  518.  DeltaMass[iMissed],
  519.  NumMod[iMissed]) != 
  520.    0) continue;
  521. // continue to next sequence if ladders not successfully made
  522.     }
  523.     else {
  524. BLadder[iMod].ClearHits();
  525. YLadder[iMod].ClearHits();
  526. B2Ladder[iMod].ClearHits();
  527. Y2Ladder[iMod].ClearHits();
  528.     }
  529.     if(
  530. #ifdef MSSTATRUN
  531.        true
  532. #else
  533.        CompareLaddersTop(BLadder[iMod], 
  534.  YLadder[iMod],
  535.  B2Ladder[iMod], 
  536.  Y2Ladder[iMod],
  537.  Peaks, MassPeak)
  538. #endif
  539.        ) {
  540. // end of new addition
  541. Peaks->SetPeptidesExamined(MassPeak->Charge)++;
  542. #ifdef CHECKGI
  543. /*if(Peaks->GetNumber() == 245)*/
  544. //     cout << testgi << " " << position << " " << endposition << endl;
  545. #endif
  546. Peaks->ClearUsedAll();
  547. CompareLadders(BLadder[iMod], 
  548.        YLadder[iMod],
  549.        B2Ladder[iMod], 
  550.        Y2Ladder[iMod],
  551.        Peaks, false, MassPeak);
  552. hits = BLadder[iMod].HitCount() + 
  553.     YLadder[iMod].HitCount() +
  554.     B2Ladder[iMod].HitCount() +
  555.     Y2Ladder[iMod].HitCount();
  556. #ifdef MSSTATRUN
  557. switch (MassPeak->Charge)
  558.     {
  559.     case 1:
  560. charge1 << hits << endl;
  561. break;
  562.     case 2:
  563. charge2 << hits << endl;
  564. break;
  565.     case 3:
  566. charge3 << hits << endl;
  567. break;
  568.     default:
  569. break;
  570.     }
  571. #endif
  572. if(hits >= MSHITMIN) {
  573.     // need to save mods.  bool map?
  574.     NewHit.SetHits(hits);
  575.     NewHit.SetCharge(MassPeak->Charge);
  576.     // only record if hit kept
  577.     if(Peaks->AddHit(NewHit, NewHitOut)) {
  578. NewHitOut->SetStart(position);
  579. NewHitOut->SetStop(endposition);
  580. NewHitOut->SetSeqIndex(iSearch);
  581. NewHitOut->SetMass(MassPeak->Mass);
  582. // record the hits
  583. Peaks->ClearUsedAll();
  584. NewHitOut->
  585.     RecordMatches(BLadder[iMod],
  586.   YLadder[iMod],
  587.   B2Ladder[iMod], 
  588.   Y2Ladder[iMod],
  589.   Peaks);
  590.     }
  591. }
  592.     } // new addition
  593. } // MassPeak
  594.     } //iMod
  595. } // iMissed
  596. if(!SequenceDone) {
  597.     // get rid of longest peptide and move the other peptides down the line
  598.     for(iMissed = 0; iMissed < Missed - 1; iMissed++) {
  599. // move masses to next missed cleavage
  600. NumMod[iMissed] = NumMod[iMissed + 1];
  601. Masses[iMissed] = Masses[iMissed + 1];
  602. // don't move EndMasses as they are recalculated
  603. // move the modification data
  604. for(iMod = 0; iMod < NumMod[iMissed]; iMod++) {
  605.     DeltaMass[iMissed][iMod] = 
  606. DeltaMass[iMissed + 1][iMod];
  607.     Site[iMissed][iMod] = 
  608. Site[iMissed + 1][iMod];
  609. }
  610. // copy starts to next missed cleavage
  611. PepStart[iMissed] = PepStart[iMissed + 1];
  612.     }
  613.     // init new start from old stop
  614.     PepEnd[Missed-1] += 1;
  615.     PepStart[Missed-1] = PepEnd[Missed-1];
  616.     // PepStart = PepEnd + 1;
  617.     }
  618. }
  619. // read out hits
  620. SetResult(PeakSet, MyResponse, MyRequest.GetCutlo(), 
  621.   MyRequest.GetCuthi(), MyRequest.GetCutinc());
  622.     } catch (NCBI_NS_STD::exception& e) {
  623. ERR_POST(Info << "Exception caught in CSearch::Search: " << e.what());
  624. throw;
  625.     }
  626.     return 0;
  627. }
  628. void CSearch::SetResult(CMSPeakSet& PeakSet, CMSResponse& MyResponse,
  629. double ThreshStart, double ThreshEnd,
  630. double ThreshInc)
  631. {
  632.     CMSPeak* Peaks;
  633.     TPeakSet::iterator iPeakSet;
  634.     TScoreList ScoreList;
  635.     TScoreList::iterator iScoreList;
  636.     CMSHit * MSHit;
  637.     unsigned header;
  638.     char *blastdefline;
  639.     SeqId *sip, *bestid;
  640.     int length;
  641.     unsigned char *Sequence;
  642.     int iSearch; // counter for the length of hit list
  643.     for(iPeakSet = PeakSet.GetPeaks().begin();
  644. iPeakSet != PeakSet.GetPeaks().end();
  645. iPeakSet++ ) {
  646. Peaks = *iPeakSet;
  647. // add to hitset
  648. CRef< CMSHitSet > HitSet (new CMSHitSet);
  649. if(!HitSet) {
  650.     ERR_POST(Error << "omssa: unable to allocate hitset");
  651.     return;
  652. }
  653. HitSet->SetNumber(Peaks->GetNumber());
  654. HitSet->SetFilename(Peaks->GetName());
  655. MyResponse.SetHitsets().push_back(HitSet);
  656. if(Peaks->GetError() == eMSHitError_notenuffpeaks) {
  657.     ERR_POST(Info << "empty set");
  658.     HitSet->SetError(eMSHitError_notenuffpeaks);
  659.     continue;
  660. }
  661. double Threshold, MinThreshold(ThreshStart), MinEval(1000000.0L);
  662. // now calculate scores and sort
  663. for(Threshold = ThreshStart; Threshold <= ThreshEnd; 
  664.     Threshold += ThreshInc) {
  665.     CalcNSort(ScoreList, Threshold, Peaks, false);
  666.     if(!ScoreList.empty()) {
  667. _TRACE("Threshold = " << Threshold <<
  668.        "EVal = " << ScoreList.begin()->first);
  669.     }
  670.     if(!ScoreList.empty() && ScoreList.begin()->first < MinEval) {
  671. MinEval = ScoreList.begin()->first;
  672. MinThreshold = Threshold;
  673.     }
  674.     ScoreList.clear();
  675. }
  676. _TRACE("Min Threshold = " << MinThreshold);
  677. CalcNSort(ScoreList,
  678. #ifdef MSSTATRUN
  679.  ThreshStart
  680. #else
  681.  MinThreshold
  682. #endif
  683. , Peaks, true);
  684. // keep a list of redundant peptides
  685. map <string, CMSHits * > PepDone;
  686. // add to hitset by score
  687. for(iScoreList = ScoreList.begin(), iSearch = 0;
  688.     iScoreList != ScoreList.end();
  689.     iScoreList++, iSearch++) {
  690.     
  691.     CMSHits * Hit;
  692.     CMSPepHit * Pephit;
  693.     MSHit = iScoreList->second;
  694.     header = 0;
  695.     while (readdb_get_header(rdfp, MSHit->GetSeqIndex(), &header,
  696.      &sip,
  697.      &blastdefline)) {
  698. bestid = SeqIdFindBest(sip, SEQID_GI);
  699. if(!bestid) continue;
  700. string seqstring;
  701. string deflinestring(blastdefline);
  702. int iseq;
  703. length = readdb_get_sequence(rdfp, MSHit->GetSeqIndex(),
  704.      &Sequence);
  705. for (iseq = MSHit->GetStart(); iseq <= MSHit->GetStop();
  706.      iseq++) {
  707.     seqstring += UniqueAA[Sequence[iseq]];
  708. }
  709. #ifdef CHECKGI
  710. CheckGi(bestid->data.intvalue);
  711. #endif
  712. if(PepDone.find(seqstring) != PepDone.end()) {
  713.     Hit = PepDone[seqstring];
  714. }
  715. else {
  716.     Hit = new CMSHits;
  717.     Hit->SetPepstring(seqstring);
  718.     double Score = iScoreList->first;
  719.     Hit->SetEvalue(Score);
  720.     Hit->SetPvalue(Score/Peaks->
  721.    GetPeptidesExamined(MSHit->
  722.        GetCharge()));    
  723.     Hit->SetCharge(MSHit->GetCharge());
  724.     CRef<CMSHits> hitref(Hit);
  725.     HitSet->SetHits().push_back(hitref);  
  726.     PepDone[seqstring] = Hit;
  727. }
  728. Pephit = new CMSPepHit;
  729. Pephit->SetStart(MSHit->GetStart());
  730. Pephit->SetStop(MSHit->GetStop());
  731. Pephit->SetGi(bestid->data.intvalue);
  732. Pephit->SetDefline(deflinestring);
  733. CRef<CMSPepHit> pepref(Pephit);
  734. Hit->SetPephits().push_back(pepref);
  735. MemFree(blastdefline);
  736. SeqIdSetFree(sip);
  737.     }
  738. }
  739. ScoreList.clear();
  740.     }
  741. }
  742. // calculate the evalues of the top hits and sort
  743. void CSearch::CalcNSort(TScoreList& ScoreList, double Threshold, CMSPeak* Peaks, bool NewScore)
  744. {
  745.     int iCharges;
  746.     int iHitList;
  747.     int length;
  748.     unsigned char *Sequence;
  749.     for(iCharges = 0; iCharges < Peaks->GetNumCharges(); iCharges++) {
  750. TMSHitList& HitList = Peaks->GetHitList(iCharges);   
  751. for(iHitList = 0; iHitList != Peaks->GetHitListIndex(iCharges);
  752.     iHitList++) {
  753. #ifdef CHECKGI
  754.     unsigned header;
  755.     char *blastdefline;
  756.     SeqId *sip, *bestid;
  757.     header = 0;
  758.     readdb_get_header(rdfp, HitList[iHitList].GetSeqIndex(),
  759.       &header, &sip,&blastdefline);
  760.     bestid = SeqIdFindBest(sip, SEQID_GI);
  761.     if(!bestid) continue;
  762.     CheckGi(bestid->data.intvalue);
  763.     MemFree(blastdefline);
  764.     SeqIdSetFree(sip);
  765. #endif
  766.     // recompute ladder
  767.     length = readdb_get_sequence(rdfp, 
  768.  HitList[iHitList].GetSeqIndex(),
  769.  &Sequence);
  770.     int tempMass = HitList[iHitList].GetMass();
  771.     int tempStart = HitList[iHitList].GetStart();
  772.     int tempStop = HitList[iHitList].GetStop();
  773.     int Charge = HitList[iHitList].GetCharge();
  774.     int Which = Peaks->GetWhich(Charge);
  775.     double a = CalcPoissonMean(tempStart, tempStop, tempMass, Peaks,
  776.        Charge, 
  777.        Threshold);
  778.     if ( a < 0) continue;  // error return;
  779.     if(HitList[iHitList].GetHits() < a) continue;
  780.     double pval;
  781.     if(NewScore) {
  782. int High, Low, NumPeaks, NumLo, NumHi;
  783. Peaks->HighLow(High, Low, NumPeaks, tempMass, Charge, Threshold, NumLo, NumHi);
  784.  
  785. double TopHitProb = ((double)MSNUMTOP)/NumPeaks;
  786. double Normal = CalcNormalTopHit(a, TopHitProb);
  787. pval = CalcPvalueTopHit(a, 
  788. HitList[iHitList].GetHits(Threshold, Peaks->GetMaxI(Which)),
  789. Peaks->GetPeptidesExamined(Charge), Normal, TopHitProb);
  790. #ifdef MSSTATRUN
  791. cout << pval << " " << a << " " << Charge << endl;
  792. // cerr << "pval = " << pval << " Normal = " << Normal << endl;
  793. #endif
  794.     }
  795.     else {
  796. pval =
  797.     CalcPvalue(a, HitList[iHitList].
  798.        GetHits(Threshold, Peaks->GetMaxI(Which)),
  799.        Peaks->GetPeptidesExamined(Charge));
  800.     }
  801.     double eval = pval * Peaks->GetPeptidesExamined(Charge);
  802.     ScoreList.insert(pair<const double, CMSHit *> 
  803.      (eval, &(HitList[iHitList])));
  804. }   
  805.     } 
  806. }
  807. //calculates the poisson times the top hit probability
  808. double CSearch::CalcPoissonTopHit(double Mean, int i, double TopHitProb)
  809. {
  810. double retval;
  811. #ifdef NCBI_OS_MSWIN
  812.     retval =  exp(-Mean) * pow(Mean, i) / exp(LnGamma(i+1));
  813. #else
  814.     retval =  exp(-Mean) * pow(Mean, i) / exp(lgamma(i+1));
  815. #endif
  816. retval *= 1.0L - pow((1.0L-TopHitProb), i);
  817. return retval;
  818. }
  819. double CSearch::CalcPoisson(double Mean, int i)
  820. {
  821. #ifdef NCBI_OS_MSWIN
  822.     return exp(-Mean) * pow(Mean, i) / exp(LnGamma(i+1));
  823. #else
  824.     return exp(-Mean) * pow(Mean, i) / exp(lgamma(i+1));
  825. #endif
  826. }
  827. double CSearch::CalcPvalue(double Mean, int Hits, int n)
  828. {
  829.     if(Hits <= 0) return 1.0L;
  830.     int i;
  831.     double retval(0.0L);
  832.     for(i = 0; i < Hits; i++)
  833. retval += CalcPoisson(Mean, i);
  834.     retval = 1.0L - pow(retval, n);
  835.     if(retval <= 0.0L) retval = numeric_limits<double>::min();
  836.     return retval;
  837. }
  838. #define MSDOUBLELIMIT 0.0000000000000001L
  839. // do full summation of probability distribution
  840. double CSearch::CalcNormalTopHit(double Mean, double TopHitProb)
  841. {
  842.     int i;
  843.     double retval(0.0L), before(-1.0L), increment;
  844.     for(i = 1; i < 1000; i++) {
  845. increment = CalcPoissonTopHit(Mean, i, TopHitProb);
  846. // convergence hack -- on linux (at least) convergence test doesn't work
  847. // for gcc release build
  848. if(increment <= MSDOUBLELIMIT) break;
  849. // if(increment <= numeric_limits<double>::epsilon()) break;
  850. retval += increment;
  851. if(retval == before) break;  // convergence
  852. before = retval;
  853.     }
  854.     return retval;
  855. }
  856. double CSearch::CalcPvalueTopHit(double Mean, int Hits, int n, double Normal, double TopHitProb)
  857. {
  858.     if(Hits <= 0) return 1.0L;
  859.     int i;
  860.     double retval(0.0L), increment;
  861.     for(i = 1; i < Hits; i++) {
  862. increment = CalcPoissonTopHit(Mean, i, TopHitProb);
  863. if(increment <= MSDOUBLELIMIT) break;
  864. retval += increment;
  865.     }
  866.     retval /= Normal;
  867.     retval = 1.0L - pow(retval, n);
  868.     if(retval <= 0.0L) retval = numeric_limits<double>::min();
  869.     return retval;
  870. }
  871. double CSearch::CalcPoissonMean(int Start, int Stop, int Mass, CMSPeak *Peaks,
  872. int Charge, double Threshold)
  873. {
  874.     double retval(1.0);
  875.     
  876.     double m; // mass of ladder
  877.     double o; // min m/z value of peaks
  878.     double r; // max m/z value of peaks
  879.     double h; // number of calculated m/z values in one ion series
  880.     double v1; // number of m/z values above mh/2 and below mh (+1 product ions)
  881.     double v2; // number of m/z value below mh/2
  882.     double v;  // number of peaks
  883.     double t; // mass tolerance width
  884.     int High, Low, NumPeaks, NumLo, NumHi;
  885.     Peaks->HighLow(High, Low, NumPeaks, Mass, Charge, Threshold, NumLo, NumHi);
  886.     if(High == -1) return -1.0; // error
  887.     o = (double)Low/MSSCALE;
  888.     r = (double)High/MSSCALE;
  889.     v1 = NumHi;
  890.     v2 = NumLo;
  891.     v = NumPeaks;
  892.     m = Mass/(double)MSSCALE;
  893.     h = Stop - Start;
  894.     t = (Peaks->GetTol())/(double)MSSCALE;
  895.     // see 12/13/02 notebook, pg. 127
  896.     retval = 4.0 * t * h * v / m;
  897.     if(Charge >= kConsiderMult) {
  898. retval *= (m - 3*o + r)/(r - o);
  899.     }    
  900. #if 0
  901.     // variation that counts +1 and +2 separately
  902.     // see 8/19/03 notebook, pg. 71
  903.     retval = 4.0 * t * h / m;
  904.     if(Charge >= kConsiderMult) {
  905. // retval *= (m - 3*o + r)/(r - o);
  906. retval *= (3 * v2 + v1);
  907.     }
  908.     else retval *= (v2 + v1);
  909. #endif
  910.     return retval;
  911. }
  912. CSearch::~CSearch()
  913. {
  914.     if(rdfp) readdb_destruct(rdfp);
  915. }
  916. /*
  917. $Log: omssa.cpp,v $
  918. Revision 1000.4  2004/06/01 18:09:10  gouriano
  919. PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.20
  920. Revision 1.20  2004/05/27 20:52:15  lewisg
  921. better exception checking, use of AutoPtr, command line parsing
  922. Revision 1.19  2004/05/21 21:41:03  gorelenk
  923. Added PCH ncbi_pch.hpp
  924. Revision 1.18  2004/04/06 19:53:20  lewisg
  925. allow adjustment of precursor charges that allow multiply charged product ions
  926. Revision 1.17  2004/04/05 20:49:16  lewisg
  927. fix missed mass bug and reorganize code
  928. Revision 1.16  2004/03/31 02:00:26  ucko
  929. +<algorithm> for sort()
  930. Revision 1.15  2004/03/30 19:36:59  lewisg
  931. multiple mod code
  932. Revision 1.14  2004/03/16 20:18:54  gorelenk
  933. Changed includes of private headers.
  934. Revision 1.13  2004/03/01 18:24:08  lewisg
  935. better mod handling
  936. Revision 1.12  2003/12/22 21:58:00  lewisg
  937. top hit code and variable mod fixes
  938. Revision 1.11  2003/12/04 23:39:08  lewisg
  939. no-overlap hits and various bugfixes
  940. Revision 1.10  2003/11/20 22:32:50  lewisg
  941. fix end of sequence X bug
  942. Revision 1.9  2003/11/20 15:40:53  lewisg
  943. fix hitlist bug, change defaults
  944. Revision 1.8  2003/11/17 18:36:56  lewisg
  945. fix cref use to make sure ref counts are decremented at loop termination
  946. Revision 1.7  2003/11/14 20:28:06  lewisg
  947. scale precursor tolerance by charge
  948. Revision 1.6  2003/11/13 19:07:38  lewisg
  949. bugs: iterate completely over nr, don't initialize blastdb by iteration
  950. Revision 1.5  2003/11/10 22:24:12  lewisg
  951. allow hitlist size to vary
  952.   Revision 1.4  2003/10/24 21:28:41  lewisg
  953.   add omssa, xomssa, omssacl to win32 build, including dll
  954.   
  955. Revision 1.3  2003/10/22 15:03:32  lewisg
  956. limits and string compare changed for gcc 2.95 compatibility
  957.   Revision 1.2  2003/10/21 21:12:17  lewisg
  958.   reorder headers
  959.   
  960. Revision 1.1  2003/10/20 21:32:13  lewisg
  961. ommsa toolkit version
  962.   Revision 1.18  2003/10/07 18:02:28  lewisg
  963.   prep for toolkit
  964.   
  965. Revision 1.17  2003/10/06 18:14:17  lewisg
  966. threshold vary
  967.   Revision 1.16  2003/08/14 23:49:22  lewisg
  968.   first pass at variable mod
  969.   
  970. Revision 1.15  2003/08/06 18:29:11  lewisg
  971. support for filenames, numbers using regex
  972.   Revision 1.14  2003/07/21 20:25:03  lewisg
  973.   fix missing peak bug
  974.   
  975. Revision 1.13  2003/07/19 15:07:38  lewisg
  976. indexed peaks
  977.   Revision 1.12  2003/07/18 20:50:34  lewisg
  978.   *** empty log message ***
  979.   
  980. Revision 1.11  2003/07/17 18:45:50  lewisg
  981. multi dta support
  982.   Revision 1.10  2003/07/07 16:17:51  lewisg
  983.   new poisson distribution and turn off histogram
  984.   
  985. Revision 1.9  2003/05/01 14:52:10  lewisg
  986. fixes to scoring
  987.   Revision 1.8  2003/04/18 20:46:52  lewisg
  988.   add graphing to omssa
  989.   
  990. Revision 1.7  2003/04/07 16:47:16  lewisg
  991. pc fixes
  992.   Revision 1.6  2003/04/04 18:43:51  lewisg
  993.   tax cut
  994.   
  995. Revision 1.5  2003/04/02 18:49:51  lewisg
  996. improved score, architectural changes
  997.   Revision 1.4  2003/03/21 21:14:40  lewisg
  998.   merge ming's code, other stuff
  999.   
  1000. Revision 1.3  2003/02/10 19:37:56  lewisg
  1001. perf and web page cleanup
  1002.   Revision 1.2  2003/02/07 16:18:23  lewisg
  1003.   bugfixes for perf and to work on exp data
  1004.   
  1005. Revision 1.1  2003/02/03 20:39:02  lewisg
  1006. omssa cgi
  1007.   
  1008. */