1 /* massXpert - the true massist's program. 2 -------------------------------------- 3 Copyright(C) 2006,2007 Filippo Rusconi 4 5 http://www.massxpert.org/massXpert 6 7 This file is part of the massXpert project. 8 9 The massxpert project is the successor to the "GNU polyxmass" 10 project that is an official GNU project package(see 11 www.gnu.org). The massXpert project is not endorsed by the GNU 12 project, although it is released ---in its entirety--- under the 13 GNU General Public License. A huge part of the code in massXpert 14 is actually a C++ rewrite of code in GNU polyxmass. As such 15 massXpert was started at the Centre National de la Recherche 16 Scientifique(FRANCE), that granted me the formal authorization to 17 publish it under this Free Software License. 18 19 This software is free software; you can redistribute it and/or 20 modify it under the terms of the GNU General Public 21 License version 3, as published by the Free Software Foundation. 22 23 24 This software is distributed in the hope that it will be useful, 25 but WITHOUT ANY WARRANTY; without even the implied warranty of 26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27 General Public License for more details. 28 29 You should have received a copy of the GNU General Public License 30 along with this software; if not, write to the 31 32 Free Software Foundation, Inc., 33 34 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. 35 */ 36 37 38 /////////////////////// Local includes 39 #include "oligomer.hpp" 40 #include "polymer.hpp" 41 #include "ionizeRule.hpp" 42 43 44 namespace massXpert 45 { 46 47 //! Constructs an oligomer. 48 /*! 49 50 \param polymer Polymer in which \c this oligomer spans a region. Cannot 51 be 0. 52 53 \param ponderable Ponderable used to initialized the data in \c 54 this. Note that the initialization is shallow, as the data in the 55 property list are not copied. 56 57 \param name Name of the oligomer. 58 59 \param startIndex Index of the first monomer of \c this oligomer in 60 the polymer sequence(note that this index is stored in the very first 61 Coordinates item in the CoordinateList). 62 63 \param endIndex Index of the last monomer of \c this oligomer in the 64 polymer sequence(note that this index is stored in the very first 65 Coordinates item in the CoordinateList). 66 67 \param ionizeRule IonizeRule to be used to initialize the Ionizable ancestor. 68 69 \param isIonized Indicates if the oligomer should be considered 70 ionized. 71 */ Oligomer(Polymer * polymer,const QString & name,const QString & description,const Ponderable & ponderable,const IonizeRule & ionizeRule,const CalcOptions & calcOptions,bool isIonized,int startIndex,int endIndex)72 Oligomer::Oligomer(Polymer *polymer , 73 const QString &name, 74 const QString &description, 75 const Ponderable &ponderable, 76 const IonizeRule &ionizeRule, 77 const CalcOptions & calcOptions, 78 bool isIonized, 79 int startIndex, int endIndex) 80 : Ionizable(polymer->polChemDef(), name, ponderable, 81 ionizeRule, isIonized), 82 mp_polymer(polymer), 83 m_description(description), 84 m_calcOptions(calcOptions) 85 { 86 setStartEndIndices(startIndex, endIndex); 87 } 88 89 90 //! Constructs an oligomer. 91 /*! The oligomer is constructed with its \c mp_polymer member set to 92 0. This means that no reference to the polymer can be done. This 93 constructor is useful when the oligomer must be created out of any 94 polymer context, like when oligomers are created starting from raw 95 text data in the MzLab window. 96 97 \param polChemDef Polymer chemistry definition on which \c this 98 oligomer is based. Cannot be 0. 99 100 \param ponderable Ponderable used to initialized the data in \c 101 this. Note that the initialization is shallow, as the data in the 102 property list are not copied. 103 104 \param name Name of the oligomer. 105 106 \param startIndex Index of the first monomer of \c this oligomer in 107 the polymer sequence(note that this index is stored in the very first 108 Coordinates item in the CoordinateList). 109 110 \param endIndex Index of the last monomer of \c this oligomer in the 111 polymer sequence(note that this index is stored in the very first 112 Coordinates item in the CoordinateList). 113 114 \param ionizeRule IonizeRule to be used to initialize the Ionizable ancestor. 115 116 \param isIonized Indicates if the oligomer should be considered 117 ionized. 118 */ Oligomer(const PolChemDef * polChemDef,const QString & name,const QString & description,const Ponderable & ponderable,const IonizeRule & ionizeRule,const CalcOptions & calcOptions,bool isIonized,int startIndex,int endIndex)119 Oligomer::Oligomer(const PolChemDef *polChemDef, 120 const QString &name, 121 const QString &description, 122 const Ponderable &ponderable, 123 const IonizeRule &ionizeRule, 124 const CalcOptions &calcOptions, 125 bool isIonized, 126 int startIndex, int endIndex) 127 : Ionizable(polChemDef, name, ponderable, ionizeRule, isIonized), 128 mp_polymer(0), 129 m_description(description), 130 m_calcOptions(calcOptions) 131 { 132 setStartEndIndices(startIndex, endIndex); 133 // if (startIndex < 0) 134 // qDebug() << __FILE__ << __LINE__ 135 // << "Construct with startIndex:" << startIndex; 136 } 137 138 139 //! Constructs an oligomer. 140 /*! 141 142 \param polymer Polymer in which \c this oligomer spans a region. Cannot 143 be 0. 144 145 \param ponderable Ponderable used to initialized the data in \c 146 this. Note that the initialization is shallow, as the data in the 147 property list are not copied. 148 149 \param name Name of the oligomer. 150 151 \param startIndex Index of the first monomer of \c this oligomer in 152 the polymer sequence(note that this index is stored in the very first 153 Coordinates item in the CoordinateList). 154 155 \param endIndex Index of the last monomer of \c this oligomer in the 156 polymer sequence(note that this index is stored in the very first 157 Coordinates item in the CoordinateList). 158 */ Oligomer(Polymer * polymer,const QString & name,const QString & description,const Ponderable & ponderable,int startIndex,int endIndex,const CalcOptions & calcOptions)159 Oligomer::Oligomer(Polymer *polymer, 160 const QString &name, 161 const QString &description, 162 const Ponderable &ponderable, 163 int startIndex, int endIndex, 164 const CalcOptions &calcOptions) 165 : Ionizable(polymer->polChemDef(), name, ponderable), 166 mp_polymer(polymer), 167 m_description(description), 168 m_calcOptions(calcOptions) 169 { 170 setStartEndIndices(startIndex, endIndex); 171 if (startIndex < 0) 172 qDebug() << __FILE__ << __LINE__ 173 << "Construct with startIndex:" << startIndex; 174 } 175 176 177 //! Constructs an oligomer. 178 /*! The oligomer is constructed with its \c mp_polymer member set to 179 0. This means that no reference to the polymer can be done. This 180 constructor is useful when the oligomer must be created out of any 181 polymer context, like when oligomers are created starting from raw 182 text data in the MzLab window. 183 184 \param polChemDef Polymer chemistry definition on which \c this 185 oligomer is based. Cannot be 0. 186 187 \param ponderable Ponderable used to initialized the data in \c 188 this. Note that the initialization is shallow, as the data in the 189 property list are not copied. 190 191 \param name Name of the oligomer. 192 193 \param startIndex Index of the first monomer of \c this oligomer in 194 the polymer sequence(note that this index is stored in the very first 195 Coordinates item in the CoordinateList). 196 197 \param endIndex Index of the last monomer of \c this oligomer in the 198 polymer sequence(note that this index is stored in the very first 199 Coordinates item in the CoordinateList). 200 */ Oligomer(const PolChemDef * polChemDef,const QString & name,const QString & description,const Ponderable & ponderable,const CalcOptions & calcOptions,int startIndex,int endIndex)201 Oligomer::Oligomer(const PolChemDef *polChemDef, 202 const QString &name, 203 const QString &description, 204 const Ponderable &ponderable, 205 const CalcOptions &calcOptions, 206 int startIndex, int endIndex) 207 : Ionizable(polChemDef, name, ponderable), 208 mp_polymer(0), 209 m_description(description), 210 m_calcOptions(calcOptions) 211 { 212 setStartEndIndices(startIndex, endIndex); 213 if (startIndex < 0) 214 qDebug() << __FILE__ << __LINE__ 215 << "Construct with startIndex:" << startIndex; 216 } 217 218 Oligomer(const Ionizable & ionizable,const CalcOptions & calcOptions,int startIndex,int endIndex)219 Oligomer::Oligomer(const Ionizable& ionizable, 220 const CalcOptions &calcOptions, 221 int startIndex, int endIndex) 222 : Ionizable(ionizable), 223 mp_polymer(0), 224 m_description("NOT_SET"), 225 m_calcOptions(calcOptions) 226 { 227 setStartEndIndices(startIndex, endIndex); 228 if (startIndex < 0) 229 qDebug() << __FILE__ << __LINE__ 230 << "Construct with startIndex:" << startIndex; 231 } 232 233 234 //! Constructs an oligomer. 235 /*! 236 237 \param polymer Polymer in which \c this oligomer spans a region. Cannot 238 be 0. 239 240 \param name Name of the oligomer. 241 242 \param startIndex Index of the first monomer of \c this oligomer in 243 the polymer sequence. 244 245 \param endIndex Index of the last monomer of \c this oligomer in the 246 polymer sequence. 247 248 \param mono Monoisotopic mass. 249 250 \param avg Average mass. 251 */ Oligomer(Polymer * polymer,const QString & name,const QString & description,double mono,double avg,int startIndex,int endIndex,const CalcOptions & calcOptions)252 Oligomer::Oligomer(Polymer *polymer , 253 const QString &name, 254 const QString &description, 255 double mono, double avg, 256 int startIndex, int endIndex, 257 const CalcOptions &calcOptions) 258 : Ionizable(mp_polymer->polChemDef(), name, Ponderable(mono, avg)), 259 mp_polymer(polymer), 260 m_description(description), 261 m_calcOptions(calcOptions) 262 { 263 setStartEndIndices(startIndex, endIndex); 264 if (startIndex < 0) 265 qDebug() << __FILE__ << __LINE__ 266 << "Construct with startIndex:" << startIndex; 267 } 268 269 270 //! Constructs an oligomer. 271 /*! The oligomer is constructed with its \c mp_polymer member set to 272 0. This means that no reference to the polymer can be done. This 273 constructor is useful when the oligomer must be created out of any 274 polymer context, like when oligomers are created starting from raw 275 text data in the MzLab window. 276 277 \param polChemDef Polymer chemistry definition on which \c this 278 oligomer is based. Cannot be 0. 279 280 \param name Name of the oligomer. 281 282 \param startIndex Index of the first monomer of \c this oligomer in 283 the polymer sequence. 284 285 \param endIndex Index of the last monomer of \c this oligomer in the 286 polymer sequence. 287 288 \param mono Monoisotopic mass. 289 290 \param avg Average mass. 291 */ Oligomer(const PolChemDef * polChemDef,const QString & name,const QString & description,const CalcOptions & calcOptions,double mono,double avg,int startIndex,int endIndex)292 Oligomer::Oligomer(const PolChemDef *polChemDef, 293 const QString &name, 294 const QString &description, 295 const CalcOptions &calcOptions, 296 double mono, double avg, 297 int startIndex, int endIndex) 298 : Ionizable(polChemDef, name, Ponderable(mono, avg)), 299 mp_polymer(0), 300 m_description(description), 301 m_calcOptions(calcOptions) 302 { 303 setStartEndIndices(startIndex, endIndex); 304 } 305 306 307 //! Constructs a copy of \p other. 308 /*! The copying is shallow, as the data in the property list are not 309 copied. 310 311 \param other oligomer to be used as a mold. 312 */ Oligomer(const Oligomer & other)313 Oligomer::Oligomer(const Oligomer &other) 314 : CoordinateList(other), Ionizable(other), PropListHolder(other), 315 mp_polymer(other.mp_polymer), 316 m_description(other.m_description), 317 m_calcOptions(other.m_calcOptions) 318 { 319 } 320 321 322 //! Destroys the oligomer. ~Oligomer()323 Oligomer::~Oligomer() 324 { 325 // qDebug() << "~Oligomer()"; 326 } 327 328 329 330 //! Returns the polymer. 331 /*! \return the polymer. 332 */ 333 const Polymer * polymer() const334 Oligomer::polymer() const 335 { 336 return mp_polymer; 337 } 338 339 340 //! Sets the start and end indices. 341 /*! \param value1 New start index 342 \param value2 New end index 343 */ 344 void setStartEndIndices(int value1,int value2)345 Oligomer::setStartEndIndices(int value1, int value2) 346 { 347 if (!CoordinateList::size()) 348 { 349 Coordinates *coordinates = new Coordinates(value1, value2); 350 append(coordinates); 351 352 // qDebug() << __FILE__ << __LINE__ 353 // << "[start--end]:" << startIndex() << endIndex(); 354 } 355 else 356 { 357 Coordinates *coordinates = first(); 358 coordinates->setStart(value1); 359 coordinates->setEnd(value2); 360 361 // qDebug() << __FILE__ << __LINE__ 362 // << "[start--end]:" << startIndex() << endIndex(); 363 } 364 } 365 366 367 //! Sets the start index. 368 /*! \param value New start index. 369 */ 370 void setStartIndex(int value)371 Oligomer::setStartIndex(int value) 372 { 373 if (value < 0) 374 qDebug() << __FILE__ << __LINE__ 375 << "setStartIndex with value:" << value; 376 377 if (!CoordinateList::size()) 378 { 379 Coordinates *coordinates = new Coordinates(); 380 coordinates->setStart(value); 381 append(coordinates); 382 } 383 else 384 { 385 Coordinates *coordinates = first(); 386 coordinates->setStart(value); 387 } 388 } 389 390 391 //! Returns the start index. 392 /*! \return the start index. 393 */ 394 int startIndex() const395 Oligomer::startIndex() const 396 { 397 if (!CoordinateList::size()) 398 return -1; 399 400 Coordinates *coordinates = first(); 401 return coordinates->start(); 402 } 403 404 405 //! Sets the end index. 406 /*! \param value New end index. 407 */ 408 void setEndIndex(int value)409 Oligomer::setEndIndex(int value) 410 { 411 if (!CoordinateList::size()) 412 { 413 Coordinates *coordinates = new Coordinates(); 414 coordinates->setEnd(value); 415 append(coordinates); 416 } 417 else 418 { 419 Coordinates *coordinates = first(); 420 coordinates->setEnd(value); 421 } 422 } 423 424 425 //! Returns the end index. 426 /*! \return the end index. 427 */ 428 int endIndex() const429 Oligomer::endIndex() const 430 { 431 if (!CoordinateList::size()) 432 return -1; 433 434 Coordinates *coordinates = first(); 435 return coordinates->end(); 436 } 437 438 439 void setDescription(const QString & description)440 Oligomer::setDescription(const QString &description) 441 { 442 m_description = description; 443 } 444 445 446 QString description() const447 Oligomer::description() const 448 { 449 return m_description; 450 } 451 452 453 int appendCoordinates(CoordinateList * list)454 Oligomer::appendCoordinates(CoordinateList *list) 455 { 456 Q_ASSERT(list); 457 458 int count = 0; 459 460 for (int iter = 0; iter < list->size(); ++iter) 461 { 462 Coordinates *iterCoordinates = list->at(iter); 463 464 Coordinates *coordinates = new Coordinates(*iterCoordinates); 465 466 append(coordinates); 467 468 ++count; 469 } 470 471 return count; 472 } 473 474 475 void setIonizeRule(IonizeRule & ionizeRule)476 Oligomer::setIonizeRule(IonizeRule &ionizeRule) 477 { 478 m_ionizeRule = ionizeRule; 479 } 480 481 482 IonizeRule & ionizeRule()483 Oligomer::ionizeRule() 484 { 485 return m_ionizeRule; 486 } 487 488 void setCalcOptions(const CalcOptions & calcOptions)489 Oligomer::setCalcOptions(const CalcOptions &calcOptions) 490 { 491 m_calcOptions = calcOptions; 492 } 493 494 495 const CalcOptions & calcOptions() const496 Oligomer::calcOptions() const 497 { 498 return m_calcOptions; 499 } 500 501 void updateCalcOptions()502 Oligomer::updateCalcOptions() 503 { 504 // The data that need update are the CoordinateList elements 505 // depending on the internal ::OligomerList data. 506 507 m_calcOptions.setCoordinateList(*(static_cast<CoordinateList *>(this))); 508 } 509 510 511 512 const Monomer & atLeftEnd() const513 Oligomer::atLeftEnd() const 514 { 515 // qDebug() << __FILE__ << __LINE__ << "Going to call at() with value" 516 // << startIndex(); 517 518 return *(mp_polymer->at(startIndex())); 519 } 520 521 522 const Monomer & atRightEnd() const523 Oligomer::atRightEnd() const 524 { 525 // qDebug() << __FILE__ << __LINE__ << "Going to call at() with value" 526 // << endIndex(); 527 528 return *(mp_polymer->at(endIndex())); 529 530 531 } 532 533 534 const Monomer * monomerAt(int index) const535 Oligomer::monomerAt(int index) const 536 { 537 Q_ASSERT(index >= 0); 538 Q_ASSERT(index < mp_polymer->size() - 1); 539 540 // qDebug() << __FILE__ << __LINE__ << "Going to call at() with value" 541 // << index; 542 543 return mp_polymer->at(index); 544 } 545 546 547 QList<CrossLink *> * crossLinkList()548 Oligomer::crossLinkList() 549 { 550 return &m_crossLinkList; 551 } 552 553 554 bool addCrossLink(CrossLink * crossLink)555 Oligomer::addCrossLink(CrossLink *crossLink) 556 { 557 // Add the cross-link only if it does not exist already. Return true 558 // only if the crossLink has been added. 559 560 if (!m_crossLinkList.contains(crossLink)) 561 { 562 m_crossLinkList.append(crossLink); 563 564 return true; 565 } 566 567 return false; 568 } 569 570 571 // ELEMENTAL CALCULATION FUNCTION 572 ///////////////////////////////// 573 574 QString elementalComposition()575 Oligomer::elementalComposition() 576 { 577 int times = 0; 578 579 if (m_calcOptions.selectionType() == SELECTION_TYPE_RESIDUAL_CHAINS) 580 { 581 times = 1; 582 583 // qDebug() << __FILE__ << __LINE__ 584 // << "SELECTION_TYPE_RESIDUAL_CHAINS ; times:" << times; 585 } 586 else 587 { 588 // times = CoordinateList::size(); 589 590 // Use the version whereby we can perform a sanity check that 591 // m_calcOptions was updated with the proper CoordinateList 592 // data. 593 594 times = m_calcOptions.coordinateList().size(); 595 if(times != CoordinateList::size()) 596 qFatal("Fatal error at %s@%d. Aborting.",__FILE__, __LINE__); 597 598 // qDebug() << __FILE__ << __LINE__ 599 // << "SELECTION_TYPE_OLIGOMERS ; times:" << times; 600 } 601 602 return mp_polymer->elementalComposition 603 (m_ionizeRule, 604 *(static_cast<CoordinateList *>(this)), 605 m_calcOptions); 606 } 607 608 609 ///////////////////////////////// 610 // ELEMENTAL CALCULATION FUNCTION 611 612 613 int makeMonomerText()614 Oligomer::makeMonomerText() 615 { 616 // Prepare the text version of the oligomer's sequence by basing 617 // it on the coordinates of *this oligomer and set that text to 618 // m_monomerText. 619 620 if (!mp_polymer) 621 return 0; 622 623 QString *text = monomerText(); 624 625 m_monomerText = *text; 626 627 delete(text); 628 629 return m_monomerText.size(); 630 } 631 632 633 QString * monomerText()634 Oligomer::monomerText() 635 { 636 // Allocate a new string to hold the text version of *this 637 // oligomer's sequence. 638 639 // There are two situations: 640 641 // 1. The mp_polymer member is non-0, we can get access to it. Ask 642 // the polymer to do the work. This is the most faithful 643 // situation. But the caller must first ensure that the polymer 644 // actually exists. 645 646 // 2. The mp_polymer member is 0, we may have the oligomer 647 // sequence stored in *this oligomer. Test that. 648 649 QString *text = new QString(); 650 651 if (mp_polymer) 652 { 653 // For each oligomer(if more than one, which is the case when the 654 // oligomer is actually a cross-linked oligomer), create a string... 655 656 int oligomerCount = CoordinateList::size(); 657 658 for(int iter = 0; iter < oligomerCount; ++iter) 659 { 660 Coordinates *coordinates = CoordinateList::at(iter); 661 662 QString *local = 663 mp_polymer->monomerText(coordinates->start(), 664 coordinates->end(), 665 true); 666 text->append(*local); 667 668 // If this is a cross-linked oligomer and we are not appending 669 // text for the __last__ oligomer, then append "~" to let the 670 // user know that the sequences are cross-linked. 671 if (oligomerCount > 1 && iter < oligomerCount - 1) 672 text->append("~"); 673 674 delete(local); 675 } 676 } 677 else 678 { 679 if(m_monomerText.size()) 680 { 681 *text = m_monomerText; 682 683 return text; 684 } 685 else 686 { 687 if (m_monomerList.size()) 688 return Sequence::monomerText(0, m_monomerList.size(), true); 689 } 690 } 691 692 return text; 693 } 694 695 696 //! Calculates the masses(mono and avg). 697 /*! The calculation is performed by computing the mono and avg masses 698 of the sequence stretch as described by the start and end indices in 699 the polymer sequence. Default calculation options are used. 700 701 \return true if calculations were successful, false otherwise. 702 703 \sa calculateMasses(const CalcOptions &calcOptions, const 704 IonizeRule &ionizeRule) 705 706 \sa Polymer::ionize() 707 708 \sa CalcOptions::CalcOptions() 709 */ 710 bool calculateMasses()711 Oligomer::calculateMasses() 712 { 713 CalcOptions calcOptions; 714 715 calcOptions.setCapping(MXT_CAP_NONE); 716 717 IonizeRule rule; 718 719 return calculateMasses(&calcOptions, &rule); 720 } 721 722 723 //! Calculates the masses(mono and avg). 724 /*! The calculation is performed by computing the mono and avg masses 725 of the sequence stretch as described by the start and end indices in 726 the polymer sequence. 727 728 \param calcOptions Calculation options to be used for the mass 729 calculation. 730 731 \param ionizeRule Ionization rule to be used for the mass 732 calculation. 733 734 \return true if calculations were successful, false otherwise. 735 736 \sa Polymer::calculateMasses() 737 738 \sa Polymer::ionize() 739 */ 740 bool calculateMasses(const CalcOptions * calcOptions,const IonizeRule * ionizeRule)741 Oligomer::calculateMasses(const CalcOptions *calcOptions, 742 const IonizeRule *ionizeRule) 743 { 744 Q_ASSERT(calcOptions); 745 746 CalcOptions localOptions(*calcOptions); 747 748 // The coordinates of the oligomer are the following: 749 750 // MAMISGMSGRKAS 751 752 // For a tryptic peptide obtained from protein above, we'd have 753 754 // MAMISGMSGR, that is in the oligomer coordinates: 755 756 // [0] MAMISGMSGR [9] 757 758 // When computing the mass of the oligomer, we have to do a 759 760 // for (iter == [0] ; iter < [9 + 1]; ++iter) 761 762 // Which is why we increment add 1 to m_endIndex in the function below. 763 764 // A polymer might be something made of more than one residual chain 765 // in case it is a cross-linked oligomer. Compute the mass fore each 766 // residual chain, without accounting for the cross-links... 767 768 m_mono = 0; 769 m_avg = 0; 770 771 // An oligomer _is_ a CoordinateList, and we need that list in the 772 // calcOptions so that we can call the Polymer::accountMasses 773 // function. 774 775 localOptions.setCoordinateList(*this); 776 777 // We do not want to take into account the cross-links because 778 // we'll be doing this here and because it cannot work if the 779 // cross-links are taken into account from the polymer. 780 781 int flags = localOptions.monomerEntities(); 782 flags &= ~MXT_MONOMER_CHEMENT_CROSS_LINK; 783 localOptions.setMonomerEntities(flags); 784 785 Polymer::accountMasses(mp_polymer, 786 localOptions, &m_mono, &m_avg); 787 788 // qDebug() << __FILE__ << __LINE__ 789 // << "After accounting masses(prior to cross-links):" 790 // << "mono mass is:" << m_mono; 791 792 // At this point, we have added the mass of each constituent 793 // oligomer's residual chain. Let's deal with the cross-links. 794 795 for (int iter = 0; iter < m_crossLinkList.size(); ++iter) 796 { 797 CrossLink *crossLink = m_crossLinkList.at(iter); 798 799 if(!crossLink->accountMasses(&m_mono, &m_avg)) 800 return false; 801 802 // qDebug() << __FILE__ << __LINE__ 803 // << "After accounting cross-link:" 804 // << crossLink->name() 805 // << "mono mass is:" << m_mono; 806 } 807 808 // If an ionizeRule is provided, use it. Otherwise, ionize 809 // automatically using the ::Ionizable IonizeRule. 810 if (ionizeRule) 811 { 812 // Note that if ionizeRule is invalid, then the ionization is 813 // not performed. 814 815 if(ionizeRule->isValid()) 816 { 817 /* 818 if (ionize(mp_polymer, *ionizeRule) == -1) 819 The line above is a huge bug. While we should be 820 ionizing this oligomer, we end up ionizing the polymer ! 821 */ 822 823 if (ionize(*ionizeRule) == -1) 824 return false; 825 } 826 } 827 else 828 { 829 if(ionize() == -1) 830 return false; 831 } 832 833 // qDebug() << __FILE__ << __LINE__ 834 // << "Coming out from the calculateMasses function:" 835 // << "mono mass is:" << m_mono; 836 837 return true; 838 } 839 840 841 //! Tells if the oligomer contains at least one modified monomer. 842 /*! Iterates in the polymer sequence from start index to end index and 843 if one of the iterated monomers contain a PxmModif modification, 844 returns true; 845 846 \return true if at least one monomer is modified, false otherwise. 847 */ 848 bool isModified()849 Oligomer::isModified() 850 { 851 int oligomerCount = CoordinateList::size(); 852 853 for (int iter = 0; iter < oligomerCount; ++iter) 854 { 855 Coordinates *coordinates = CoordinateList::at(iter); 856 857 for(int jter = coordinates->start(); 858 jter < coordinates->end() + 1; ++jter) 859 { 860 // qDebug() << __FILE__ << __LINE__ << "Going to call at() with value" 861 // << iter; 862 863 const Monomer *monomer = mp_polymer->at(jter); 864 865 if (monomer->isModified()) 866 return true; 867 } 868 } 869 870 return false; 871 } 872 873 874 int size()875 Oligomer::size() 876 { 877 int sum = 0; 878 879 int oligomerCount = CoordinateList::size(); 880 881 // The size of an oligomer is the sum of all its oligomeric 882 // components as described by the various coordinates. 883 884 for (int iter = 0; iter < oligomerCount; ++iter) 885 { 886 Coordinates *coordinates = CoordinateList::at(iter); 887 888 sum += coordinates->length(); 889 } 890 891 return sum; 892 } 893 894 895 bool encompasses(int index) const896 Oligomer::encompasses(int index) const 897 { 898 int oligomerCount = CoordinateList::size(); 899 900 for (int iter = 0; iter < oligomerCount; ++iter) 901 { 902 Coordinates *coordinates = CoordinateList::at(iter); 903 904 if(index <= coordinates->start() && index >= coordinates->end()) 905 return true; 906 } 907 908 return false; 909 } 910 911 912 913 bool encompasses(const Monomer * monomer) const914 Oligomer::encompasses(const Monomer *monomer) const 915 { 916 int oligomerCount = CoordinateList::size(); 917 918 for (int iter = 0; iter < oligomerCount; ++iter) 919 { 920 Coordinates *coordinates = CoordinateList::at(iter); 921 922 for(int jter = coordinates->start(); 923 jter < coordinates->end() + 1; ++jter) 924 { 925 // qDebug() << __FILE__ << __LINE__ << "Going to call at() with value" 926 // << jter; 927 928 if (mp_polymer->at(jter) == monomer) 929 return true; 930 } 931 } 932 933 return false; 934 } 935 936 } // namespace massXpert 937